This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 23231 - [Custom]: Custom Element order isn't well defined for imported documents
Summary: [Custom]: Custom Element order isn't well defined for imported documents
Status: RESOLVED FIXED
Alias: None
Product: WebAppsWG
Classification: Unclassified
Component: HISTORICAL - Component Model (show other bugs)
Version: unspecified
Hardware: PC Linux
: P2 normal
Target Milestone: ---
Assignee: Dimitri Glazkov
QA Contact: public-webapps-bugzilla
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 14968
  Show dependency treegraph
 
Reported: 2013-09-13 03:14 UTC by Dominic Cooney
Modified: 2013-10-04 19:56 UTC (History)
0 users

See Also:


Attachments

Description Dominic Cooney 2013-09-13 03:14:18 UTC
Here are a few observations that I think are suggestive of problems:

CUSTOM ELEMENT ORDER is defined imperatively (a parser encounters a close tag) but later the definition of HIGHEST STABLE ORDER uses CUSTOM ELEMENT ORDER to define a total order across imported documents. This doesn't seem right, since the order in which those parsers respectively encounter close tags isn't defined.

HIGHEST STABLE ORDER refers to link tags and flattened trees, but that is fraught because a given link tag can move around, or be removed entirely. There's a mantra that "imperatively inserting a link tag is synchronous" but it's really not for Custom Element upgrade. Just for script tags. (I note the way script tags are blocked is very imperative--by checking a flag.)

HIGHEST STABLE ORDER refers to CUSTOM ELEMENT UPGRADE ORDER in an imported document, which isn't defined if the imported document hasn't parsed a custom element.

CUSTOM ELEMENT ORDER is defined for elements created with means other than a parser. What is that? Would those ever end up in the BASE ELEMENT QUEUE? Maybe that should be removed.

I think the solution needs to be something more imperative, and it needs to put imports in the base element queue as insertion points. There's also a critical object, the IMPORT, which *is not* a link tag. It's the placeholder for the document that may be parsed when processing an import. If a link tag is removed and reinserted, I think there's a new IMPORT happening.

I'm going to try prototyping something along these lines:

When an IMPORT happens, add it to the BEQ. If the parent document isn't an import, add it to the end; if the parent document is an import, insert the new IMPORT in the BEQ at the position right before the parent document's IMPORT. (Not sure what to do if the parent document's IMPORT has already expired from the queue. Maybe we only care about the operation of the parser, in which case we just clarify the algorithm to only do this insertion as a result of the parser. But maybe imperative should be isomorphic to parsing--which makes document.write more consistent I guess--in which case we need to specify walking the parent tree of imports or something.)

So this means that the base element queue now also contains a model of the imports tree. Note that the imports tree is very different to the flattened tree of link elements, etc. It's very imperative, defined by when an import is kicked off, etc. We need to model the imports tree in the base element queue because that is the goal of the whole exercise--providing a consistent model of both of these things to order them.

Next, when the parser encounters a Custom Element close tag, it adds it to the BEQ. This is defined similarly: If the document is not an import, add it to the end; if the document is an import, insert it right before the IMPORT marker in the BEQ for this document. This means that the IMPORT for a given document comes right after the elements in that document (if any).

When processing the BEQ, on encountering an IMPORT, if the import is not ready, leave it in the queue and stop processing the queue (new elements might be inserted in front of it. Processing restarts from the front each time.)

Here's a worked example for a trivial case:

m.html:
1: <x-a>
2: <link rel="import" href="p.html">
3: <x-b>

p.html:
1: <link rel="import" href="q.html">
2: <x-c>

q.html:
1: <x-d>
2: <x-e>

We basically have three concurrent actors parsing m (main), p and q. The only constraint is that an actors starts when the parent encounters the link tag. So imagine we have an interleaving like:

m1, m2, p1, q1, m3, q2, p2

This ordering would build a queue like:

m1: A
m2: AP
p1: AQP
q1: ADQP
m3: ADQPB
q2: ADEQPB
p2: ADEQCPB

You could imagine another possible ordering like:

m1, m2, p1, q1, q2, p2, m3

This would build a queue like:

m1: A
m2: AP
p1: AQP
q1: ADQP
q2: ADEQP
p2: ADEQCP
m3: ADEQCPB

Of course we could encounter microtask checkpoints at basically any point, but the total order will be the same and consistent because an import never drops out of the queue until its READY flag is set. So P and Q act as gates to the processing of the queue.

This is basically an imperatively constructed serialization of the "tree of trees". I think that would also be an OK formulation.
Comment 1 Dimitri Glazkov 2013-10-04 19:56:17 UTC
https://dvcs.w3.org/hg/webcomponents/rev/e61c2252e3f4