WICG / local-font-access

Web API for enumerating fonts on the local system
https://wicg.github.io/local-font-access
Apache License 2.0
75 stars 16 forks source link

Specifying the async iterator #50

Closed jakearchibald closed 3 years ago

jakearchibald commented 3 years ago

Sorry @domenic, I think I need your help on this one.

If we were to solve https://github.com/WICG/local-font-access/issues/27, I'd go for an API like:

class SystemFonts {
  async* matchAll(query = {}) {
    while (true) {
      const match = await getNextMatchSomehow(query);
      if (match) yield match;
      else return;
    }
  }

  [Symbol.asyncIterator]() {
    return this.matchAll();
  }
}

self.systemFonts = new SystemFonts();

In this case:

for await (const match of self.systemFonts) …

…is an alias of:

for await (const match of self.systemFonts.matchAll()) … 

But matchAll provides the ability to query:

for await (const match of self.systemFonts.matchAll({ name: 'foo' })) … 

You could also do:

for await (const match of self.systemFonts[Symbol.asyncIterator]({ name: 'foo' })) … 

…but I think it's worth providing the named method for ergonomics.

However, I can't see a way in IDL to declare a method that returns an async iterator like this. I guess I could call the @@asynciterator directly, but that seems not-how-we-usually-do-things.

domenic commented 3 years ago

Async iterators can take arguments! So there's no need for matchAll(); you can just use self.systemFonts[Symbol.asyncIterator]({ name: 'foo' }), or self.systemFonts.values({ name: 'foo' }). This is done in IDL by using the syntax

async iterable<value_type>(optional SomeOptionsDict options = {});

For specifying this, see https://streams.spec.whatwg.org/#rs-asynciterator plus the IDL block at https://streams.spec.whatwg.org/#rs-class-definition for an example.

jakearchibald commented 3 years ago

Ohhh, self.systemFonts.values({ name: 'foo' }) provides the ergonomics I was looking for. I felt self.systemFonts[Symbol.asyncIterator]({ name: 'foo' }) was too ugly.