dart-lang / web

Lightweight browser API bindings built around JS static interop.
https://pub.dev/packages/web
BSD 3-Clause "New" or "Revised" License
134 stars 23 forks source link

FileSystemDirectoryHandle is missing the methods to enumerate its content #318

Open gdurandrexel opened 3 days ago

gdurandrexel commented 3 days ago

In version 1.1.0, there is no values(), keys() or entries() defined in FileSystemDirectoryHandle.

I understand only standard API is emitted but in this case, in MDN, only Android Webview is not supported, which is exactly the same as removeEntry() which is emitted.

Did I miss something?

srujzs commented 3 days ago

You're correct - they are missing and need to be added. As always, the workaround is to use external extension methods until this is added. I believe this is a duplicate of https://github.com/dart-lang/web/issues/21, except here it's async: https://github.com/w3c/webref/blob/23c3d948f58f16e420d388269d29312f04cc419f/ed/idl/fs.idl#L45.

The Web IDL definition is here: https://webidl.spec.whatwg.org/#idl-iterable. There's an async section after that as well: https://webidl.spec.whatwg.org/#idl-async-iterable. This would add entries, keys, values, and forEach (if not async). We may want to add an Iterator type to dart:js_interop or package:web to support this.

I thought we somewhat handled this with handling getter/setter and adding a List wrapper type, but we did not.

gdurandrexel commented 1 day ago

For those wanting an implementation right now, here is some code that works (with no exception handling):

extension FileSystemDirectoryHandleEx on FileSystemDirectoryHandle {
  Stream<FileSystemHandle> values() {
    final iterator = callMethod<JSObject>('values'.toJS);

    return _asyncIterator<FileSystemHandle>(iterator);
  }
}

Stream<T> _asyncIterator<T extends JSObject>(JSObject iterator) async* {
  while (true) {
    final next = await iterator.callMethod<JSPromise<T>>('next'.toJS).toDart;

    if (next.getProperty<JSBoolean>('done'.toJS).toDart) {
      break;
    }

    yield next.getProperty<T>('value'.toJS);
  }
}

Use like this:

await for (FileSystemHandle handle in directoryHandle.values()) {
  ...
}