Commit 886077da authored by Marijn Kruisselbrink's avatar Marijn Kruisselbrink Committed by Commit Bot

[NativeFS] Update async iterable API to match spec.

Matching the changes from https://github.com/WICG/native-file-system/pull/177
Since the bindings layer doesn't support async iterables yet, this CL
does this in a bit of a hacky way, that isn't entirely web-idl
compliant. It is much closer to the desired API than what we had though,
so seems an improvement until bindings properly support async iterables.

Bug: 1011539, 1087157
Change-Id: I2eb0a3b1d6383149b769a9961bf890eaf6956b2b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2248414Reviewed-by: default avatarTrent Apted <tapted@chromium.org>
Reviewed-by: default avatarYuki Shiino <yukishiino@chromium.org>
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#790486}
parent 87b556b1
...@@ -720,9 +720,9 @@ IN_PROC_BROWSER_TEST_P( ...@@ -720,9 +720,9 @@ IN_PROC_BROWSER_TEST_P(
web_contents, web_contents,
"(async function() {" "(async function() {"
" let fileNames = [];" " let fileNames = [];"
" const files = await window.launchParams.files[0].getEntries();" " const files = await window.launchParams.files[0].keys();"
" for await (const f of files)" " for await (const name of files)"
" fileNames.push(f.name);" " fileNames.push(name);"
" domAutomationController.send(fileNames.sort().join(';'));" " domAutomationController.send(fileNames.sort().join(';'));"
"})();", "})();",
&file_names)); &file_names));
......
...@@ -532,7 +532,7 @@ async function processOtherFilesInDirectory( ...@@ -532,7 +532,7 @@ async function processOtherFilesInDirectory(
const relatedFiles = []; const relatedFiles = [];
// TODO(b/158149714): Clear out old tokens as well? Care needs to be taken to // TODO(b/158149714): Clear out old tokens as well? Care needs to be taken to
// ensure any file currently open with unsaved changes can still be saved. // ensure any file currently open with unsaved changes can still be saved.
for await (const /** !FileSystemHandle */ handle of directory.getEntries()) { for await (const /** !FileSystemHandle */ handle of directory.values()) {
if (localLaunchNumber !== globalLaunchNumber) { if (localLaunchNumber !== globalLaunchNumber) {
// Abort, another more up to date launch in progress. // Abort, another more up to date launch in progress.
return ProcessOtherFilesResult.ABORT; return ProcessOtherFilesResult.ABORT;
...@@ -565,7 +565,7 @@ async function processOtherFilesInDirectory( ...@@ -565,7 +565,7 @@ async function processOtherFilesInDirectory(
return ProcessOtherFilesResult.ABORT; return ProcessOtherFilesResult.ABORT;
} }
// Iteration order is not guaranteed using `directory.getEntries()`, so we // Iteration order is not guaranteed using `directory.entries()`, so we
// sort it afterwards by modification time to ensure a consistent and logical // sort it afterwards by modification time to ensure a consistent and logical
// order. More recent (i.e. higher timestamp) files should appear first. // order. More recent (i.e. higher timestamp) files should appear first.
relatedFiles.sort((a, b) => { relatedFiles.sort((a, b) => {
......
...@@ -140,8 +140,12 @@ class FileSystemDirectoryHandle extends FileSystemHandle { ...@@ -140,8 +140,12 @@ class FileSystemDirectoryHandle extends FileSystemHandle {
*/ */
getDirectoryHandle(name, options) {} getDirectoryHandle(name, options) {}
/** @return {!AsyncIterable<!Array<string|!FileSystemHandle>>} */
entries() {}
/** @return {!AsyncIterable<string>} */
keys() {}
/** @return {!AsyncIterable<!FileSystemHandle>} */ /** @return {!AsyncIterable<!FileSystemHandle>} */
getEntries() {} values() {}
/** /**
* @param {string} name * @param {string} name
......
...@@ -216,13 +216,35 @@ class FakeFileSystemDirectoryHandle extends FakeFileSystemHandle { ...@@ -216,13 +216,35 @@ class FakeFileSystemDirectoryHandle extends FakeFileSystemHandle {
} }
/** @override */ /** @override */
getDirectoryHandle(name, options) {} getDirectoryHandle(name, options) {}
/**
* @override
* @return {!AsyncIterable<!Array<string|!FileSystemHandle>>}
* @suppress {reportUnknownTypes} suppress [JSC_UNKNOWN_EXPR_TYPE] for `yield
* [file.name, file]`.
*/
async * entries() {
for (const file of this.files) {
yield [file.name, file];
}
}
/**
* @override
* @return {!AsyncIterable<string>}
* @suppress {reportUnknownTypes} suppress [JSC_UNKNOWN_EXPR_TYPE] for `yield
* file.name`.
*/
async * keys() {
for (const file of this.files) {
yield file.name;
}
}
/** /**
* @override * @override
* @return {!AsyncIterable<!FileSystemHandle>} * @return {!AsyncIterable<!FileSystemHandle>}
* @suppress {reportUnknownTypes} suppress [JSC_UNKNOWN_EXPR_TYPE] for `yield * @suppress {reportUnknownTypes} suppress [JSC_UNKNOWN_EXPR_TYPE] for `yield
* file`. * file`.
*/ */
async * getEntries() { async * values() {
for (const file of this.files) { for (const file of this.files) {
yield file; yield file;
} }
......
...@@ -381,7 +381,6 @@ static_idl_files_in_modules = get_path_info( ...@@ -381,7 +381,6 @@ static_idl_files_in_modules = get_path_info(
"//third_party/blink/renderer/modules/native_file_system/file_system_writable_file_stream.idl", "//third_party/blink/renderer/modules/native_file_system/file_system_writable_file_stream.idl",
"//third_party/blink/renderer/modules/native_file_system/get_system_directory_options.idl", "//third_party/blink/renderer/modules/native_file_system/get_system_directory_options.idl",
"//third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.idl", "//third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.idl",
"//third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator_entry.idl",
"//third_party/blink/renderer/modules/native_file_system/open_file_picker_options.idl", "//third_party/blink/renderer/modules/native_file_system/open_file_picker_options.idl",
"//third_party/blink/renderer/modules/native_file_system/save_file_picker_options.idl", "//third_party/blink/renderer/modules/native_file_system/save_file_picker_options.idl",
"//third_party/blink/renderer/modules/native_file_system/window_native_file_system.idl", "//third_party/blink/renderer/modules/native_file_system/window_native_file_system.idl",
......
...@@ -529,6 +529,26 @@ static void Install{{v8_class}}Template( ...@@ -529,6 +529,26 @@ static void Install{{v8_class}}Template(
{% endfilter %} {% endfilter %}
{% endif %} {% endif %}
{% if interface_name == 'FileSystemDirectoryHandle' %}
// Temporary @@asyncIterator support for FileSystemDirectoryHandle
// TODO(https://crbug.com/1087157): Replace with proper bindings support.
static const V8DOMConfiguration::SymbolKeyedMethodConfiguration
kSymbolKeyedIteratorConfiguration = {
v8::Symbol::GetAsyncIterator,
"entries",
V8FileSystemDirectoryHandle::EntriesMethodCallback,
0,
v8::DontEnum,
V8DOMConfiguration::kOnPrototype,
V8DOMConfiguration::kCheckHolder,
V8DOMConfiguration::kDoNotCheckAccess,
V8DOMConfiguration::kHasSideEffect
};
V8DOMConfiguration::InstallMethod(
isolate, world, prototype_template, signature,
kSymbolKeyedIteratorConfiguration);
{% endif %}
{% if interface_name == 'Iterator' %} {% if interface_name == 'Iterator' %}
// The WebIDL spec says when an interface has pair iterators the iterators it // The WebIDL spec says when an interface has pair iterators the iterators it
// returns must be instances of the "default iterator object" whose // returns must be instances of the "default iterator object" whose
...@@ -566,6 +586,17 @@ static void Install{{v8_class}}Template( ...@@ -566,6 +586,17 @@ static void Install{{v8_class}}Template(
interface_template->Inherit(intrinsic_iterator_prototype_interface_template); interface_template->Inherit(intrinsic_iterator_prototype_interface_template);
{% endif %} {% endif %}
{% if interface_name == 'NativeFileSystemDirectoryIterator' %}
// Temporary @@asyncIterator support for FileSystemDirectoryHandle
// TODO(https://crbug.com/1087157): Replace with proper bindings support.
v8::Local<v8::FunctionTemplate> intrinsic_iterator_prototype_interface_template =
v8::FunctionTemplate::New(isolate);
intrinsic_iterator_prototype_interface_template->RemovePrototype();
intrinsic_iterator_prototype_interface_template->SetIntrinsicDataProperty(
V8AtomicString(isolate, "prototype"), v8::kAsyncIteratorPrototype);
interface_template->Inherit(intrinsic_iterator_prototype_interface_template);
{% endif %}
{% if interface_name == 'DOMException' %} {% if interface_name == 'DOMException' %}
// The WebIDL spec states that DOMException objects have a few peculiarities. // The WebIDL spec states that DOMException objects have a few peculiarities.
// One of them is similar to what it mandates for Iterator objects when it // One of them is similar to what it mandates for Iterator objects when it
......
...@@ -10,6 +10,14 @@ ...@@ -10,6 +10,14 @@
RuntimeEnabled=NativeFileSystem, RuntimeEnabled=NativeFileSystem,
ImplementedAs=NativeFileSystemDirectoryHandle ImplementedAs=NativeFileSystemDirectoryHandle
] interface FileSystemDirectoryHandle : FileSystemHandle { ] interface FileSystemDirectoryHandle : FileSystemHandle {
// TODO(https://crbug.com/1087157): This interface defines an async
// iterable, however that isn't supported yet by the bindings. So for now
// just explicitly define what an async iterable definition implies.
//async iterable<USVString, FileSystemHandle>;
NativeFileSystemDirectoryIterator entries();
NativeFileSystemDirectoryIterator keys();
NativeFileSystemDirectoryIterator values();
[CallWith=ScriptState, RuntimeEnabled=LegacyNativeFileSystem, ImplementedAs=getFileHandle] [CallWith=ScriptState, RuntimeEnabled=LegacyNativeFileSystem, ImplementedAs=getFileHandle]
Promise<FileSystemFileHandle> getFile(USVString name, optional FileSystemGetFileOptions options = {}); Promise<FileSystemFileHandle> getFile(USVString name, optional FileSystemGetFileOptions options = {});
[CallWith=ScriptState, RuntimeEnabled=LegacyNativeFileSystem, ImplementedAs=getDirectoryHandle] [CallWith=ScriptState, RuntimeEnabled=LegacyNativeFileSystem, ImplementedAs=getDirectoryHandle]
...@@ -18,7 +26,7 @@ ...@@ -18,7 +26,7 @@
[CallWith=ScriptState] Promise<FileSystemFileHandle> getFileHandle(USVString name, optional FileSystemGetFileOptions options = {}); [CallWith=ScriptState] Promise<FileSystemFileHandle> getFileHandle(USVString name, optional FileSystemGetFileOptions options = {});
[CallWith=ScriptState] Promise<FileSystemDirectoryHandle> getDirectoryHandle(USVString name, optional FileSystemGetDirectoryOptions options = {}); [CallWith=ScriptState] Promise<FileSystemDirectoryHandle> getDirectoryHandle(USVString name, optional FileSystemGetDirectoryOptions options = {});
[CallWith=ScriptState] object getEntries(); [CallWith=ScriptState, RuntimeEnabled=LegacyNativeFileSystem] object getEntries();
[CallWith=ScriptState] Promise<void> removeEntry(USVString name, optional FileSystemRemoveOptions options = {}); [CallWith=ScriptState] Promise<void> removeEntry(USVString name, optional FileSystemRemoveOptions options = {});
......
...@@ -23,7 +23,6 @@ modules_dictionary_idl_files = [ ...@@ -23,7 +23,6 @@ modules_dictionary_idl_files = [
"file_system_remove_options.idl", "file_system_remove_options.idl",
"get_system_directory_options.idl", "get_system_directory_options.idl",
"open_file_picker_options.idl", "open_file_picker_options.idl",
"native_file_system_directory_iterator_entry.idl",
"save_file_picker_options.idl", "save_file_picker_options.idl",
"write_params.idl", "write_params.idl",
] ]
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "third_party/blink/public/mojom/native_file_system/native_file_system_manager.mojom-blink.h" #include "third_party/blink/public/mojom/native_file_system/native_file_system_manager.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_directory_handle.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_get_directory_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_get_directory_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_get_file_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_get_file_options.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_remove_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_remove_options.h"
...@@ -43,6 +44,24 @@ NativeFileSystemDirectoryHandle::NativeFileSystemDirectoryHandle( ...@@ -43,6 +44,24 @@ NativeFileSystemDirectoryHandle::NativeFileSystemDirectoryHandle(
DCHECK(mojo_ptr_.is_bound()); DCHECK(mojo_ptr_.is_bound());
} }
NativeFileSystemDirectoryIterator* NativeFileSystemDirectoryHandle::entries() {
return MakeGarbageCollected<NativeFileSystemDirectoryIterator>(
this, NativeFileSystemDirectoryIterator::Mode::kKeyValue,
GetExecutionContext());
}
NativeFileSystemDirectoryIterator* NativeFileSystemDirectoryHandle::keys() {
return MakeGarbageCollected<NativeFileSystemDirectoryIterator>(
this, NativeFileSystemDirectoryIterator::Mode::kKey,
GetExecutionContext());
}
NativeFileSystemDirectoryIterator* NativeFileSystemDirectoryHandle::values() {
return MakeGarbageCollected<NativeFileSystemDirectoryIterator>(
this, NativeFileSystemDirectoryIterator::Mode::kValue,
GetExecutionContext());
}
ScriptPromise NativeFileSystemDirectoryHandle::getFileHandle( ScriptPromise NativeFileSystemDirectoryHandle::getFileHandle(
ScriptState* script_state, ScriptState* script_state,
const String& name, const String& name,
...@@ -119,7 +138,8 @@ void ReturnDataFunction(const v8::FunctionCallbackInfo<v8::Value>& info) { ...@@ -119,7 +138,8 @@ void ReturnDataFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
ScriptValue NativeFileSystemDirectoryHandle::getEntries( ScriptValue NativeFileSystemDirectoryHandle::getEntries(
ScriptState* script_state) { ScriptState* script_state) {
auto* iterator = MakeGarbageCollected<NativeFileSystemDirectoryIterator>( auto* iterator = MakeGarbageCollected<NativeFileSystemDirectoryIterator>(
this, ExecutionContext::From(script_state)); this, NativeFileSystemDirectoryIterator::Mode::kValue,
ExecutionContext::From(script_state));
auto* isolate = script_state->GetIsolate(); auto* isolate = script_state->GetIsolate();
auto context = script_state->GetContext(); auto context = script_state->GetContext();
v8::Local<v8::Object> result = v8::Object::New(isolate); v8::Local<v8::Object> result = v8::Object::New(isolate);
......
...@@ -15,6 +15,7 @@ class FileSystemGetDirectoryOptions; ...@@ -15,6 +15,7 @@ class FileSystemGetDirectoryOptions;
class FileSystemGetFileOptions; class FileSystemGetFileOptions;
class FileSystemRemoveOptions; class FileSystemRemoveOptions;
class GetSystemDirectoryOptions; class GetSystemDirectoryOptions;
class NativeFileSystemDirectoryIterator;
class NativeFileSystemDirectoryHandle final : public NativeFileSystemHandle { class NativeFileSystemDirectoryHandle final : public NativeFileSystemHandle {
DEFINE_WRAPPERTYPEINFO(); DEFINE_WRAPPERTYPEINFO();
...@@ -25,6 +26,11 @@ class NativeFileSystemDirectoryHandle final : public NativeFileSystemHandle { ...@@ -25,6 +26,11 @@ class NativeFileSystemDirectoryHandle final : public NativeFileSystemHandle {
const String& name, const String& name,
mojo::PendingRemote<mojom::blink::NativeFileSystemDirectoryHandle>); mojo::PendingRemote<mojom::blink::NativeFileSystemDirectoryHandle>);
// FileSystemDirectoryHandle IDL interface:
NativeFileSystemDirectoryIterator* entries();
NativeFileSystemDirectoryIterator* keys();
NativeFileSystemDirectoryIterator* values();
bool isDirectory() const override { return true; } bool isDirectory() const override { return true; }
ScriptPromise getFileHandle(ScriptState*, ScriptPromise getFileHandle(ScriptState*,
......
...@@ -4,8 +4,9 @@ ...@@ -4,8 +4,9 @@
#include "third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.h" #include "third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_native_file_system_directory_iterator_entry.h" #include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/fileapi/file_error.h" #include "third_party/blink/renderer/core/fileapi/file_error.h"
#include "third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h" #include "third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h"
...@@ -17,8 +18,10 @@ namespace blink { ...@@ -17,8 +18,10 @@ namespace blink {
NativeFileSystemDirectoryIterator::NativeFileSystemDirectoryIterator( NativeFileSystemDirectoryIterator::NativeFileSystemDirectoryIterator(
NativeFileSystemDirectoryHandle* directory, NativeFileSystemDirectoryHandle* directory,
Mode mode,
ExecutionContext* execution_context) ExecutionContext* execution_context)
: ExecutionContextClient(execution_context), : ExecutionContextClient(execution_context),
mode_(mode),
directory_(directory), directory_(directory),
receiver_(this, execution_context) { receiver_(this, execution_context) {
directory_->MojoHandle()->GetEntries(receiver_.BindNewPipeAndPassRemote( directory_->MojoHandle()->GetEntries(receiver_.BindNewPipeAndPassRemote(
...@@ -35,10 +38,25 @@ ScriptPromise NativeFileSystemDirectoryIterator::next( ...@@ -35,10 +38,25 @@ ScriptPromise NativeFileSystemDirectoryIterator::next(
} }
if (!entries_.IsEmpty()) { if (!entries_.IsEmpty()) {
NativeFileSystemDirectoryIteratorEntry* result = NativeFileSystemHandle* handle = entries_.TakeFirst();
NativeFileSystemDirectoryIteratorEntry::Create(); ScriptValue result;
result->setValue(entries_.TakeFirst()); switch (mode_) {
return ScriptPromise::Cast(script_state, ToV8(result, script_state)); case Mode::kKey:
result = V8IteratorResult(script_state, handle->name());
break;
case Mode::kValue:
result = V8IteratorResult(script_state, handle);
break;
case Mode::kKeyValue:
HeapVector<ScriptValue, 2> keyvalue;
keyvalue.push_back(ScriptValue(script_state->GetIsolate(),
ToV8(handle->name(), script_state)));
keyvalue.push_back(ScriptValue(script_state->GetIsolate(),
ToV8(handle, script_state)));
result = V8IteratorResult(script_state, keyvalue);
break;
}
return ScriptPromise::Cast(script_state, result);
} }
if (waiting_for_more_entries_) { if (waiting_for_more_entries_) {
...@@ -47,10 +65,7 @@ ScriptPromise NativeFileSystemDirectoryIterator::next( ...@@ -47,10 +65,7 @@ ScriptPromise NativeFileSystemDirectoryIterator::next(
return pending_next_->Promise(); return pending_next_->Promise();
} }
NativeFileSystemDirectoryIteratorEntry* result = return ScriptPromise::Cast(script_state, V8IteratorResultDone(script_state));
NativeFileSystemDirectoryIteratorEntry::Create();
result->setDone(true);
return ScriptPromise::Cast(script_state, ToV8(result, script_state));
} }
void NativeFileSystemDirectoryIterator::Trace(Visitor* visitor) const { void NativeFileSystemDirectoryIterator::Trace(Visitor* visitor) const {
......
...@@ -28,7 +28,11 @@ class NativeFileSystemDirectoryIterator final ...@@ -28,7 +28,11 @@ class NativeFileSystemDirectoryIterator final
USING_GARBAGE_COLLECTED_MIXIN(NativeFileSystemDirectoryIterator); USING_GARBAGE_COLLECTED_MIXIN(NativeFileSystemDirectoryIterator);
public: public:
// Should this iterator returns keys, values or both?
enum Mode { kKey, kValue, kKeyValue };
NativeFileSystemDirectoryIterator(NativeFileSystemDirectoryHandle* directory, NativeFileSystemDirectoryIterator(NativeFileSystemDirectoryHandle* directory,
Mode mode,
ExecutionContext* execution_context); ExecutionContext* execution_context);
ScriptPromise next(ScriptState*); ScriptPromise next(ScriptState*);
...@@ -40,6 +44,7 @@ class NativeFileSystemDirectoryIterator final ...@@ -40,6 +44,7 @@ class NativeFileSystemDirectoryIterator final
Vector<mojom::blink::NativeFileSystemEntryPtr> entries, Vector<mojom::blink::NativeFileSystemEntryPtr> entries,
bool has_more_entries) override; bool has_more_entries) override;
Mode mode_;
mojom::blink::NativeFileSystemErrorPtr error_; mojom::blink::NativeFileSystemErrorPtr error_;
bool waiting_for_more_entries_ = true; bool waiting_for_more_entries_ = true;
HeapDeque<Member<NativeFileSystemHandle>> entries_; HeapDeque<Member<NativeFileSystemHandle>> entries_;
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Used by NativeFileSystemDirectoryIterator to represents results of next() calls.
// https://github.com/WICG/writable-files/blob/master/EXPLAINER.md
// https://www.ecma-international.org/ecma-262/9.0/index.html#sec-iteratorresult-interface
dictionary NativeFileSystemDirectoryIteratorEntry {
FileSystemHandle value;
boolean done = false;
};
...@@ -39,7 +39,7 @@ PASS FileSystemDirectoryHandle interface object name ...@@ -39,7 +39,7 @@ PASS FileSystemDirectoryHandle interface object name
PASS FileSystemDirectoryHandle interface: existence and properties of interface prototype object PASS FileSystemDirectoryHandle interface: existence and properties of interface prototype object
PASS FileSystemDirectoryHandle interface: existence and properties of interface prototype object's "constructor" property PASS FileSystemDirectoryHandle interface: existence and properties of interface prototype object's "constructor" property
PASS FileSystemDirectoryHandle interface: existence and properties of interface prototype object's @@unscopables property PASS FileSystemDirectoryHandle interface: existence and properties of interface prototype object's @@unscopables property
FAIL FileSystemDirectoryHandle interface: async iterable<USVString, FileSystemHandle> Cannot read property 'writable' of undefined FAIL FileSystemDirectoryHandle interface: async iterable<USVString, FileSystemHandle> assert_equals: entries method should be the same as @@asyncIterator method expected function "function entries() { [native code] }" but got function "function entries() { [native code] }"
PASS FileSystemDirectoryHandle interface: operation getFileHandle(USVString, optional FileSystemGetFileOptions) PASS FileSystemDirectoryHandle interface: operation getFileHandle(USVString, optional FileSystemGetFileOptions)
PASS FileSystemDirectoryHandle interface: operation getDirectoryHandle(USVString, optional FileSystemGetDirectoryOptions) PASS FileSystemDirectoryHandle interface: operation getDirectoryHandle(USVString, optional FileSystemGetDirectoryOptions)
PASS FileSystemDirectoryHandle interface: operation removeEntry(USVString, optional FileSystemRemoveOptions) PASS FileSystemDirectoryHandle interface: operation removeEntry(USVString, optional FileSystemRemoveOptions)
......
...@@ -39,7 +39,7 @@ PASS FileSystemDirectoryHandle interface object name ...@@ -39,7 +39,7 @@ PASS FileSystemDirectoryHandle interface object name
PASS FileSystemDirectoryHandle interface: existence and properties of interface prototype object PASS FileSystemDirectoryHandle interface: existence and properties of interface prototype object
PASS FileSystemDirectoryHandle interface: existence and properties of interface prototype object's "constructor" property PASS FileSystemDirectoryHandle interface: existence and properties of interface prototype object's "constructor" property
PASS FileSystemDirectoryHandle interface: existence and properties of interface prototype object's @@unscopables property PASS FileSystemDirectoryHandle interface: existence and properties of interface prototype object's @@unscopables property
FAIL FileSystemDirectoryHandle interface: async iterable<USVString, FileSystemHandle> Cannot read property 'writable' of undefined FAIL FileSystemDirectoryHandle interface: async iterable<USVString, FileSystemHandle> assert_equals: entries method should be the same as @@asyncIterator method expected function "function entries() { [native code] }" but got function "function entries() { [native code] }"
PASS FileSystemDirectoryHandle interface: operation getFileHandle(USVString, optional FileSystemGetFileOptions) PASS FileSystemDirectoryHandle interface: operation getFileHandle(USVString, optional FileSystemGetFileOptions)
PASS FileSystemDirectoryHandle interface: operation getDirectoryHandle(USVString, optional FileSystemGetDirectoryOptions) PASS FileSystemDirectoryHandle interface: operation getDirectoryHandle(USVString, optional FileSystemGetDirectoryOptions)
PASS FileSystemDirectoryHandle interface: operation removeEntry(USVString, optional FileSystemRemoveOptions) PASS FileSystemDirectoryHandle interface: operation removeEntry(USVString, optional FileSystemRemoveOptions)
......
...@@ -7,4 +7,4 @@ ...@@ -7,4 +7,4 @@
<script src="/resources/testdriver-vendor.js"></script> <script src="/resources/testdriver-vendor.js"></script>
<script src="resources/test-helpers.js"></script> <script src="resources/test-helpers.js"></script>
<script src="resources/native-fs-test-helpers.js"></script> <script src="resources/native-fs-test-helpers.js"></script>
<script src="script-tests/FileSystemDirectoryHandle-getEntries.js"></script> <script src="script-tests/FileSystemDirectoryHandle-iteration.js"></script>
...@@ -77,7 +77,7 @@ async function serialize_file_system_directory_handle(directory_handle) { ...@@ -77,7 +77,7 @@ async function serialize_file_system_directory_handle(directory_handle) {
// Serialize the contents of the directory. // Serialize the contents of the directory.
const serialized_files = []; const serialized_files = [];
const serialized_directories = []; const serialized_directories = [];
for await (const child_handle of directory_handle.getEntries()) { for await (const child_handle of directory_handle.values()) {
const serialized_child_handle = await serialize_handle(child_handle); const serialized_child_handle = await serialize_handle(child_handle);
if (child_handle.kind === "directory") { if (child_handle.kind === "directory") {
serialized_directories.push(serialized_child_handle); serialized_directories.push(serialized_child_handle);
......
...@@ -21,7 +21,7 @@ const directory_promise = (async () => { ...@@ -21,7 +21,7 @@ const directory_promise = (async () => {
const entries = await self.showDirectoryPicker(); const entries = await self.showDirectoryPicker();
assert_true(entries instanceof FileSystemHandle); assert_true(entries instanceof FileSystemHandle);
assert_true(entries instanceof FileSystemDirectoryHandle); assert_true(entries instanceof FileSystemDirectoryHandle);
for await (const entry of entries.getEntries()) { for await (const entry of entries) {
assert_unreached('Selected directory is not empty'); assert_unreached('Selected directory is not empty');
} }
return entries; return entries;
...@@ -32,7 +32,7 @@ function directory_test(func, description) { ...@@ -32,7 +32,7 @@ function directory_test(func, description) {
const directory = await directory_promise; const directory = await directory_promise;
// To be resilient against tests not cleaning up properly, cleanup before // To be resilient against tests not cleaning up properly, cleanup before
// every test. // every test.
for await (let entry of directory.getEntries()) { for await (let entry of directory.values()) {
await directory.removeEntry( await directory.removeEntry(
entry.name, {recursive: entry.kind === 'directory'}); entry.name, {recursive: entry.kind === 'directory'});
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
async function cleanupSandboxedFileSystem() { async function cleanupSandboxedFileSystem() {
const dir = const dir =
await self.getOriginPrivateDirectory(); await self.getOriginPrivateDirectory();
for await (let entry of dir.getEntries()) for await (let entry of dir.values())
await dir.removeEntry(entry.name, {recursive: entry.kind === 'directory'}); await dir.removeEntry(entry.name, {recursive: entry.kind === 'directory'});
} }
......
...@@ -25,7 +25,7 @@ async function getFileContents(handle) { ...@@ -25,7 +25,7 @@ async function getFileContents(handle) {
async function getDirectoryEntryCount(handle) { async function getDirectoryEntryCount(handle) {
let result = 0; let result = 0;
for await (let entry of handle.getEntries()) { for await (let entry of handle) {
result++; result++;
} }
return result; return result;
...@@ -33,7 +33,7 @@ async function getDirectoryEntryCount(handle) { ...@@ -33,7 +33,7 @@ async function getDirectoryEntryCount(handle) {
async function getSortedDirectoryEntries(handle) { async function getSortedDirectoryEntries(handle) {
let result = []; let result = [];
for await (let entry of handle.getEntries()) { for await (let entry of handle.values()) {
if (entry.kind === 'directory') if (entry.kind === 'directory')
result.push(entry.name + '/'); result.push(entry.name + '/');
else else
......
// META: script=resources/test-helpers.js // META: script=resources/test-helpers.js
// META: script=resources/sandboxed-fs-test-helpers.js // META: script=resources/sandboxed-fs-test-helpers.js
// META: script=script-tests/FileSystemDirectoryHandle-getEntries.js // META: script=script-tests/FileSystemDirectoryHandle-iteration.js
directory_test(async (t, root) => {
const file_name1 = 'foo1.txt';
const file_name2 = 'foo2.txt';
await createFileWithContents(t, file_name1, 'contents', /*parent=*/ root);
await createFileWithContents(t, file_name2, 'contents', /*parent=*/ root);
let abortIter = async (dir) => {
for await (let entry of dir.getEntries()) {
return entry.name;
}
};
try {
await abortIter(root);
} catch(e) {
assert_unreached('Error thrown on iteration abort.');
}
}, 'getEntries(): returning early from an iteration works');
directory_test(async (t, root) => {
const file_name1 = 'foo1.txt';
const file_name2 = 'foo2.txt';
await createFileWithContents(t, file_name1, 'contents', /*parent=*/ root);
await createFileWithContents(t, file_name2, 'contents', /*parent=*/ root);
let fullIter = async (dir) => {
let name;
for await (let entry of dir.getEntries()) {
name = entry.name;
}
return name;
};
try {
await fullIter(root);
} catch(e) {
assert_unreached('Error thrown on iteration.');
}
}, 'getEntries(): full iteration works');
directory_test(async (t, root) => {
const file_name1 = 'foo1.txt';
const file_name2 = 'foo2.txt';
await createFileWithContents(t, file_name1, 'contents', /*parent=*/ root);
await createFileWithContents(t, file_name2, 'contents', /*parent=*/ root);
for await (let entry of root) {
break;
}
}, 'returning early from an iteration doesn\'t crash');
directory_test(async (t, root) => {
const file_name1 = 'foo1.txt';
const file_name2 = 'foo2.txt';
await createFileWithContents(t, file_name1, 'contents', /*parent=*/ root);
await createFileWithContents(t, file_name2, 'contents', /*parent=*/ root);
let names = [];
for await (let entry of root) {
assert_true(Array.isArray(entry));
assert_equals(entry.length, 2);
assert_equals(typeof entry[0], 'string');
assert_true(entry[1] instanceof FileSystemFileHandle);
assert_equals(entry[0], entry[1].name);
names.push(entry[0]);
}
names.sort();
assert_array_equals(names, [file_name1, file_name2]);
}, '@@asyncIterator: full iteration works');
directory_test(async (t, root) => {
const file_name1 = 'foo1.txt';
const file_name2 = 'foo2.txt';
await createFileWithContents(t, file_name1, 'contents', /*parent=*/ root);
await createFileWithContents(t, file_name2, 'contents', /*parent=*/ root);
let names = [];
for await (let entry of root.entries()) {
assert_true(Array.isArray(entry));
assert_equals(entry.length, 2);
assert_equals(typeof entry[0], 'string');
assert_true(entry[1] instanceof FileSystemFileHandle);
assert_equals(entry[0], entry[1].name);
names.push(entry[0]);
}
names.sort();
assert_array_equals(names, [file_name1, file_name2]);
}, 'entries: full iteration works');
directory_test(async (t, root) => {
const file_name1 = 'foo1.txt';
const file_name2 = 'foo2.txt';
await createFileWithContents(t, file_name1, 'contents', /*parent=*/ root);
await createFileWithContents(t, file_name2, 'contents', /*parent=*/ root);
let names = [];
for await (let entry of root.values()) {
assert_true(entry instanceof FileSystemFileHandle);
names.push(entry.name);
}
names.sort();
assert_array_equals(names, [file_name1, file_name2]);
}, 'values: full iteration works');
directory_test(async (t, root) => {
const file_name1 = 'foo1.txt';
const file_name2 = 'foo2.txt';
await createFileWithContents(t, file_name1, 'contents', /*parent=*/ root);
await createFileWithContents(t, file_name2, 'contents', /*parent=*/ root);
let names = [];
for await (let entry of root.keys()) {
assert_equals(typeof entry, 'string');
names.push(entry);
}
names.sort();
assert_array_equals(names, [file_name1, file_name2]);
}, 'keys: full iteration works');
...@@ -13,7 +13,7 @@ test(t => { ...@@ -13,7 +13,7 @@ test(t => {
OriginTrialsHelper.check_properties_exist(this, { OriginTrialsHelper.check_properties_exist(this, {
'FileSystemHandle': ['kind', 'name', 'queryPermission', 'requestPermission'], 'FileSystemHandle': ['kind', 'name', 'queryPermission', 'requestPermission'],
'FileSystemFileHandle': ['getFile', 'createWritable'], 'FileSystemFileHandle': ['getFile', 'createWritable'],
'FileSystemDirectoryHandle': ['getFileHandle', 'getDirectoryHandle', 'getEntries', 'removeEntry'], 'FileSystemDirectoryHandle': ['getFileHandle', 'getDirectoryHandle', 'entries', 'removeEntry'],
'FileSystemWritableFileStream': ['write', 'truncate', 'close', 'seek'], 'FileSystemWritableFileStream': ['write', 'truncate', 'close', 'seek'],
'global': ['showOpenFilePicker', 'showSaveFilePicker', 'showDirectoryPicker', 'getOriginPrivateDirectory'], 'global': ['showOpenFilePicker', 'showSaveFilePicker', 'showDirectoryPicker', 'getOriginPrivateDirectory'],
}); });
......
...@@ -559,12 +559,15 @@ interface FileReader : EventTarget ...@@ -559,12 +559,15 @@ interface FileReader : EventTarget
setter onprogress setter onprogress
interface FileSystemDirectoryHandle : FileSystemHandle interface FileSystemDirectoryHandle : FileSystemHandle
attribute @@toStringTag attribute @@toStringTag
method @@asyncIterator
method constructor method constructor
method entries
method getDirectoryHandle method getDirectoryHandle
method getEntries
method getFileHandle method getFileHandle
method keys
method removeEntry method removeEntry
method resolve method resolve
method values
interface FileSystemFileHandle : FileSystemHandle interface FileSystemFileHandle : FileSystemHandle
attribute @@toStringTag attribute @@toStringTag
method constructor method constructor
......
...@@ -87,6 +87,7 @@ function isWebIDLConstructor(propertyKey) { ...@@ -87,6 +87,7 @@ function isWebIDLConstructor(propertyKey) {
} }
var wellKnownSymbols = new Map([ var wellKnownSymbols = new Map([
[Symbol.asyncIterator, "@@asyncIterator"],
[Symbol.hasInstance, "@@hasInstance"], [Symbol.hasInstance, "@@hasInstance"],
[Symbol.isConcatSpreadable, "@@isConcatSpreadable"], [Symbol.isConcatSpreadable, "@@isConcatSpreadable"],
[Symbol.iterator, "@@iterator"], [Symbol.iterator, "@@iterator"],
......
...@@ -494,12 +494,15 @@ Starting worker: resources/global-interface-listing-worker.js ...@@ -494,12 +494,15 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] method readAsText [Worker] method readAsText
[Worker] interface FileSystemDirectoryHandle : FileSystemHandle [Worker] interface FileSystemDirectoryHandle : FileSystemHandle
[Worker] attribute @@toStringTag [Worker] attribute @@toStringTag
[Worker] method @@asyncIterator
[Worker] method constructor [Worker] method constructor
[Worker] method entries
[Worker] method getDirectoryHandle [Worker] method getDirectoryHandle
[Worker] method getEntries
[Worker] method getFileHandle [Worker] method getFileHandle
[Worker] method keys
[Worker] method removeEntry [Worker] method removeEntry
[Worker] method resolve [Worker] method resolve
[Worker] method values
[Worker] interface FileSystemFileHandle : FileSystemHandle [Worker] interface FileSystemFileHandle : FileSystemHandle
[Worker] attribute @@toStringTag [Worker] attribute @@toStringTag
[Worker] method constructor [Worker] method constructor
......
...@@ -2445,12 +2445,15 @@ interface FileReader : EventTarget ...@@ -2445,12 +2445,15 @@ interface FileReader : EventTarget
setter onprogress setter onprogress
interface FileSystemDirectoryHandle : FileSystemHandle interface FileSystemDirectoryHandle : FileSystemHandle
attribute @@toStringTag attribute @@toStringTag
method @@asyncIterator
method constructor method constructor
method entries
method getDirectoryHandle method getDirectoryHandle
method getEntries
method getFileHandle method getFileHandle
method keys
method removeEntry method removeEntry
method resolve method resolve
method values
interface FileSystemFileHandle : FileSystemHandle interface FileSystemFileHandle : FileSystemHandle
attribute @@toStringTag attribute @@toStringTag
method constructor method constructor
......
...@@ -489,12 +489,15 @@ Starting worker: resources/global-interface-listing-worker.js ...@@ -489,12 +489,15 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] method readAsText [Worker] method readAsText
[Worker] interface FileSystemDirectoryHandle : FileSystemHandle [Worker] interface FileSystemDirectoryHandle : FileSystemHandle
[Worker] attribute @@toStringTag [Worker] attribute @@toStringTag
[Worker] method @@asyncIterator
[Worker] method constructor [Worker] method constructor
[Worker] method entries
[Worker] method getDirectoryHandle [Worker] method getDirectoryHandle
[Worker] method getEntries
[Worker] method getFileHandle [Worker] method getFileHandle
[Worker] method keys
[Worker] method removeEntry [Worker] method removeEntry
[Worker] method resolve [Worker] method resolve
[Worker] method values
[Worker] interface FileSystemFileHandle : FileSystemHandle [Worker] interface FileSystemFileHandle : FileSystemHandle
[Worker] attribute @@toStringTag [Worker] attribute @@toStringTag
[Worker] method constructor [Worker] method constructor
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment