dart-lang / web

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

Implement `iterable` on types where it's defined #21

Open kevmoo opened 1 year ago

kevmoo commented 1 year ago

Not sure if this in on your radar or not, @joshualitt

srujzs commented 11 months ago

To make this more concrete, there are iterable types in the IDL e.g. NodeList

https://github.com/w3c/webref/blob/75015f219dc2fede4af8c953d93b1517c1691204/ed/idl/dom.idl#L158

that should expose iterable methods like forEach. https://webidl.spec.whatwg.org/#idl-iterable

ditman commented 7 months ago

I checked and the FileList type seems to not be marked iterable, but in the MDN example, they use it with for ... of:

for (const file of fileInput.files) {
  output.innerText += `\n${file.name}`;
}

It'd be nice if there was some way of wrapping those "things that have length and item(i)" in something that lets me use them as lists in Dart!


PS, I added this:

/// Adds a `toList` method to [web.FileList] objects.
extension WebFileListToDartList on web.FileList {
  /// Converts a [web.FileList] into a [List] of [web.File].
  ///
  /// This method makes a copy.
  List<web.File> get toList =>
      <web.File>[for (int i = 0; i < length; i++) item(i)!];
}
srujzs commented 7 months ago

There's a similar issue here: https://github.com/dart-lang/web/issues/91 (see point b).

I think going the route of adding a toDartIterable in the SDK makes sense for types like this which behave very similar to lists but are not Arrays e.g.

extension on JSObject {
  /// Wraps this object with an [Iterable] implementation whose
  /// methods forward to the object.
  external Iterable<T> toDartIterable<T extends JSAny?>();
}

These types don't really have a supertype in JS that groups them in some kind of "list-like" category, so there isn't a concrete separation from JSObject. We could make it return a List<T> as well, I'm just not sure if types like FileList support all the methods we need for that interface.

I don't want to expose APIs that copy over the values into a Dart list as it's more expensive and users likely iterate over the list only once.