Re: Why can't we just use constructor instead of createdCallback?

2014-02-18 Thread Adam Klein
On Tue, Feb 18, 2014 at 3:26 PM, Dimitri Glazkov  wrote:
> On Tue, Feb 18, 2014 at 2:59 PM, Jonas Sicking  wrote:
> > On Tue, Feb 18, 2014 at 10:35 AM, Dimitri Glazkov  
> > wrote:
> > > The thing that really bothers me is that this approach is contradicting
> > > itself. We go to into pretty elaborate lengths to enable running
> > > constructors during parsing, but the key performance lesson developers 
> > > will
> > > immediately learn is to avoid constructors on custom elements, because 
> > > they
> > > will trigger the two-phase code path during parsing. Here's a thing that 
> > > you
> > > can use, but you probably don't want to ever use it.
> >
> > The above paragraph appears to assume that creating this list is slow.
> > Do you have data to back that up?
>
> No, of course not :) It's a first intuitive reaction.

One example that seems intuitively problematic about this approach (to
me, anyway) are those parts of the parser that inspect the tree during
parsing: foster parenting. I'm not sure it's a performance issue so
much as a complexity issue. Consider:


  

  

When following the spec
(http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#appropriate-place-for-inserting-a-node),
any text in that algorithm which says "parent node" need to be patched
to say something about this new list of to-be-attached nodes.

Patching all such references seems likely to be difficult and
error-prone, but I admit that I can't quantify those worries.

- Adam



Re: Why can't we just use constructor instead of createdCallback?

2014-02-18 Thread Dimitri Glazkov
On Tue, Feb 18, 2014 at 2:59 PM, Jonas Sicking  wrote:

> On Tue, Feb 18, 2014 at 10:35 AM, Dimitri Glazkov 
> wrote:
> >
> >
> >
> > On Fri, Feb 14, 2014 at 3:58 PM, Jonas Sicking  wrote:
> >>
> >>
> >> What I mean is that for nodes that doesn't have a constructor, and
> >> whose parent doesn't have a constructor, no need to add them to the
> >> above arrays. Just insert them into their parent. That means that when
> >> that the constructor of an element runs, the element doesn't have any
> >> parents or children.
> >>
> >> So no need to hide parents or children anywhere.
> >
> >
> > Okay, let me see if I got this right. The list is effectively a
> serialized
> > representation of a document subtree. The parent + order in the list
> > provides all the necessary information. We use this list to separate tree
> > construction into two stages: one before custom element constructors are
> > called, and one after.
>
> Yes
>
> > In cases when the custom element is just a like button widget (a leaf in
> the
> > tree), the list is short and just contains the widgets.
>
> Yes
>
> > In cases like " ... the entire doc tree ...
> > ", the list contains the entire subtree of ,
> which
> > is effectively the document.
>
> Well. With the optimization I mentioned you only need to make the
>  element and it's immediate children into the list. Any
> grand-children of  can immediately be inserted into their
> parent.
>
> So I guess you could say that the list contains basically the whole
> document. But most nodes would only indirectly be in the list. I.e.
> the list would be short, but each entry could contain large subtrees.
>
> > In cases like ". ... more siblings
> > ... ", the list will contain at least all siblings of ,
> > because they can't be inserted into tree until after 's
> constructor
> > runs.
>
> Yes
>
> > When run, the constructors are free to explore the partially-completed
> tree,
> > which enables interesting hacks like this:
> >
> > in document:
> >  lots more markup...
> >
> > in my-bar constructor:
> > var myFutureParent = document.querySelector("#a");
> > // redirect tree construction to resume at a new point.
> > document.body.appendChild(myFutureParent);
> >
> > Or, in my-bar constructor:
> > var myFutureParent = document.querySelector("#a");
> > var iframe = document.body.appendChild(document.createElement("iframe"));
> > // teleport the tree into another frame
> > iframe.contentDocument.body.appendChild(myFutureParent);
>
> Yup
>
> > I can't immediately tell whether these hacks are cool or scary.
>
> You can already do exactly this with 

Re: Why can't we just use constructor instead of createdCallback?

2014-02-18 Thread Erik Arvidsson
On Tue, Feb 18, 2014 at 5:59 PM, Jonas Sicking  wrote:

> On Tue, Feb 18, 2014 at 10:35 AM, Dimitri Glazkov 
> wrote:
> >
> >
> >
> > On Fri, Feb 14, 2014 at 3:58 PM, Jonas Sicking  wrote:
> >>
> >>
> >> What I mean is that for nodes that doesn't have a constructor, and
> >> whose parent doesn't have a constructor, no need to add them to the
> >> above arrays. Just insert them into their parent. That means that when
> >> that the constructor of an element runs, the element doesn't have any
> >> parents or children.
> >>
> >> So no need to hide parents or children anywhere.
> >
> >
> > Okay, let me see if I got this right. The list is effectively a
> serialized
> > representation of a document subtree. The parent + order in the list
> > provides all the necessary information. We use this list to separate tree
> > construction into two stages: one before custom element constructors are
> > called, and one after.
>
> Yes
>
> > In cases when the custom element is just a like button widget (a leaf in
> the
> > tree), the list is short and just contains the widgets.
>
> Yes
>
> > In cases like " ... the entire doc tree ...
> > ", the list contains the entire subtree of ,
> which
> > is effectively the document.
>
> Well. With the optimization I mentioned you only need to make the
>  element and it's immediate children into the list. Any
> grand-children of  can immediately be inserted into their
> parent.
>
> So I guess you could say that the list contains basically the whole
> document. But most nodes would only indirectly be in the list. I.e.
> the list would be short, but each entry could contain large subtrees.
>

Would that cause issues with the order of the mutation record reported by
mutation observers?


>
> > In cases like ". ... more siblings
> > ... ", the list will contain at least all siblings of ,
> > because they can't be inserted into tree until after 's
> constructor
> > runs.
>
> Yes
>
> > When run, the constructors are free to explore the partially-completed
> tree,
> > which enables interesting hacks like this:
> >
> > in document:
> >  lots more markup...
> >
> > in my-bar constructor:
> > var myFutureParent = document.querySelector("#a");
> > // redirect tree construction to resume at a new point.
> > document.body.appendChild(myFutureParent);
> >
> > Or, in my-bar constructor:
> > var myFutureParent = document.querySelector("#a");
> > var iframe = document.body.appendChild(document.createElement("iframe"));
> > // teleport the tree into another frame
> > iframe.contentDocument.body.appendChild(myFutureParent);
>
> Yup
>
> > I can't immediately tell whether these hacks are cool or scary.
>
> You can already do exactly this with 

Re: Why can't we just use constructor instead of createdCallback?

2014-02-18 Thread Jonas Sicking
On Tue, Feb 18, 2014 at 10:35 AM, Dimitri Glazkov  wrote:
>
>
>
> On Fri, Feb 14, 2014 at 3:58 PM, Jonas Sicking  wrote:
>>
>>
>> What I mean is that for nodes that doesn't have a constructor, and
>> whose parent doesn't have a constructor, no need to add them to the
>> above arrays. Just insert them into their parent. That means that when
>> that the constructor of an element runs, the element doesn't have any
>> parents or children.
>>
>> So no need to hide parents or children anywhere.
>
>
> Okay, let me see if I got this right. The list is effectively a serialized
> representation of a document subtree. The parent + order in the list
> provides all the necessary information. We use this list to separate tree
> construction into two stages: one before custom element constructors are
> called, and one after.

Yes

> In cases when the custom element is just a like button widget (a leaf in the
> tree), the list is short and just contains the widgets.

Yes

> In cases like " ... the entire doc tree ...
> ", the list contains the entire subtree of , which
> is effectively the document.

Well. With the optimization I mentioned you only need to make the
 element and it's immediate children into the list. Any
grand-children of  can immediately be inserted into their
parent.

So I guess you could say that the list contains basically the whole
document. But most nodes would only indirectly be in the list. I.e.
the list would be short, but each entry could contain large subtrees.

> In cases like ". ... more siblings
> ... ", the list will contain at least all siblings of ,
> because they can't be inserted into tree until after 's constructor
> runs.

Yes

> When run, the constructors are free to explore the partially-completed tree,
> which enables interesting hacks like this:
>
> in document:
>  lots more markup...
>
> in my-bar constructor:
> var myFutureParent = document.querySelector("#a");
> // redirect tree construction to resume at a new point.
> document.body.appendChild(myFutureParent);
>
> Or, in my-bar constructor:
> var myFutureParent = document.querySelector("#a");
> var iframe = document.body.appendChild(document.createElement("iframe"));
> // teleport the tree into another frame
> iframe.contentDocument.body.appendChild(myFutureParent);

Yup

> I can't immediately tell whether these hacks are cool or scary.

You can already do exactly this with 

Re: Why can't we just use constructor instead of createdCallback?

2014-02-18 Thread Ryosuke Niwa
On Feb 18, 2014, at 10:35 AM, Dimitri Glazkov  wrote:
> On Fri, Feb 14, 2014 at 3:58 PM, Jonas Sicking  wrote:
> 
> What I mean is that for nodes that doesn't have a constructor, and
> whose parent doesn't have a constructor, no need to add them to the
> above arrays. Just insert them into their parent. That means that when
> that the constructor of an element runs, the element doesn't have any
> parents or children.
> 
> So no need to hide parents or children anywhere.
> 
> Okay, let me see if I got this right. The list is effectively a serialized 
> representation of a document subtree. The parent + order in the list provides 
> all the necessary information. We use this list to separate tree construction 
> into two stages: one before custom element constructors are called, and one 
> after.
> 
> In cases when the custom element is just a like button widget (a leaf in the 
> tree), the list is short and just contains the widgets.
> 
> In cases like " ... the entire doc tree ... 
> ", the list contains the entire subtree of , which is 
> effectively the document.
> 
> In cases like ". ... more siblings ... 
> ", the list will contain at least all siblings of , because 
> they can't be inserted into tree until after 's constructor runs.
> 
> When run, the constructors are free to explore the partially-completed tree, 
> which enables interesting hacks like this:
> 
> in document:
>  lots more markup...
> 
> in my-bar constructor:
> var myFutureParent = document.querySelector("#a");
> // redirect tree construction to resume at a new point.
> document.body.appendChild(myFutureParent);
> 
> Or, in my-bar constructor:
> var myFutureParent = document.querySelector("#a");
> var iframe = document.body.appendChild(document.createElement("iframe"));
> // teleport the tree into another frame
> iframe.contentDocument.body.appendChild(myFutureParent);

You can already do this in a regular script element so this isn't a new issue 
custom element's constructor is introducing.


> The thing that really bothers me is that this approach is contradicting 
> itself. We go to into pretty elaborate lengths to enable running constructors 
> during parsing, but the key performance lesson developers will immediately 
> learn is to avoid constructors on custom elements, because they will trigger 
> the two-phase code path during parsing. Here's a thing that you can use, but 
> you probably don't want to ever use it.

Have you tried implementing this and found that you can't implement it 
efficiently?  Could you quantify the runtime or memory cost?

> Here's an alternative proposal:
> 
> 1) The Web developers are already aware of the fact that you can create new 
> instances of JS objects without running their constructors with Object.create
> 
> 2) Let's make sure that when they call constructors directly (as in var b = 
> new MyB(arg1,arg2);), the constructor is actually called.
> 
> 3) When the parser instantiates the element, it does the equivalent of 
> Object.create, so no constructor is called.

I don't see why we want to make the edge case like the one you described above 
prevent us from making common cases easy to use and understand.

Just call constructor whenever a custom element is created.  If you're doing 
weird stuff in constructor, then weird things happen.

- R. Niwa



Re: Why can't we just use constructor instead of createdCallback?

2014-02-18 Thread Dimitri Glazkov
On Tue, Feb 18, 2014 at 11:24 AM, Erik Arvidsson  wrote:

>
> On Tue, Feb 18, 2014 at 1:35 PM, Dimitri Glazkov wrote:
>
>> Here's an alternative proposal:
>>
>> 1) The Web developers are already aware of the fact that you can create
>> new instances of JS objects without running their constructors with
>> Object.create
>>
>
> These are not the instances you are looking for.
>
> We need to have real instances here. @@create gives us the semantics for
> doing this.
>

Ah, yes. Sorry :)


>
>
>> 2) Let's make sure that when they call constructors directly (as in var b
>> = new MyB(arg1,arg2);), the constructor is actually called.
>>
>> 3) When the parser instantiates the element, it does the equivalent of
>> Object.create, so no constructor is called.
>>
>
> That would not set the internal state as needed. It would not know how to
> associate the instance object with the C++ backing object for example.
> Also, all the DOM methods are using brand checks (and not instanceof
> checks) so the brand needs to be setup as well.
>
> The solution is to call `MyElement[Symbol.create]()` which would setup the
> internal state as needed. We can make this non writable, non configurable
> which allows the implementation to skip calling any js code at that point
> because the semantics is unobservable.
>
>
>> It seems simple and easy to understand.
>>
>
> With ES6 it is possible to create instance objects without ever calling
> the constructor (this is NOT possible in ES5) so maybe we should just give
> up on having the parser calling the constructor?
>

Sounds good to me.

:DG<


Re: Why can't we just use constructor instead of createdCallback?

2014-02-18 Thread Erik Arvidsson
On Tue, Feb 18, 2014 at 1:35 PM, Dimitri Glazkov wrote:

> Here's an alternative proposal:
>
> 1) The Web developers are already aware of the fact that you can create
> new instances of JS objects without running their constructors with
> Object.create
>

These are not the instances you are looking for.

We need to have real instances here. @@create gives us the semantics for
doing this.


> 2) Let's make sure that when they call constructors directly (as in var b
> = new MyB(arg1,arg2);), the constructor is actually called.
>
> 3) When the parser instantiates the element, it does the equivalent of
> Object.create, so no constructor is called.
>

That would not set the internal state as needed. It would not know how to
associate the instance object with the C++ backing object for example.
Also, all the DOM methods are using brand checks (and not instanceof
checks) so the brand needs to be setup as well.

The solution is to call `MyElement[Symbol.create]()` which would setup the
internal state as needed. We can make this non writable, non configurable
which allows the implementation to skip calling any js code at that point
because the semantics is unobservable.


> It seems simple and easy to understand.
>

With ES6 it is possible to create instance objects without ever calling the
constructor (this is NOT possible in ES5) so maybe we should just give up
on having the parser calling the constructor?


-- 
erik


Re: Why can't we just use constructor instead of createdCallback?

2014-02-18 Thread Dimitri Glazkov
On Fri, Feb 14, 2014 at 3:58 PM, Jonas Sicking  wrote:

>
> What I mean is that for nodes that doesn't have a constructor, and
> whose parent doesn't have a constructor, no need to add them to the
> above arrays. Just insert them into their parent. That means that when
> that the constructor of an element runs, the element doesn't have any
> parents or children.
>
> So no need to hide parents or children anywhere.
>

Okay, let me see if I got this right. The list is effectively a serialized
representation of a document subtree. The parent + order in the list
provides all the necessary information. We use this list to separate tree
construction into two stages: one before custom element constructors are
called, and one after.

In cases when the custom element is just a like button widget (a leaf in
the tree), the list is short and just contains the widgets.

In cases like " ... the entire doc tree ...
", the list contains the entire subtree of , which
is effectively the document.

In cases like ". ... more siblings
... ", the list will contain at least all siblings of ,
because they can't be inserted into tree until after 's constructor
runs.

When run, the constructors are free to explore the partially-completed
tree, which enables interesting hacks like this:

in document:
 lots more markup...

in my-bar constructor:
var myFutureParent = document.querySelector("#a");
// redirect tree construction to resume at a new point.
document.body.appendChild(myFutureParent);

Or, in my-bar constructor:
var myFutureParent = document.querySelector("#a");
var iframe = document.body.appendChild(document.createElement("iframe"));
// teleport the tree into another frame
iframe.contentDocument.body.appendChild(myFutureParent);

I can't immediately tell whether these hacks are cool or scary.

The thing that really bothers me is that this approach is contradicting
itself. We go to into pretty elaborate lengths to enable running
constructors during parsing, but the key performance lesson developers will
immediately learn is to avoid constructors on custom elements, because they
will trigger the two-phase code path during parsing. Here's a thing that
you can use, but you probably don't want to ever use it.

Here's an alternative proposal:

1) The Web developers are already aware of the fact that you can create new
instances of JS objects without running their constructors with
Object.create

2) Let's make sure that when they call constructors directly (as in var b =
new MyB(arg1,arg2);), the constructor is actually called.

3) When the parser instantiates the element, it does the equivalent of
Object.create, so no constructor is called.

It seems simple and easy to understand.

:DG<


Re: Why can't we just use constructor instead of createdCallback?

2014-02-14 Thread Jonas Sicking
On Fri, Feb 14, 2014 at 10:50 AM, Dimitri Glazkov  wrote:
>
>
>
> On Fri, Feb 14, 2014 at 10:36 AM, Jonas Sicking  wrote:
>>
>> On Fri, Feb 14, 2014 at 9:25 AM, Dimitri Glazkov 
>> wrote:
>> > On Thu, Feb 13, 2014 at 6:50 PM, Jonas Sicking  wrote:
>> >>
>> >> Dimitri, I'd still love to hear feedback from you on the idea above.
>> >> Seems like it could fix one of the design issues that a lot of people
>> >> have reacted to.
>> >
>> >
>> > I am not sure I fully understand how this will work. Let me try to
>> > repeat it
>> > back and see if I got this right.
>> >
>> > Basically, we are modifying the tree construction algorithm to be a
>> > 3-pass
>> > system:
>> >
>> > 1) Build a meta tree (each node in the tree is a meta object that
>> > represents
>> > an element that will be constructed)
>> > 2) Instantiate all elements by calling constructors on them
>> > 3) Build the tree of elements from the meta tree.
>> >
>> > Right?
>>
>> I'd rather put it as:
>>
>> 1) Construct the objects, but rather than inserting them in their
>> parents, remember which parent they should be inserted in.
>
> Sure, this is the meta tree construction. At the limit, if every element is
> a custom element, then you're effectively building a tree of things that
> remember where their respective elements need to be.

I don't think that you need a tree of "things". What you need is an
array of objects that need to be inserted, and an array of parents
that they need to insert them into. That's it.

>> So no need to construct any meta objects.
>
> Okay, we don't have to call them meta objects, but we need some storage to
> remember where the element should go :)

Sure. You'll need two arrays. Or really, you'll need one array of
node+parent tuples.

>> You can further optimize by only doing this for custom elements with a
>> constructor.
>
> Interesting. What if the element's constructor decides to walk the DOM tree
> or mutate it? What does it see? Are there holes for elements that haven't
> yet been inserted, or are the elements just appended regardless of their
> initial position in the tree?

What I mean is that for nodes that doesn't have a constructor, and
whose parent doesn't have a constructor, no need to add them to the
above arrays. Just insert them into their parent. That means that when
that the constructor of an element runs, the element doesn't have any
parents or children.

So no need to hide parents or children anywhere.

/ Jonas



Re: Why can't we just use constructor instead of createdCallback?

2014-02-14 Thread Boris Zbarsky

On 2/14/14 2:03 PM, Erik Arvidsson wrote:

Then we need to guard all DOM traversal and DOM mutation methods and
throw if the counter is non zero.


This is a fairly nontrivial whack-a-mole exercise, sadly (starting with 
defining "traversal").


-Boris



Re: Why can't we just use constructor instead of createdCallback?

2014-02-14 Thread Erik Arvidsson
Another alternative is to disallow DOM traversal and DOM mutation inside
these constructors. By disallow I mean throw an error! Here is a rough
outline of what the algorithm might look like.

Let there be a global counter CostomElementConstructionCounter which is
initially set to 0.

1. Parse and build the DOM tree as usual. Keep track of all custom elements
we encounter.
2. At some later point, before any script is run:
3. For each pending custom element (in tree order):
  1. Create the instance objects for the custom element.
  2. Increment CostomElementConstructionCounter
  3. Call the constructructor for the custom element, passing the object
instance as `this`.
  4. Decrement CostomElementConstructionCounter

Then we need to guard all DOM traversal and DOM mutation methods and throw
if the counter is non zero.

The point is that the timing of the constructor invocation is mostly not
observable. If an implementation wants to invoke it as it builds the DOM
that also works since there is no way to traverse the tree at that time.



On Fri, Feb 14, 2014 at 1:50 PM, Dimitri Glazkov wrote:

>
>
>
> On Fri, Feb 14, 2014 at 10:36 AM, Jonas Sicking  wrote:
>
>> On Fri, Feb 14, 2014 at 9:25 AM, Dimitri Glazkov 
>> wrote:
>> > On Thu, Feb 13, 2014 at 6:50 PM, Jonas Sicking 
>> wrote:
>> >>
>> >> Dimitri, I'd still love to hear feedback from you on the idea above.
>> >> Seems like it could fix one of the design issues that a lot of people
>> >> have reacted to.
>> >
>> >
>> > I am not sure I fully understand how this will work. Let me try to
>> repeat it
>> > back and see if I got this right.
>> >
>> > Basically, we are modifying the tree construction algorithm to be a
>> 3-pass
>> > system:
>> >
>> > 1) Build a meta tree (each node in the tree is a meta object that
>> represents
>> > an element that will be constructed)
>> > 2) Instantiate all elements by calling constructors on them
>> > 3) Build the tree of elements from the meta tree.
>> >
>> > Right?
>>
>> I'd rather put it as:
>>
>> 1) Construct the objects, but rather than inserting them in their
>> parents, remember which parent they should be inserted in.
>>
>
> Sure, this is the meta tree construction. At the limit, if every element
> is a custom element, then you're effectively building a tree of things that
> remember where their respective elements need to be.
>
>
>> 2) Call constructors on all elements
>>
>
> Yup.
>
>
>> 3) Insert elements in their parent
>>
>
> Yup.
>
>
>>
>> So no need to construct any meta objects.
>>
>
> Okay, we don't have to call them meta objects, but we need some storage to
> remember where the element should go :)
>
>
>>
>> You can further optimize by only doing this for custom elements with a
>> constructor.
>>
>
> Interesting. What if the element's constructor decides to walk the DOM
> tree or mutate it? What does it see? Are there holes for elements that
> haven't yet been inserted, or are the elements just appended regardless of
> their initial position in the tree?
>
> :DG<
>



-- 
erik


Re: Why can't we just use constructor instead of createdCallback?

2014-02-14 Thread Dimitri Glazkov
On Fri, Feb 14, 2014 at 10:36 AM, Jonas Sicking  wrote:

> On Fri, Feb 14, 2014 at 9:25 AM, Dimitri Glazkov 
> wrote:
> > On Thu, Feb 13, 2014 at 6:50 PM, Jonas Sicking  wrote:
> >>
> >> Dimitri, I'd still love to hear feedback from you on the idea above.
> >> Seems like it could fix one of the design issues that a lot of people
> >> have reacted to.
> >
> >
> > I am not sure I fully understand how this will work. Let me try to
> repeat it
> > back and see if I got this right.
> >
> > Basically, we are modifying the tree construction algorithm to be a
> 3-pass
> > system:
> >
> > 1) Build a meta tree (each node in the tree is a meta object that
> represents
> > an element that will be constructed)
> > 2) Instantiate all elements by calling constructors on them
> > 3) Build the tree of elements from the meta tree.
> >
> > Right?
>
> I'd rather put it as:
>
> 1) Construct the objects, but rather than inserting them in their
> parents, remember which parent they should be inserted in.
>

Sure, this is the meta tree construction. At the limit, if every element is
a custom element, then you're effectively building a tree of things that
remember where their respective elements need to be.


> 2) Call constructors on all elements
>

Yup.


> 3) Insert elements in their parent
>

Yup.


>
> So no need to construct any meta objects.
>

Okay, we don't have to call them meta objects, but we need some storage to
remember where the element should go :)


>
> You can further optimize by only doing this for custom elements with a
> constructor.
>

Interesting. What if the element's constructor decides to walk the DOM tree
or mutate it? What does it see? Are there holes for elements that haven't
yet been inserted, or are the elements just appended regardless of their
initial position in the tree?

:DG<


Re: Why can't we just use constructor instead of createdCallback?

2014-02-14 Thread Jonas Sicking
On Fri, Feb 14, 2014 at 9:25 AM, Dimitri Glazkov  wrote:
> On Thu, Feb 13, 2014 at 6:50 PM, Jonas Sicking  wrote:
>>
>> Dimitri, I'd still love to hear feedback from you on the idea above.
>> Seems like it could fix one of the design issues that a lot of people
>> have reacted to.
>
>
> I am not sure I fully understand how this will work. Let me try to repeat it
> back and see if I got this right.
>
> Basically, we are modifying the tree construction algorithm to be a 3-pass
> system:
>
> 1) Build a meta tree (each node in the tree is a meta object that represents
> an element that will be constructed)
> 2) Instantiate all elements by calling constructors on them
> 3) Build the tree of elements from the meta tree.
>
> Right?

I'd rather put it as:

1) Construct the objects, but rather than inserting them in their
parents, remember which parent they should be inserted in.
2) Call constructors on all elements
3) Insert elements in their parent

So no need to construct any meta objects.

You can further optimize by only doing this for custom elements with a
constructor.

/ Jonas



Re: Why can't we just use constructor instead of createdCallback?

2014-02-14 Thread Dimitri Glazkov
On Thu, Feb 13, 2014 at 6:50 PM, Jonas Sicking  wrote:

> Dimitri, I'd still love to hear feedback from you on the idea above.
> Seems like it could fix one of the design issues that a lot of people
> have reacted to.
>

I am not sure I fully understand how this will work. Let me try to repeat
it back and see if I got this right.

Basically, we are modifying the tree construction algorithm to be a 3-pass
system:

1) Build a meta tree (each node in the tree is a meta object that
represents an element that will be constructed)
2) Instantiate all elements by calling constructors on them
3) Build the tree of elements from the meta tree.

Right?

:DG<


Re: Why can't we just use constructor instead of createdCallback?

2014-02-13 Thread Ryosuke Niwa
We (Apple) support this proposal assuming that we can implement the proposed 
algorithm efficiently.

We would try to prototype it in WebKit in the coming months and will report 
implementation issues, including the feasibility of efficient implementation, 
if exists.

- R. Niwa

On Feb 13, 2014, at 6:50 PM, Jonas Sicking  wrote:

> Dimitri, I'd still love to hear feedback from you on the idea above.
> Seems like it could fix one of the design issues that a lot of people
> have reacted to.
> 
> / Jonas
> 
> On Wed, Jan 22, 2014 at 5:21 PM, Jonas Sicking  wrote:
>> On Thu, Jan 9, 2014 at 9:27 PM, Boris Zbarsky  wrote:
 One idea that came out of our discussion is was to add an additional step
 in the parser to call constructors on all "pending" elements before they're
 being constructed into the DOM tree.
>>> 
>>> Isn't that the bad thing we _don't_ want to do?  That is, invoke arbitrary
>>> page JS from the middle of the parsing algorithm?
>> 
>> The idea was to do something like this:
>> 
>> 1. While parsing, when you hit a custom element (with a constructor)
>> don't insert that element into its parent, nor insert any of its
>> children into the element.
>> 2. Put each such element into an array along with meta-info about what
>> parent and children it should have.
>> 3. Once you're done parsing as much as you want to parse (i.e. until
>> you hit a network boundary or feel the need to return to the event
>> loop), unwind enough of the calling stack until you feel comfortable
>> running content JS.
>> 4. Run the constructor for the first element in the array.
>> 5. After a constructor has been run, insert the element into its
>> parent, and insert its children into the element.
>> 6. Remove the element from the array and, unless the array is empty,
>> go back to step 4.
>> 
>> This is somewhat simplified. You also have to make sure not to insert
>> an elements into a parent where previous siblings are still pending to
>> be inserted.
>> 
>> The big question of course is if tracking the elements in the separate
>> array and inserting them after their constructor has run will be a
>> performance issue.
>> 
>> In Gecko it might be a bit of a problem since we can get O(n^2)
>> performance issues where n is the nesting depth of custom elements.
>> This is due to our recursive BindToTree notification which cause
>> problems when trees are constructed "bottom up"
>> 
>> But possibly this can be solved. And possibly other implementations
>> doesn't have the same problem. Or possibly they have worse problems.
>> 
>> But it wasn't immediately obvious to me that this wouldn't work.
>> 
>> / Jonas




Re: Why can't we just use constructor instead of createdCallback?

2014-02-13 Thread Jonas Sicking
Dimitri, I'd still love to hear feedback from you on the idea above.
Seems like it could fix one of the design issues that a lot of people
have reacted to.

/ Jonas

On Wed, Jan 22, 2014 at 5:21 PM, Jonas Sicking  wrote:
> On Thu, Jan 9, 2014 at 9:27 PM, Boris Zbarsky  wrote:
>>> One idea that came out of our discussion is was to add an additional step
>>> in the parser to call constructors on all "pending" elements before they're
>>> being constructed into the DOM tree.
>>
>> Isn't that the bad thing we _don't_ want to do?  That is, invoke arbitrary
>> page JS from the middle of the parsing algorithm?
>
> The idea was to do something like this:
>
> 1. While parsing, when you hit a custom element (with a constructor)
> don't insert that element into its parent, nor insert any of its
> children into the element.
> 2. Put each such element into an array along with meta-info about what
> parent and children it should have.
> 3. Once you're done parsing as much as you want to parse (i.e. until
> you hit a network boundary or feel the need to return to the event
> loop), unwind enough of the calling stack until you feel comfortable
> running content JS.
> 4. Run the constructor for the first element in the array.
> 5. After a constructor has been run, insert the element into its
> parent, and insert its children into the element.
> 6. Remove the element from the array and, unless the array is empty,
> go back to step 4.
>
> This is somewhat simplified. You also have to make sure not to insert
> an elements into a parent where previous siblings are still pending to
> be inserted.
>
> The big question of course is if tracking the elements in the separate
> array and inserting them after their constructor has run will be a
> performance issue.
>
> In Gecko it might be a bit of a problem since we can get O(n^2)
> performance issues where n is the nesting depth of custom elements.
> This is due to our recursive BindToTree notification which cause
> problems when trees are constructed "bottom up"
>
> But possibly this can be solved. And possibly other implementations
> doesn't have the same problem. Or possibly they have worse problems.
>
> But it wasn't immediately obvious to me that this wouldn't work.
>
> / Jonas



Re: Why can't we just use constructor instead of createdCallback?

2014-01-22 Thread Jonas Sicking
On Thu, Jan 9, 2014 at 9:27 PM, Boris Zbarsky  wrote:
>> One idea that came out of our discussion is was to add an additional step
>> in the parser to call constructors on all “pending” elements before they’re
>> being constructed into the DOM tree.
>
> Isn't that the bad thing we _don't_ want to do?  That is, invoke arbitrary
> page JS from the middle of the parsing algorithm?

The idea was to do something like this:

1. While parsing, when you hit a custom element (with a constructor)
don't insert that element into its parent, nor insert any of its
children into the element.
2. Put each such element into an array along with meta-info about what
parent and children it should have.
3. Once you're done parsing as much as you want to parse (i.e. until
you hit a network boundary or feel the need to return to the event
loop), unwind enough of the calling stack until you feel comfortable
running content JS.
4. Run the constructor for the first element in the array.
5. After a constructor has been run, insert the element into its
parent, and insert its children into the element.
6. Remove the element from the array and, unless the array is empty,
go back to step 4.

This is somewhat simplified. You also have to make sure not to insert
an elements into a parent where previous siblings are still pending to
be inserted.

The big question of course is if tracking the elements in the separate
array and inserting them after their constructor has run will be a
performance issue.

In Gecko it might be a bit of a problem since we can get O(n^2)
performance issues where n is the nesting depth of custom elements.
This is due to our recursive BindToTree notification which cause
problems when trees are constructed "bottom up"

But possibly this can be solved. And possibly other implementations
doesn't have the same problem. Or possibly they have worse problems.

But it wasn't immediately obvious to me that this wouldn't work.

/ Jonas



Re: Why can't we just use constructor instead of createdCallback?

2014-01-10 Thread Ryosuke Niwa

On Jan 10, 2014, at 8:16 AM, Boris Zbarsky  wrote:

> On 1/10/14 11:10 AM, Erik Arvidsson wrote:
>> My hope was that it would be rare to override Symbol.create for Elements
>> so in most cases we would not need to call user code.
> 
> For spec purposes and parser implementation design purposes that doesn't 
> matter.  If user code can be called, the algorithms involved have to handle 
> user code being called at that point and potentially tearing the world down 
> (or apart, or just rearranging it in macabre ways like user code tends to 
> do)...
> 
>> After further discussing this with Dominic and others I've given up the
>> hope that an object instance cannot be reached before the constructor
>> has been called. This can happen due to navigating the DOM tree but also
>> be manually calling `MyCustomElement[Symbol.create]()`. At this point I
>> believe we should just resolve to best practice and that is to not use
>> @@create directly and do not navigate the DOM tree in your constructors.
> 
> Yeah, agreed.

An alternative idea we had was to “recursively” call constructors on the 
“unconstructed” elements in such situations.  So if the constructor of an 
element A tries to access to another unconstrcuted element B, then call B’s 
constructor at that point.

Either solution is better than not being able to use ES6 classes in my opinion.

- R. Niwa




Re: Why can't we just use constructor instead of createdCallback?

2014-01-10 Thread Boris Zbarsky

On 1/10/14 11:10 AM, Erik Arvidsson wrote:

My hope was that it would be rare to override Symbol.create for Elements
so in most cases we would not need to call user code.


For spec purposes and parser implementation design purposes that doesn't 
matter.  If user code can be called, the algorithms involved have to 
handle user code being called at that point and potentially tearing the 
world down (or apart, or just rearranging it in macabre ways like user 
code tends to do)...



After further discussing this with Dominic and others I've given up the
hope that an object instance cannot be reached before the constructor
has been called. This can happen due to navigating the DOM tree but also
be manually calling `MyCustomElement[Symbol.create]()`. At this point I
believe we should just resolve to best practice and that is to not use
@@create directly and do not navigate the DOM tree in your constructors.


Yeah, agreed.

-Boris




Re: Why can't we just use constructor instead of createdCallback?

2014-01-10 Thread Erik Arvidsson
On Thu, Jan 9, 2014 at 10:57 PM, Ryosuke Niwa  wrote:

> > 1. The parser does not know that it needs to use MyElement.@@create to
> create the JS objects when it sees a .
>
> On the other hand, solving this seems to require running some author
> scripts at the element creation time, at some later time but before the
> node is inserted into the document.


My hope was that it would be rare to override Symbol.create for Elements so
in most cases we would not need to call user code.

After further discussing this with Dominic and others I've given up the
hope that an object instance cannot be reached before the constructor has
been called. This can happen due to navigating the DOM tree but also be
manually calling `MyCustomElement[Symbol.create]()`. At this point I
believe we should just resolve to best practice and that is to not use
@@create directly and do not navigate the DOM tree in your constructors.


-- 
erik


Re: Why can't we just use constructor instead of createdCallback?

2014-01-09 Thread Andrew Fedoniouk
On Thu, Jan 9, 2014 at 9:27 PM, Boris Zbarsky  wrote:
> On 1/9/14 10:57 PM, Ryosuke Niwa wrote:
>>>
>>> Given that, we could maybe cheat and in fact do some sort of delayed
>>> calling of the constructor of ES6 subclasses of elements.  You'd still be
>>> able to observe these objects in an "unconstructed" state from the subclass
>>> pov, but at least it wouldn't be a security issue in terms of operating on a
>>> DOM that's in an inconsistent state from the point of view of privileged
>>> code.
>>
>>
>> Calling constructors after the tree had been constructed will be an issue
>> because then you could access “unconstructed” nodes via nextSibling,
>> parentNode, etc...
>
>
> Right, I did say that above.  Is that really a problem in practice, though?
>
>> One idea that came out of our discussion is was to add an additional step
>> in the parser to call constructors on all “pending” elements before they’re
>> being constructed into the DOM tree.
>
>
> Isn't that the bad thing we _don't_ want to do?  That is, invoke arbitrary
> page JS from the middle of the parsing algorithm?
>
>> On the other hand, solving this seems to require running some author
>> scripts at the element creation time, at some later time but before the node
>> is inserted into the document.
>
>
> The parser is expected to insert the nodes into the document pretty much
> immediately after creating them, no?
>
> -Boris
>

Calling of constructors (in JS/ES sense) instead of callbacks is not
semantically correct I would say.

Consider this declaration:

class MyElement inherits HTMLElement {
public  prop = 1;
constructor( text ) {
   super("my-element");
   this.textContent = text;
}
}

UA simply cannot call such constructor as it requires parameter.
UA can call only implicit default constructor,  :  ({ prop:1
}).__proto__ =  MyElement;  in this case.
And call some designated method of the class ('callback' in this
discussion) when element gets
attached to the DOM tree.

Constructors are used for 'external' element creation:

  var myel = new MyElement("woo-hoo!");

About "callbacks":

It should be two callbacks actually:

attached() - called when element *gets attached to the DOM*, it is not
a constructor, sic!
detached() - when it gets detached from the DOM.

so here:

  var myel = new MyElement("woo-hoo!");
  someParent.append(myel);

call of myel.attached() will happen inside the append() above.

  detached() is called when parent.removeChild() for the element is called.

Just in case: this is how it is implemented and works in my Sciter [1]
and I didn't find any problems with element/script life cycles.

And yet. I also have dynamic element class assignment
by CSS with custom 'prototype' property, e.g.:

  input[type="masked"] { prototype: MaskedInput url(code/widgets.tis); }

In that case attached/detached are also called when the element
gets/looses that style. But that's probably another story.

[1] http://terrainformatica.com/sciter


-- 
Andrew Fedoniouk.

http://terrainformatica.com



Re: Why can't we just use constructor instead of createdCallback?

2014-01-09 Thread Boris Zbarsky

On 1/9/14 10:57 PM, Ryosuke Niwa wrote:

Given that, we could maybe cheat and in fact do some sort of delayed calling of the 
constructor of ES6 subclasses of elements.  You'd still be able to observe these objects 
in an "unconstructed" state from the subclass pov, but at least it wouldn't be 
a security issue in terms of operating on a DOM that's in an inconsistent state from the 
point of view of privileged code.


Calling constructors after the tree had been constructed will be an issue 
because then you could access “unconstructed” nodes via nextSibling, 
parentNode, etc...


Right, I did say that above.  Is that really a problem in practice, though?


One idea that came out of our discussion is was to add an additional step in 
the parser to call constructors on all “pending” elements before they’re being 
constructed into the DOM tree.


Isn't that the bad thing we _don't_ want to do?  That is, invoke 
arbitrary page JS from the middle of the parsing algorithm?



On the other hand, solving this seems to require running some author scripts at 
the element creation time, at some later time but before the node is inserted 
into the document.


The parser is expected to insert the nodes into the document pretty much 
immediately after creating them, no?


-Boris



Re: Why can't we just use constructor instead of createdCallback?

2014-01-09 Thread Ryosuke Niwa
Jonas, William, Ted, and I had some discussion about this last month.  (Sorry 
for the delayed response).

On Dec 5, 2013, at 10:58 PM, Boris Zbarsky  wrote:
> On 12/6/13 1:49 AM, Ryosuke Niwa wrote:
>> Then how do we define a custom element using ES6 classes?  Are we going to 
>> not call the constructor?
> 
> An excellent question, indeed.  I don't have a good answer for you.
> 
> If we do make elements subclassable (which it seems like we should), we would 
> presumably need to make the actual default constructor of the built-in 
> element classes a no-op, since we can't actually rely on the subclass calling 
> it.  All the relevant setup would need to be done by @@create.
> 
> Given that, we could maybe cheat and in fact do some sort of delayed calling 
> of the constructor of ES6 subclasses of elements.  You'd still be able to 
> observe these objects in an "unconstructed" state from the subclass pov, but 
> at least it wouldn't be a security issue in terms of operating on a DOM 
> that's in an inconsistent state from the point of view of privileged code.

Calling constructors after the tree had been constructed will be an issue 
because then you could access “unconstructed” nodes via nextSibling, 
parentNode, etc...

> It's not clear to me how OK such an "unconstructed" state is.  I suppose it's 
> no worse than someone extending the ES6 subclass in question and then never 
> calling its constructor...  But that's a programming error on the someone's 
> part, typically, while here we would be effectively forcing this sort of 
> thing on all Element subclasses.
> 
> All that still seems more palatable than trying to completely revise HTML 
> parsing to be robust to constructors running when the element is created….

One idea that came out of our discussion is was to add an additional step in 
the parser to call constructors on all “pending” elements before they’re being 
constructed into the DOM tree.


On Dec 6, 2013, at 7:05 AM, Erik Arvidsson  wrote:
> The custom element draft does add a new synchronization point. After setting 
> innerHTML (for example), before returning to the script the callbacks for the 
> custom elements created by innerHTML are called in tree order.
> 
> This does lead to the possibility to observer objects that have not yet had 
> their created callback been called yet. I think this trade off is inevitable, 
> no matter whether we use @@create, constructor or created. I just don't see 
> us being able to call user code every time a node is created.


I do understand your concern.

On Dec 6, 2013, at 7:37 AM, Erik Arvidsson  wrote:
> The things that fail here are:
> 
> 1. The parser does not know that it needs to use MyElement.@@create to create 
> the JS objects when it sees a .

On the other hand, solving this seems to require running some author scripts at 
the element creation time, at some later time but before the node is inserted 
into the document.

> 2. No callbacks for enteredView, leftView and attributeChanged.
> 3. It depend on the magic of document.createElement which is circular. A 
> better way would be to do `super('my-element')` or something like that.


- R. Niwa




Re: [WebComponents] List for new bug announcements [Was: Re: Why can't we just use constructor instead of createdCallback?]

2013-12-07 Thread Edward O’Connor
Art wrote:

> For consistency reasons, and to facilitate transparency, it seems like all 
> new Web Component bugs should be announced on public-webapps. Does anyone 
> object to that?

I think that's a fine idea.


Ted



[WebComponents] List for new bug announcements [Was: Re: Why can't we just use constructor instead of createdCallback?]

2013-12-07 Thread Arthur Barstow

On 12/6/13 3:28 PM, ext Ryosuke Niwa wrote:


On Dec 6, 2013, at 7:37 AM, Erik Arvidsson > wrote:


1. The parser does not know that it needs to use MyElement.@@create 
to create the JS objects when it sees a .

2. No callbacks for enteredView, leftView and attributeChanged.
3. It depend on the magic of document.createElement which is 
circular. A better way would be to do `super('my-element')` or 
something like that.


I wish we could resolve these remaining issues.


In fact, fixing these issues is a requirement for us.


I just noticed that yesterday Erik filed three Custom Element bugs but I 
didn't receive an announcement about them:


* [Custom]: No way to pass parameters to constructor


* [Custom]: No way to associate class/constructor function


* [Custom]: A tag name should be associated with the constructor and not 
the prototype



Unlike other specs/components, new Web Components bugs are not announced 
on public-webapps (although like all of WebApps' components, new Web 
Components bugs are announced on public-webapps-bugzilla [which only has 
5 subscribers]).


For consistency reasons, and to facilitate transparency, it seems like 
all new Web Component bugs should be announced on public-webapps. Does 
anyone object to that?


-AB




Re: Why can't we just use constructor instead of createdCallback?

2013-12-06 Thread Ryosuke Niwa

On Dec 6, 2013, at 7:37 AM, Erik Arvidsson  wrote:

> On Fri, Dec 6, 2013 at 2:33 AM, Ryosuke Niwa  wrote:
> It appears to me that we should definitely have a good answer for this 
> question before the specification reaches CR
> given that the definition of ES6 classes is pretty stable at this point.
> 
> ES6 classes do not introduce any new semantics over ES5. However I do agree 
> that we need to think about user ergonomics here. If we cannot use ES6 class 
> syntax to do custom elements we have failed. What we have now is OK but not 
> perfect.
> 
> Here is how you can use class syntax today
> 
> ```js
> class MyElement extends HTMLElement {
>   createdCallback() {
> console.log("I'm not a real boy");
>   }
> }
> MyElement = document.create('my-element, MyElement);
> 
> // or
> 
> var MyElement = document.create('my-element, class extends HTMLElement {
>   createdCallback() {
> console.log("I'm not a real boy");
>   }
> });
> ```

What if that class definition had constructor() in it?  It would be called?  If 
so, when?

> 1. The parser does not know that it needs to use MyElement.@@create to create 
> the JS objects when it sees a .
> 2. No callbacks for enteredView, leftView and attributeChanged.
> 3. It depend on the magic of document.createElement which is circular. A 
> better way would be to do `super('my-element')` or something like that.
> 
> I wish we could resolve these remaining issues.

In fact, fixing these issues is a requirement for us.

- R. Niwa



Re: Why can't we just use constructor instead of createdCallback?

2013-12-06 Thread Erik Arvidsson
On Fri, Dec 6, 2013 at 2:33 AM, Ryosuke Niwa  wrote:

> It appears to me that we should definitely have a good answer for this
> question before the specification reaches CR
> given that the definition of ES6 classes is pretty stable at this point.


ES6 classes do not introduce any new semantics over ES5. However I do agree
that we need to think about user ergonomics here. If we cannot use ES6
class syntax to do custom elements we have failed. What we have now is OK
but not perfect.

Here is how you can use class syntax today

```js
class MyElement extends HTMLElement {
  createdCallback() {
console.log("I'm not a real boy");
  }
}
MyElement = document.create('my-element, MyElement);

// or

var MyElement = document.create('my-element, class extends HTMLElement {
  createdCallback() {
console.log("I'm not a real boy");
  }
});
```

This works fine in Blink today: http://goo.gl/HZLpqG

The relevant addition to ES6 is how @@create participates in object
creation.

I've previously voiced concern that custom elements do not use @@create and
the spec draft was changed in a way where it would allow using it in the
future. There was strong concern from Mozilla that they did not want custom
elements to depend on this ES6 feature due to them needing
document.register ASAP.

The way this would work without custom elements is:

```js
class MyElement extends HTMLElement {
  constructor(name) {
console.log(`I'm a real boy and my name is ${name}`);
  }
  [Symbol.create]() {
return document.createElement('my-element');
  }
}
new MyElement('Pinocchio');
```

The things that fail here are:

1. The parser does not know that it needs to use MyElement.@@create to
create the JS objects when it sees a .
2. No callbacks for enteredView, leftView and attributeChanged.
3. It depend on the magic of document.createElement which is circular. A
better way would be to do `super('my-element')` or something like that.

I wish we could resolve these remaining issues.

-- 
erik


Re: Why can't we just use constructor instead of createdCallback?

2013-12-06 Thread Erik Arvidsson
The custom element draft does add a new synchronization point. After
setting innerHTML (for example), before returning to the script the
callbacks for the custom elements created by innerHTML are called in tree
order.

This does lead to the possibility to observer objects that have not yet had
their created callback been called yet. I think this trade off is
inevitable, no matter whether we use @@create, constructor or created. I
just don't see us being able to call user code every time a node is created.




On Fri, Dec 6, 2013 at 1:58 AM, Boris Zbarsky  wrote:

> On 12/6/13 1:49 AM, Ryosuke Niwa wrote:
>
>> Then how do we define a custom element using ES6 classes?  Are we going
>> to not call the constructor?
>>
>
> An excellent question, indeed.  I don't have a good answer for you.
>
> If we do make elements subclassable (which it seems like we should), we
> would presumably need to make the actual default constructor of the
> built-in element classes a no-op, since we can't actually rely on the
> subclass calling it.  All the relevant setup would need to be done by
> @@create.
>
> Given that, we could maybe cheat and in fact do some sort of delayed
> calling of the constructor of ES6 subclasses of elements.  You'd still be
> able to observe these objects in an "unconstructed" state from the subclass
> pov, but at least it wouldn't be a security issue in terms of operating on
> a DOM that's in an inconsistent state from the point of view of privileged
> code.
>
> It's not clear to me how OK such an "unconstructed" state is.  I suppose
> it's no worse than someone extending the ES6 subclass in question and then
> never calling its constructor...  But that's a programming error on the
> someone's part, typically, while here we would be effectively forcing this
> sort of thing on all Element subclasses.
>
> All that still seems more palatable than trying to completely revise HTML
> parsing to be robust to constructors running when the element is created
>
> Might be worth checking on public-script-coord to see what the TC39 folks
> think about all this.
>
> -Boris
>
>


-- 
erik


Re: Why can't we just use constructor instead of createdCallback?

2013-12-05 Thread Ryosuke Niwa
On Dec 5, 2013, at 10:58 PM, Boris Zbarsky  wrote:
> On 12/6/13 1:49 AM, Ryosuke Niwa wrote:
>> Then how do we define a custom element using ES6 classes?  Are we going to 
>> not call the constructor?
> 
> An excellent question, indeed.  I don't have a good answer for you.

It appears to me that we should definitely have a good answer for this question 
before the specification reaches CR
given that the definition of ES6 classes is pretty stable at this point.

> If we do make elements subclassable (which it seems like we should), we would 
> presumably need to make the actual default constructor of the built-in 
> element classes a no-op, since we can't actually rely on the subclass calling 
> it.  All the relevant setup would need to be done by @@create.
> 
> Given that, we could maybe cheat and in fact do some sort of delayed calling 
> of the constructor of ES6 subclasses of elements.  You'd still be able to 
> observe these objects in an "unconstructed" state from the subclass pov, but 
> at least it wouldn't be a security issue in terms of operating on a DOM 
> that's in an inconsistent state from the point of view of privileged code.

Right.  I know it sounds so cheesy but I was suggesting something along that 
line.

> It's not clear to me how OK such an "unconstructed" state is.  I suppose it's 
> no worse than someone extending the ES6 subclass in question and then never 
> calling its constructor...  But that's a programming error on the someone's 
> part, typically, while here we would be effectively forcing this sort of 
> thing on all Element subclasses.

I think the question is how observable such a delay is and what implications it 
would have.

> All that still seems more palatable than trying to completely revise HTML 
> parsing to be robust to constructors running when the element is created….

Indeed.

> Might be worth checking on public-script-coord to see what the TC39 folks 
> think about all this.

Sounds like a good idea.

- R. Niwa




Re: Why can't we just use constructor instead of createdCallback?

2013-12-05 Thread Boris Zbarsky

On 12/6/13 1:49 AM, Ryosuke Niwa wrote:

Then how do we define a custom element using ES6 classes?  Are we going to not 
call the constructor?


An excellent question, indeed.  I don't have a good answer for you.

If we do make elements subclassable (which it seems like we should), we 
would presumably need to make the actual default constructor of the 
built-in element classes a no-op, since we can't actually rely on the 
subclass calling it.  All the relevant setup would need to be done by 
@@create.


Given that, we could maybe cheat and in fact do some sort of delayed 
calling of the constructor of ES6 subclasses of elements.  You'd still 
be able to observe these objects in an "unconstructed" state from the 
subclass pov, but at least it wouldn't be a security issue in terms of 
operating on a DOM that's in an inconsistent state from the point of 
view of privileged code.


It's not clear to me how OK such an "unconstructed" state is.  I suppose 
it's no worse than someone extending the ES6 subclass in question and 
then never calling its constructor...  But that's a programming error on 
the someone's part, typically, while here we would be effectively 
forcing this sort of thing on all Element subclasses.


All that still seems more palatable than trying to completely revise 
HTML parsing to be robust to constructors running when the element is 
created


Might be worth checking on public-script-coord to see what the TC39 
folks think about all this.


-Boris



Re: Why can't we just use constructor instead of createdCallback?

2013-12-05 Thread Ryosuke Niwa
On Dec 5, 2013, at 10:44 PM, Boris Zbarsky  wrote:

> On 12/6/13 12:03 AM, Ryosuke Niwa wrote:
>> That sounds like an implementation detail of Blink/WebKit.
> 
> It seems like a pretty fundamental restriction for all current HTML parsers.  
> In particular, the HTML parsing algorithm has no provisions for script 
> mutating the DOM at random points in the algorithm (in fact, pretty much 
> anywhere other than when 

Re: Why can't we just use constructor instead of createdCallback?

2013-12-05 Thread Boris Zbarsky

On 12/6/13 12:03 AM, Ryosuke Niwa wrote:

That sounds like an implementation detail of Blink/WebKit.


It seems like a pretty fundamental restriction for all current HTML 
parsers.  In particular, the HTML parsing algorithm has no provisions 
for script mutating the DOM at random points in the algorithm (in fact, 
pretty much anywhere other than when 

Re: Why can't we just use constructor instead of createdCallback?

2013-12-05 Thread Ryosuke Niwa
On Dec 5, 2013, at 9:23 PM, Dimitri Glazkov  wrote:
> On Thu, Dec 5, 2013 at 9:03 PM, Ryosuke Niwa  wrote:
> On Dec 5, 2013, at 8:43 PM, Dimitri Glazkov  wrote:
>> There were several threads around this in March/April, but the main gist is 
>> that we can't allow running user code when the parser is building the tree, 
>> and thus we would need to decouple the timing of the constructor being 
>> called from the [[Construct]] internal method to make constructors workable.
> 
> That sounds like an implementation detail of Blink/WebKit.  Also, JS 
> "wrappers" aren't even constructed immediately for builtin elements in WebKit 
> and Blink so delaying the construction of elements until later time (e.g. end 
> of micro task) seems fine.
> 
> FWIW, the concern was brought up first by Microsoft's Tony Ross and then 
> separately Mozilla's Jonas Sicking. Technically, both Blink and WebKit are 
> capable of doing this. It's just mostly a terrible idea to interrupt tree 
> construction with user code. Delaying construction of elements until end of 
> microtask doesn't solve the problem -- you're just shifting the timing of 
> tree construction.

I'm not suggesting to do that.  Simply call the constructor at when 
createdCallback is currently called.

- R. Niwa



Re: Why can't we just use constructor instead of createdCallback?

2013-12-05 Thread Dimitri Glazkov
On Thu, Dec 5, 2013 at 9:03 PM, Ryosuke Niwa  wrote:

> On Dec 5, 2013, at 8:43 PM, Dimitri Glazkov  wrote:
>
> There were several threads around this in March/April, but the main gist
> is that we can't allow running user code when the parser is building the
> tree, and thus we would need to decouple the timing of the constructor
> being called from the [[Construct]] internal method to make constructors
> workable.
>
>
> That sounds like an implementation detail of Blink/WebKit.  Also, JS
> "wrappers" aren't even constructed immediately for builtin elements in
> WebKit and Blink so delaying the construction of elements until later time
> (e.g. end of micro task) seems fine.
>

FWIW, the concern was brought up first by Microsoft's Tony Ross and then
separately Mozilla's Jonas Sicking. Technically, both Blink and WebKit are
capable of doing this. It's just mostly a terrible idea to interrupt tree
construction with user code. Delaying construction of elements until end of
microtask doesn't solve the problem -- you're just shifting the timing of
tree construction.

:DG<


Re: Why can't we just use constructor instead of createdCallback?

2013-12-05 Thread Ryosuke Niwa
On Dec 5, 2013, at 8:43 PM, Dimitri Glazkov  wrote:
> There were several threads around this in March/April, but the main gist is 
> that we can't allow running user code when the parser is building the tree, 
> and thus we would need to decouple the timing of the constructor being called 
> from the [[Construct]] internal method to make constructors workable.

That sounds like an implementation detail of Blink/WebKit.  Also, JS "wrappers" 
aren't even constructed immediately for builtin elements in WebKit and Blink so 
delaying the construction of elements until later time (e.g. end of micro task) 
seems fine.

> But then they aren't constructors, but callbacks, since the object would 
> already be exist (and be in a tree). So we decided to not lie and just call 
> them callbacks, rather than constructors.

It would be extremely unfortunate if authors can't use constructor() in the 
world we have ES6 classes.

class MyButtonElement extends HTMLElement {
constructor() {
...
}
}

looks much more natural than

class MyButtonElement extends HTMLElement {
constructor() {
// Would I ever be called? If so, when?  Is that safe?
}
createdCallback() {
...
}
}

> http://lists.w3.org/Archives/Public/public-webapps/2013JanMar/0728.html
> http://lists.w3.org/Archives/Public/public-webapps/2013AprJun/thread.html#msg152
> I am probably forgetting some…

Thanks for the pointers again.

- R. Niwa



Re: Why can't we just use constructor instead of createdCallback?

2013-12-05 Thread Dimitri Glazkov
There were several threads around this in March/April, but the main gist is
that we can't allow running user code when the parser is building the tree,
and thus we would need to decouple the timing of the constructor being
called from the [[Construct]] internal method to make constructors
workable. But then they aren't constructors, but callbacks, since the
object would already be exist (and be in a tree). So we decided to not lie
and just call them callbacks, rather than constructors.

http://lists.w3.org/Archives/Public/public-webapps/2013JanMar/0728.html
http://lists.w3.org/Archives/Public/public-webapps/2013AprJun/thread.html#msg152
I am probably forgetting some...


:DG<


On Thu, Dec 5, 2013 at 5:31 PM, Ryosuke Niwa  wrote:

> Could someone point me to a discussion/reasoning behind why we're using
> createdCallback as opposed to the constructor
> as a way of instantiating a custom element?
>
> It's so awkward to have a separate callback in the world where we have ES6
> classes.
>
> - R. Niwa
>
>
>


Why can't we just use constructor instead of createdCallback?

2013-12-05 Thread Ryosuke Niwa
Could someone point me to a discussion/reasoning behind why we're using 
createdCallback as opposed to the constructor
as a way of instantiating a custom element?

It's so awkward to have a separate callback in the world where we have ES6 
classes.

- R. Niwa