Re: alternate view on constructors for custom elements
> On Jul 17, 2015, at 1:14 PM, Travis Leithead > wrote: > > From: Domenic Denicola [mailto:d...@domenic.me] > >>> window.XFoo = document.registerElement(‘x-foo’, XFooStartup); >> >> Why is XFoo different from XFooStartup? If I define a method in XFooStartup, >> does it exist in XFoo? > > This won't work as I described it, given what you've told me, but my > assumption was essentially, that XFooStartup would act as if it didn't really > depend on HTMLElement for construction. So, it's constructor wouldn't be > linked to the actual custom element creation. Therefore XFoo (the > platform-provided constructor function is the thing that is actually used to > trigger construction, which would then result in the XFooStartup constructor > running. Basically, like this (reverting to non-class syntax): > > function XFooStartup(val1, val2) { > this.prop = val1; > this.prop2 = val2; > } > window.XFoo = document.registerElement(‘x-foo’, XFooStartup); > > all I was trying to express different from the current design is: > 1) replacing the createdCallback with the function constructor (and passing > the new element instance as 'this' when calling it) > 2) passing through params from the XFoo platform-native constructor to the > XFooStartup function > 3) calling XFooStartup synchronously We can do this without wrapping author supplied constructor. In ES6/ES2015 classes, `this` variable is in the temporary dead zone (TDZ) until `super()` which allocates `this` and any attempt to access it will throw `ReferenceError`. In other words, XFooStartup has no way of accessing the newly constructed object until `super()` has returned. This in turns allows browser engines to create a native (C++) backing store for the HTML element inside HTMLElement’s constructor (or an equivalent code that runs as a part of call to `super()` from the direct subclass of HTMLElement) since the newly constructed (this) element is never accessed until the highest superclass' `super()` (which is HTMLElement in this case) had been called. - R. Niwa
RE: alternate view on constructors for custom elements
From: Travis Leithead [mailto:travis.leith...@microsoft.com] > if super() is absolutely required for a constructor in a class > that extends something, is there a requirement about when in the > constructor method it be invoked? Must it always be the first call? Can it be > later on, say at the end of the function? It must be before `this` is referenced. > Basically, like this (reverting to non-class syntax): Yeah, and at that point you might as well make it a method on the actual class, and give it a nice name, like, say, createdCallback ;). Or, make it a function that takes the element as a parameter, and keep it separate from the class, perhaps in a "hooks" object ;).
RE: alternate view on constructors for custom elements
From: Domenic Denicola [mailto:d...@domenic.me] > >From: Travis Leithead [mailto:travis.leith...@microsoft.com] > >> Something magical happens here. The use of super() is supposed to call the >> constructor of the HTMLElement class—but that’s not a normal JS class. It >> doesn’t have a defined constructor() method [yet?]. > >Yep. We'd need to define one; it's absolutely required. ES2015 classes that >don't call super() in their constructor simply aren't allowed, which means >inheriting from a constructor that throws (like HTMLElement currently does) is >impossible. > >https://github.com/domenic/element-constructors is a start at this. Hmm. This does help. A lot. I wasn't aware that ES2015 classes added all these restrictions on top of the syntactic sugar over the classing function technique. Now I have some study to do to catch up. One question though before I do that: if super() is absolutely required for a constructor in a class that extends something, is there a requirement about when in the constructor method it be invoked? Must it always be the first call? Can it be later on, say at the end of the function? >I take it when you said in [1]: > > I've discussed this issue with some of Edge's key parser developers. From a > technical ground, we do not have a problem with stopping the parser to > callout to author code in order to run a constructor, either during parsing > or cloning. For example, in parsing, I would expect that the callout happens > after initial instance creation, but before the target node is attached to > the DOM tree by the parser. > >you were not aware of this? Maybe now you better understand my follow-up >question in [2], Yep. :-| >> window.XFoo = document.registerElement(‘x-foo’, XFooStartup); > >Why is XFoo different from XFooStartup? If I define a method in XFooStartup, >does it exist in XFoo? This won't work as I described it, given what you've told me, but my assumption was essentially, that XFooStartup would act as if it didn't really depend on HTMLElement for construction. So, it's constructor wouldn't be linked to the actual custom element creation. Therefore XFoo (the platform-provided constructor function is the thing that is actually used to trigger construction, which would then result in the XFooStartup constructor running. Basically, like this (reverting to non-class syntax): function XFooStartup(val1, val2) { this.prop = val1; this.prop2 = val2; } window.XFoo = document.registerElement(‘x-foo’, XFooStartup); all I was trying to express different from the current design is: 1) replacing the createdCallback with the function constructor (and passing the new element instance as 'this' when calling it) 2) passing through params from the XFoo platform-native constructor to the XFooStartup function 3) calling XFooStartup synchronously
Re: alternate view on constructors for custom elements
On 7/17/15 2:03 PM, Travis Leithead wrote: Something magical happens here. The use of super() is supposed to call the constructor of the HTMLElement class—but that’s not a normal JS class. It doesn’t have a defined constructor() method Sure, but neither does Array. What super() actually does is get the prototype of the current constructor and call it. So in your case: class CustomElement extends HTMLElement { constructor() { super(); } } it would call the HTMLElement constructor. Now there's a slight problem here, which is that HTMLElement is not defined to have a constructor in the spec right now. We need to fix that, clearly, for this subclassing of elements with constructors stuff to make sense. Also, as has been pointed out, running the CustomElement constructor code _/before/_ instantiating the actual element (at parse-time for example) I'm not sure what "before" means here. In the hypothetical world in which we call the CustomElement constructor from the parser, the parser would do that, and get back an object. That would be the "actual element". ·Javascript classes are mutable—what if CustomElement’s proto chain is mutated later? Then you get something that may not be an HTMLElement when you construct via it. Obviously consumers who care (like the parser, perhaps; though it may only care about getting Element) would need to check and handle that problem. 1.Native [internal] element is created with appropriate tag name, attributes, etc. 2.JS constructor is called and provided the instance (as ‘this’) The only problem with that is what Anne pointed out: there are some proposed ES spec additions that would require that the initial JS object allocation take the subclassing bits into account to determine which immutable state it's preallocated with. Note that I'm not convinced that means we need to call JS from the parser; just that's the problem Anne is trying to solve. Need to chew a bit on your XFooStartup proposal before I can comment on it intelligently. -Boris
Two new custom elements ideas
Hi all, Over the last few days I’ve worked on two new potential ideas for custom elements, hoping to shake things up with new possibilities. These are both largely geared around how we react to the key custom elements question [1]. https://github.com/w3c/webcomponents/blob/gh-pages/proposals/Optional-Upgrades-Optional-Constructors.md : this proposal assumes we come out in favor of running author code during parsing/cloning/editing/etc. It allows component authors to choose between using constructors, thus disallowing their components to be used with server-side rendering/progressive enhancement, and using a createdCallback-style two-stage initialization, which will then allow progressive enhancement. It is meant explicitly as a compromise proposal, similar in spirit to the { mode: "open"/"closed" } proposal, since we know different parties have different values and the way forward may be to simply accommodate both value systems and let developers light a path. https://github.com/w3c/webcomponents/blob/gh-pages/proposals/Parser-Created-Constructors.md : this proposal assumes we do not achieve consensus to run author code during parsing/cloning/editing/etc. It recognizes that, if we disallow this, we cannot allow custom constructors, and then tries to make the best of that world. In particular, it is an alternative to the “Dmitry” proposal, designed to entirely avoid the dreaded proto-swizzling, while still having many of the same benefits. If you scroll to the bottom, you note how it also leaves the door open for future custom constructors, if we decide that it's something that we want in the future, but simply cannot afford to specify or implement right now due to how hard that is. In this sense it's meant somewhat as a bridging proposal, similar in spirit to the slots proposal, which falls short of the ideal imperative distribution API but will probably work for most developers anyway. These are largely meant to get ideas moving, and to avoid polarizing the discussion into two camps. As I noted in [2], there are several degrees of freedom here; the key custom elements question is distinct from upgrades, which is distinct from ES2015 class syntax, which is distinct from constructor vs. created lifecycle hook, etc. The possibility space is pretty varied, and we have multiple tools in our toolbox to help arrive at a resolution that everyone finds agreeable. Comments are of course welcome, and if you have time to read these before the F2F that would be really appreciated. Thanks, -Domenic [1]: https://lists.w3.org/Archives/Public/public-webapps/2015JulSep/0159.html [2]: https://lists.w3.org/Archives/Public/public-webapps/2015JulSep/0162.html
RE: alternate view on constructors for custom elements
From: Travis Leithead [mailto:travis.leith...@microsoft.com] > Something magical happens here. The use of super() is supposed to call the > constructor of the HTMLElement class—but that’s not a normal JS class. It > doesn’t have a defined constructor() method [yet?]. Yep. We'd need to define one; it's absolutely required. ES2015 classes that don't call super() in their constructor simply aren't allowed, which means inheriting from a constructor that throws (like HTMLElement currently does) is impossible. https://github.com/domenic/element-constructors is a start at this. > I’m trying to rationalize the custom elements previous design with the use of > constructors. Basically, I think it should still be a two-stage creation > model: > 1. Native [internal] element is created with appropriate tag name, > attributes, etc. > 2. JS constructor is called and provided the instance (as ‘this’) > > #1 is triggered by the parser, or by a native constructor function. That > constructor function could either be provided separately like it is returned > from registerElement today, or in some other way (replacing the original > constructor?). Since replacing the original constructor sounds weird and > probably violates a bunch of JS invariants, I’ll assume sticking with the > original model. > > This makes it much safer for implementations, since the native custom element > can always be safely created first, before running JS code. It also means > there’s no magic super() at work—which seems to leave too much control up to > author code to get right. Ah! This is a big mistake!! You simply cannot do this split with ES2015 classes. ES2015 classes are predicated on the idea that construction is an atomic operation, consisting of both allocation and initialization in one step. As such, class constructors cannot be called, only `new`ed. You cannot apply them with an already-created `this`, as if they were methods. This is fundamental to the class design; any other model needs to fall back to simply functions, not classes. Indeed, the currently-specced design had a two-stage model---allocation/base initialization by the UA-generated constructor returned by document.registerElement, and author-controlled initialization by createdCallback(). This separation is, as you point out, makes things safer and easier to specify. And it is absolutely impossible to achieve if you insist on custom constructors, because in that case all allocation and initialization must happen together atomically. If we allow custom constructors, the allocation and initialization must both happen with a synchronous call to the custom constructor (which itself must call super()). I take it when you said in [1]: > I've discussed this issue with some of Edge's key parser developers. From a > technical ground, we do not have a problem with stopping the parser to > callout to author code in order to run a constructor, either during parsing > or cloning. For example, in parsing, I would expect that the callout happens > after initial instance creation, but before the target node is attached to > the DOM tree by the parser. you were not aware of this? Maybe now you better understand my follow-up question in [2], > Can you expand on this more? In particular I am confused on how "initial > instance creation" can happen without calling the constructor. [1]: https://lists.w3.org/Archives/Public/public-webapps/2015JulSep/0161.html [2]: https://lists.w3.org/Archives/Public/public-webapps/2015JulSep/0162.html > Basic example of what I’m thinking: > > class XFooStartup extends HTMLElement { > constructor(val1, val2) { > this.prop = val1; > this.prop2 = val2; This is invalid at runtime, since it fails to call super(). > } > } > window.XFoo = document.registerElement(‘x-foo’, XFooStartup); Why is XFoo different from XFooStartup? If I define a method in XFooStartup, does it exist in XFoo? > // (1) > var x1 = new XFooStartup(“first”, “second”); > // (2) > var x2 = new XFoo(“first”, “second”); > > Calling (1) does not create a custom element. Extending from HTMLElement is > not magical, it’s just a prototype inheritance, as can be done today. super() > would do whatever super() does when the super class has no defined method to > invoke. (It would throw, in other words.) > x1 is a regular JS object with a .prop and .prop2. This can't be true. Either x1 doesn't exist, because you didn't call super() and so `new XFooStartup` threw. Or x1 called super(), and it is no longer an ordinary JS object, because by calling super() (which is basically shorthand for `this = new super()`) you have made sure that it is a true allocated-and-initialized-by-the-UA HTMLElement. > Calling (2) runs the platform-provided constructor function which internally > inits a new HTMLElement in the C++ (or could be Element if in XML document?). > Then the platform immediately (synchronously) invokes the provided > construc
alternate view on constructors for custom elements
OK, after reading Dominic's proposal [1], I'm a little confused. I thought that I understood how constructors should work, but there's some magic going on that I can't follow... I'm sure you folks can help. ``` class CustomElement extends HTMLElement { constructor() { super(); } } Something magical happens here. The use of super() is supposed to call the constructor of the HTMLElement class-but that's not a normal JS class. It doesn't have a defined constructor() method [yet?]. Also, as has been pointed out, running the CustomElement constructor code _before_ instantiating the actual element (at parse-time for example) opens up a world of potential problems as have been explored: *Javascript classes are mutable-what if CustomElement's proto chain is mutated later? *What if the constructor throws? ...just to name a few. I'm trying to rationalize the custom elements previous design with the use of constructors. Basically, I think it should still be a two-stage creation model: 1. Native [internal] element is created with appropriate tag name, attributes, etc. 2. JS constructor is called and provided the instance (as 'this') #1 is triggered by the parser, or by a native constructor function. That constructor function could either be provided separately like it is returned from registerElement today, or in some other way (replacing the original constructor?). Since replacing the original constructor sounds weird and probably violates a bunch of JS invariants, I'll assume sticking with the original model. This makes it much safer for implementations, since the native custom element can always be safely created first, before running JS code. It also means there's no magic super() at work-which seems to leave too much control up to author code to get right. Basic example of what I'm thinking: class XFooStartup extends HTMLElement { constructor(val1, val2) { this.prop = val1; this.prop2 = val2; } } window.XFoo = document.registerElement('x-foo', XFooStartup); // (1) var x1 = new XFooStartup("first", "second"); // (2) var x2 = new XFoo("first", "second"); Calling (1) does not create a custom element. Extending from HTMLElement is not magical, it's just a prototype inheritance, as can be done today. super() would do whatever super() does when the super class has no defined method to invoke. x1 is a regular JS object with a .prop and .prop2. Calling (2) runs the platform-provided constructor function which internally inits a new HTMLElement in the C++ (or could be Element if in XML document?). Then the platform immediately (synchronously) invokes the provided constructor function as if: XFooStartup.apply(newHTMLElementInstance, argsPassedThroughFromCall); so that XFooStartup's constructor operates on the 'this' being the instance created by the platform. [1] https://github.com/w3c/webcomponents/blob/gh-pages/proposals/Optional-Upgrades-Optional-Constructors.md
Re: The key custom elements question: custom constructors?
On 7/17/15 12:05 PM, Anne van Kesteren wrote: True, but either way this doesn't seem like a problem. You can create a DocumentFragment, insert a new , and then let it be GC'd, today. Sure. In practice it won't get GC'd until the load completes, which is sucky, but that's life. -Boris
Re: The key custom elements question: custom constructors?
On Fri, Jul 17, 2015 at 5:47 PM, Boris Zbarsky wrote: > On 7/17/15 10:38 AM, Anne van Kesteren wrote: >> If I look at "update the image data" step 6 it seems it might be >> fetched at a later point? > > Yes, but in practice the fetch will go ahead, no? There's nothing to > prevent it from happening, so it's going to happen once you reach a stable > state... True, but either way this doesn't seem like a problem. You can create a DocumentFragment, insert a new , and then let it be GC'd, today. -- https://annevankesteren.nl/
Re: The key custom elements question: custom constructors?
On 7/17/15 10:38 AM, Anne van Kesteren wrote: If I look at "update the image data" step 6 it seems it might be fetched at a later point? Yes, but in practice the fetch will go ahead, no? There's nothing to prevent it from happening, so it's going to happen once you reach a stable state... -Boris
Re: The key custom elements question: custom constructors?
On Fri, Jul 17, 2015 at 4:15 PM, Domenic Denicola wrote: > From: Anne van Kesteren [mailto:ann...@annevk.nl] >> It fails atomically, based on the definition of innerHTML. > > What if that 512 KiB of HTML contains ? Following > definitions, I assume we fire off the network request? If I look at "update the image data" step 6 it seems it might be fetched at a later point? > What if it contains a where XBaz's constructor does > `document.body.innerHTML = "Hello"`? Can the parsing algorithm deal > with the (following the definitions, required) re-entrancy? I think the specification can, since it just invokes the fragment parser with some parameters and then replaces the contents of XBaz with the obtained DocumentFragment. Implementations probably can too. E.g., document.body.innerHTML = "..." is quite similar. -- https://annevankesteren.nl/
RE: The key custom elements question: custom constructors?
From: Anne van Kesteren [mailto:ann...@annevk.nl] >> // What about >> document.body.innerHTML = "[512 KiB of normal HTML] "; >> // ? does the HTML make it in, or does the operation fail atomically, or >> something else? > > It fails atomically, based on the definition of innerHTML. What if that 512 KiB of HTML contains ? Following definitions, I assume we fire off the network request? What if it contains a where XBaz's constructor does `document.body.innerHTML = "Hello"`? Can the parsing algorithm deal with the (following the definitions, required) re-entrancy?
[Bug 28614] Weaken the requirement of the time of running async steps
https://www.w3.org/Bugs/Public/show_bug.cgi?id=28614 Anne changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |WORKSFORME --- Comment #7 from Anne --- Yeah, Philip is correct. Resize can already take any amount of time. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug 27162] Browser differences in graphical layout of fullscreen mode.
https://www.w3.org/Bugs/Public/show_bug.cgi?id=27162 Anne changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |WORKSFORME -- You are receiving this mail because: You are on the CC list for the bug.
Re: Informal Service Worker working session
Thanks everyone! Started a draft agenda page here; please pile in! https://github.com/slightlyoff/ServiceWorker/wiki/july_20_2015_meeting_agenda On Wed, Jul 15, 2015 at 10:38 PM, Benjamin Kelly wrote: > On Sat, Jul 4, 2015 at 7:26 AM, Alex Russell > wrote: > >> As many SW participants are going to be in town for the WebApps F2F on >> the 21st, Google San Francisco is hosting a working day, 9am-5pm PST on >> July 20th to work through open issues and discuss future work. >> >> If you're attending, or would like to, simply RSVP here: >> http://doodle.com/hqm3ga8pfepidy7r >> > > Alex, > > Thanks for hosting! > > In preparation for the meeting we've come up with a rough list of things > we'd like to discuss next week: > > - Clarify behavior in places where the fetch spec has not been integrated > into other specs yet. For example, intercepting something that is > currently same-origin with a synthetic or CORS response, how interception > works with CSP, etc. Clearly Chrome has done something for these cases and > we'd like to be compatible where possible. > - Consider adding a "foreign fetch" feature to communicate with a SW on a > different origin. Straw man of the concept can be found at > https://wiki.whatwg.org/wiki/Foreign_Fetch . > - Discuss navigator.connect(). In particular, can the use cases > motivating navigator.connect() be satisfied with a simpler solution like > the "foreign fetch" concept. > - Discuss how to make it easier to use multiple service workers for the > same site. For example, currently its difficult to update two service > workers coherently. One will always be a newer version than the other. > - Discuss how to handle heavy-weight processing for things like > background sync without introducing fetch event latency. This could be > using multiple service workers (with issues above addressed) or possible > supporting SharedWorker, etc. > - Consider using the service worker script URL to identify the service > worker instead of its scope. This would move us closer to not requiring a > scope for service workers that aren't handling fetch events. > - Consider allowing specific features, like fetch and push, to be > specified at registration time. Again, the goal is to get away from the > current situation where registering a service worker immediately implies > fetch event handling. > - Consider providing an API for creating a service worker without going > through the installation life cycle. > - Share information about how we plan to avoid abuse of push and > background sync events. > > Anyway, we just wanted to give people a chance to think about some of this > before we meet. Obviously we may not have time to cover all of this in a > day, but it would be nice to cover any contentious bits. > > Thanks again and see you all next week. > > Ben >
Re: The key custom elements question: custom constructors?
On Thu, Jul 16, 2015 at 10:36 PM, Domenic Denicola wrote: > I have a related question: what happens if the constructor throws? Right, this is the kind of thing we need to figure out. > > > "use strict"; > > window.throwingMode = true; > > class XFoo extends HTMLElement { > constructor() { > if (window.throwingMode) { > throw new Error("uh-oh!"); > } > } > } > > document.registerElement("x-foo", XFoo); > > > > >