- IO streams. (Domenic is leading an effort on GitHub. This is high priority, like promises was last year.)
- Asynchronous iteration (event streams?). (Database cursor, going through a directory, going through entries in storage, scanning TV channels.)
- A plan around distinct Error types and detection (e.g. for APIs that can fail in multiple ways where you might want to recover from certain class of errors; think network APIs, databases)
- A better way to define ES APIs than WebIDL. (Part of the problem here is lack of maintenance. So maybe it's as "simple" as finding someone.)
-
-
Save annevk/3db3fbda2b95e5ae9427 to your computer and use it in GitHub Desktop.
- A non-broken way of subclassing Map and Set.
There are currently two ways to "subclass" Map and Set, both of which are broken in several ways:
- Use standard subclassing, putting Map.prototype on your prototype chain. This works fine if you're not doing anything interesting, but if you want to, say, enforce a particular type constraint on the values in the Map by overriding
.set()
, you can't, because authors can always doMap.prototype.set.call(yourMapSubclass, key, stupidValue)
and bypass your protections. This means that this approach is worthless for using Maps in DOM, where typing constraints or conversions are common, and working around this issue is confusing and difficult. - Use "containment" style subclassing, defining an independent object which holds a private ref to a Map/Set that holds the actual data, and reproduces all the Map/Set methods manually. This sucks because the class doesn't type as a Map/Set (
yourMap typeof Map
is false), any any new methods or properties added to Map/Set either by the language or by the page author don't show up on your custom Map/Set. Also,Map.prototype.set.call(yourMap, ...)
doesn't work at all, which makes it harder to do generic programming.
As far as I can tell, the right way to go about this is to define a MapCore/SetCore object that only has the most basic calls on it (probably get
, set
, has
, delete
, clear
, and [[iterator]]
for Map, similar things for Set), and define that Map/Set contain a private ref to a MapCore/SetCore object that actually holds the data. Then there needs to be a way to swap out the MapCore/SetCore object with something of your own, during construction only. That way you can subclass something like:
class FontFaceSet extends Set {
constructor(...) {
super(...);
this.swapStorage(new FontFaceSetCore());
}
}
class FontFaceSetCore {
get(...){...}
set(...){/* typecheck for FontFace objects */ ...}
...
}
Transform Streams might be a good model for async iteration, the ability to make long pipelines that hook up to IO stream ends up making them particularly powerful
Specifically on "A better way to define ES APIs than WebIDL", I'd like to suggest TypeScript interfaces at least as base work. The latest spec (yeah, it's a .docx, whatev's ) is under OWF 1.0 (which is close enough to a Creative Commons licence. A lawyer will tell the difference better than I can. Maybe something related to patents?). See section 7 for interfaces specifically.
Microsoft went all the way to formalize the ECMAScript 5 (and parts of 6) API, the DOM and browser APIs and the jQuery API in the TypeScript interface language.
The community contributes TS interface files for all major JS APIs including Node.js, d3.js, Q. I'm just picking randomly. Full list at https://github.com/borisyankov/DefinitelyTyped/
It's fair to say that this API description language is expressive enough for developers to describe JS interfaces (even the DOM which is annoying in various ways to describe). The language is formalize, there is already tooling around it, some people use it. Sounds like a good place to start without having to bother TC39.
It of course all depends on what you meant by "A better way" ;-)