whatwg / webidl

Web IDL Standard
https://webidl.spec.whatwg.org/
Other
403 stars 161 forks source link

Define a callback constructor type #701

Open annevk opened 5 years ago

annevk commented 5 years ago

In particular something we verify to be a callback that also passes https://tc39.github.io/ecma262/#sec-isconstructor.

This could be used to remove the first step of https://html.spec.whatwg.org/multipage/custom-elements.html#dom-customelementregistry-define.

It would also help https://github.com/WebAudio/web-audio-api/pull/1843 and other Worklet APIs dealing with constructors.

Invoking the constructor would go through https://heycam.github.io/webidl/#construct-a-callback-function though that can be tightened up a bit by no longer having to check that it's a constructor.

bzbarsky commented 5 years ago

How do people feel about callback constructor Name = returnType(args) kind of syntax?

@domenic @Ms2ger

bzbarsky commented 5 years ago

It has the drawback of adding a new reserved word to IDL and hence needing to munge various places that want "identifier or anything that looks like one" in the grammar, but we should be able to just find all of those by searching the grammar for "interface", by analogy with callback interface.

domenic commented 5 years ago

callback constructor Name = returnType(args) SGTM

domenic commented 5 years ago

Note however we may want to consider defining this feature more holistically. For example custom elements, and I believe worklet APIs, want to not only construct the constructor, but pull properties off of it (e.g. step 10 of https://html.spec.whatwg.org/multipage/custom-elements.html#dom-customelementregistry-define). That could lead to different syntax.

bzbarsky commented 5 years ago

I did consider callback class Name = ... which looks a lot like the callback interface bits we have been busy removing...

That said the audio worklet case just seems to want to construct the thing. I agree we should look at the other possible consumers to see what they want.

Ms2ger commented 5 years ago

Looks like Gecko already got an implementation of this in https://bugzilla.mozilla.org/show_bug.cgi?id=1542932

bzbarsky commented 5 years ago

Note that at the moment that does not have the semantics proposed above. In particular we do not verify that the passed-in function is a constructor in the binding layer. From the point of view of observable binding behavior it's just an alias for callback, but exposes a Construct rather than Call on the Gecko side. In other words, it's Gecko developer ergonomics convenience, but without web-visible changes of any sort (which this proposal would have, due to doing IsConstructor checks earlier).

dead-claudia commented 4 years ago

What about something like this:

// No inheritance required
interface dictionary Foo {
    // Same `constructor` as usual
    constructor(...);

    // Works like standard `dictionary` properties
    static Type someStaticProp;
    static Type someStaticProp = "default";
    required static Type someStaticProp;

    // Instance property
    attribute Type someInstanceProp;
    attribute Type someInstanceProp = "default";
    required attribute Type someInstanceProp;

    // Instance method
    attribute Type someMethod(...);
    required attribute Type someMethod(...);
};

// Works like above, but requires instances to extend a particular interface,
// like via `class MyFoo extends Bar {}`. Note: it can only otherwise extend
// other interface dictionaries, much like how dictionaries can only extend
// from other dictionaries.
interface Bar { ... }
interface dictionary Foo : Bar { ... }

Concept is rough, and it is technically larger than everything else that's been proposed here, but it aligns pretty well conceptually with WebIDL's current processing model and shouldn't require more than mechanical changes from how it's currently consumed. It also is intended to satisfy the needs of both Houdini, custom elements, and worklets.

bzbarsky commented 4 years ago

What are the actual semantics of that proposal?

dead-claudia commented 4 years ago

@bzbarsky So here's what I was thinking:

I was trying to avoid over-specifying here, and I probably left a few holes here by accident. But hopefully this clarifies what I'm suggesting. The overarching goal is to have a solution that solves the needs at hand flexibly while still being intuitively WebIDL. (And implementations can just desugar, abstract, and track a few new invariants - it's not a radical change to implement.)