Re: The key custom elements question: custom constructors?

2015-07-17 Thread Anne van Kesteren
On Fri, Jul 17, 2015 at 4:15 PM, Domenic Denicola d...@domenic.me wrote:
 From: Anne van Kesteren [mailto:ann...@annevk.nl]
 It fails atomically, based on the definition of innerHTML.

 What if that 512 KiB of HTML contains img src=foo.png? Following 
 definitions, I assume we fire off the network request?

If I look at update the image data step 6 it seems it might be
fetched at a later point?


 What if it contains a x-baz/x-baz where XBaz's constructor does 
 `document.body.innerHTML = pHello/p`? Can the parsing algorithm deal 
 with the (following the definitions, required) re-entrancy?

I think the specification can, since it just invokes the fragment
parser with some parameters and then replaces the contents of XBaz
with the obtained DocumentFragment. Implementations probably can too.
E.g., scriptdocument.body.innerHTML = ... /script is quite
similar.


-- 
https://annevankesteren.nl/



RE: The key custom elements question: custom constructors?

2015-07-17 Thread Domenic Denicola
From: Anne van Kesteren [mailto:ann...@annevk.nl] 

 // What about
 document.body.innerHTML = [512 KiB of normal HTML] x-foo/x-foo; 
 // ? does the HTML make it in, or does the operation fail atomically, or 
 something else?

 It fails atomically, based on the definition of innerHTML.

What if that 512 KiB of HTML contains img src=foo.png? Following 
definitions, I assume we fire off the network request?

What if it contains a x-baz/x-baz where XBaz's constructor does 
`document.body.innerHTML = pHello/p`? Can the parsing algorithm deal with 
the (following the definitions, required) re-entrancy?



Re: The key custom elements question: custom constructors?

2015-07-17 Thread Anne van Kesteren
On Fri, Jul 17, 2015 at 5:47 PM, Boris Zbarsky bzbar...@mit.edu wrote:
 On 7/17/15 10:38 AM, Anne van Kesteren wrote:
 If I look at update the image data step 6 it seems it might be
 fetched at a later point?

 Yes, but in practice the fetch will go ahead, no?  There's nothing to
 prevent it from happening, so it's going to happen once you reach a stable
 state...

True, but either way this doesn't seem like a problem. You can create
a DocumentFragment, insert a new img, and then let it be GC'd,
today.


-- 
https://annevankesteren.nl/



Re: The key custom elements question: custom constructors?

2015-07-17 Thread Anne van Kesteren
On Thu, Jul 16, 2015 at 10:36 PM, Domenic Denicola d...@domenic.me wrote:
 I have a related question: what happens if the constructor throws?

Right, this is the kind of thing we need to figure out.


 !DOCTYPE html
 script
 use strict;

 window.throwingMode = true;

 class XFoo extends HTMLElement {
 constructor() {
 if (window.throwingMode) {
 throw new Error(uh-oh!);
 }
 }
 }

 document.registerElement(x-foo, XFoo);
 /script

 x-foo/x-foo

 script
 use strict;

 // What does the DOM tree look like here? Is an x-foo present in some form?
 // HTMLUnknownElement maybe? Just removed from existence?

I guess if the constructor doesn't return an instance but an
exception, we'd rethrow the exception (ends up at window.onerror). We
could have fallback for creating an element anyway, but I'm not sure
that's necessary.


 // This will presumably throw:
 document.body.innerHTML = x-foo/x-foo;

That makes sense. Provided we don't offer fallback instance creation
for the parser case.


 // But will it wipe out body first?

Based on 
https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-innerHTML
I'd say no. Fragment parsing fails, so we never reach replace all.


 // What about
 document.body.innerHTML = [512 KiB of normal HTML] x-foo/x-foo;
 // ? does the HTML make it in, or does the operation fail atomically, or 
 something else?

It fails atomically, based on the definition of innerHTML.


 // Now let's try something weirder.
 // Assume x-bar / XBar is a well-behaved custom element.

 window.throwingMode = false;
 const el = document.createElement(div);
 el.innerHTML = 
 pa/px-bar/x-barx-foob/x-foopb/px-bar/x-bar;

 window.throwingMode = true;
 el.cloneNode(true); // this will throw, presumably...
 // ... but does the XBar constructor run or not?
 // ... if so, how many times?

If we decide to rethrow, it would only be invoked once. However, given
the other algorithms that use cloneNode(), it's not clear that
throwing is acceptable or what that means when you copy something as a
user (though maybe you just end up copying nothing at all, doesn't
seem too bad).


-- 
https://annevankesteren.nl/



Re: The key custom elements question: custom constructors?

2015-07-17 Thread Boris Zbarsky

On 7/17/15 12:05 PM, Anne van Kesteren wrote:

True, but either way this doesn't seem like a problem. You can create
a DocumentFragment, insert a new img, and then let it be GC'd,
today.


Sure.  In practice it won't get GC'd until the load completes, which is 
sucky, but that's life.


-Boris




Re: The key custom elements question: custom constructors?

2015-07-17 Thread Boris Zbarsky

On 7/17/15 10:38 AM, Anne van Kesteren wrote:

If I look at update the image data step 6 it seems it might be
fetched at a later point?


Yes, but in practice the fetch will go ahead, no?  There's nothing to 
prevent it from happening, so it's going to happen once you reach a 
stable state...


-Boris



Re: The key custom elements question: custom constructors?

2015-07-16 Thread Olli Pettay

On 07/16/2015 08:30 AM, Domenic Denicola wrote:

From: Travis Leithead [mailto:travis.leith...@microsoft.com]


I've discussed this issue with some of Edge's key parser developers.


Awesome; thank you for doing that!


I believe to be the most straightforward approach that most closely matches how 
the platform itself works


Thanks, it's helpful to get this non-implementation-focused reasoning out in 
the open.

What are your responses to Olli's concerns about how this is hard to spec properly? 
I.e. no one ever managed to spec MutationEvents properly, and
running author code during cloneNode(true) is at least as hard problem to 
solve. Are you concerned about interop? It sounds like it's technically
feasible for you, but do you think it will be technically feasible in a way 
that is interoperable? (I realize that's a hard question to answer.)


For example, in parsing, I would expect that the callout happens after initial 
instance creation, but before the target node is attached to the
DOM tree by the parser.


Can you expand on this more? In particular I am confused on how initial instance 
creation can happen without calling the constructor.


I am sympathetic to this concern, but have my own reservations about the 
proto-swizzle technique.


I think this is not the correct positioning for this question. There are two 
independent questions: is it OK to run author code during parsing and
cloning? And separately, is there utility to be gained from proto-swizzling? 
You can imagine (at least) four solutions for this 2x2 grid of yes/no
responses. In this particular thread I really want to focus on the former 
question since it is foundational.

---

It sounds like so far we have:

- Mozilla against running author code during these times

That is too strongly said, at least if you refer to my email
(where I expressed my opinions, but as usually, others from Mozilla may have 
different opinions).
I said I'd prefer if we could avoid that [Running author code during 
cloneNode(true)].

And my worry is largely in the spec level.
It would be also a bit sad to reintroduce some of the issues MutationEvents 
have to the platform, now that we're
finally getting rid of those events




- Microsoft for running author code during these times, but sympathetic to 
concerns in the
opposite direction

Is this correct so far?

I suppose I should also note

- Google against running author code during these times, based on investigation by 
Dominic (with an i) into the complexity it would add to the
platform/event loop/etc. (I believe the exact phrase MutationEvents all over 
again was used.)







Re: The key custom elements question: custom constructors?

2015-07-16 Thread Anne van Kesteren
On Thu, Jul 16, 2015 at 6:49 PM, Domenic Denicola d...@domenic.me wrote:
 Even if it can be specced/implemented, should it? I.e., why would this be OK 
 where MutationEvents are not?

Apart from the verbosity and performance issues with mutation events,
I think the main problem with mutation events has been the lack of a
clear processing model (and that is true to this day), causing crashes
in user agents:
https://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html

In other words, the specification authors invented something, but
didn't do the due diligence of writing down how that invention would
actually impact the overall model. (This is a problem to this day.
E.g., UI events.)

So the main problem with custom constructors seems to be the
processing model, combined with the work of actually implementing and
vetting that.


-- 
https://annevankesteren.nl/



Re: The key custom elements question: custom constructors?

2015-07-16 Thread Anne van Kesteren
On Thu, Jul 16, 2015 at 6:03 PM, Domenic Denicola d...@domenic.me wrote:
 Ah OK, thanks. Is there any way to get a consensus from Mozilla as a whole, 
 preferably ahead of the F2F?

I think the problem is that nobody has yet tried to figure out what
invariants that would break and how we could solve them. I'm not too
worried about the parser as it already has script synchronization, but
cloneNode(), ranges, and editing, do seem problematic. If there is a
clear processing model, Mozilla might be fine with running JavaScript
during those operations.

I've been a bit too occupied with Fetch et al to put in the hours
myself ahead of the meeting.


-- 
https://annevankesteren.nl/



RE: The key custom elements question: custom constructors?

2015-07-16 Thread Domenic Denicola
From: Anne van Kesteren [mailto:ann...@annevk.nl]

 I think the problem is that nobody has yet tried to figure out what invariants
 that would break and how we could solve them. I'm not too worried about
 the parser as it already has script synchronization, but cloneNode(), ranges,
 and editing, do seem problematic. If there is a clear processing model,
 Mozilla might be fine with running JavaScript during those operations.

Even if it can be specced/implemented, should it? I.e., why would this be OK 
where MutationEvents are not?



RE: The key custom elements question: custom constructors?

2015-07-16 Thread Domenic Denicola
From: Olli Pettay [mailto:o...@pettay.fi]

 That is too strongly said, at least if you refer to my email (where I 
 expressed
 my opinions, but as usually, others from Mozilla may have different opinions).
 I said I'd prefer if we could avoid that [Running author code during
 cloneNode(true)].
 
 And my worry is largely in the spec level.
 It would be also a bit sad to reintroduce some of the issues MutationEvents
 have to the platform, now that we're finally getting rid of those events

Ah OK, thanks. Is there any way to get a consensus from Mozilla as a whole, 
preferably ahead of the F2F?



RE: The key custom elements question: custom constructors?

2015-07-16 Thread Domenic Denicola
From: Jonas Sicking [mailto:jo...@sicking.cc]

 Like Anne says, if it was better defined when the callbacks should happen,
 and that it was defined that they all happen after all internal datastructures
 had been updated, but before the API call returns, then that would have
 been much easier to implement.

Right, but that's not actually possible with custom constructors. In 
particular, you need to insert the elements into the tree *after* calling out 
to author code that constructs them. What you mention is more like the 
currently-specced custom elements lifecycle callback approach.

Or am I misunderstanding? 

 This is a problem inherent with synchronous callbacks and I can't think of a
 way to improve specifications or implementations to help here. It's entirely
 the responsibility of web authors to deal with this complexity.

Well, specifications could just not allow synchronous callbacks of this sort, 
which is kind of what we're discussing in this thread. That would help avoid 
the horrors of

class XFoo extends HTMLElement {
  constructor(stuff) {
super();

// Set up some default content that happens to use another custom element
this.innerHTML = `x-barp${stuff}/p/x-bar`;

// All foos should also appear in a list off on the side!
// Let's take care of that automatically for any consumers!
document.querySelector(#list-of-foos).appendChild(this.cloneNode(true));
  }
}

which seems like a well-meaning thing that authors could do, without knowing 
what they've unleashed.


RE: The key custom elements question: custom constructors?

2015-07-16 Thread Domenic Denicola
I have a related question: what happens if the constructor throws? Example:

!DOCTYPE html
script
use strict;

window.throwingMode = true;

class XFoo extends HTMLElement {
constructor() {
if (window.throwingMode) {
throw new Error(uh-oh!);
}
}
}

document.registerElement(x-foo, XFoo);
/script

x-foo/x-foo

script
use strict;

// What does the DOM tree look like here? Is an x-foo present in some form?
// HTMLUnknownElement maybe? Just removed from existence?

// This will presumably throw:
document.body.innerHTML = x-foo/x-foo;
// But will it wipe out body first?

// What about
document.body.innerHTML = [512 KiB of normal HTML] x-foo/x-foo;
// ? does the HTML make it in, or does the operation fail atomically, or 
something else?


// Now let's try something weirder.
// Assume x-bar / XBar is a well-behaved custom element.

window.throwingMode = false;
const el = document.createElement(div);
el.innerHTML = pa/px-bar/x-barx-foob/x-foopb/px-bar/x-bar;

window.throwingMode = true;
el.cloneNode(true); // this will throw, presumably...
// ... but does the XBar constructor run or not?
// ... if so, how many times?
/script

 -Original Message-
 From: Domenic Denicola [mailto:d...@domenic.me]
 Sent: Wednesday, July 15, 2015 20:45
 To: public-webapps
 Subject: The key custom elements question: custom constructors?
 
 Hi all,
 
 Ahead of next week's F2F, I'm trying to pull together some clarifying and
 stage-setting materials, proposals, lists of open issues, etc. In the end, 
 they
 all get blocked on one key question:
 
 **Is it OK to run author code during parsing/cloning/editing/printing (in
 Gecko)/etc.?**
 
 If we allow custom elements to have custom constructors, then those must
 run in order to create properly-allocated instances of those elements; there
 is simply no other way to create those objects. You can shuffle the timing
 around a bit: e.g., while cloning a tree, you could either run the 
 constructors
 at the normal times, or try to do something like almost-synchronous
 constructors [1] where you run them after constructing a skeleton of the
 cloned tree, but before inserting them into the tree. But the fact remains
 that if custom elements have custom constructors, those custom
 constructors must run in the middle of all those operations.
 
 We've danced around this question many times. But I think we need a clear
 answer from the various implementers involved before we can continue. In
 particular, I'm not interested in whether the implementers think it's
 technically feasible. I'd like to know whether they think it's something we
 should standardize.
 
 I'm hoping we can settle this on-list over the next day or two so that we all
 come to the meeting with a clear starting point. Thanks very much, and
 looking forward to your replies,
 
 -Domenic
 
 [1]: https://lists.w3.org/Archives/Public/public-
 webapps/2014JanMar/0098.html



Re: The key custom elements question: custom constructors?

2015-07-16 Thread Jonas Sicking
On Thu, Jul 16, 2015 at 9:49 AM, Domenic Denicola d...@domenic.me wrote:
 From: Anne van Kesteren [mailto:ann...@annevk.nl]

 I think the problem is that nobody has yet tried to figure out what 
 invariants
 that would break and how we could solve them. I'm not too worried about
 the parser as it already has script synchronization, but cloneNode(), ranges,
 and editing, do seem problematic. If there is a clear processing model,
 Mozilla might be fine with running JavaScript during those operations.

 Even if it can be specced/implemented, should it? I.e., why would this be OK 
 where MutationEvents are not?

I think there were two big problems with MutationEvents.

From an implementation point of view, the big problem was that we
couldn't use an implementation strategy like:

1. Perform requested task
2. Get all internal datastructures and invariants updated.
3. Fire MutationEvents callback.
4. Return to JS.

Since step 4 can run arbitrary webpage logic, it's fine that step 3,
which is run right before, does as well. I.e. we could essentially
treat step 3 and 4 as the same.

This was particularly a problem for DOMNodeRemoved since it was
required to run *before* the required task was supposed to be done.
But it was also somewhat a problem for DOMNodeInserted since it could
be interpreted as something that should be done interweaved with other
operations, for example when a single DOM API call caused multiple
nodes to be inserted.

Like Anne says, if it was better defined when the callbacks should
happen, and that it was defined that they all happen after all
internal datastructures had been updated, but before the API call
returns, then that would have been much easier to implement.


The second problem is that it causes webpages to have to deal with
reentrancy issues. Synchronous callbacks are arguably just as big of a
problem for webpages as it is for browser engines. It meant that the
callback which is synchronously called when a node is inserted might
remove that node. Or might remove some other node, or do a ton of
other changes.

Callbacks which are called synchronously have a huge responsibility to
not do crazy things. This gets quite complex as code bases grow. A
synchronous callback might do something that seems safe in and of
itself, but that in turn triggers a couple of other synchronous
callbacks, which trigger yet more callbacks, which reenters something
unexpected.

The only way to deal with this is for webpages to do the absolute
minium thing they can in the synchronous callback, and do anything
else asynchronously. That is what implementations tries to do. The
code that's run during element construction tries to only touch a
minimal number of things in the rest of the outside world, ideally
nothing.

This is a problem inherent with synchronous callbacks and I can't
think of a way to improve specifications or implementations to help
here. It's entirely the responsibility of web authors to deal with
this complexity.

/ Jonas



Re: The key custom elements question: custom constructors?

2015-07-16 Thread Jonas Sicking
On Thu, Jul 16, 2015 at 12:16 PM, Domenic Denicola d...@domenic.me wrote:
 From: Jonas Sicking [mailto:jo...@sicking.cc]

 Like Anne says, if it was better defined when the callbacks should happen,
 and that it was defined that they all happen after all internal 
 datastructures
 had been updated, but before the API call returns, then that would have
 been much easier to implement.

 Right, but that's not actually possible with custom constructors. In 
 particular, you need to insert the elements into the tree *after* calling out 
 to author code that constructs them. What you mention is more like the 
 currently-specced custom elements lifecycle callback approach.

 Or am I misunderstanding?

No, that is a good point. The constructor callback does indeed need to
happen between an element is created and the element is inserted.

I think though that in this case it might be possible that we depend
on very little mutable state between the callbacks. I.e. that none of
the state that we depend on while the algorithm is running can be
mutated by the page.

In essence the only state we need to keep is the pointers to the
elements, and the parents that the elements should be inserted into.
And since pages can't delete any objects, those pointers will remain
valid throughout.

The only thing that I could think of might be tricky is around tables,
where sometimes we don't insert elements last in the childlist of
their parent. In that case we'll also carry state about where to
insert a given child. That state might get outdated since the page can
mess around with the DOM.

 This is a problem inherent with synchronous callbacks and I can't think of a
 way to improve specifications or implementations to help here. It's entirely
 the responsibility of web authors to deal with this complexity.

 Well, specifications could just not allow synchronous callbacks of this sort, 
 which is kind of what we're discussing in this thread.

Agreed. What I meant was that if we're specifying synchronous
callbacks, there's nothing we can do in the specification to help with
this type of problem.

 That would help avoid the horrors of

 class XFoo extends HTMLElement {
   constructor(stuff) {
 super();

 // Set up some default content that happens to use another custom element
 this.innerHTML = `x-barp${stuff}/p/x-bar`;

 // All foos should also appear in a list off on the side!
 // Let's take care of that automatically for any consumers!
 document.querySelector(#list-of-foos).appendChild(this.cloneNode(true));
   }
 }

 which seems like a well-meaning thing that authors could do, without knowing 
 what they've unleashed.

Exactly.

/ Jonas



RE: The key custom elements question: custom constructors?

2015-07-15 Thread Travis Leithead
I've discussed this issue with some of Edge's key parser developers. From a 
technical ground, we do not have a problem with stopping the parser to callout 
to author code in order to run a constructor, either during parsing or cloning. 
For example, in parsing, I would expect that the callout happens after initial 
instance creation, but before the target node is attached to the DOM tree by 
the parser.

Having put my support in for this design, which I believe to be the most 
straightforward approach that most closely matches how the platform itself 
works, and which would not be a problematic issue for our implementation, I did 
have a chance to discuss this briefly with Alex Russell, who felt that running 
synchronous author code at such early stages in the loading pipeline (e.g., 
while initial parsing due to a previously encountered document.registerElement 
call was an anti-pattern that he'd like to avoid. He is a strong supporter of 
the proto-swizzle technique that happens later with retro-active upgrades to 
previously-seen custom elements. I am sympathetic to this concern, but have my 
own reservations about the proto-swizzle technique.

-Original Message-
From: Domenic Denicola [mailto:d...@domenic.me] 
Sent: Thursday, July 16, 2015 2:45 AM
To: public-webapps
Subject: The key custom elements question: custom constructors?

Hi all,

Ahead of next week's F2F, I'm trying to pull together some clarifying and 
stage-setting materials, proposals, lists of open issues, etc. In the end, they 
all get blocked on one key question:

**Is it OK to run author code during parsing/cloning/editing/printing (in 
Gecko)/etc.?**

If we allow custom elements to have custom constructors, then those must run in 
order to create properly-allocated instances of those elements; there is simply 
no other way to create those objects. You can shuffle the timing around a bit: 
e.g., while cloning a tree, you could either run the constructors at the normal 
times, or try to do something like almost-synchronous constructors [1] where 
you run them after constructing a skeleton of the cloned tree, but before 
inserting them into the tree. But the fact remains that if custom elements have 
custom constructors, those custom constructors must run in the middle of all 
those operations.

We've danced around this question many times. But I think we need a clear 
answer from the various implementers involved before we can continue. In 
particular, I'm not interested in whether the implementers think it's 
technically feasible. I'd like to know whether they think it's something we 
should standardize.

I'm hoping we can settle this on-list over the next day or two so that we all 
come to the meeting with a clear starting point. Thanks very much, and looking 
forward to your replies,

-Domenic

[1]: https://lists.w3.org/Archives/Public/public-webapps/2014JanMar/0098.html




Re: The key custom elements question: custom constructors?

2015-07-15 Thread Olli Pettay

On 07/16/2015 03:45 AM, Domenic Denicola wrote:

Hi all,

Ahead of next week's F2F, I'm trying to pull together some clarifying and 
stage-setting materials, proposals, lists of open issues, etc. In the
end, they all get blocked on one key question:

**Is it OK to run author code during parsing/cloning/editing/printing (in 
Gecko)/etc.?**


As of now, clone-document-for-printing is a gecko implementation detail and 
shouldn't limit anything here.
I think we'll just clone whatever data is needed to be cloned without running 
any scripts, since scripts won't run in the static clone anyway.
(but from implementation point of view I can say clone-document-for-printing is 
rather nice feature, simplified Gecko's printing setup quite a bit ;))


Running author code during cloneNode(true) can be very hard to spec and 
implement correctly, so I'd prefer if we could avoid that.





If we allow custom elements to have custom constructors, then those must run in 
order to create properly-allocated instances of those elements;
there is simply no other way to create those objects. You can shuffle the 
timing around a bit: e.g., while cloning a tree, you could either run the
constructors at the normal times, or try to do something like 
almost-synchronous constructors [1] where you run them after constructing a 
skeleton
of the cloned tree, but before inserting them into the tree. But the fact 
remains that if custom elements have custom constructors, those custom
constructors must run in the middle of all those operations.

We've danced around this question many times. But I think we need a clear 
answer from the various implementers involved before we can continue. In
particular, I'm not interested in whether the implementers think it's 
technically feasible. I'd like to know whether they think it's something we
should standardize.

It is also about someone writing a good spec for this all - no one ever managed 
to spec MutationEvents properly, and running author code during
cloneNode(true) is at least as hard problem to solve.



-Olli



I'm hoping we can settle this on-list over the next day or two so that we all 
come to the meeting with a clear starting point. Thanks very much,
and looking forward to your replies,

-Domenic

[1]: https://lists.w3.org/Archives/Public/public-webapps/2014JanMar/0098.html