Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Elements #16

Closed
ylafon opened this issue Oct 24, 2013 · 13 comments
Closed

Custom Elements #16

ylafon opened this issue Oct 24, 2013 · 13 comments
Assignees

Comments

@ylafon
Copy link
Member

ylafon commented Oct 24, 2013

LC As of http://www.w3.org/TR/2013/WD-custom-elements-20131024/
Edcopy: https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html

@annevk
Copy link
Member

annevk commented Oct 24, 2013

See also #13.

It seems that monkey patching http://dom.spec.whatwg.org/ as done in this specification is very bad.

@domenic
Copy link
Member

domenic commented Jan 29, 2014

There's something going on here around "nanotasks" http://w3c.github.io/webcomponents/spec/custom/#enqueuing-and-invoking-callbacks

@annevk had a conversation with @dglazkov in #whatwg about it that may have cleared things up, but I had a hard time following along. It's definitely worth figuring out what's going on there though.

@domenic
Copy link
Member

domenic commented Jan 29, 2014

This line in particular is very worrying:

When transitioning back from the user agent code to script, pop the element queue from the processing stack and invoke callbacks in that queue.

Since that is pretty much the role of the event loop, and having it superceded by one line of prose seems... bad.

@dglazkov
Copy link

pretty much the role of the event loop

Well, no. Transitions from UA code to script occur much more frequently. Anytime you call a DOM method, you're leaving script and going into UA code, and back. Here's a simple example:

div.innerHTML = "<foo-bar></foo-bar>";
div.querySelector("foo-bar").doSomething();

The user of <foo-bar> expects the createCallback to be called synchronously. We can't do that, since invoking script in the middle of a parser is a Bad Idea (tm). That's what this machinery is for. It separates enqueuing callbacks from invoking callbacks, and provides a safe/consistent mechanism to invoke the callbacks in a way that appears synchronous to the user.

In the example above, the createCallback is enqueued as the elements are constructed and is invoked just before innerHTML returns.

This type of write barrier will be especially necessary when we try to make DOM self-hosted. There are many places where the UA needs to ensure that the user code doesn't run.

The bug with all the gory details: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22459

@annevk
Copy link
Member

annevk commented Jan 29, 2014

Running callbacks just before you return from a large number of methods and getters that previously did not have that behavior is a new concept. I guess we might need it, but I would like us to be much more clear and explicit about it.

@dglazkov
Copy link

I would assert that the concept of running callbacks as an effect of executing a method/getter is not new. This happens all the time in JS frameworks. What's new is a mechanism that enables web platform to do this without jeopardizing integrity of DOM operations.

I wonder if the right way to define it is as a separate DOM write barrier abstraction that could be used to provide "synchronous on the outside, asynchronous on the inside" semantics. I could give it a shot. WDYT?

@domenic
Copy link
Member

domenic commented Jan 29, 2014

I wonder if the right way to define it is as a separate DOM write barrier abstraction that could be used to provide "synchronous on the outside, asynchronous on the inside" semantics.

I am having a hard time understanding this; it seems to contradict the earlier description of the situation as simply running some callbacks before returning (which seems like it has nothing to do with asynchronicity).

I know it's a lot to ask, but could you provide some JS code samples to explain what exactly is going on here? E.g., if we were to implement this behavior purely in JS, by monkeypatching a bunch of DOM methods, what would that look like?

@dglazkov
Copy link

Sure. First, the setup:

class Queue() {
constructor() {
   this.queue = [];
}
enqueue(callback) {
    this.queue.push(callback);
}
invoke() {
    this.queue.forEach(function(callback) {
        callback();
    });
}
}

var queue = new Queue();

Now, let's suppose innerHTML enqueues callbacks by calling queue.enqueue(callback):

class Element {
...
set innerHTML(value) {
    // per http://domparsing.spec.whatwg.org/#dom-element-innerhtml
    ...
    // when HTML parser creates a new element, it enqueues the created callback
    // per http://w3c.github.io/webcomponents/spec/custom/#parsing
    queue.enqueue(newlyBornElementsCreatedCallback);
    ...
    // just before returning, we drain the queue
    queue.invoke();
}
...   
}

From the perspective of the HTML parser, the operation is asynchronous -- it only enqueues the callbacks.
From the perspective of the user of Element.innerHTML, the operation is synchronous -- the callbacks were invoked as a result of calling the setter. Hence "asynchronous on the inside, synchronous on the ouside".

@domenic
Copy link
Member

domenic commented Jan 29, 2014

Ah! Thank you, that clears things up immensely. However, I'd encourage you to not use the term "asynchronous" for this, as traditionally in JS we use that to refer to defering something outside of the current event loop tick. This behavior would definitely be called synchronous, at least how we normally use the terms in JS.

With that cleared up, I think my concerns reduce to match those of @annevk, namely that the blanket monkey-patching of "when transitioning back from the user agent code to script" is a bit more wishy-washy than we'd hope for. I'll leave it to @annevk as Master of the DOM to say what the best way of addressing that is though, whether via the write-barrier abstraction you mention or something else.

@annevk
Copy link
Member

annevk commented Jan 29, 2014

I think making it explicit in the binding layer (IDL) as I suggested on public-webapps would make the most sense conceptually.

@mnot
Copy link
Member

mnot commented Sep 30, 2014

Discussed at London F2F; needs to be transferred to a bug. @domenic to do.

@mnot
Copy link
Member

mnot commented Jan 8, 2015

Discussed in NYC; dominic following up.

@domenic
Copy link
Member

domenic commented Jan 14, 2015

Found the bug, was filed already https://www.w3.org/Bugs/Public/show_bug.cgi?id=24579 and has recently come up again on public-webapps.

@domenic domenic closed this as completed Jan 14, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants