Re: Using readyCallback for built-in elements, was: [webcomponents]: Of weird script elements and Benadryl
On Wed, Apr 17, 2013 at 3:00 AM, Anne van Kesteren ann...@annevk.nl wrote: On Tue, Apr 16, 2013 at 10:33 PM, Dimitri Glazkov dglaz...@google.com wrote: On Mon, Apr 15, 2013 at 6:59 AM, Anne van Kesteren ann...@annevk.nl wrote: The other problem we need to solve is that document.createElement(x) currently gives different results from new x's interface. E.g. new Audio() sets an attribute, document.createElement(audio) does not. I think we should settle for document.createElement(audio) also creating an attribute here. What if we use the newly-found power if readyCallback here? Suppose that HTMLAudioElement has a readyCallback that, among other things does: if (!this.parentNode) // aha! I am created imperatively this.setAttribute(controls); I don't understand. In either new Audio() or document.createElement(audio) there's no parentNode. You're right. Sorry for the noise. :DG
Re: [webcomponents]: Of weird script elements and Benadryl
On Tue, Apr 16, 2013 at 9:51 PM, Bjoern Hoehrmann derhoe...@gmx.net wrote: * Rick Waldron wrote: Of course, but we'd also eat scraps from the trash if that was the only edible food left on earth. document.createElement() is and has always been the wrong way—the numbers shown in those graphs are grossly skewed by a complete lack of any real alternative. If I want to make a new button to put in the document, the first thing my JS programming experience tells me: new Button(); And if you read code like `new A();` your programming experience would probably tell you that you are looking at machine-generated code. I'm not sure what your own experience is, but I completely disagree. And if you read `new Time();` you would have no idea whether this creates some `new Date();`-like object, or throw an exception because the browser you try to run that code on does not support the `time /` element yet or I would expect a time element to be constructed with: new HTMLTimeElement(); ... since that's the name of the constructor/prototype that's defined for the time element. anymore (the element was proposed, withdrawn, and then proposed again) and if it's something like var font = new Font(Arial 12pt); canvas.drawText(Hello World!, font); The idea that you are constructing `font /` elements probably wouldn't cross your mind much. Because I would constructor a font element with: new HTMLFontElement() ... since that's the name of the constructor/prototype that's defined for the font element. And between new HTMLButtonElement(); and new Element('button'); I don't see why anyone would want the former in an environment where you cannot rely on `HTMLHGroupElement` existing (the `hgroup` element had been proposed, and is currently withdrawn, or not, depending on where you get your news from). The latter is indeed a much nicer to look at then the former, but Element is higher then HTMLButtonElement, so how would Element know that an argument with the value button indicated that a HTMLButtonElement should be allocated and initialized? Some kind of nodeName = constructor map, I suppose...? (thinking out loud) Furthermore, there actually are a number of dependencies to take into account, like in var agent = new XMLHttpRequest(); ... agent.open('GET', 'example'); Should that fail because the code does not say where to get `example` from, or should it succeed by picking up some base reference magically from the environment (and which one, is `example` relative to from the script code, or the document the code has been transcluded into, and when is that decision made as code moves across global objects, and so on)? I'm not sure how this is a dependency or even relevant to the discussion. Same question for `new Element('a')`, if the object exposes some method to obtain the absolute value of the `href` attribute in some way. But I live in the bad old days (assuming my children won't have to use garbage APIs to program the web) and my reality is still here: document.createElement(button); That very clearly binds the return value to `document` so you actually can do var button = document.createElement(button); ... button.ownerDocument.example(...); As a static factory, sure, but implied ownerDocument context binding isn't a strong argument for neutering the specific element constructors. Really, I should be able to do both... If I create a new element, I should have the ability to bind that element to whatever document that makes the most sense for my application's needs (an iframe's document? an xml document?). Inserting a new-born-detached element into a specific document or explicitly binding that element to a document via some imperative mechanism makes just as much sense as your example. in contrast to, if you will, var button = new Button(); button.ownerDocument.example(...); I would expect this: var button = new HTMLButtonElement(); button.ownerDocument === null; // true document.body.appendChild(button); button.ownerDocument === document; // true Or // pass a context arg? var button = new HTMLButtonElement(document); button.ownerDocument === document; // true OR var button = new HTMLButtonElement(); // explicitly set the context? button.ownerDocument = document; where `button.ownerDocument` could only have a Document value if there is some dependency on global state that your own code did not create. I agree that's bad I would expect that code to fail because the ownerDocument has not been specified, I should hope so as well and even if I would expect that particular code to succeed, I would be unable to tell what would happen if `example` was invoked in some other way, especially when `example` comes from another global. document !== [[Global]], so I'm not sure what other global this `example` method could be defined on that this would ever possibly
Re: [webcomponents]: Of weird script elements and Benadryl
On Wed, Apr 17, 2013 at 8:14 PM, Rick Waldron waldron.r...@gmail.com wrote: document !== [[Global]], so I'm not sure what other global this `example` method could be defined on that this would ever possibly be true. Let's just agree that this will fail for all the right reasons. That would be different from how new Image(), new Document(), new XMLHttpRequest(), and most platform objects really behave today. They all find the document associated with the browsing context for which the script is running (or a variant thereof). -- http://annevankesteren.nl/
Re: [webcomponents]: Of weird script elements and Benadryl
* Rick Waldron wrote: On Tue, Apr 16, 2013 at 9:51 PM, Bjoern Hoehrmann derhoe...@gmx.net wrote: * Rick Waldron wrote: If I want to make a new button to put in the document, the first thing my JS programming experience tells me: new Button(); And if you read code like `new A();` your programming experience would probably tell you that you are looking at machine-generated code. I'm not sure what your own experience is, but I completely disagree. I think it is easy to agree with your analogy above. My purpose was to offer reasons why it is a bad analogy that does not hold when you take into account various other constraints and problems. For the specific example, I think it is unreasonable for humans to define single-letter global names in a shared namespace, and even more unreasonable for some standards organisation to do so. With `A` in particular, there is also the problem that `a` might be HTML or it might be SVG, so mapping `new Button()` to `button` is not an analogy that works all the time. And between new HTMLButtonElement(); and new Element('button'); I don't see why anyone would want the former in an environment where you cannot rely on `HTMLHGroupElement` existing (the `hgroup` element had been proposed, and is currently withdrawn, or not, depending on where you get your news from). The latter is indeed a much nicer to look at then the former, but Element is higher then HTMLButtonElement, so how would Element know that an argument with the value button indicated that a HTMLButtonElement should be allocated and initialized? Some kind of nodeName = constructor map, I suppose...? (thinking out loud) As above, `new Element('a')` does not indicate whether you want a HTML `a` element or a a SVG `a` element. When parsing strings there is, in essence, such a map, but there is more context than just the name. That may well be a design error, perhaps HTML and SVG should never have been separate namespaces. in contrast to, if you will, var button = new Button(); button.ownerDocument.example(...); I would expect this: var button = new HTMLButtonElement(); button.ownerDocument === null; // true document.body.appendChild(button); button.ownerDocument === document; // true Indeed. But browser vendors do not think like that. -- Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de 25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/
Re: [webcomponents]: Of weird script elements and Benadryl
On Wed, Apr 17, 2013 at 10:34 PM, Bjoern Hoehrmann derhoe...@gmx.netwrote: * Rick Waldron wrote: On Tue, Apr 16, 2013 at 9:51 PM, Bjoern Hoehrmann derhoe...@gmx.net wrote: * Rick Waldron wrote: If I want to make a new button to put in the document, the first thing my JS programming experience tells me: new Button(); And if you read code like `new A();` your programming experience would probably tell you that you are looking at machine-generated code. I'm not sure what your own experience is, but I completely disagree. I think it is easy to agree with your analogy above. My purpose was to offer reasons why it is a bad analogy that does not hold when you take into account various other constraints and problems. For the specific example, I think it is unreasonable for humans to define single-letter global names in a shared namespace, and even more unreasonable for some standards organisation to do so. With `A` in particular, there is also the problem that `a` might be HTML or it might be SVG, so mapping `new Button()` to `button` is not an analogy that works all the time. It's a good thing I never suggested this... I never assumed anything cheaper then HTMLFooElement to construct a foo And between new HTMLButtonElement(); and new Element('button'); I don't see why anyone would want the former in an environment where you cannot rely on `HTMLHGroupElement` existing (the `hgroup` element had been proposed, and is currently withdrawn, or not, depending on where you get your news from). The latter is indeed a much nicer to look at then the former, but Element is higher then HTMLButtonElement, so how would Element know that an argument with the value button indicated that a HTMLButtonElement should be allocated and initialized? Some kind of nodeName = constructor map, I suppose...? (thinking out loud) As above, `new Element('a')` does not indicate whether you want a HTML `a` element or a a SVG `a` element. When parsing strings there is, in essence, such a map, but there is more context than just the name. That may well be a design error, perhaps HTML and SVG should never have been separate namespaces. I'm with you here, certainly unfortunate. But new SVGAElement() is pretty straightforward. in contrast to, if you will, var button = new Button(); button.ownerDocument.example(...); I would expect this: var button = new HTMLButtonElement(); button.ownerDocument === null; // true document.body.appendChild(button); button.ownerDocument === document; // true Indeed. But browser vendors do not think like that. I'm of the mind that browser vendors and implementors need to be accountable to the developers using the platform, instead of developers being hostages of the platform. Rick -- Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de 25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/
Re: [webcomponents]: Of weird script elements and Benadryl
On 4/17/13 11:16 PM, Rick Waldron wrote: I'm of the mind that browser vendors and implementors need to be accountable to the developers using the platform, instead of developers being hostages of the platform. As this specifically applies to .ownerDocument, note that lots of elements have all sorts of behavior that depends on the document that they're associated with, and that developers using the platform use those features every single day. Making newly-created elements not be associated with a document would cause them to be pretty broken in all sorts of interesting ways... -Boris
Using readyCallback for built-in elements, was: [webcomponents]: Of weird script elements and Benadryl
On Mon, Apr 15, 2013 at 6:59 AM, Anne van Kesteren ann...@annevk.nl wrote: I think we should go for one interface per element here. abstract classes not being constructable seems fine. Node/CharacterData are similar to that. This would mean HTMLH1Element, ..., of which compatibility impact has not been measured. The other problem we need to solve is that document.createElement(x) currently gives different results from new x's interface. E.g. new Audio() sets an attribute, document.createElement(audio) does not. I think we should settle for document.createElement(audio) also creating an attribute here. What if we use the newly-found power if readyCallback here? Suppose that HTMLAudioElement has a readyCallback that, among other things does: if (!this.parentNode) // aha! I am created imperatively this.setAttribute(controls); Several HTML elements will need to use the callback to build their shadow trees and set internal state, like textarea, input, details, fieldset, etc. If we just build readyCallback into DOM, we have cake. :DG
Re: [webcomponents]: Of weird script elements and Benadryl
Wow. What a thread. I look away for a day, and this magic beanstalk is all the way to the clouds. I am happy to see that all newcomers are now up to speed. I am heartened to recognize the same WTFs and grumbling that we went through along the path. I feel your pain -- I've been there myself. As Hixie once told me (paraphrasing, can't remember exact words), All the good choices have been made. We're only left with terrible ones. I could be wrong (please correct me), but we didn't birth any new ideas so far, now that everyone has caught up with the constraints. The good news is that the imperative syntax is solid. It's nicely compatible with ES6, ES3/5, and can be even used to make built-in HTML elements (modulo security/isolation problem, which we shouldn't tackle here). I am going to offer a cop-out option: maybe we simply don't offer imperative syntax as part of the spec? Should we let libraries/frameworks build their own custom elements (with opinion and flair) to implement declarative syntax systems? :DG
Re: [webcomponents]: Of weird script elements and Benadryl
*I am going to offer a cop-out option: maybe we simply don't offer imperative syntax as part of the spec? * Why would we do this if the imperative syntax is solid, nicely compatible, and relatively uncontentious? Did you mean to say declarative? Daniel J. Buchner Product Manager, Developer Ecosystem Mozilla Corporation On Tue, Apr 16, 2013 at 2:56 PM, Dimitri Glazkov dglaz...@google.comwrote: Wow. What a thread. I look away for a day, and this magic beanstalk is all the way to the clouds. I am happy to see that all newcomers are now up to speed. I am heartened to recognize the same WTFs and grumbling that we went through along the path. I feel your pain -- I've been there myself. As Hixie once told me (paraphrasing, can't remember exact words), All the good choices have been made. We're only left with terrible ones. I could be wrong (please correct me), but we didn't birth any new ideas so far, now that everyone has caught up with the constraints. The good news is that the imperative syntax is solid. It's nicely compatible with ES6, ES3/5, and can be even used to make built-in HTML elements (modulo security/isolation problem, which we shouldn't tackle here). I am going to offer a cop-out option: maybe we simply don't offer imperative syntax as part of the spec? Should we let libraries/frameworks build their own custom elements (with opinion and flair) to implement declarative syntax systems? :DG
Re: [webcomponents]: Of weird script elements and Benadryl
On Tue, Apr 16, 2013 at 3:00 PM, Daniel Buchner dan...@mozilla.com wrote: I am going to offer a cop-out option: maybe we simply don't offer imperative syntax as part of the spec? Why would we do this if the imperative syntax is solid, nicely compatible, and relatively uncontentious? Did you mean to say declarative? DERP. Yes, thank you Daniel. I mean to say: I am going to offer a cop-out option: maybe we simply don't offer DECLARATIVE syntax as part of the spec? Should we let libraries/frameworks build their own custom elements (with opinion and flair) to implement declarative syntax systems? :DG
Re: [webcomponents]: Of weird script elements and Benadryl
One thing I've heard from many of our in-house developers, is that they prefer the imperative syntax, with one caveat: we provide an easy way to allow components import/require/rely-upon other components. This could obviously be done using ES6 Modules, but is there anything we can do to address that use case for the web of today? On Tue, Apr 16, 2013 at 3:02 PM, Dimitri Glazkov dglaz...@google.comwrote: On Tue, Apr 16, 2013 at 3:00 PM, Daniel Buchner dan...@mozilla.com wrote: I am going to offer a cop-out option: maybe we simply don't offer imperative syntax as part of the spec? Why would we do this if the imperative syntax is solid, nicely compatible, and relatively uncontentious? Did you mean to say declarative? DERP. Yes, thank you Daniel. I mean to say: I am going to offer a cop-out option: maybe we simply don't offer DECLARATIVE syntax as part of the spec? Should we let libraries/frameworks build their own custom elements (with opinion and flair) to implement declarative syntax systems? :DG
Re: [webcomponents]: Of weird script elements and Benadryl
On Tue, Apr 16, 2013 at 3:07 PM, Daniel Buchner dan...@mozilla.com wrote: One thing I've heard from many of our in-house developers, is that they prefer the imperative syntax, with one caveat: we provide an easy way to allow components import/require/rely-upon other components. This could obviously be done using ES6 Modules, but is there anything we can do to address that use case for the web of today? Yes, one key ability we lose here is the declarative quality -- with the declarative syntax, you don't have to run script in order to comprehend what custom elements could be used by a document. :DG
Re: Using readyCallback for built-in elements, was: [webcomponents]: Of weird script elements and Benadryl
On Tue, Apr 16, 2013 at 5:33 PM, Dimitri Glazkov dglaz...@google.comwrote: On Mon, Apr 15, 2013 at 6:59 AM, Anne van Kesteren ann...@annevk.nl wrote: I think we should go for one interface per element here. abstract classes not being constructable seems fine. Node/CharacterData are similar to that. This would mean HTMLH1Element, ..., of which compatibility impact has not been measured. The other problem we need to solve is that document.createElement(x) currently gives different results from new x's interface. E.g. new Audio() sets an attribute, document.createElement(audio) does not. I think we should settle for document.createElement(audio) also creating an attribute here. What if we use the newly-found power if readyCallback here? Suppose that HTMLAudioElement has a readyCallback that, among other things does: if (!this.parentNode) // aha! I am created imperatively this.setAttribute(controls); Several HTML elements will need to use the callback to build their shadow trees and set internal state, like textarea, input, details, fieldset, etc. If we just build readyCallback into DOM, we have cake. Can someone point me to the discussion that lead to the name choice readyCallback? Thanks Rick :DG
Re: Using readyCallback for built-in elements, was: [webcomponents]: Of weird script elements and Benadryl
I think there were several f2f conversations around that. I can't remember if we had an email thread around this. It used to be called created, but the timing at which the callback is called makes the name misleading. For example, when parsing, by the time the callback is invoked, the custom element not only had been created, but also populated with attributes and put in the tree. It's essentially now ready for operation. :DG
Re: [webcomponents]: Of weird script elements and Benadryl
On Apr 16, 2013, at 3:13 PM, Dimitri Glazkov wrote: On Tue, Apr 16, 2013 at 3:07 PM, Daniel Buchner dan...@mozilla.com wrote: One thing I've heard from many of our in-house developers, is that they prefer the imperative syntax, with one caveat: we provide an easy way to allow components import/require/rely-upon other components. This could obviously be done using ES6 Modules, but is there anything we can do to address that use case for the web of today? Yes, one key ability we lose here is the declarative quality -- with the declarative syntax, you don't have to run script in order to comprehend what custom elements could be used by a document. My sense is that the issues of concern (at least on this thread) with declaratively defining custom elements all related to how custom behavior (ie, script stuff) is declaratively associated. I'm not aware (but also not very familiar) with similar issues relating to template and other possible element subelement. I also imagine that there is probably a set of use cases that don't actually need any custom behavior. That suggests to me, that a possible middle ground, for now, is to still have declarative custom element definitions but don't provide any declarative mechanism for associating script with them. Imperative code could presumably make that association, if it needed to. I've been primarily concerned about approaches that would be future hostile toward the use of applicable ES features that are emerging. I think we'll be see those features in browsers within the next 12 months. Deferring just the script features of element would help with the timing and probably allow a better long term solution to be designed. Allen
Re: [webcomponents]: Of weird script elements and Benadryl
*Deferring just the script features of element would help with the timing and probably allow a better long term solution to be designed.* If the callbacks are not mutable or become inert after registration (as I believe was the case), how would a developer do this -- *Imperative code could presumably make that association, if it needed to.* On Tue, Apr 16, 2013 at 3:47 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Apr 16, 2013, at 3:13 PM, Dimitri Glazkov wrote: On Tue, Apr 16, 2013 at 3:07 PM, Daniel Buchner dan...@mozilla.com wrote: One thing I've heard from many of our in-house developers, is that they prefer the imperative syntax, with one caveat: we provide an easy way to allow components import/require/rely-upon other components. This could obviously be done using ES6 Modules, but is there anything we can do to address that use case for the web of today? Yes, one key ability we lose here is the declarative quality -- with the declarative syntax, you don't have to run script in order to comprehend what custom elements could be used by a document. My sense is that the issues of concern (at least on this thread) with declaratively defining custom elements all related to how custom behavior (ie, script stuff) is declaratively associated. I'm not aware (but also not very familiar) with similar issues relating to template and other possible element subelement. I also imagine that there is probably a set of use cases that don't actually need any custom behavior. That suggests to me, that a possible middle ground, for now, is to still have declarative custom element definitions but don't provide any declarative mechanism for associating script with them. Imperative code could presumably make that association, if it needed to. I've been primarily concerned about approaches that would be future hostile toward the use of applicable ES features that are emerging. I think we'll be see those features in browsers within the next 12 months. Deferring just the script features of element would help with the timing and probably allow a better long term solution to be designed. Allen
Re: [webcomponents]: Of weird script elements and Benadryl
On Apr 16, 2013, at 4:08 PM, Daniel Buchner wrote: Deferring just the script features of element would help with the timing and probably allow a better long term solution to be designed. If the callbacks are not mutable or become inert after registration (as I believe was the case), how would a developer do this -- Imperative code could presumably make that association, if it needed to. Here is what I suggested earlier on this thread for what to do if a constructor= attribute wasn't supplied, when we were talking about that scheme: 1) create a new anonymous constructor object that inherits from HTMLElement. It wouldn't have any unique behavior but it would be uniquely associated with the particular element that defined it and it might be useful for doing instanceof tests. It would be the constructor that you register with the tag. If that was done, it seems reasonable that the provided constructor object could be available as the value of an attribute of the HTMLElementElement that corresponds to the element. So, imperative code could lookup the HTMLElementElement based on its name property and retrieve the constructor object. The constructor object would have a prototype whose value is the actual prototype object used for these custom elements objects and the imperative code could assign methods. The script that assigns such methods would need to be placed to run after the element is parsed but before any other imperative code that actually makes use of those methods. Prototype objects are not normally immutable so there is no problem with delaying the installation of such methods even until after instances of the custom element have actually been created by the HTML parser. Allen On Tue, Apr 16, 2013 at 3:47 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Apr 16, 2013, at 3:13 PM, Dimitri Glazkov wrote: On Tue, Apr 16, 2013 at 3:07 PM, Daniel Buchner dan...@mozilla.com wrote: One thing I've heard from many of our in-house developers, is that they prefer the imperative syntax, with one caveat: we provide an easy way to allow components import/require/rely-upon other components. This could obviously be done using ES6 Modules, but is there anything we can do to address that use case for the web of today? Yes, one key ability we lose here is the declarative quality -- with the declarative syntax, you don't have to run script in order to comprehend what custom elements could be used by a document. My sense is that the issues of concern (at least on this thread) with declaratively defining custom elements all related to how custom behavior (ie, script stuff) is declaratively associated. I'm not aware (but also not very familiar) with similar issues relating to template and other possible element subelement. I also imagine that there is probably a set of use cases that don't actually need any custom behavior. That suggests to me, that a possible middle ground, for now, is to still have declarative custom element definitions but don't provide any declarative mechanism for associating script with them. Imperative code could presumably make that association, if it needed to. I've been primarily concerned about approaches that would be future hostile toward the use of applicable ES features that are emerging. I think we'll be see those features in browsers within the next 12 months. Deferring just the script features of element would help with the timing and probably allow a better long term solution to be designed. Allen
Re: [webcomponents]: Of weird script elements and Benadryl
* Rick Waldron wrote: Of course, but we'd also eat scraps from the trash if that was the only edible food left on earth. document.createElement() is and has always been the wrong way—the numbers shown in those graphs are grossly skewed by a complete lack of any real alternative. If I want to make a new button to put in the document, the first thing my JS programming experience tells me: new Button(); And if you read code like `new A();` your programming experience would probably tell you that you are looking at machine-generated code. And if you read `new Time();` you would have no idea whether this creates some `new Date();`-like object, or throw an exception because the browser you try to run that code on does not support the `time /` element yet or anymore (the element was proposed, withdrawn, and then proposed again) and if it's something like var font = new Font(Arial 12pt); canvas.drawText(Hello World!, font); The idea that you are constructing `font /` elements probably wouldn't cross your mind much. And between new HTMLButtonElement(); and new Element('button'); I don't see why anyone would want the former in an environment where you cannot rely on `HTMLHGroupElement` existing (the `hgroup` element had been proposed, and is currently withdrawn, or not, depending on where you get your news from). Furthermore, there actually are a number of dependencies to take into account, like in var agent = new XMLHttpRequest(); ... agent.open('GET', 'example'); Should that fail because the code does not say where to get `example` from, or should it succeed by picking up some base reference magically from the environment (and which one, is `example` relative to from the script code, or the document the code has been transcluded into, and when is that decision made as code moves across global objects, and so on)? Same question for `new Element('a')`, if the object exposes some method to obtain the absolute value of the `href` attribute in some way. But I live in the bad old days (assuming my children won't have to use garbage APIs to program the web) and my reality is still here: document.createElement(button); That very clearly binds the return value to `document` so you actually can do var button = document.createElement(button); ... button.ownerDocument.example(...); in contrast to, if you will, var button = new Button(); button.ownerDocument.example(...); where `button.ownerDocument` could only have a Document value if there is some dependency on global state that your own code did not create. I would expect that code to fail because the ownerDocument has not been specified, and even if I would expect that particular code to succeed, I would be unable to tell what would happen if `example` was invoked in some other way, especially when `example` comes from another global. -- Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de 25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/
Re: [webcomponents]: Of weird script elements and Benadryl
On 4/14/13 1:49 PM, Scott Miles wrote: Erik Arvidsson came up with a strategy for overcoming this in Blink, but to my recollection Boris Zbarsky said this was a non-starter in Gecko. Just to be clear, the proposal there was to take an already existing function object and call some UA-provided method that under the hood changes its [[Construct]] internal symbol. Which is a non-starter for us in the short term simply because Gecko currently has no concept of different [[Construct]] for different _function_ objects (as opposed to other objects). -Boris
Re: [webcomponents]: Of weird script elements and Benadryl
On 4/14/13 3:07 PM, Allen Wirfs-Brock wrote: 2, 3, 4 I believe have been suggested in one form or another, but as I mentioned, were determined to be non-starters for Gecko. I don't think we've heard anything from IE team. Well #4 has been accepted for ES6 by all TC39 participants including Mozilla and Microsoft and is going to happen. The basic scheme was actually suggested a member of the SpiderMonkey team so I'm sure we'll get it worked out for Gecko. Note that in #4 we know statically, when we're creating the object for the constructor, that it's going to need to create special objects, so we can go ahead and create something that has the right [[Construct]] to start with. And again note that this is all a question of timeframes. I doubt ES6 class support in SpiderMonkey will happen in the next several months, which was the timeframe people were talking about for web components. -Boris
Re: [webcomponents]: Of weird script elements and Benadryl
On 4/14/13 5:35 PM, Rick Waldron wrote: I have a better understanding of problem caused by these generated HTML*Element constructors: they aren't constructable. I'd like to understand what's meant here. I have a good understanding of how these constructors work in Gecko+SpiderMonkey, but I'm not sure what the lacking bit is, other than the fact that they have to create JS objects that have special state associated with them, so can't work with an object created by the [[Construct]] of a typical function. Is that what you're referring to, or something else? -Boris
Re: [webcomponents]: Of weird script elements and Benadryl
On Mon, Apr 15, 2013 at 1:55 PM, Boris Zbarsky bzbar...@mit.edu wrote: On 4/14/13 4:57 PM, Rick Waldron wrote: Of course, but we'd also eat scraps from the trash if that was the only edible food left on earth. document.createElement() is and has always been the wrong way—the numbers shown in those graphs are grossly skewed by a complete lack of any real alternative. Amen. I strongly support making all *Element constructors actually work. The hard part is dealing with the cases when lots of elements share the same interface... I think we should go for one interface per element here. abstract classes not being constructable seems fine. Node/CharacterData are similar to that. This would mean HTMLH1Element, ..., of which compatibility impact has not been measured. The other problem we need to solve is that document.createElement(x) currently gives different results from new x's interface. E.g. new Audio() sets an attribute, document.createElement(audio) does not. I think we should settle for document.createElement(audio) also creating an attribute here. And the last problem (I think) is determining the document object. I think we should follow http://dom.spec.whatwg.org/#dom-document new Document() and friends for that. -- http://annevankesteren.nl/
Re: [webcomponents]: Of weird script elements and Benadryl
On Mon, Apr 15, 2013 at 8:57 AM, Boris Zbarsky bzbar...@mit.edu wrote: On 4/14/13 5:35 PM, Rick Waldron wrote: I have a better understanding of problem caused by these generated HTML*Element constructors: they aren't constructable. I'd like to understand what's meant here. I have a good understanding of how these constructors work in Gecko+SpiderMonkey, but I'm not sure what the lacking bit is, other than the fact that they have to create JS objects that have special state associated with them, so can't work with an object created by the [[Construct]] of a typical function. Is that what you're referring to, or something else? Sorry, I should've been more specific. What I meant was that: new HTMLButtonElement(); Doesn't construct an HTMLButtonElement, it throws with an illegal constructor in Chrome and HTMLButtonElement is not a constructor in Firefox (I'm sure this is the same across other browsers) Which of course means that this is not possible even today: function Smile() { HTMLButtonElement.call(this); this.textContent = :); } Smile.prototype = Object.create(HTMLButtonElement.prototype); Since this doesn't work, the prototype method named readyCallback was invented as a bolt-on stand-in for the actual [[Construct]] Hopefully that clarifies? Rick PS. A bit of trivial... A long time ago some users requested that jQuery facilitate a custom constructor; to make this work, John put the actual constructor code in a prototype method called init and set that method's prototype to jQuery's own prototype. The thing called readyCallback is similar. For those that are interested, I created a gist with a minimal illustration here: https://gist.github.com/rwldrn/5388544 -Boris
Re: [webcomponents]: Of weird script elements and Benadryl
On 4/15/13 10:45 AM, Rick Waldron wrote: Sorry, I should've been more specific. What I meant was that: new HTMLButtonElement(); Doesn't construct an HTMLButtonElement, it throws with an illegal constructor in Chrome and HTMLButtonElement is not a constructor in Firefox (I'm sure this is the same across other browsers) Oh, I see. That's not anything inherent, for what it's worth; making this particular case work would be 10 lines of code. Less on a per-element basis if we want to do this for most elements. function Smile() { HTMLButtonElement.call(this); this.textContent = :); } Smile.prototype = Object.create(HTMLButtonElement.prototype); Ah, so... This would not work even if new HTMLButtonElement worked, right? In particular, if HTMLButtonElement were actually something that could construct things in Gecko, it would still ignore its argument when called and always creates a new object. You can see the behavior with something like XMLHttpRequest if you want. Hopefully that clarifies? Somewhat. Trying to understand what things we really need to support here and in what ways, long-term... -Boris
Re: [webcomponents]: Of weird script elements and Benadryl
Again, 'readyCallback' exists because it's a Bad Idea to run user code during parsing (tree construction). Ready-time is not the same as construct-time. This is the Pinocchio problem: http://lists.w3.org/Archives/Public/public-webapps/2013JanMar/0728.html Scott On Mon, Apr 15, 2013 at 7:45 AM, Rick Waldron waldron.r...@gmail.comwrote: On Mon, Apr 15, 2013 at 8:57 AM, Boris Zbarsky bzbar...@mit.edu wrote: On 4/14/13 5:35 PM, Rick Waldron wrote: I have a better understanding of problem caused by these generated HTML*Element constructors: they aren't constructable. I'd like to understand what's meant here. I have a good understanding of how these constructors work in Gecko+SpiderMonkey, but I'm not sure what the lacking bit is, other than the fact that they have to create JS objects that have special state associated with them, so can't work with an object created by the [[Construct]] of a typical function. Is that what you're referring to, or something else? Sorry, I should've been more specific. What I meant was that: new HTMLButtonElement(); Doesn't construct an HTMLButtonElement, it throws with an illegal constructor in Chrome and HTMLButtonElement is not a constructor in Firefox (I'm sure this is the same across other browsers) Which of course means that this is not possible even today: function Smile() { HTMLButtonElement.call(this); this.textContent = :); } Smile.prototype = Object.create(HTMLButtonElement.prototype); Since this doesn't work, the prototype method named readyCallback was invented as a bolt-on stand-in for the actual [[Construct]] Hopefully that clarifies? Rick PS. A bit of trivial... A long time ago some users requested that jQuery facilitate a custom constructor; to make this work, John put the actual constructor code in a prototype method called init and set that method's prototype to jQuery's own prototype. The thing called readyCallback is similar. For those that are interested, I created a gist with a minimal illustration here: https://gist.github.com/rwldrn/5388544 -Boris
Re: [webcomponents]: Of weird script elements and Benadryl
Why do the constructors of component instances run during component loading? Why not use standard events rather than callbacks? Thanks, jjb On Apr 15, 2013 9:04 AM, Scott Miles sjmi...@google.com wrote: Again, 'readyCallback' exists because it's a Bad Idea to run user code during parsing (tree construction). Ready-time is not the same as construct-time. This is the Pinocchio problem: http://lists.w3.org/Archives/Public/public-webapps/2013JanMar/0728.html Scott On Mon, Apr 15, 2013 at 7:45 AM, Rick Waldron waldron.r...@gmail.comwrote: On Mon, Apr 15, 2013 at 8:57 AM, Boris Zbarsky bzbar...@mit.edu wrote: On 4/14/13 5:35 PM, Rick Waldron wrote: I have a better understanding of problem caused by these generated HTML*Element constructors: they aren't constructable. I'd like to understand what's meant here. I have a good understanding of how these constructors work in Gecko+SpiderMonkey, but I'm not sure what the lacking bit is, other than the fact that they have to create JS objects that have special state associated with them, so can't work with an object created by the [[Construct]] of a typical function. Is that what you're referring to, or something else? Sorry, I should've been more specific. What I meant was that: new HTMLButtonElement(); Doesn't construct an HTMLButtonElement, it throws with an illegal constructor in Chrome and HTMLButtonElement is not a constructor in Firefox (I'm sure this is the same across other browsers) Which of course means that this is not possible even today: function Smile() { HTMLButtonElement.call(this); this.textContent = :); } Smile.prototype = Object.create(HTMLButtonElement.prototype); Since this doesn't work, the prototype method named readyCallback was invented as a bolt-on stand-in for the actual [[Construct]] Hopefully that clarifies? Rick PS. A bit of trivial... A long time ago some users requested that jQuery facilitate a custom constructor; to make this work, John put the actual constructor code in a prototype method called init and set that method's prototype to jQuery's own prototype. The thing called readyCallback is similar. For those that are interested, I created a gist with a minimal illustration here: https://gist.github.com/rwldrn/5388544 -Boris
Re: [webcomponents]: Of weird script elements and Benadryl
Why do the constructors of component instances run during component loading? I'm not sure what you are referring to. What does 'component loading' mean? Why not use standard events rather than callbacks? This was discussed quite a bit, here is my off-the-cuff response. I may have to do archaeology to get a better one. Custom elements can inherit from custom elements. The callbacks are convenient because (1) there is no question of 'who registers a listener' (2) I can simply call my 'super' callback (or not) to get inherited behavior. IIRC, it is also advantageous for performance and for having control over the timing these calls. Scott On Mon, Apr 15, 2013 at 9:37 AM, John J Barton johnjbar...@johnjbarton.comwrote: Why do the constructors of component instances run during component loading? Why not use standard events rather than callbacks? Thanks, jjb On Apr 15, 2013 9:04 AM, Scott Miles sjmi...@google.com wrote: Again, 'readyCallback' exists because it's a Bad Idea to run user code during parsing (tree construction). Ready-time is not the same as construct-time. This is the Pinocchio problem: http://lists.w3.org/Archives/Public/public-webapps/2013JanMar/0728.html Scott On Mon, Apr 15, 2013 at 7:45 AM, Rick Waldron waldron.r...@gmail.comwrote: On Mon, Apr 15, 2013 at 8:57 AM, Boris Zbarsky bzbar...@mit.edu wrote: On 4/14/13 5:35 PM, Rick Waldron wrote: I have a better understanding of problem caused by these generated HTML*Element constructors: they aren't constructable. I'd like to understand what's meant here. I have a good understanding of how these constructors work in Gecko+SpiderMonkey, but I'm not sure what the lacking bit is, other than the fact that they have to create JS objects that have special state associated with them, so can't work with an object created by the [[Construct]] of a typical function. Is that what you're referring to, or something else? Sorry, I should've been more specific. What I meant was that: new HTMLButtonElement(); Doesn't construct an HTMLButtonElement, it throws with an illegal constructor in Chrome and HTMLButtonElement is not a constructor in Firefox (I'm sure this is the same across other browsers) Which of course means that this is not possible even today: function Smile() { HTMLButtonElement.call(this); this.textContent = :); } Smile.prototype = Object.create(HTMLButtonElement.prototype); Since this doesn't work, the prototype method named readyCallback was invented as a bolt-on stand-in for the actual [[Construct]] Hopefully that clarifies? Rick PS. A bit of trivial... A long time ago some users requested that jQuery facilitate a custom constructor; to make this work, John put the actual constructor code in a prototype method called init and set that method's prototype to jQuery's own prototype. The thing called readyCallback is similar. For those that are interested, I created a gist with a minimal illustration here: https://gist.github.com/rwldrn/5388544 -Boris
Re: [webcomponents]: Of weird script elements and Benadryl
The callbacks are convenient because (1) there is no question of 'who registers a listener' (2) I can simply call my 'super' callback (or not) to get inherited behavior. One minute later, these seem like bad reasons. I shouldn't have shot from the hip, let me do some research. On Mon, Apr 15, 2013 at 9:44 AM, Scott Miles sjmi...@google.com wrote: Why do the constructors of component instances run during component loading? I'm not sure what you are referring to. What does 'component loading' mean? Why not use standard events rather than callbacks? This was discussed quite a bit, here is my off-the-cuff response. I may have to do archaeology to get a better one. Custom elements can inherit from custom elements. The callbacks are convenient because (1) there is no question of 'who registers a listener' (2) I can simply call my 'super' callback (or not) to get inherited behavior. IIRC, it is also advantageous for performance and for having control over the timing these calls. Scott On Mon, Apr 15, 2013 at 9:37 AM, John J Barton johnjbar...@johnjbarton.com wrote: Why do the constructors of component instances run during component loading? Why not use standard events rather than callbacks? Thanks, jjb On Apr 15, 2013 9:04 AM, Scott Miles sjmi...@google.com wrote: Again, 'readyCallback' exists because it's a Bad Idea to run user code during parsing (tree construction). Ready-time is not the same as construct-time. This is the Pinocchio problem: http://lists.w3.org/Archives/Public/public-webapps/2013JanMar/0728.html Scott On Mon, Apr 15, 2013 at 7:45 AM, Rick Waldron waldron.r...@gmail.comwrote: On Mon, Apr 15, 2013 at 8:57 AM, Boris Zbarsky bzbar...@mit.eduwrote: On 4/14/13 5:35 PM, Rick Waldron wrote: I have a better understanding of problem caused by these generated HTML*Element constructors: they aren't constructable. I'd like to understand what's meant here. I have a good understanding of how these constructors work in Gecko+SpiderMonkey, but I'm not sure what the lacking bit is, other than the fact that they have to create JS objects that have special state associated with them, so can't work with an object created by the [[Construct]] of a typical function. Is that what you're referring to, or something else? Sorry, I should've been more specific. What I meant was that: new HTMLButtonElement(); Doesn't construct an HTMLButtonElement, it throws with an illegal constructor in Chrome and HTMLButtonElement is not a constructor in Firefox (I'm sure this is the same across other browsers) Which of course means that this is not possible even today: function Smile() { HTMLButtonElement.call(this); this.textContent = :); } Smile.prototype = Object.create(HTMLButtonElement.prototype); Since this doesn't work, the prototype method named readyCallback was invented as a bolt-on stand-in for the actual [[Construct]] Hopefully that clarifies? Rick PS. A bit of trivial... A long time ago some users requested that jQuery facilitate a custom constructor; to make this work, John put the actual constructor code in a prototype method called init and set that method's prototype to jQuery's own prototype. The thing called readyCallback is similar. For those that are interested, I created a gist with a minimal illustration here: https://gist.github.com/rwldrn/5388544 -Boris
Re: [webcomponents]: Of weird script elements and Benadryl
Sorry for the extra posts. I promise to slow down. Why not use standard events rather than callbacks? I believe a better answer is that it was decided these callbacks had to work synchronously relative to imperative construction. So, I can do var xfoo = document.createElement('x-foo'); xfoo.doImportantThing(); On Mon, Apr 15, 2013 at 9:46 AM, Scott Miles sjmi...@google.com wrote: The callbacks are convenient because (1) there is no question of 'who registers a listener' (2) I can simply call my 'super' callback (or not) to get inherited behavior. One minute later, these seem like bad reasons. I shouldn't have shot from the hip, let me do some research. On Mon, Apr 15, 2013 at 9:44 AM, Scott Miles sjmi...@google.com wrote: Why do the constructors of component instances run during component loading? I'm not sure what you are referring to. What does 'component loading' mean? Why not use standard events rather than callbacks? This was discussed quite a bit, here is my off-the-cuff response. I may have to do archaeology to get a better one. Custom elements can inherit from custom elements. The callbacks are convenient because (1) there is no question of 'who registers a listener' (2) I can simply call my 'super' callback (or not) to get inherited behavior. IIRC, it is also advantageous for performance and for having control over the timing these calls. Scott On Mon, Apr 15, 2013 at 9:37 AM, John J Barton johnjbar...@johnjbarton.com wrote: Why do the constructors of component instances run during component loading? Why not use standard events rather than callbacks? Thanks, jjb On Apr 15, 2013 9:04 AM, Scott Miles sjmi...@google.com wrote: Again, 'readyCallback' exists because it's a Bad Idea to run user code during parsing (tree construction). Ready-time is not the same as construct-time. This is the Pinocchio problem: http://lists.w3.org/Archives/Public/public-webapps/2013JanMar/0728.html Scott On Mon, Apr 15, 2013 at 7:45 AM, Rick Waldron waldron.r...@gmail.comwrote: On Mon, Apr 15, 2013 at 8:57 AM, Boris Zbarsky bzbar...@mit.eduwrote: On 4/14/13 5:35 PM, Rick Waldron wrote: I have a better understanding of problem caused by these generated HTML*Element constructors: they aren't constructable. I'd like to understand what's meant here. I have a good understanding of how these constructors work in Gecko+SpiderMonkey, but I'm not sure what the lacking bit is, other than the fact that they have to create JS objects that have special state associated with them, so can't work with an object created by the [[Construct]] of a typical function. Is that what you're referring to, or something else? Sorry, I should've been more specific. What I meant was that: new HTMLButtonElement(); Doesn't construct an HTMLButtonElement, it throws with an illegal constructor in Chrome and HTMLButtonElement is not a constructor in Firefox (I'm sure this is the same across other browsers) Which of course means that this is not possible even today: function Smile() { HTMLButtonElement.call(this); this.textContent = :); } Smile.prototype = Object.create(HTMLButtonElement.prototype); Since this doesn't work, the prototype method named readyCallback was invented as a bolt-on stand-in for the actual [[Construct]] Hopefully that clarifies? Rick PS. A bit of trivial... A long time ago some users requested that jQuery facilitate a custom constructor; to make this work, John put the actual constructor code in a prototype method called init and set that method's prototype to jQuery's own prototype. The thing called readyCallback is similar. For those that are interested, I created a gist with a minimal illustration here: https://gist.github.com/rwldrn/5388544 -Boris
Re: [webcomponents]: Of weird script elements and Benadryl
On Mon, Apr 15, 2013 at 9:44 AM, Scott Miles sjmi...@google.com wrote: Why do the constructors of component instances run during component loading? I'm not sure what you are referring to. What does 'component loading' mean? Why not use standard events rather than callbacks? I'll some of the doc you link below and re-ask. On Apr 15, 2013 9:04 AM, Scott Miles sjmi...@google.com wrote: Again, 'readyCallback' exists because it's a Bad Idea to run user code during parsing (tree construction). Ready-time is not the same as construct-time. This is the Pinocchio problem: http://lists.w3.org/Archives/Public/public-webapps/2013JanMar/0728.html --- Here's why: i) when we load component document, it blocks scripts just like a stylesheet (http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#a-style-sheet-that-is-blocking-scripts) ii) this is okay, since our constructors are generated (no user code) and most of the tree could be constructed while the component is loaded. iii) However, if we make constructors run at the time of tree construction, the tree construction gets blocked much sooner, which effectively makes component loading synchronous. Which is bad. Why do the constructors of component *instances* which don't need to run until instances are created, need to block the load of component documents? Seems to me that you could dictate that script in components load async WRT components but block instance construction. jjb
Re: [webcomponents]: Of weird script elements and Benadryl
Dimitri is trying to avoid 'block[ing] instance construction' because instances can be in the main document markup. The main document can have a bunch of markup for custom elements. If the user has made element definitions a-priori to parsing that markup (including inside link rel='import'), he expects those nodes to be 'born' correctly. Sidebar: running user's instance code while the parser is constructing the tree is Bad(tm) so we already have deferred init code until immediately after the parsing step. This is why I keep saying 'ready-time' is different from 'construct-time'. Today, I don't see how we can construct a custom element with the right prototype at parse-time without blocking on imported scripts (which is another side-effect of using script execution for defining prototype, btw.) If we don't block, the parser has to construct some kind of place holder for each custom instance, and then we upgrade them in a second pass. On Mon, Apr 15, 2013 at 9:54 AM, John J Barton johnjbar...@johnjbarton.comwrote: On Mon, Apr 15, 2013 at 9:44 AM, Scott Miles sjmi...@google.com wrote: Why do the constructors of component instances run during component loading? I'm not sure what you are referring to. What does 'component loading' mean? Why not use standard events rather than callbacks? I'll some of the doc you link below and re-ask. On Apr 15, 2013 9:04 AM, Scott Miles sjmi...@google.com wrote: Again, 'readyCallback' exists because it's a Bad Idea to run user code during parsing (tree construction). Ready-time is not the same as construct-time. This is the Pinocchio problem: http://lists.w3.org/Archives/Public/public-webapps/2013JanMar/0728.html --- Here's why: i) when we load component document, it blocks scripts just like a stylesheet (http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#a-style-sheet-that-is-blocking-scripts) ii) this is okay, since our constructors are generated (no user code) and most of the tree could be constructed while the component is loaded. iii) However, if we make constructors run at the time of tree construction, the tree construction gets blocked much sooner, which effectively makes component loading synchronous. Which is bad. Why do the constructors of component *instances* which don't need to run until instances are created, need to block the load of component documents? Seems to me that you could dictate that script in components load async WRT components but block instance construction. jjb
Re: [webcomponents]: Of weird script elements and Benadryl
On Mon, Apr 15, 2013 at 10:38 AM, Scott Miles sjmi...@google.com wrote: Dimitri is trying to avoid 'block[ing] instance construction' because instances can be in the main document markup. Yes we sure hope so! The main document can have a bunch of markup for custom elements. If the user has made element definitions a-priori to parsing that markup (including inside link rel='import'), he expects those nodes to be 'born' correctly. Sure. Sidebar: running user's instance code while the parser is constructing the tree is Bad(tm) so we already have deferred init code until immediately after the parsing step. This is why I keep saying 'ready-time' is different from 'construct-time'. ? user's instance code? Do you mean: Running component instance initialization during document construction is Bad? Today, I don't see how we can construct a custom element with the right prototype at parse-time without blocking on imported scripts (which is another side-effect of using script execution for defining prototype, btw.) You must block creating instances of components until component documents are parsed and initialized. Because of limitations in HTML DOM construction, you may have to block HTML parsing until instances of components are created. Thus I imagine that creating instances may block HTML parsing until component documents are parsed and initialized or the HTML parsing must have two passes as your Pinocchio link outlines. But my original question concerns blocking component documents on their own script tag compilation. Maybe I misunderstood. jjb On Mon, Apr 15, 2013 at 9:54 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 9:44 AM, Scott Miles sjmi...@google.com wrote: Why do the constructors of component instances run during component loading? I'm not sure what you are referring to. What does 'component loading' mean? Why not use standard events rather than callbacks? I'll some of the doc you link below and re-ask. On Apr 15, 2013 9:04 AM, Scott Miles sjmi...@google.com wrote: Again, 'readyCallback' exists because it's a Bad Idea to run user code during parsing (tree construction). Ready-time is not the same as construct-time. This is the Pinocchio problem: http://lists.w3.org/Archives/Public/public-webapps/2013JanMar/0728.html --- Here's why: i) when we load component document, it blocks scripts just like a stylesheet (http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#a-style-sheet-that-is-blocking-scripts) ii) this is okay, since our constructors are generated (no user code) and most of the tree could be constructed while the component is loaded. iii) However, if we make constructors run at the time of tree construction, the tree construction gets blocked much sooner, which effectively makes component loading synchronous. Which is bad. Why do the constructors of component *instances* which don't need to run until instances are created, need to block the load of component documents? Seems to me that you could dictate that script in components load async WRT components but block instance construction. jjb
Re: [webcomponents]: Of weird script elements and Benadryl
On Mon, Apr 15, 2013 at 11:29 AM, Scott Miles sjmi...@google.com wrote: Thank you for your patience. :) ditto. ? user's instance code? Do you mean: Running component instance initialization during document construction is Bad? My 'x-foo' has an 'init' method that I wrote that has to execute before the instance is fully 'constructed'. Parser encounters an x-foo/x-foo and constructs it. My understanding is that calling 'init' from the parser at that point is a non-starter. I think the Pinocchio link makes the case that you have only three choices: 1) call 'init' when component instance tag is encountered, blocking parsing, 2) call 'init' later, causing reflows and losing the value of not blocking parsing, 3) don't allow 'init' at all, limiting components. So non-starter is just a vote against one of three Bad choices as far as I can tell. In other words, these are all non-starters ;-). But my original question concerns blocking component documents on their own script tag compilation. Maybe I misunderstood. I don't think imports (nee component documents) have any different semantics from the main document in this regard. The import document may have an x-foo instance in it's markup, and element tags or link rel=import just like the main document. Indeed, however the relative order of the component's script tag processing and the component's tag element is all I was talking about. On Mon, Apr 15, 2013 at 11:23 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 10:38 AM, Scott Miles sjmi...@google.com wrote: Dimitri is trying to avoid 'block[ing] instance construction' because instances can be in the main document markup. Yes we sure hope so! The main document can have a bunch of markup for custom elements. If the user has made element definitions a-priori to parsing that markup (including inside link rel='import'), he expects those nodes to be 'born' correctly. Sure. Sidebar: running user's instance code while the parser is constructing the tree is Bad(tm) so we already have deferred init code until immediately after the parsing step. This is why I keep saying 'ready-time' is different from 'construct-time'. ? user's instance code? Do you mean: Running component instance initialization during document construction is Bad? Today, I don't see how we can construct a custom element with the right prototype at parse-time without blocking on imported scripts (which is another side-effect of using script execution for defining prototype, btw.) You must block creating instances of components until component documents are parsed and initialized. Because of limitations in HTML DOM construction, you may have to block HTML parsing until instances of components are created. Thus I imagine that creating instances may block HTML parsing until component documents are parsed and initialized or the HTML parsing must have two passes as your Pinocchio link outlines. But my original question concerns blocking component documents on their own script tag compilation. Maybe I misunderstood. jjb On Mon, Apr 15, 2013 at 9:54 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 9:44 AM, Scott Miles sjmi...@google.comwrote: Why do the constructors of component instances run during component loading? I'm not sure what you are referring to. What does 'component loading' mean? Why not use standard events rather than callbacks? I'll some of the doc you link below and re-ask. On Apr 15, 2013 9:04 AM, Scott Miles sjmi...@google.com wrote: Again, 'readyCallback' exists because it's a Bad Idea to run user code during parsing (tree construction). Ready-time is not the same as construct-time. This is the Pinocchio problem: http://lists.w3.org/Archives/Public/public-webapps/2013JanMar/0728.html --- Here's why: i) when we load component document, it blocks scripts just like a stylesheet (http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#a-style-sheet-that-is-blocking-scripts) ii) this is okay, since our constructors are generated (no user code) and most of the tree could be constructed while the component is loaded. iii) However, if we make constructors run at the time of tree construction, the tree construction gets blocked much sooner, which effectively makes component loading synchronous. Which is bad. Why do the constructors of component *instances* which don't need to run until instances are created, need to block the load of component documents? Seems to me that you could dictate that script in components load async WRT components but block instance construction. jjb
Re: [webcomponents]: Of weird script elements and Benadryl
On Mon, Apr 15, 2013 at 11:59 AM, Boris Zbarsky bzbar...@mit.edu wrote: On 4/15/13 10:45 AM, Rick Waldron wrote: Sorry, I should've been more specific. What I meant was that: new HTMLButtonElement(); Doesn't construct an HTMLButtonElement, it throws with an illegal constructor in Chrome and HTMLButtonElement is not a constructor in Firefox (I'm sure this is the same across other browsers) Oh, I see. That's not anything inherent, for what it's worth; making this particular case work would be 10 lines of code. Less on a per-element basis if we want to do this for most elements. function Smile() { HTMLButtonElement.call(this); this.textContent = :); } Smile.prototype = Object.create(**HTMLButtonElement.prototype); Ah, so... This would not work even if new HTMLButtonElement worked, right? I guess I assumed this would work if new HTMLButtonElement() could construct things In particular, if HTMLButtonElement were actually something that could construct things in Gecko, it would still ignore its argument when called and always creates a new object. You can see the behavior with something like XMLHttpRequest if you want. What I was expecting the above to produce is a constructor capable of something like this: var smile = new Smile(); smile.nodeType === 1; smile.outerHTML === button:)/button; // true // (and so forth) document.body.appendChild(smile); results in something like this: http://gul.ly/de0 Rick Hopefully that clarifies? Somewhat. Trying to understand what things we really need to support here and in what ways, long-term... -Boris
Re: [webcomponents]: Of weird script elements and Benadryl
1) call 'init' when component instance tag is encountered, blocking parsing, Fwiw, it was said that calling user code from inside the Parser could cause Armageddon, not just block the parser. I don't recall the details, unfortunately. On Mon, Apr 15, 2013 at 11:44 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 11:29 AM, Scott Miles sjmi...@google.com wrote: Thank you for your patience. :) ditto. ? user's instance code? Do you mean: Running component instance initialization during document construction is Bad? My 'x-foo' has an 'init' method that I wrote that has to execute before the instance is fully 'constructed'. Parser encounters an x-foo/x-foo and constructs it. My understanding is that calling 'init' from the parser at that point is a non-starter. I think the Pinocchio link makes the case that you have only three choices: 1) call 'init' when component instance tag is encountered, blocking parsing, 2) call 'init' later, causing reflows and losing the value of not blocking parsing, 3) don't allow 'init' at all, limiting components. So non-starter is just a vote against one of three Bad choices as far as I can tell. In other words, these are all non-starters ;-). But my original question concerns blocking component documents on their own script tag compilation. Maybe I misunderstood. I don't think imports (nee component documents) have any different semantics from the main document in this regard. The import document may have an x-foo instance in it's markup, and element tags or link rel=import just like the main document. Indeed, however the relative order of the component's script tag processing and the component's tag element is all I was talking about. On Mon, Apr 15, 2013 at 11:23 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 10:38 AM, Scott Miles sjmi...@google.comwrote: Dimitri is trying to avoid 'block[ing] instance construction' because instances can be in the main document markup. Yes we sure hope so! The main document can have a bunch of markup for custom elements. If the user has made element definitions a-priori to parsing that markup (including inside link rel='import'), he expects those nodes to be 'born' correctly. Sure. Sidebar: running user's instance code while the parser is constructing the tree is Bad(tm) so we already have deferred init code until immediately after the parsing step. This is why I keep saying 'ready-time' is different from 'construct-time'. ? user's instance code? Do you mean: Running component instance initialization during document construction is Bad? Today, I don't see how we can construct a custom element with the right prototype at parse-time without blocking on imported scripts (which is another side-effect of using script execution for defining prototype, btw.) You must block creating instances of components until component documents are parsed and initialized. Because of limitations in HTML DOM construction, you may have to block HTML parsing until instances of components are created. Thus I imagine that creating instances may block HTML parsing until component documents are parsed and initialized or the HTML parsing must have two passes as your Pinocchio link outlines. But my original question concerns blocking component documents on their own script tag compilation. Maybe I misunderstood. jjb On Mon, Apr 15, 2013 at 9:54 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 9:44 AM, Scott Miles sjmi...@google.comwrote: Why do the constructors of component instances run during component loading? I'm not sure what you are referring to. What does 'component loading' mean? Why not use standard events rather than callbacks? I'll some of the doc you link below and re-ask. On Apr 15, 2013 9:04 AM, Scott Miles sjmi...@google.com wrote: Again, 'readyCallback' exists because it's a Bad Idea to run user code during parsing (tree construction). Ready-time is not the same as construct-time. This is the Pinocchio problem: http://lists.w3.org/Archives/Public/public-webapps/2013JanMar/0728.html --- Here's why: i) when we load component document, it blocks scripts just like a stylesheet (http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#a-style-sheet-that-is-blocking-scripts) ii) this is okay, since our constructors are generated (no user code) and most of the tree could be constructed while the component is loaded. iii) However, if we make constructors run at the time of tree construction, the tree construction gets blocked much sooner, which effectively makes component loading synchronous. Which is bad. Why do the constructors of component *instances* which don't need to run until instances are created, need to block the load of component documents? Seems to me that
Re: [webcomponents]: Of weird script elements and Benadryl
*At least somebody explain why this is conceptually wrong. * Nothing is conceptually wrong with what you've stated Scott. I could live with a prototype element that is scoped to the element as long as there was some sort of 'registeredCallback' (as you previously alluded to many posts back) that would be executed with access to the global scope just once before the 'DOMElementsUpgraded' event fired. This preserves the ability to setup, with minimal effort and hackery, delegate listeners and other useful top-level scaffolding a component may require. Is this pretty or optimal in terms of developer ergonomics? No - but it meet the requirements. For what it's worth: I talked to Brendan about this quandary and he favored the creation of a special tag specifically for defining a component's interface. On Mon, Apr 15, 2013 at 12:46 PM, Rick Waldron waldron.r...@gmail.comwrote: On Mon, Apr 15, 2013 at 11:59 AM, Boris Zbarsky bzbar...@mit.edu wrote: On 4/15/13 10:45 AM, Rick Waldron wrote: Sorry, I should've been more specific. What I meant was that: new HTMLButtonElement(); Doesn't construct an HTMLButtonElement, it throws with an illegal constructor in Chrome and HTMLButtonElement is not a constructor in Firefox (I'm sure this is the same across other browsers) Oh, I see. That's not anything inherent, for what it's worth; making this particular case work would be 10 lines of code. Less on a per-element basis if we want to do this for most elements. function Smile() { HTMLButtonElement.call(this); this.textContent = :); } Smile.prototype = Object.create(**HTMLButtonElement.prototype); Ah, so... This would not work even if new HTMLButtonElement worked, right? I guess I assumed this would work if new HTMLButtonElement() could construct things In particular, if HTMLButtonElement were actually something that could construct things in Gecko, it would still ignore its argument when called and always creates a new object. You can see the behavior with something like XMLHttpRequest if you want. What I was expecting the above to produce is a constructor capable of something like this: var smile = new Smile(); smile.nodeType === 1; smile.outerHTML === button:)/button; // true // (and so forth) document.body.appendChild(smile); results in something like this: http://gul.ly/de0 Rick Hopefully that clarifies? Somewhat. Trying to understand what things we really need to support here and in what ways, long-term... -Boris
Re: [webcomponents]: Of weird script elements and Benadryl
What happens if the construction/initialization of the custom element calls one of the element's member functions overridden by code in a prototype? IIRC it's not possible to override methods that will be called from inside of builtins, so I don't believe this is an issue (unless we change the playfield). How, as component author, do I ensure that my imperative set up code runs and modifies my element DOM content before the user sees the un-modified custom element declared in mark-up? (I'm cheating, since this issue isn't specific to your prototype) This is another can of worms. Right now we blanket solve this by waiting for an 'all clear' event (also being discussed, 'DOMComponentsReady' or something) and handling this appropriately for our application. On Mon, Apr 15, 2013 at 1:46 PM, John J Barton johnjbar...@johnjbarton.comwrote: What happens if the construction/initialization of the custom element calls one of the element's member functions overridden by code in a prototype? How, as component author, do I ensure that my imperative set up code runs and modifies my element DOM content before the user sees the un-modified custom element declared in mark-up? (I'm cheating, since this issue isn't specific to your prototype) On Mon, Apr 15, 2013 at 12:39 PM, Scott Miles sjmi...@google.com wrote: Sorry for beating this horse, because I don't like 'prototype' element anymore than anybody else, but I can't help thinking if there was a way to express a prototype without script 98% of this goes away. The parser can generate an object with the correct prototype, we can run init code directly after parsing, there are no 'this' issues or problems associating element with script. At least somebody explain why this is conceptually wrong. On Mon, Apr 15, 2013 at 11:52 AM, Scott Miles sjmi...@google.com wrote: 1) call 'init' when component instance tag is encountered, blocking parsing, Fwiw, it was said that calling user code from inside the Parser could cause Armageddon, not just block the parser. I don't recall the details, unfortunately. On Mon, Apr 15, 2013 at 11:44 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 11:29 AM, Scott Miles sjmi...@google.comwrote: Thank you for your patience. :) ditto. ? user's instance code? Do you mean: Running component instance initialization during document construction is Bad? My 'x-foo' has an 'init' method that I wrote that has to execute before the instance is fully 'constructed'. Parser encounters an x-foo/x-foo and constructs it. My understanding is that calling 'init' from the parser at that point is a non-starter. I think the Pinocchio link makes the case that you have only three choices: 1) call 'init' when component instance tag is encountered, blocking parsing, 2) call 'init' later, causing reflows and losing the value of not blocking parsing, 3) don't allow 'init' at all, limiting components. So non-starter is just a vote against one of three Bad choices as far as I can tell. In other words, these are all non-starters ;-). But my original question concerns blocking component documents on their own script tag compilation. Maybe I misunderstood. I don't think imports (nee component documents) have any different semantics from the main document in this regard. The import document may have an x-foo instance in it's markup, and element tags or link rel=import just like the main document. Indeed, however the relative order of the component's script tag processing and the component's tag element is all I was talking about. On Mon, Apr 15, 2013 at 11:23 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 10:38 AM, Scott Miles sjmi...@google.comwrote: Dimitri is trying to avoid 'block[ing] instance construction' because instances can be in the main document markup. Yes we sure hope so! The main document can have a bunch of markup for custom elements. If the user has made element definitions a-priori to parsing that markup (including inside link rel='import'), he expects those nodes to be 'born' correctly. Sure. Sidebar: running user's instance code while the parser is constructing the tree is Bad(tm) so we already have deferred init code until immediately after the parsing step. This is why I keep saying 'ready-time' is different from 'construct-time'. ? user's instance code? Do you mean: Running component instance initialization during document construction is Bad? Today, I don't see how we can construct a custom element with the right prototype at parse-time without blocking on imported scripts (which is another side-effect of using script execution for defining prototype, btw.) You must block creating instances of components until component documents are parsed and initialized. Because of limitations in HTML DOM construction, you may have to block HTML parsing
Re: [webcomponents]: Of weird script elements and Benadryl
*How, as component author, do I ensure that my imperative set up code runs and modifies my element DOM content before the user sees the un-modified custom element declared in mark-up? (I'm cheating, since this issue isn't specific to your prototype) * When you say ...runs before the user sees the unmodified..., what do you mean? The 'readyCallback' is the *run-once-per-instance* imperative code associated with a component, and would always run *after *something like 'registeredCallback*', *the *run-once-per-component* imperative code...unless we are talking about different things? As far as what the user visually sees, there is an understanding that a render my happen wherein components are not yet inflated/upgraded - in this instance, the developer should create some styles to account for the non-upgraded state. This has been the thinking all along btw. On Mon, Apr 15, 2013 at 1:46 PM, John J Barton johnjbar...@johnjbarton.comwrote: What happens if the construction/initialization of the custom element calls one of the element's member functions overridden by code in a prototype? How, as component author, do I ensure that my imperative set up code runs and modifies my element DOM content before the user sees the un-modified custom element declared in mark-up? (I'm cheating, since this issue isn't specific to your prototype) On Mon, Apr 15, 2013 at 12:39 PM, Scott Miles sjmi...@google.com wrote: Sorry for beating this horse, because I don't like 'prototype' element anymore than anybody else, but I can't help thinking if there was a way to express a prototype without script 98% of this goes away. The parser can generate an object with the correct prototype, we can run init code directly after parsing, there are no 'this' issues or problems associating element with script. At least somebody explain why this is conceptually wrong. On Mon, Apr 15, 2013 at 11:52 AM, Scott Miles sjmi...@google.com wrote: 1) call 'init' when component instance tag is encountered, blocking parsing, Fwiw, it was said that calling user code from inside the Parser could cause Armageddon, not just block the parser. I don't recall the details, unfortunately. On Mon, Apr 15, 2013 at 11:44 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 11:29 AM, Scott Miles sjmi...@google.comwrote: Thank you for your patience. :) ditto. ? user's instance code? Do you mean: Running component instance initialization during document construction is Bad? My 'x-foo' has an 'init' method that I wrote that has to execute before the instance is fully 'constructed'. Parser encounters an x-foo/x-foo and constructs it. My understanding is that calling 'init' from the parser at that point is a non-starter. I think the Pinocchio link makes the case that you have only three choices: 1) call 'init' when component instance tag is encountered, blocking parsing, 2) call 'init' later, causing reflows and losing the value of not blocking parsing, 3) don't allow 'init' at all, limiting components. So non-starter is just a vote against one of three Bad choices as far as I can tell. In other words, these are all non-starters ;-). But my original question concerns blocking component documents on their own script tag compilation. Maybe I misunderstood. I don't think imports (nee component documents) have any different semantics from the main document in this regard. The import document may have an x-foo instance in it's markup, and element tags or link rel=import just like the main document. Indeed, however the relative order of the component's script tag processing and the component's tag element is all I was talking about. On Mon, Apr 15, 2013 at 11:23 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 10:38 AM, Scott Miles sjmi...@google.comwrote: Dimitri is trying to avoid 'block[ing] instance construction' because instances can be in the main document markup. Yes we sure hope so! The main document can have a bunch of markup for custom elements. If the user has made element definitions a-priori to parsing that markup (including inside link rel='import'), he expects those nodes to be 'born' correctly. Sure. Sidebar: running user's instance code while the parser is constructing the tree is Bad(tm) so we already have deferred init code until immediately after the parsing step. This is why I keep saying 'ready-time' is different from 'construct-time'. ? user's instance code? Do you mean: Running component instance initialization during document construction is Bad? Today, I don't see how we can construct a custom element with the right prototype at parse-time without blocking on imported scripts (which is another side-effect of using script execution for defining prototype, btw.) You must block creating instances of components until component documents are parsed and
Re: [webcomponents]: Of weird script elements and Benadryl
On 4/15/13 3:46 PM, Rick Waldron wrote: What I was expecting the above to produce is a constructor capable of something like this: var smile = new Smile(); smile.nodeType === 1; For that, you have to have a way for Smile to get the @@construct of HTMLButtonElement. There's no way to do that with ES5. :( -Boris
Re: [webcomponents]: Of weird script elements and Benadryl
So we can override some methods but not others, depending on the implementation? You can override methods that will be called from JS, but not from C++ (depending on platform). Gee, that's not very encouraging I was trying to just say we have been aware of these issue too and there are efforts going on here. We are already building apps on these techniques and are exploring these issues with developers. I'd rather not get into all those issues too on this thread. Rather, for the hard-core platform peeps here, I'd prefer to focus on some semantics for document.register and element that doesn't cause hives (see what I did there?). Scott On Mon, Apr 15, 2013 at 2:23 PM, John J Barton johnjbar...@johnjbarton.comwrote: On Mon, Apr 15, 2013 at 2:01 PM, Scott Miles sjmi...@google.com wrote: What happens if the construction/initialization of the custom element calls one of the element's member functions overridden by code in a prototype? IIRC it's not possible to override methods that will be called from inside of builtins, so I don't believe this is an issue (unless we change the playfield). Ugh. So we can override some methods but not others, depending on the implementation? So really these methods are more like callbacks with a funky kind of registration. It's not like inheriting and overriding, it's like onLoad implemented with an inheritance-like wording. An API users doesn't think like an object, rather they ask the Internet some HowTo questions and get a recipe for a particular function override. Ok, I'm exaggerating, but I still think the emphasis on inheritance in the face of so me is a high tax on this problem. How, as component author, do I ensure that my imperative set up code runs and modifies my element DOM content before the user sees the un-modified custom element declared in mark-up? (I'm cheating, since this issue isn't specific to your prototype) This is another can of worms. Right now we blanket solve this by waiting for an 'all clear' event (also being discussed, 'DOMComponentsReady' or something) and handling this appropriately for our application. Gee, that's not very encouraging: this is the most important kind of issue for a developer, more so than whether the API is inheritance-like or not. On Mon, Apr 15, 2013 at 1:46 PM, John J Barton johnjbar...@johnjbarton.com wrote: What happens if the construction/initialization of the custom element calls one of the element's member functions overridden by code in a prototype? How, as component author, do I ensure that my imperative set up code runs and modifies my element DOM content before the user sees the un-modified custom element declared in mark-up? (I'm cheating, since this issue isn't specific to your prototype) On Mon, Apr 15, 2013 at 12:39 PM, Scott Miles sjmi...@google.comwrote: Sorry for beating this horse, because I don't like 'prototype' element anymore than anybody else, but I can't help thinking if there was a way to express a prototype without script 98% of this goes away. The parser can generate an object with the correct prototype, we can run init code directly after parsing, there are no 'this' issues or problems associating element with script. At least somebody explain why this is conceptually wrong. On Mon, Apr 15, 2013 at 11:52 AM, Scott Miles sjmi...@google.comwrote: 1) call 'init' when component instance tag is encountered, blocking parsing, Fwiw, it was said that calling user code from inside the Parser could cause Armageddon, not just block the parser. I don't recall the details, unfortunately. On Mon, Apr 15, 2013 at 11:44 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 11:29 AM, Scott Miles sjmi...@google.comwrote: Thank you for your patience. :) ditto. ? user's instance code? Do you mean: Running component instance initialization during document construction is Bad? My 'x-foo' has an 'init' method that I wrote that has to execute before the instance is fully 'constructed'. Parser encounters an x-foo/x-foo and constructs it. My understanding is that calling 'init' from the parser at that point is a non-starter. I think the Pinocchio link makes the case that you have only three choices: 1) call 'init' when component instance tag is encountered, blocking parsing, 2) call 'init' later, causing reflows and losing the value of not blocking parsing, 3) don't allow 'init' at all, limiting components. So non-starter is just a vote against one of three Bad choices as far as I can tell. In other words, these are all non-starters ;-). But my original question concerns blocking component documents on their own script tag compilation. Maybe I misunderstood. I don't think imports (nee component documents) have any different semantics from the main document in this regard. The import document may have an x-foo instance in it's markup, and element tags
Re: [webcomponents]: Of weird script elements and Benadryl
On Mon, Apr 15, 2013 at 2:01 PM, Scott Miles sjmi...@google.com wrote: What happens if the construction/initialization of the custom element calls one of the element's member functions overridden by code in a prototype? IIRC it's not possible to override methods that will be called from inside of builtins, so I don't believe this is an issue (unless we change the playfield). Ugh. So we can override some methods but not others, depending on the implementation? So really these methods are more like callbacks with a funky kind of registration. It's not like inheriting and overriding, it's like onLoad implemented with an inheritance-like wording. An API users doesn't think like an object, rather they ask the Internet some HowTo questions and get a recipe for a particular function override. Ok, I'm exaggerating, but I still think the emphasis on inheritance in the face of so me is a high tax on this problem. How, as component author, do I ensure that my imperative set up code runs and modifies my element DOM content before the user sees the un-modified custom element declared in mark-up? (I'm cheating, since this issue isn't specific to your prototype) This is another can of worms. Right now we blanket solve this by waiting for an 'all clear' event (also being discussed, 'DOMComponentsReady' or something) and handling this appropriately for our application. Gee, that's not very encouraging: this is the most important kind of issue for a developer, more so than whether the API is inheritance-like or not. On Mon, Apr 15, 2013 at 1:46 PM, John J Barton johnjbar...@johnjbarton.com wrote: What happens if the construction/initialization of the custom element calls one of the element's member functions overridden by code in a prototype? How, as component author, do I ensure that my imperative set up code runs and modifies my element DOM content before the user sees the un-modified custom element declared in mark-up? (I'm cheating, since this issue isn't specific to your prototype) On Mon, Apr 15, 2013 at 12:39 PM, Scott Miles sjmi...@google.com wrote: Sorry for beating this horse, because I don't like 'prototype' element anymore than anybody else, but I can't help thinking if there was a way to express a prototype without script 98% of this goes away. The parser can generate an object with the correct prototype, we can run init code directly after parsing, there are no 'this' issues or problems associating element with script. At least somebody explain why this is conceptually wrong. On Mon, Apr 15, 2013 at 11:52 AM, Scott Miles sjmi...@google.comwrote: 1) call 'init' when component instance tag is encountered, blocking parsing, Fwiw, it was said that calling user code from inside the Parser could cause Armageddon, not just block the parser. I don't recall the details, unfortunately. On Mon, Apr 15, 2013 at 11:44 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 11:29 AM, Scott Miles sjmi...@google.comwrote: Thank you for your patience. :) ditto. ? user's instance code? Do you mean: Running component instance initialization during document construction is Bad? My 'x-foo' has an 'init' method that I wrote that has to execute before the instance is fully 'constructed'. Parser encounters an x-foo/x-foo and constructs it. My understanding is that calling 'init' from the parser at that point is a non-starter. I think the Pinocchio link makes the case that you have only three choices: 1) call 'init' when component instance tag is encountered, blocking parsing, 2) call 'init' later, causing reflows and losing the value of not blocking parsing, 3) don't allow 'init' at all, limiting components. So non-starter is just a vote against one of three Bad choices as far as I can tell. In other words, these are all non-starters ;-). But my original question concerns blocking component documents on their own script tag compilation. Maybe I misunderstood. I don't think imports (nee component documents) have any different semantics from the main document in this regard. The import document may have an x-foo instance in it's markup, and element tags or link rel=import just like the main document. Indeed, however the relative order of the component's script tag processing and the component's tag element is all I was talking about. On Mon, Apr 15, 2013 at 11:23 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 10:38 AM, Scott Miles sjmi...@google.comwrote: Dimitri is trying to avoid 'block[ing] instance construction' because instances can be in the main document markup. Yes we sure hope so! The main document can have a bunch of markup for custom elements. If the user has made element definitions a-priori to parsing that markup (including inside link rel='import'), he expects those nodes to be 'born' correctly. Sure.
Re: [webcomponents]: Of weird script elements and Benadryl
* * *Gee, that's not very encouraging: this is the most important kind of issue for a developer, more so than whether the API is inheritance-like or not.* IMO, the not-yet-upgraded case is nothing new, and developers will hardly be surprised. This nit is no different than if devs include a jQuery plugin script at the bottom of the body that 'upgrades' various elements on the page after render - basically, it's an unfortunate case of That's Just Life™ Daniel J. Buchner Product Manager, Developer Ecosystem Mozilla Corporation On Mon, Apr 15, 2013 at 2:23 PM, John J Barton johnjbar...@johnjbarton.comwrote: On Mon, Apr 15, 2013 at 2:01 PM, Scott Miles sjmi...@google.com wrote: What happens if the construction/initialization of the custom element calls one of the element's member functions overridden by code in a prototype? IIRC it's not possible to override methods that will be called from inside of builtins, so I don't believe this is an issue (unless we change the playfield). Ugh. So we can override some methods but not others, depending on the implementation? So really these methods are more like callbacks with a funky kind of registration. It's not like inheriting and overriding, it's like onLoad implemented with an inheritance-like wording. An API users doesn't think like an object, rather they ask the Internet some HowTo questions and get a recipe for a particular function override. Ok, I'm exaggerating, but I still think the emphasis on inheritance in the face of so me is a high tax on this problem. How, as component author, do I ensure that my imperative set up code runs and modifies my element DOM content before the user sees the un-modified custom element declared in mark-up? (I'm cheating, since this issue isn't specific to your prototype) This is another can of worms. Right now we blanket solve this by waiting for an 'all clear' event (also being discussed, 'DOMComponentsReady' or something) and handling this appropriately for our application. Gee, that's not very encouraging: this is the most important kind of issue for a developer, more so than whether the API is inheritance-like or not. On Mon, Apr 15, 2013 at 1:46 PM, John J Barton johnjbar...@johnjbarton.com wrote: What happens if the construction/initialization of the custom element calls one of the element's member functions overridden by code in a prototype? How, as component author, do I ensure that my imperative set up code runs and modifies my element DOM content before the user sees the un-modified custom element declared in mark-up? (I'm cheating, since this issue isn't specific to your prototype) On Mon, Apr 15, 2013 at 12:39 PM, Scott Miles sjmi...@google.comwrote: Sorry for beating this horse, because I don't like 'prototype' element anymore than anybody else, but I can't help thinking if there was a way to express a prototype without script 98% of this goes away. The parser can generate an object with the correct prototype, we can run init code directly after parsing, there are no 'this' issues or problems associating element with script. At least somebody explain why this is conceptually wrong. On Mon, Apr 15, 2013 at 11:52 AM, Scott Miles sjmi...@google.comwrote: 1) call 'init' when component instance tag is encountered, blocking parsing, Fwiw, it was said that calling user code from inside the Parser could cause Armageddon, not just block the parser. I don't recall the details, unfortunately. On Mon, Apr 15, 2013 at 11:44 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 11:29 AM, Scott Miles sjmi...@google.comwrote: Thank you for your patience. :) ditto. ? user's instance code? Do you mean: Running component instance initialization during document construction is Bad? My 'x-foo' has an 'init' method that I wrote that has to execute before the instance is fully 'constructed'. Parser encounters an x-foo/x-foo and constructs it. My understanding is that calling 'init' from the parser at that point is a non-starter. I think the Pinocchio link makes the case that you have only three choices: 1) call 'init' when component instance tag is encountered, blocking parsing, 2) call 'init' later, causing reflows and losing the value of not blocking parsing, 3) don't allow 'init' at all, limiting components. So non-starter is just a vote against one of three Bad choices as far as I can tell. In other words, these are all non-starters ;-). But my original question concerns blocking component documents on their own script tag compilation. Maybe I misunderstood. I don't think imports (nee component documents) have any different semantics from the main document in this regard. The import document may have an x-foo instance in it's markup, and element tags or link rel=import just like the main document. Indeed, however the relative order of the component's script tag
Re: [webcomponents]: Of weird script elements and Benadryl
I think that rendering a placeholder (eg blank image) then filling it in rather than blocking is good if done well (eg images with pre-allocated space). Otherwise it's bad but less bad than blocking ;-). But if you allow this implementation, then this whole discussion confuses me even more. I'm thinking: If you don't need the custom constructors during parsing, just wait for them to arrive, then call them. Something else is going on I suppose, so I'm just wasting your time. On Mon, Apr 15, 2013 at 2:42 PM, Daniel Buchner dan...@mozilla.com wrote: * * *Gee, that's not very encouraging: this is the most important kind of issue for a developer, more so than whether the API is inheritance-like or not.* IMO, the not-yet-upgraded case is nothing new, and developers will hardly be surprised. This nit is no different than if devs include a jQuery plugin script at the bottom of the body that 'upgrades' various elements on the page after render - basically, it's an unfortunate case of That's Just Life™ Daniel J. Buchner Product Manager, Developer Ecosystem Mozilla Corporation On Mon, Apr 15, 2013 at 2:23 PM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 2:01 PM, Scott Miles sjmi...@google.com wrote: What happens if the construction/initialization of the custom element calls one of the element's member functions overridden by code in a prototype? IIRC it's not possible to override methods that will be called from inside of builtins, so I don't believe this is an issue (unless we change the playfield). Ugh. So we can override some methods but not others, depending on the implementation? So really these methods are more like callbacks with a funky kind of registration. It's not like inheriting and overriding, it's like onLoad implemented with an inheritance-like wording. An API users doesn't think like an object, rather they ask the Internet some HowTo questions and get a recipe for a particular function override. Ok, I'm exaggerating, but I still think the emphasis on inheritance in the face of so me is a high tax on this problem. How, as component author, do I ensure that my imperative set up code runs and modifies my element DOM content before the user sees the un-modified custom element declared in mark-up? (I'm cheating, since this issue isn't specific to your prototype) This is another can of worms. Right now we blanket solve this by waiting for an 'all clear' event (also being discussed, 'DOMComponentsReady' or something) and handling this appropriately for our application. Gee, that's not very encouraging: this is the most important kind of issue for a developer, more so than whether the API is inheritance-like or not. On Mon, Apr 15, 2013 at 1:46 PM, John J Barton johnjbar...@johnjbarton.com wrote: What happens if the construction/initialization of the custom element calls one of the element's member functions overridden by code in a prototype? How, as component author, do I ensure that my imperative set up code runs and modifies my element DOM content before the user sees the un-modified custom element declared in mark-up? (I'm cheating, since this issue isn't specific to your prototype) On Mon, Apr 15, 2013 at 12:39 PM, Scott Miles sjmi...@google.comwrote: Sorry for beating this horse, because I don't like 'prototype' element anymore than anybody else, but I can't help thinking if there was a way to express a prototype without script 98% of this goes away. The parser can generate an object with the correct prototype, we can run init code directly after parsing, there are no 'this' issues or problems associating element with script. At least somebody explain why this is conceptually wrong. On Mon, Apr 15, 2013 at 11:52 AM, Scott Miles sjmi...@google.comwrote: 1) call 'init' when component instance tag is encountered, blocking parsing, Fwiw, it was said that calling user code from inside the Parser could cause Armageddon, not just block the parser. I don't recall the details, unfortunately. On Mon, Apr 15, 2013 at 11:44 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 11:29 AM, Scott Miles sjmi...@google.comwrote: Thank you for your patience. :) ditto. ? user's instance code? Do you mean: Running component instance initialization during document construction is Bad? My 'x-foo' has an 'init' method that I wrote that has to execute before the instance is fully 'constructed'. Parser encounters an x-foo/x-foo and constructs it. My understanding is that calling 'init' from the parser at that point is a non-starter. I think the Pinocchio link makes the case that you have only three choices: 1) call 'init' when component instance tag is encountered, blocking parsing, 2) call 'init' later, causing reflows and losing the value of not blocking parsing, 3) don't allow 'init' at all, limiting components. So
Re: [webcomponents]: Of weird script elements and Benadryl
Would this be possible using the Scott and Brendan's idea of using a specific element for prototyping? -- https://gist.github.com/csuwldcat/5392291 On Mon, Apr 15, 2013 at 3:33 PM, John J Barton johnjbar...@johnjbarton.comwrote: I think that rendering a placeholder (eg blank image) then filling it in rather than blocking is good if done well (eg images with pre-allocated space). Otherwise it's bad but less bad than blocking ;-). But if you allow this implementation, then this whole discussion confuses me even more. I'm thinking: If you don't need the custom constructors during parsing, just wait for them to arrive, then call them. Something else is going on I suppose, so I'm just wasting your time. On Mon, Apr 15, 2013 at 2:42 PM, Daniel Buchner dan...@mozilla.comwrote: * * *Gee, that's not very encouraging: this is the most important kind of issue for a developer, more so than whether the API is inheritance-like or not.* IMO, the not-yet-upgraded case is nothing new, and developers will hardly be surprised. This nit is no different than if devs include a jQuery plugin script at the bottom of the body that 'upgrades' various elements on the page after render - basically, it's an unfortunate case of That's Just Life™ Daniel J. Buchner Product Manager, Developer Ecosystem Mozilla Corporation On Mon, Apr 15, 2013 at 2:23 PM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 2:01 PM, Scott Miles sjmi...@google.com wrote: What happens if the construction/initialization of the custom element calls one of the element's member functions overridden by code in a prototype? IIRC it's not possible to override methods that will be called from inside of builtins, so I don't believe this is an issue (unless we change the playfield). Ugh. So we can override some methods but not others, depending on the implementation? So really these methods are more like callbacks with a funky kind of registration. It's not like inheriting and overriding, it's like onLoad implemented with an inheritance-like wording. An API users doesn't think like an object, rather they ask the Internet some HowTo questions and get a recipe for a particular function override. Ok, I'm exaggerating, but I still think the emphasis on inheritance in the face of so me is a high tax on this problem. How, as component author, do I ensure that my imperative set up code runs and modifies my element DOM content before the user sees the un-modified custom element declared in mark-up? (I'm cheating, since this issue isn't specific to your prototype) This is another can of worms. Right now we blanket solve this by waiting for an 'all clear' event (also being discussed, 'DOMComponentsReady' or something) and handling this appropriately for our application. Gee, that's not very encouraging: this is the most important kind of issue for a developer, more so than whether the API is inheritance-like or not. On Mon, Apr 15, 2013 at 1:46 PM, John J Barton johnjbar...@johnjbarton.com wrote: What happens if the construction/initialization of the custom element calls one of the element's member functions overridden by code in a prototype? How, as component author, do I ensure that my imperative set up code runs and modifies my element DOM content before the user sees the un-modified custom element declared in mark-up? (I'm cheating, since this issue isn't specific to your prototype) On Mon, Apr 15, 2013 at 12:39 PM, Scott Miles sjmi...@google.comwrote: Sorry for beating this horse, because I don't like 'prototype' element anymore than anybody else, but I can't help thinking if there was a way to express a prototype without script 98% of this goes away. The parser can generate an object with the correct prototype, we can run init code directly after parsing, there are no 'this' issues or problems associating element with script. At least somebody explain why this is conceptually wrong. On Mon, Apr 15, 2013 at 11:52 AM, Scott Miles sjmi...@google.comwrote: 1) call 'init' when component instance tag is encountered, blocking parsing, Fwiw, it was said that calling user code from inside the Parser could cause Armageddon, not just block the parser. I don't recall the details, unfortunately. On Mon, Apr 15, 2013 at 11:44 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 15, 2013 at 11:29 AM, Scott Miles sjmi...@google.comwrote: Thank you for your patience. :) ditto. ? user's instance code? Do you mean: Running component instance initialization during document construction is Bad? My 'x-foo' has an 'init' method that I wrote that has to execute before the instance is fully 'constructed'. Parser encounters an x-foo/x-foo and constructs it. My understanding is that calling 'init' from the parser at that point is a non-starter. I think the Pinocchio link makes the case that you have only
Re: [webcomponents]: Of weird script elements and Benadryl
Can Scott or Daniel or someone explain the challenge with creating a normal constructor that has been mentioned a few times (Scott mentioned has-a). I get the feeling that several people are playing catch up on that challenge and the implications that are causing worry. Until people have some shared understanding it is difficult to impossible to reach something acceptable all around. Hard to solve the unknown problems.
Re: [webcomponents]: Of weird script elements and Benadryl
the challenge with creating a normal constructor Forgive me if my language is imprecise, but the basic notion is that in general one cannot create a constructor that creates a DOM node because (most? all?) browsers make under the hood mappings to internal code (C++ for Blink and Webkit). For example, note that HTMLElement and descendents are not callable from JS. Erik Arvidsson came up with a strategy for overcoming this in Blink, but to my recollection Boris Zbarsky said this was a non-starter in Gecko. Because of this constraint Dimitri's current system involves supplying only a prototype to the system, which hands you back a generated constructor. Wrt 'has-a' and 'is-a', at one point I polyfilled a system where the user object has-a Element instead of is-a Element. This gets around the constructor problem, but has some drawbacks: e.g. users want custom API on the node (at instance time we populated the node with public API, a per-instance cost). The fatal problem was that utlimately users rejected the separation between the true element and the code they wrote (which boils down to 'this !== Element instance' in the custom code). HTH, Scott On Sun, Apr 14, 2013 at 6:11 AM, Brian Kardell bkard...@gmail.com wrote: Can Scott or Daniel or someone explain the challenge with creating a normal constructor that has been mentioned a few times (Scott mentioned has-a). I get the feeling that several people are playing catch up on that challenge and the implications that are causing worry. Until people have some shared understanding it is difficult to impossible to reach something acceptable all around. Hard to solve the unknown problems.
Re: [webcomponents]: Of weird script elements and Benadryl
On Sat, Apr 13, 2013 at 10:16 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: I see two ways you might do this: 1) create a new *anonymous* constructor object that inherits from HTMLElement. It wouldn't have any unique behavior but it would be uniquely associated the particular element that defined it and it might be useful for doing instanceof tests. It would be the constructor that you register with the tag. This is much better then the semantics I described for handling cases where no explicit constructor exists—nice! 2) Have a new kind of HTML*Element that is used when instantiating all custom elements that don't have explicit constructors. As a placeholder name I'll use HTMLAppDefinedElement. One system defined HTMLAppDefinedElement constructor can be used for all such custom elements because they have no distinguishing behavior. So every x-foo would have a dom node that was an instance of HTMLAppDefinedElement and so would every x-bar. The instances only differ in their identify and the value of the tag names (and their children, etc.). Note in both these cases there are no element specific behaviors and hence no need to install prototype properties. I think if an element needs such custom behavior it should be required to use a constructor= attribute to associate an app provided constructor object with the element and the constructor should be specified in a normal script bock using normal JS techniques. It would be a mistake to automatically generate the constructor and then to invent some new convention to be used in a special kind of nested script block for installing properties into a prototype of the generated constructor. This is one of the main things I was objecting to, JS already has multiple ways to define constructors and ES6 will have a very straightforward way using class declarations. We don't need a new ad hoc way for this specific use case. For what it's worth, I have nothing against making constructor= an option that is used instead of the tag name, but why force extra boilerplate if people would be just as comfortable dealing with a constructor name based on the tag name they specify? (as elements do now) The purpose of constructor= should be to explicitly say, this element uses a app defined element constructor which is hereby identified. The absence should indicate that a platform provided element constructor will be used Exactly and I apologize if I was previously unclear about this. Rick Allen
Re: [webcomponents]: Of weird script elements and Benadryl
First of all, thanks for diving in on this Allen (and Rick and Blake et al). all built-in HTML*Element constructors are global so making app defined custom elements also be global doesn't seem like it is introducing any new ugliness Yes, but that set of constructors is tightly controlled, and application level custom elements will be the Wild West. I may have to give on this one, but I really appreciated that document.register let me do my work without having to name a global symbol. Here are four ways to avoid the subclassing problem for custom elements 1) Only allow instances of custome dom elements to be instantiated using document.createElement(x-foo). Wearing web developer hat, I never make elements any other way than createElement (or HTML), so this would be standard operating procedure, so that's all good if we can get buy in. 2, 3, 4 I believe have been suggested in one form or another, but as I mentioned, were determined to be non-starters for Gecko. I don't think we've heard anything from IE team. On Sun, Apr 14, 2013 at 11:28 AM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Apr 13, 2013, at 9:13 PM, Scott Miles wrote: I think if an element needs such custom behavior it should be required to use a constructor= attribute to associate an app provided constructor object with the element and I don't like this because it requires me to make a global symbol. document.register, as you pointed out does not. In the original scenario, the nesting of the script in the element provided the linkage between them (however it played out), I hate to lose that. If you think this is a bogus objection, please let me know (and I will take it seriously). Well, all built-in HTML*Element constructors are global so making app defined custom elements also be global doesn't seem like it is introducing any new ugliness. Regardless, I believe when I first described constructor= is suggest that its value should be interpreted as a script expression. In that case you can say things like: element name=x-foo constructor=appNamespace.FooElement /element element name=x-foo constructor=myExtensionRegistry.lookup('x-foo') /element etc. the constructor should be specified in a normal script bock using normal JS techniques. There is a practical problem that we cannot make a constructor using 'normal' techniques that creates a DOM node, so sayeth the Gecko guys (iirc). There was a suggestion to make the custom objects have-a node instead of be-a node, which has many positives, but we tried that in polyfills and the users revolted against 'this !== my-element-instance' inside their class. What they are referring to is what in the TC39 world we call the built-ins subclassing problem. The issue is that many built-in objects (for example arrays) and many host objects have special implementation specific object representations that gives them special runtime characteristics and that simply inheriting from their prototype isn't enough to give an object created by a subclass constructor those special characteristics. In TC39 we use the term exotic object for any object with such special characteristics. In ES specs. we talk about the [[Construct]] behavior of a function. This is the protocol that is followed when the new operator is applied to a constructor function. The normal default [[Construct]] behavior is to allocated a new normal object and then to call the constructor function to initialize the state of that object. Exotic object typically have a different dispatch at a low level to a special [[Construct]] implementation that knows how to allocate and initialize the appropriate form of exotic object. Here are four ways to avoid the subclassing problem for custom elements: 1) Only allow instances of custome dom elements to be instantiated using document.createElement(x-foo). createElement would instantiate the appropriate implementation level exotic dom element object structure and then invoke the app provided constructor (with this bound to the new exotic instance) to initialize the instance. 2) Whenever a constructor is associated with an element either via a constructor= attribute or via a call to document.register the implementation would modify (if necessary) the [[Construct]] dispatch of the app provided constructor to first crate an implementation specific exotic dom element object and then to call the provided constructor to do any app specific initialization. This would allow saying things like: new HTMLXFooElement() to instantiate custom elements 3) Provide a new API that blesses an app provided constructor as an DOM element constructor. Only blessed constructors would be allowed to be associated with an element. The blessing process would be essentially the same as describe for #2 above. 4) ES6 includes specified behavior that eliminates the built-in subclassing problem and browsers will be implementing it.
Re: [webcomponents]: Of weird script elements and Benadryl
On Apr 14, 2013, at 10:49 AM, Scott Miles wrote: the challenge with creating a normal constructor Forgive me if my language is imprecise, but the basic notion is that in general one cannot create a constructor that creates a DOM node because (most? all?) browsers make under the hood mappings to internal code (C++ for Blink and Webkit). For example, note that HTMLElement and descendents are not callable from JS. Erik Arvidsson came up with a strategy for overcoming this in Blink, but to my recollection Boris Zbarsky said this was a non-starter in Gecko. Because of this constraint Dimitri's current system involves supplying only a prototype to the system, which hands you back a generated constructor. I addressed this issue in a follow message. For background on the problem and general solution see http://wiki.ecmascript.org/lib/exe/fetch.php?id=meetings%3Ameeting_jan_29_2013cache=cachemedia=meetings:subclassing_builtins.pdf Also http://www.2ality.com/2013/03/subclassing-builtins-es6.html Allen
Re: [webcomponents]: Of weird script elements and Benadryl
Re: subclassing builtins, the problem we have is stated here: http://lists.w3.org/Archives/Public/public-webapps/2013JanMar/0266.html On Sun, Apr 14, 2013 at 11:52 AM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Apr 14, 2013, at 10:49 AM, Scott Miles wrote: the challenge with creating a normal constructor Forgive me if my language is imprecise, but the basic notion is that in general one cannot create a constructor that creates a DOM node because (most? all?) browsers make under the hood mappings to internal code (C++ for Blink and Webkit). For example, note that HTMLElement and descendents are not callable from JS. Erik Arvidsson came up with a strategy for overcoming this in Blink, but to my recollection Boris Zbarsky said this was a non-starter in Gecko. Because of this constraint Dimitri's current system involves supplying only a prototype to the system, which hands you back a generated constructor. I addressed this issue in a follow message. For background on the problem and general solution see http://wiki.ecmascript.org/lib/exe/fetch.php?id=meetings%3Ameeting_jan_29_2013cache=cachemedia=meetings:subclassing_builtins.pdfhttp://wiki.ecmascript.org/lib/exe/fetch.php?id=meetings:meeting_jan_29_2013cache=cachemedia=meetings:subclassing_builtins.pdf Also http://www.2ality.com/2013/03/subclassing-builtins-es6.html Allen
Re: [webcomponents]: Of weird script elements and Benadryl
On Apr 14, 2013, at 11:40 AM, Scott Miles wrote: Here are four ways to avoid the subclassing problem for custom elements 1) Only allow instances of custome dom elements to be instantiated using document.createElement(x-foo). Wearing web developer hat, I never make elements any other way than createElement (or HTML), so this would be standard operating procedure, so that's all good if we can get buy in. However, I believe that some people such as Alex Russell have been advocating that WebIDL should be allow constructor-like interfaces to support expressions such as: new HTMLWhateverElement() It would be future hostile to make that impossible, but support could reasonably wait for ES6 support. 2, 3, 4 I believe have been suggested in one form or another, but as I mentioned, were determined to be non-starters for Gecko. I don't think we've heard anything from IE team. Well #4 has been accepted for ES6 by all TC39 participants including Mozilla and Microsoft and is going to happen. The basic scheme was actually suggested a member of the SpiderMonkey team so I'm sure we'll get it worked out for Gecko. Allen
Re: [webcomponents]: Of weird script elements and Benadryl
* Here are four ways to avoid the subclassing problem for custom elements * * 1) Only allow instances of custome dom elements to be instantiated using document.createElement(x-foo). * * * *Wearing web developer hat, I never make elements any other way than createElement (or HTML), so this would be standard operating procedure, so that's all good if we can get buy in.* As long as the above supports all other DOM element creation vectors (innerHTML, outerHTML, etc), then this is fine. Practically speaking, if it so happened that custom elements could *never *be instantiated with constructors, developers on the web today wouldn't shed a tear, they use doc.createElement(), not constructors -- https://docs.google.com/forms/d/16cNqHRe-7CFRHRVcFo94U6tIYnohEpj7NZhY02ejiXQ/viewanalytics - * Alex Russell have been advocating that WebIDL should be allow constructor-like interfaces* * * *Absolutely agree. But these are horns of this dilemma.* * * * #4 has been accepted for ES6 by all TC39 participants* * * *Yes, I believe this is a timing issue. I am told it will be a long time before #4 is practical.* Yes, it will be along time, especially for IE9 and 10 (read: never), which are support targets for custom element polyfills. Reliance on anything that is optional or future should be avoided for the custom element base case. Right now the polyfills for document.register(), and a few of the declarative proposals, can give developers these awesome APIs today - please, do not imperil this. On Sun, Apr 14, 2013 at 12:22 PM, Scott Miles sjmi...@google.com wrote: errata: XFooPrototype = Object.create(HTMLElement.prototype, { On Sun, Apr 14, 2013 at 12:21 PM, Scott Miles sjmi...@google.com wrote: Alex Russell have been advocating that WebIDL should be allow constructor-like interfaces Absolutely agree. But these are horns of this dilemma. #4 has been accepted for ES6 by all TC39 participants Yes, I believe this is a timing issue. I am told it will be a long time before #4 is practical. Gecko and Blink have already landed forms of 'document.register', to wit: Grail-shaped version of document.register: // use whatever 'class-like' thing you want class XFoo extends HTMLElement { constructor() { super(); this.textContent = XFoo Ftw; } } document.register('x-foo', XFoo); But since (today!) we cannot extend HTMLElement et al this way, the landed implementations use: // prototype only XFooPrototype = Object.create(HTMLElement, { readyCallback: { value: function() { // we invented this for constructor-like semantics super(); // some way of doing this } } }; // capture the constructor if you care [XFoo =] document.register('x-foo', {prototype: XFooPrototype); Which for convenience, I like to write this way (but there are footguns): class XFooThunk extends HTMLElement { // any constructor here will be ignored readyCallback() { // we invented this for constructor-like semantics super(); } } // capture the real constructor if you care [XFoo =] document.register('x-foo', XFooThunk); On Sun, Apr 14, 2013 at 12:07 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Apr 14, 2013, at 11:40 AM, Scott Miles wrote: Here are four ways to avoid the subclassing problem for custom elements 1) Only allow instances of custome dom elements to be instantiated using document.createElement(x-foo). Wearing web developer hat, I never make elements any other way than createElement (or HTML), so this would be standard operating procedure, so that's all good if we can get buy in. However, I believe that some people such as Alex Russell have been advocating that WebIDL should be allow constructor-like interfaces to support expressions such as: new HTMLWhateverElement() It would be future hostile to make that impossible, but support could reasonably wait for ES6 support. 2, 3, 4 I believe have been suggested in one form or another, but as I mentioned, were determined to be non-starters for Gecko. I don't think we've heard anything from IE team. Well #4 has been accepted for ES6 by all TC39 participants including Mozilla and Microsoft and is going to happen. The basic scheme was actually suggested a member of the SpiderMonkey team so I'm sure we'll get it worked out for Gecko. Allen
Re: [webcomponents]: Of weird script elements and Benadryl
On Sun, Apr 14, 2013 at 3:46 PM, Daniel Buchner dan...@mozilla.com wrote: * Here are four ways to avoid the subclassing problem for custom elements * * 1) Only allow instances of custome dom elements to be instantiated using document.createElement(x-foo). * * * *Wearing web developer hat, I never make elements any other way than createElement (or HTML), so this would be standard operating procedure, so that's all good if we can get buy in.* As long as the above supports all other DOM element creation vectors (innerHTML, outerHTML, etc), then this is fine. Practically speaking, if it so happened that custom elements could *never *be instantiated with constructors, developers on the web today wouldn't shed a tear, they use doc.createElement(), not constructors -- https://docs.google.com/forms/d/16cNqHRe-7CFRHRVcFo94U6tIYnohEpj7NZhY02ejiXQ/viewanalytics Of course, but we'd also eat scraps from the trash if that was the only edible food left on earth. document.createElement() is and has always been the wrong way—the numbers shown in those graphs are grossly skewed by a complete lack of any real alternative. If I want to make a new button to put in the document, the first thing my JS programming experience tells me: new Button(); But I live in the bad old days (assuming my children won't have to use garbage APIs to program the web) and my reality is still here: document.createElement(button); This indicates nothing about state or initialization. And of course developers are going to fill out a survey and say they use this API—there isn't any other API to use! It would be awkward to have a few new Image() or new Option() expressions sprinkled around your code—unless all element instantiation looked like that, then it would be the status quo and that survey would have very different results. - * Alex Russell have been advocating that WebIDL should be allow constructor-like interfaces* * * *Absolutely agree. But these are horns of this dilemma.* * * * #4 has been accepted for ES6 by all TC39 participants* * * *Yes, I believe this is a timing issue. I am told it will be a long time before #4 is practical.* Yes, it will be along time, especially for IE9 and 10 (read: never), which are support targets for custom element polyfills. Reliance on anything that is optional or future should be avoided for the custom element base case. Right now the polyfills for document.register(), and a few of the declarative proposals, can give developers these awesome APIs today - please, do not imperil this. And progress suffers. Rick
Re: [webcomponents]: Of weird script elements and Benadryl
On Sun, Apr 14, 2013 at 3:46 PM, Daniel Buchner dan...@mozilla.com wrote: * Here are four ways to avoid the subclassing problem for custom elements * * 1) Only allow instances of custome dom elements to be instantiated using document.createElement(x-foo). * * * *Wearing web developer hat, I never make elements any other way than createElement (or HTML), so this would be standard operating procedure, so that's all good if we can get buy in.* As long as the above supports all other DOM element creation vectors (innerHTML, outerHTML, etc), then this is fine. Practically speaking, if it so happened that custom elements could *never *be instantiated with constructors, developers on the web today wouldn't shed a tear, they use doc.createElement(), not constructors -- https://docs.google.com/forms/d/16cNqHRe-7CFRHRVcFo94U6tIYnohEpj7NZhY02ejiXQ/viewanalytics - * Alex Russell have been advocating that WebIDL should be allow constructor-like interfaces* * * *Absolutely agree. But these are horns of this dilemma.* * * * #4 has been accepted for ES6 by all TC39 participants* * * *Yes, I believe this is a timing issue. I am told it will be a long time before #4 is practical.* Yes, it will be along time, especially for IE9 and 10 (read: never), which are support targets for custom element polyfills. Reliance on anything that is optional or future should be avoided for the custom element base case. Right now the polyfills for document.register(), and a few of the declarative proposals, can give developers these awesome APIs today - please, do not imperil this. After reading Scott Miles' post here http://lists.w3.org/Archives/Public/public-webapps/2013AprJun/0209.html, I have a better understanding of problem caused by these generated HTML*Element constructors: they aren't constructable. No amount of ES6 subclass support will fix that problem. The platforms need to make them constructable—and that can't be polyfilled. I also now understand why such great lengths have been taken to hack around the problem, and the resulting solution with bolt-on ready* callbacks (that aren't really callbacks, just prototype methods that will be called after some turn of execution has initialized some element state) as stand-ins for the real constructor function. This is somehow ok because it's polyfillable? Rick
Re: [webcomponents]: Of weird script elements and Benadryl
This is somehow ok because it's polyfillable? The polyfill thing is a red-herring, let's not cloud the issue. The platforms need to make them constructable Agreed, but the estimates are months or years to make it so, which is too long to block these features. hack around the problem Many good people have been trying to solve this over-constrained problem for months. I don't think this is a fair characterization. bolt-on ready* callbacks The 'callback' naming and semantics were the result of a long debate. Can you make your objections clearer? Also, please refer to this thread http://lists.w3.org/Archives/Public/public-webapps/2013JanMar/0728.html for more information about 'readyCallback' in particular. On Sun, Apr 14, 2013 at 2:35 PM, Rick Waldron waldron.r...@gmail.comwrote: On Sun, Apr 14, 2013 at 3:46 PM, Daniel Buchner dan...@mozilla.comwrote: * Here are four ways to avoid the subclassing problem for custom elements * * 1) Only allow instances of custome dom elements to be instantiated using document.createElement(x-foo). * * * *Wearing web developer hat, I never make elements any other way than createElement (or HTML), so this would be standard operating procedure, so that's all good if we can get buy in.* As long as the above supports all other DOM element creation vectors (innerHTML, outerHTML, etc), then this is fine. Practically speaking, if it so happened that custom elements could *never *be instantiated with constructors, developers on the web today wouldn't shed a tear, they use doc.createElement(), not constructors -- https://docs.google.com/forms/d/16cNqHRe-7CFRHRVcFo94U6tIYnohEpj7NZhY02ejiXQ/viewanalytics - * Alex Russell have been advocating that WebIDL should be allow constructor-like interfaces* * * *Absolutely agree. But these are horns of this dilemma.* * * * #4 has been accepted for ES6 by all TC39 participants* * * *Yes, I believe this is a timing issue. I am told it will be a long time before #4 is practical.* Yes, it will be along time, especially for IE9 and 10 (read: never), which are support targets for custom element polyfills. Reliance on anything that is optional or future should be avoided for the custom element base case. Right now the polyfills for document.register(), and a few of the declarative proposals, can give developers these awesome APIs today - please, do not imperil this. After reading Scott Miles' post here http://lists.w3.org/Archives/Public/public-webapps/2013AprJun/0209.html, I have a better understanding of problem caused by these generated HTML*Element constructors: they aren't constructable. No amount of ES6 subclass support will fix that problem. The platforms need to make them constructable—and that can't be polyfilled. I also now understand why such great lengths have been taken to hack around the problem, and the resulting solution with bolt-on ready* callbacks (that aren't really callbacks, just prototype methods that will be called after some turn of execution has initialized some element state) as stand-ins for the real constructor function. This is somehow ok because it's polyfillable? Rick
Re: [webcomponents]: Of weird script elements and Benadryl
On Apr 13, 2013 8:57 PM, Daniel Buchner dan...@mozilla.com wrote: @Rick - if we generated a constructor that was in scope when the script was executed, there is no need for rebinding 'this'. I'd gladly ditch the rebinding in favor of sane, default, generated constructors. I think we need someone to summarize where we are at this point :) Is anyone besides scott in favor of the 2) Invent a new element specifically for the purpose of defining prototypes For the record, i am not.
Re: [webcomponents]: Of weird script elements and Benadryl
@Scott - interesting, but there are valid reasons for having access to the global scope/document: - Components that benefit from top-level delegation - Components that need to analyze their destination environment before codifying their definition Know what I mean? On Fri, Apr 12, 2013 at 2:25 PM, Scott Miles sjmi...@google.com wrote: I realize this doesn't fit any existing conceptual model (that I know of) but I think it's worth pointing out that all we really want to do is define a prototype for the element (as opposed to running arbitrary script). Invented pseudo-code (not a proposal, just trying to identify a mental model): element name=x-foo extends=something !-- prototype for markup -- template template !-- prototype for instances -- prototype readyCallback: function() { }, someApi: function() { }, someProperty: null /prototype /element On Fri, Apr 12, 2013 at 2:13 PM, Erik Arvidsson a...@chromium.org wrote: Daniel, what happens in this case? element name=x-foo script class XFoo extends SVGElement { } /script /element This points out 2 short comings with your proposal. 1. This would just replace the global constructor. That might be OK, and we can detect this override to register the class as needed. 2. Prefixing with HTML seems like an anti pattern. On Fri, Apr 12, 2013 at 5:08 PM, Daniel Buchner dan...@mozilla.comwrote: @John - what about what I just sent through? It hops over the magical rebinding issue (or so I think), your thoughts? On Fri, Apr 12, 2013 at 2:06 PM, John J Barton johnjbar...@johnjbarton.com wrote: Some suggestions: On Fri, Apr 12, 2013 at 12:30 PM, Dimitri Glazkov dglaz...@google.comwrote: ... or How the heck do we initialize custom elements in declarative syntax? There were good questions raised about the nature of script element in the platonic form thread. Consider this syntax: element name=foo-bar element constructor=FooBar script .../script template ... /template /element The way element should work is like this: a) when /element is seen b) generate a constructor for this element b) call the nominated ctor, new FooBar(elt). I'm unclear on the practical advantages the instance inheriting from HTMLElement (new FooBar(), prototype inherits) vs manipulating the element from the outside (new FooBar(elt), prototype Object). b) run document.register c) run initialization code As I see it, the problem is twofold: 1) The script element timing is weird. Since script is initialization code, it has to run after the /element is seen. This is already contrary to a typical script element expectations. Why? new FooBar() has to be called, but the outer init is anytime before that. 2) The script element needs a way to refer to the custom element prototype it is initializing. Enclosing it in a function and calling it with element as |this| seemed like a simplest thing to do, but Rick and John had allergic reactions and had to be hospitalized. For me its the implicit declarative binding + wired in to 'this' that makes the original solution very magical and inflexible. I can understand ensuring that a component can be self-contained, but cannot understand why it needs an ordered and hierarchical when script isn't rendered. So far, I haven't seen any other workable alternatives. TC39 peeps and others, help me find them. Thanks for asking ;-) :DG -- erik
Re: [webcomponents]: Of weird script elements and Benadryl
On Fri, Apr 12, 2013 at 7:14 PM, Dimitri Glazkov dglaz...@google.comwrote: On Fri, Apr 12, 2013 at 3:56 PM, Rick Waldron waldron.r...@gmail.com wrote: On Fri, Apr 12, 2013 at 6:52 PM, Dimitri Glazkov dglaz...@google.com Can you point me to some concrete example, docs, implementation, code (anything) that I might gain some insight into these generated constructors you speak of? Thanks :) Spec: https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#elements-and-dom-interfaces Implementation in Blink/WebKit: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/WebCore/dom/CustomElementConstructor.h Implementation in Mozilla: https://hg.mozilla.org/integration/mozilla-inbound/diff/871fea464883/content/base/src/nsDocument.cpp#l1.245 Hope this helps! This does help, but at the moment I can't think of a solution to your earlier con point. Thanks for the info! Rick :DG
Re: [webcomponents]: Of weird script elements and Benadryl
On Fri, Apr 12, 2013 at 3:56 PM, Rick Waldron waldron.r...@gmail.com wrote: On Fri, Apr 12, 2013 at 6:52 PM, Dimitri Glazkov dglaz...@google.com Can you point me to some concrete example, docs, implementation, code (anything) that I might gain some insight into these generated constructors you speak of? Thanks :) Spec: https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#elements-and-dom-interfaces Implementation in Blink/WebKit: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/WebCore/dom/CustomElementConstructor.h Implementation in Mozilla: https://hg.mozilla.org/integration/mozilla-inbound/diff/871fea464883/content/base/src/nsDocument.cpp#l1.245 Hope this helps! :DG
Re: [webcomponents]: Of weird script elements and Benadryl
On Fri, Apr 12, 2013 at 3:20 PM, Dimitri Glazkov dglaz...@google.comwrote: 2) since we do have to live with generated constructors -- at least for a little while, we have two decoupled operations: a) create prototype b) generate constructor. Is this order required? Can we not generate the constructor, then let the developer modify it using the same means they have since the beginning of time - or if *they choose*, use slick ES6 syntax?
Re: [webcomponents]: Of weird script elements and Benadryl
On Fri, Apr 12, 2013 at 2:25 PM, Scott Miles sjmi...@google.com wrote: I realize this doesn't fit any existing conceptual model (that I know of) but I think it's worth pointing out that all we really want to do is define a prototype for the element (as opposed to running arbitrary script). Invented pseudo-code (not a proposal, just trying to identify a mental model): element name=x-foo extends=something !-- prototype for markup -- template template !-- prototype for instances -- prototype readyCallback: function() { }, someApi: function() { }, someProperty: null /prototype /element This is actually pretty close to implementation element in XBL2 (http://dev.w3.org/2006/xbl2/#the-implementation-element). I was really hoping to avoid inventing another element whose content is script. But you can sort of see the |this| hack is an extraction of implementation. :DG