domenic / html-as-custom-elements

HTML as Custom Elements
https://domenic.github.io/html-as-custom-elements/
Apache License 2.0
259 stars 20 forks source link

Create framework for generating full classes from impl + .idl #32

Closed domenic closed 10 years ago

domenic commented 10 years ago

Spawned from #31:

Given

interface Foo : Bar {
    attribute unsigned long x;
    readonly attribute unsigned long y;
    boolean method(DOMString arg);
}

plus the text

"the x attribute must reflect the content attribute of the same name"

in the spec, we would commit an IDL file containing

// Foo.idl
interface Foo : Bar {
    [Reflect] attribute unsigned long x;
    readonly attribute long y;
    boolean method(DOMString arg);
}

Then we'd write the following ES6:

// FooImpl.js
class FooImpl {
    get y() { return Math.random() * 1000; }
    method(arg) { return arg.toLowerCase(); }
}

Things to note:

What will then happen is that we do something like

registerImpl("custom-foo", FooImpl);

and registerImpl generates a wrapper class Foo that delegates to FooImpl and does all the other stuff determined by the IDL. If we were to write it out, it would look like

// FooGenerated.js
import reflector from "./lib/webidl/reflector";
import conversions from "./lib/webidl/conversions";

class Foo extends Bar {
    get x() { return reflector["unsigned long"].get(this, "x"); }
    set x(v) { reflector["unsigned long"].set(this, "x", v); }

    get y() {
        var implGetter = Object.getOwnPropertyDescriptor(FooImpl.prototype, "y").get;
        var implResult = implGetter.call(this);
        return conversions["long"](implResult);
    }

    method(arg) {
        arg = conversions["DOMString"](arg);
        var implMethod = FooImpl.prototype.method;
        var implResult = implMethod.call(this, arg);
        return conversions["boolean"](implResult);
    }
}

I am unsure whether we should generate the wrapper class at runtime or at compile time. Runtime seems easier off the top of my head, but that is partially because I do not have as much experience with parsers/generators as I would like.


Steps:

I will probably do this work in a separate repo. Will link as it happens.

annevk commented 10 years ago

One thing of interest here is that we should probably just standardize [Reflect]. Why have all that unneeded potentially buggy prose?

domenic commented 10 years ago

But [Reflect] is very HTML-specific, isn't it? Do we have any other parts of WebIDL that apply only to HTMLElements?

(I guess it could be made semi-generic if it said something like "let string be Invoke(this, "getAttribute", attrName). Perform conversions..." But that would be a web-observable change, since it would mandate that changing el.getAttribute would cause el's behavior with reflected properties to change.)

annevk commented 10 years ago

Well, we could make IDL extensible. Also, the whole idea of layering does not quite apply as IDL requires some stuff from HTML already, such as settings objects.

domenic commented 10 years ago

I like that idea. Specs could define their own IDL thingies when they use them enough. I will send a public-script-coord email to help us figure out our near-term plan.

domenic commented 10 years ago

This project is https://github.com/domenic/webidl-class-generator