Re: [webcomponents] Proposal for Cross Origin Use Case and Declarative Syntax
On Nov 12, 2013, at 8:12 AM, Dimitri Glazkov dglaz...@chromium.org wrote: On Sun, Nov 10, 2013 at 6:49 PM, Arthur Barstow art.bars...@nokia.com wrote: On 11/9/13 3:24 AM, ext Ryosuke Niwa wrote: Hi all, We have been discussing cross-orign use case and declarative syntax of web components internally at Apple, and here are our straw man proposal to amend the existing Web Components specifications to support it. *1. Modify HTML Imports to run scripts in the imported document itself* This allows the importee and the importer to not share the same script context, etc… This could be an option and shouldn’t be the default. I don’t think we want to add a yet another flag to control the behavior. By running scripts in a different context, we are ejecting the primary use case of enabling frameworks/libraries to better manage their assets and dependencies (aka the Bootstrap use case). That would force same-origin and cross-origin use cases to have different behaviors because we can’t run the untrusted script in the host document. In particular, it’s important for the global (window) object to have a consistent behavior between untrusted cross-origin and trusted same-origin use cases. Rob Dodson’s article has a nice progression explaining the use case: http://robdodson.me/blog/2013/08/20/exploring-html-imports/ I don’t think this blog post contains any argument for either behavior. Also, check out newly minted Eric Bidelman's article on imports (especially the use cases section at the bottom): http://www.html5rocks.com/en/tutorials/webcomponents/imports/ I see the following argument for the current behavior: Script in the import is executed in the context of the window that contains the importingdocument. So window.document refers to the main page document. This has two useful corollaries: functions defined in an import end up on window. you don't have to do anything crazy like append the import's script blocks to the main page. Again, script gets executed. What we’re proposing is to execute the script in the imported document so the only real argument is the point that “functions defined in an imported end up on window” (of the host document). I think that’s a bad thing. We don’t want imported documents to start polluting global scope without the user explicitly importing them. e.g. import X in Python doesn’t automatically import stuff inside the module into your global scope. To do that, you explicitly say “import * from X”. Similarly, “using std” is discouraged in C++. I don’t think the argument that this is how external script and stylesheet fly either because the whole point of web components is about improving the modularity and reusability of the Web. Re: Custom Elements LC, this is an issue to handle in HTML Imports specification, not related to Custom Elements. *2. Add “importcomponents content attribute on link element* It defines the list of custom element tag names to be imported from the imported HTML document. e.g. link rel=import href=~ importcomponents=tag-1 tag-2 will export custom elements of tag names tag-1 and tag-2 from ~. Any name that didn't have a definition in the import document is ignored (i.e. if tag-2 was not defined in ~, it would be skipped but tag-1 will be still imported). This mechanism prevents the imported document from defining arbitrary components in the host document. Re: Custom Elements LC, this should be handled in HTML Imports specification. HTML Imports can rely on Custom Elements specification. Any additional hooks that could be needed to facilitate this feature could be added in Custom Elements Level 2 specification. *3. Support static (write-once) binding of a HTML template* e.g. template id=cardTemplateName: {{name}}brEmail:{{email}}/template script document.body.appendChild(cardTemplate.instantiate({name: Ryosuke Niwa, email:rn...@webkit.org mailto:rn...@webkit.org})); /script This seems very similar to the Rafael Weinstein's MDV work. You guys should collaborate :) Yes, we had an informal discussion about it a couple of weeks ago, and we’re interested in continuing our discussion with him on public-webapps. Re: Custom Elements LC, this is unrelated to specification. *4. Add “interface content attribute to template element* This content attribute specifies the name of the JavaScript constructor function to be created in the global scope. The UA creates one and will be used to instantiate a given custom element. The author can then setup the prototype chain as needed: template defines=name-card interface=NameCardElement Name: {{name}}brEmail:{{email}} /template script NameCardElement.prototype.name = function () {...} NameCardElement.prototype.email = function () {...} /script This is similar to doing: var NameCardElement = document.register(’name-card'); This is another take on the declarative custom elements (a variant
Re: [webcomponents] Proposal for Cross Origin Use Case and Declarative Syntax
On Tue, Nov 12, 2013 at 12:45 AM, Ryosuke Niwa rn...@apple.com wrote: [...] - Script in the import is executed in the context of the window that contains the importingdocument. So window.document refers to the main page document. This has two useful corollaries: - functions defined in an import end up on window. - you don't have to do anything crazy like append the import's script blocks to the main page. Again, script gets executed. What we’re proposing is to execute the script in the imported document so the only real argument is the point that “functions defined in an imported end up on window” (of the host document). I think that’s a bad thing. We don’t want imported documents to start polluting global scope without the user explicitly importing them. e.g. import X in Python doesn’t automatically import stuff inside the module into your global scope. To do that, you explicitly say “import * from X”. Similarly, “using std” is discouraged in C++. I don’t think the argument that this is how external script and stylesheet fly either because the whole point of web components is about improving the modularity and reusability of the Web. What you're proposing breaks a primary use case of: link rel=import href=//apis.google.com/jquery-ui.html Authors don't want to list every single component from jQuery UI in the import directive, and they don't want the jQuery UI logic to be in a different global object. They want to be able to import jQuery UI and have it transitively import jQuery thus providing $ in the window in addition to all the widgets and their API. ex. body.appendChild(new JQUIPanel()).showPanel(). Note also that using a different global produces craziness like Array being different or the prototypes of nodes being different. You definitely don't want that for the same origin or CORS use case. Fortunately, there is already a boundary that we built that might be just the right fit for this problem: the shadow DOM boundary. A while back, we had lunch with Mozilla security researchers who were interested in harnessing the power of Shadow DOM, and Elliott (cc'd) came up with a pretty nifty proposal called the DOMWorker. I nagged him and he is hopefully going to post it on public-webapps. I am pretty sure that his proposal can address your use case and not cripple the rest of the spec in the process. Assuming you’re referring to https://docs.google.com/document/d/1V7ci1-lBTY6AJxgN99aCMwjZKCjKv1v3y_7WLtcgM00/edit, the security model of our proposal is very similar. All we’re doing is using a HTML-imported document instead of a worker to isolate the cross-origin component. Since we don’t want to run the cross-origin component on a separate thread, I don’t think worker is a good model for cross-origin components. A DOMWorker doesn't run on another thread, see the Note in the introduction. - E
Re: [webcomponents] Proposal for Cross Origin Use Case and Declarative Syntax
I'm not sure I would want jQuery UI to pollute the window object with $, with ES6 modules around the corner it seems like a step backwards for imports to start polluting window objects with their libraries... On Tue, Nov 12, 2013 at 9:01 PM, Elliott Sprehn espr...@gmail.com wrote: On Tue, Nov 12, 2013 at 12:45 AM, Ryosuke Niwa rn...@apple.com wrote: [...] Script in the import is executed in the context of the window that contains the importingdocument. So window.document refers to the main page document. This has two useful corollaries: functions defined in an import end up on window. you don't have to do anything crazy like append the import's script blocks to the main page. Again, script gets executed. What we’re proposing is to execute the script in the imported document so the only real argument is the point that “functions defined in an imported end up on window” (of the host document). I think that’s a bad thing. We don’t want imported documents to start polluting global scope without the user explicitly importing them. e.g. import X in Python doesn’t automatically import stuff inside the module into your global scope. To do that, you explicitly say “import * from X”. Similarly, “using std” is discouraged in C++. I don’t think the argument that this is how external script and stylesheet fly either because the whole point of web components is about improving the modularity and reusability of the Web. What you're proposing breaks a primary use case of: link rel=import href=//apis.google.com/jquery-ui.html Authors don't want to list every single component from jQuery UI in the import directive, and they don't want the jQuery UI logic to be in a different global object. They want to be able to import jQuery UI and have it transitively import jQuery thus providing $ in the window in addition to all the widgets and their API. ex. body.appendChild(new JQUIPanel()).showPanel(). Note also that using a different global produces craziness like Array being different or the prototypes of nodes being different. You definitely don't want that for the same origin or CORS use case. Fortunately, there is already a boundary that we built that might be just the right fit for this problem: the shadow DOM boundary. A while back, we had lunch with Mozilla security researchers who were interested in harnessing the power of Shadow DOM, and Elliott (cc'd) came up with a pretty nifty proposal called the DOMWorker. I nagged him and he is hopefully going to post it on public-webapps. I am pretty sure that his proposal can address your use case and not cripple the rest of the spec in the process. Assuming you’re referring to https://docs.google.com/document/d/1V7ci1-lBTY6AJxgN99aCMwjZKCjKv1v3y_7WLtcgM00/edit, the security model of our proposal is very similar. All we’re doing is using a HTML-imported document instead of a worker to isolate the cross-origin component. Since we don’t want to run the cross-origin component on a separate thread, I don’t think worker is a good model for cross-origin components. A DOMWorker doesn't run on another thread, see the Note in the introduction. - E
Re: [webcomponents] Proposal for Cross Origin Use Case and Declarative Syntax
On Nov 13, 2013, at 7:21 AM, Brian Di Palma off...@gmail.com wrote: I'm not sure I would want jQuery UI to pollute the window object with $, with ES6 modules around the corner it seems like a step backwards for imports to start polluting window objects with their libraries… Indeed! On Tue, Nov 12, 2013 at 9:01 PM, Elliott Sprehn espr...@gmail.com wrote: On Tue, Nov 12, 2013 at 12:45 AM, Ryosuke Niwa rn...@apple.com wrote: [...] Script in the import is executed in the context of the window that contains the importingdocument. So window.document refers to the main page document. This has two useful corollaries: functions defined in an import end up on window. you don't have to do anything crazy like append the import's script blocks to the main page. Again, script gets executed. What we’re proposing is to execute the script in the imported document so the only real argument is the point that “functions defined in an imported end up on window” (of the host document). I think that’s a bad thing. We don’t want imported documents to start polluting global scope without the user explicitly importing them. e.g. import X in Python doesn’t automatically import stuff inside the module into your global scope. To do that, you explicitly say “import * from X”. Similarly, “using std” is discouraged in C++. I don’t think the argument that this is how external script and stylesheet fly either because the whole point of web components is about improving the modularity and reusability of the Web. What you're proposing breaks a primary use case of: link rel=import href=//apis.google.com/jquery-ui.html Authors don't want to list every single component from jQuery UI in the import directive, and they don't want the jQuery UI logic to be in a different global object. They want to be able to import jQuery UI and have it transitively import jQuery thus providing $ in the window in addition to all the widgets and their API. ex. body.appendChild(new JQUIPanel()).showPanel(). I think we can support something like import=* that'll import all global symbols defined in the component into your namespace. Note also that using a different global produces craziness like Array being different or the prototypes of nodes being different. You definitely don't want that for the same origin or CORS use case. I'm not sure. If you have a funky library that ends up polluting Array's prototype for example, then you don't want that pollution to get into other library you're using on the same page. The fact each library has its own clean slate to play with is a good thing. Fortunately, there is already a boundary that we built that might be just the right fit for this problem: the shadow DOM boundary. A while back, we had lunch with Mozilla security researchers who were interested in harnessing the power of Shadow DOM, and Elliott (cc'd) came up with a pretty nifty proposal called the DOMWorker. I nagged him and he is hopefully going to post it on public-webapps. I am pretty sure that his proposal can address your use case and not cripple the rest of the spec in the process. Assuming you’re referring to https://docs.google.com/document/d/1V7ci1-lBTY6AJxgN99aCMwjZKCjKv1v3y_7WLtcgM00/edit, the security model of our proposal is very similar. All we’re doing is using a HTML-imported document instead of a worker to isolate the cross-origin component. Since we don’t want to run the cross-origin component on a separate thread, I don’t think worker is a good model for cross-origin components. A DOMWorker doesn't run on another thread, see the Note in the introduction. I know that. What I'm saying is that it completely defeats the point of using worker. To quote Maciej: Other reasons the worker proposal seems weaker than a separate Window-like global object holding the import document: (1) The proposal says: Note: No asynchronous guarantees are made for DOMWorker, specifically a busy loop inside the worker may hang the main page completely unlike a regular worker. Developers should assume that a DOMWorker is time sharing the same event loops as the owning document. Doesn't this completely defeat any benefit to using a Worker instead of, say, a Window-like global object with its own document? (2) Using a worker (which therefore has no source document) makes it awkward to use templates, if you wanted to. (3) The custom element binding and setup code still runs in the host document, so this doesn't create a strong security boundary because you'd still need to embed external JS and run it in your own security context to set up the custom element. At best this can protect the component from the embedder, but not vice versa. - R. Niwa
Re: [webcomponents] Proposal for Cross Origin Use Case and Declarative Syntax
pollute the window object with $, with ES6 modules around the corner The $ was just an example, the import could also happily define one or more modules. This concept allows us to decouple scoping from imports. Now, the import is only a vehicle, but it advances the state of the art by also delivering canonical HTML and CSS (instead of requiring JavaScript to load or encode additional resources). We right away have an efficient method for draining some of the existing resource management swamp. From there I can see paths to supporting opt-in isolation models, either directly, or by delegating to an agent like DOMWorker. On Tue, Nov 12, 2013 at 3:21 PM, Brian Di Palma off...@gmail.com wrote: I'm not sure I would want jQuery UI to pollute the window object with $, with ES6 modules around the corner it seems like a step backwards for imports to start polluting window objects with their libraries... On Tue, Nov 12, 2013 at 9:01 PM, Elliott Sprehn espr...@gmail.com wrote: On Tue, Nov 12, 2013 at 12:45 AM, Ryosuke Niwa rn...@apple.com wrote: [...] Script in the import is executed in the context of the window that contains the importingdocument. So window.document refers to the main page document. This has two useful corollaries: functions defined in an import end up on window. you don't have to do anything crazy like append the import's script blocks to the main page. Again, script gets executed. What we’re proposing is to execute the script in the imported document so the only real argument is the point that “functions defined in an imported end up on window” (of the host document). I think that’s a bad thing. We don’t want imported documents to start polluting global scope without the user explicitly importing them. e.g. import X in Python doesn’t automatically import stuff inside the module into your global scope. To do that, you explicitly say “import * from X”. Similarly, “using std” is discouraged in C++. I don’t think the argument that this is how external script and stylesheet fly either because the whole point of web components is about improving the modularity and reusability of the Web. What you're proposing breaks a primary use case of: link rel=import href=//apis.google.com/jquery-ui.html Authors don't want to list every single component from jQuery UI in the import directive, and they don't want the jQuery UI logic to be in a different global object. They want to be able to import jQuery UI and have it transitively import jQuery thus providing $ in the window in addition to all the widgets and their API. ex. body.appendChild(new JQUIPanel()).showPanel(). Note also that using a different global produces craziness like Array being different or the prototypes of nodes being different. You definitely don't want that for the same origin or CORS use case. Fortunately, there is already a boundary that we built that might be just the right fit for this problem: the shadow DOM boundary. A while back, we had lunch with Mozilla security researchers who were interested in harnessing the power of Shadow DOM, and Elliott (cc'd) came up with a pretty nifty proposal called the DOMWorker. I nagged him and he is hopefully going to post it on public-webapps. I am pretty sure that his proposal can address your use case and not cripple the rest of the spec in the process. Assuming you’re referring to https://docs.google.com/document/d/1V7ci1-lBTY6AJxgN99aCMwjZKCjKv1v3y_7WLtcgM00/edit , the security model of our proposal is very similar. All we’re doing is using a HTML-imported document instead of a worker to isolate the cross-origin component. Since we don’t want to run the cross-origin component on a separate thread, I don’t think worker is a good model for cross-origin components. A DOMWorker doesn't run on another thread, see the Note in the introduction. - E
Re: [webcomponents] Proposal for Cross Origin Use Case and Declarative Syntax
On Nov 11, 2013, at 3:56 PM, Adam Barth w...@adambarth.com wrote: Can you help me understand what security properties your proposal achieves and how it achieves them? I spent some time thinking about this problem a couple of years ago when this issue was discussed in depth, but I couldn't come up with a design that was simultaneously useful and secure. For example, your proposal seems to have the vulnerability described below: == Trusted container document == link rel=import href=https://untrusted.org/untrusted-components.html; importcomponents=name-card body name-card /name-card == untrusted-components.html == template defines=name-card interface=NameCardElement Name: {{name}}brEmail:{{email}} /template script NameCardElement.prototype.created = function (shadowRoot) { var victim = shadowRoot.ownerDocument; var script = victim.createElement(script); script.textContent = alert(/hacked/);; victim.body.appendChild(script); }; /script Maybe I'm not understanding your proposal correct? If this issue is indeed a vulnerability with your proposal, I have no doubt that you can modify your proposal to patch this hole, but iterating in that way isn't likely to lead to a secure design. The owner document of the shadow root in that case will be that of the component; i.e. https://untrusted.org/untrusted-components.html in this case. In other words, we’re inserting a security boundary between the host element and the shadow root. The shadow root in this case is a funky node object in that it has its host element in an entirely different document. - R. Niwa
Re: [webcomponents] Proposal for Cross Origin Use Case and Declarative Syntax
On Mon, Nov 11, 2013 at 12:57 AM, Ryosuke Niwa rn...@apple.com wrote: On Nov 11, 2013, at 3:56 PM, Adam Barth w...@adambarth.com wrote: Can you help me understand what security properties your proposal achieves and how it achieves them? I spent some time thinking about this problem a couple of years ago when this issue was discussed in depth, but I couldn't come up with a design that was simultaneously useful and secure. For example, your proposal seems to have the vulnerability described below: == Trusted container document == link rel=import href=https://untrusted.org/untrusted-components.html; importcomponents=name-card body name-card /name-card == untrusted-components.html == template defines=name-card interface=NameCardElement Name: {{name}}brEmail:{{email}} /template script NameCardElement.prototype.created = function (shadowRoot) { var victim = shadowRoot.ownerDocument; var script = victim.createElement(script); script.textContent = alert(/hacked/);; victim.body.appendChild(script); }; /script Maybe I'm not understanding your proposal correct? If this issue is indeed a vulnerability with your proposal, I have no doubt that you can modify your proposal to patch this hole, but iterating in that way isn't likely to lead to a secure design. The owner document of the shadow root in that case will be that of the component; i.e. https://untrusted.org/untrusted-components.html in this case. In other words, we’re inserting a security boundary between the host element and the shadow root. The shadow root in this case is a funky node object in that it has its host element in an entirely different document. Was that written somewhere in your proposal and I missed it? Adam
Re: [webcomponents] Proposal for Cross Origin Use Case and Declarative Syntax
On Nov 11, 2013, at 5:33 PM, Ryosuke Niwa rn...@apple.com wrote: On Nov 11, 2013, at 5:13 PM, Adam Barth w...@adambarth.com wrote: On Mon, Nov 11, 2013 at 12:57 AM, Ryosuke Niwa rn...@apple.com wrote: On Nov 11, 2013, at 3:56 PM, Adam Barth w...@adambarth.com wrote: Can you help me understand what security properties your proposal achieves and how it achieves them? I spent some time thinking about this problem a couple of years ago when this issue was discussed in depth, but I couldn't come up with a design that was simultaneously useful and secure. For example, your proposal seems to have the vulnerability described below: == Trusted container document == link rel=import href=https://untrusted.org/untrusted-components.html; importcomponents=name-card body name-card /name-card == untrusted-components.html == template defines=name-card interface=NameCardElement Name: {{name}}brEmail:{{email}} /template script NameCardElement.prototype.created = function (shadowRoot) { var victim = shadowRoot.ownerDocument; var script = victim.createElement(script); script.textContent = alert(/hacked/);; victim.body.appendChild(script); }; /script Maybe I'm not understanding your proposal correct? If this issue is indeed a vulnerability with your proposal, I have no doubt that you can modify your proposal to patch this hole, but iterating in that way isn't likely to lead to a secure design. The owner document of the shadow root in that case will be that of the component; i.e. https://untrusted.org/untrusted-components.html in this case. In other words, we’re inserting a security boundary between the host element and the shadow root. The shadow root in this case is a funky node object in that it has its host element in an entirely different document. Was that written somewhere in your proposal and I missed it? I intended to state this in point 6 but now I realize it wasn’t entirely clear from the way I phrase it so let me elaborate a little more on this point. When a cross-origin custom element is instantiated, the browser creates the JS wrapper for the custom element in the context of the imported document. It then creates a shadow root inside the imported document, attaches it to the host element, and calls createdCallback with the shadow root. The custom element JS object is only visible inside the imported document. It’s HTMLUnknownElement in the context of the host document although we’re open to creating a proxy/fake element subclass which is not visible in the global scope and identical to HTMLKnownElement in its prototype chain in the host document as well. Of course, the imported document will have a different script context (i.e. global object) than the host document. (Anne: Thank you for pointing this out). - R. Niwa
Re: [webcomponents] Proposal for Cross Origin Use Case and Declarative Syntax
On Mon, Nov 11, 2013 at 1:33 AM, Ryosuke Niwa rn...@apple.com wrote: [...] we’re open to creating a proxy/fake element subclass which is not visible in the global scope and identical to HTMLKnownElement in its prototype chain in the host document as well. Can you clarify why it can't be visible in the global scope? Why can't I do document.body.appendChild(new FBLikeButton()) or document.body.firstElementChild instanceof FBLikeButton? -E
Re: [webcomponents] Proposal for Cross Origin Use Case and Declarative Syntax
On Nov 12, 2013, at 6:22 AM, Elliott Sprehn espr...@gmail.com wrote: On Mon, Nov 11, 2013 at 1:33 AM, Ryosuke Niwa rn...@apple.com wrote: [...] we’re open to creating a proxy/fake element subclass which is not visible in the global scope and identical to HTMLKnownElement in its prototype chain in the host document as well. Can you clarify why it can't be visible in the global scope? Allowing the imported document to define arbitrary interface to the global scope of the host document will be a security vulnerability unless the host document explicitly lists the name of interfaces, or there is a strict mapping between tag names and interface names. Why can't I do document.body.appendChild(new FBLikeButton()) or document.body.firstElementChild instanceof FBLikeButton? One way to accomplish this will be adding yet another attribute that imports the list of interfaces; e.g. link ref=import importelements=“like-button” importinterfaces=“FBLikeButton” or defining a map between tag names and interface names (e.g. tag-name TagName), or exporting it on the link element. e.g. likeButtonLinkElement.importedcomponents.FBLikeButton. - R. Niwa
Re: [webcomponents] Proposal for Cross Origin Use Case and Declarative Syntax
On Sun, Nov 10, 2013 at 6:49 PM, Arthur Barstow art.bars...@nokia.comwrote: Hi Dimitri, Dominic, Ryosuke is here in Shezhen at WebApps' f2f meeting. We would like to have one or both of you join us (via voice conference) on Tuesday morning to talk about Web Components and his comments below. Please look at the agenda page and let us know your availability for the one of the open slots before lunch (all times are local to Shenzhen): http://www.w3.org/wiki/Webapps/November2013Meeting# Agenda_Tuesday_November_12 I dropped something at 9:30am. I think that's 5:30pm Mountain View and 10:30am Tokyo, right? -Thanks, ArtB On 11/9/13 3:24 AM, ext Ryosuke Niwa wrote: Hi all, We have been discussing cross-orign use case and declarative syntax of web components internally at Apple, and here are our straw man proposal to amend the existing Web Components specifications to support it. *1. Modify HTML Imports to run scripts in the imported document itself* This allows the importee and the importer to not share the same script context, etc… This could be an option and shouldn’t be the default. By running scripts in a different context, we are ejecting the primary use case of enabling frameworks/libraries to better manage their assets and dependencies (aka the Bootstrap use case). Rob Dodson’s article has a nice progression explaining the use case: http://robdodson.me/blog/2013/08/20/exploring-html-imports/ Also, check out newly minted Eric Bidelman's article on imports (especially the use cases section at the bottom): http://www.html5rocks.com/en/tutorials/webcomponents/imports/ *Re: Custom Elements LC*, this is an issue to handle in HTML Imports specification, not related to Custom Elements. *2. Add “importcomponents content attribute on link element* It defines the list of custom element tag names to be imported from the imported HTML document. e.g. link rel=import href=~ importcomponents=tag-1 tag-2 will export custom elements of tag names tag-1 and tag-2 from ~. Any name that didn't have a definition in the import document is ignored (i.e. if tag-2 was not defined in ~, it would be skipped but tag-1 will be still imported). This mechanism prevents the imported document from defining arbitrary components in the host document. *Re: Custom Elements LC*, this should be handled in HTML Imports specification. HTML Imports can rely on Custom Elements specification. Any additional hooks that could be needed to facilitate this feature could be added in Custom Elements Level 2 specification. *3. Support static (write-once) binding of a HTML template* e.g. template id=cardTemplateName: {{name}}brEmail:{{email}}/template script document.body.appendChild(cardTemplate.instantiate({name: Ryosuke Niwa, email:rn...@webkit.org mailto:rn...@webkit.org})); /script This seems very similar to the Rafael Weinstein's MDV work. You guys should collaborate :) *Re: Custom Elements LC*, this is unrelated to specification. *4. Add “interface content attribute to template element* This content attribute specifies the name of the JavaScript constructor function to be created in the global scope. The UA creates one and will be used to instantiate a given custom element. The author can then setup the prototype chain as needed: template defines=name-card interface=NameCardElement Name: {{name}}brEmail:{{email}} /template script NameCardElement.prototype.name = function () {...} NameCardElement.prototype.email = function () {...} /script This is similar to doing: var NameCardElement = document.register(’name-card'); This is another take on the declarative custom elements (a variant of [1]). This particular approach has four problems that the WG was able to resolve (at least the first three) in previous iterations: 1) It is not friendly to ES6 classes. In fact, you can't use class syntax and this syntax together. 2) It couples templates, shadow DOM, and custom elements in a way that's highly opinionated and inflexible. Throughout this year, we've tried many various ways to get this right, and failed [2]. I highly recommend that we avoid putting this into a specification now. Instead, we should let the best practices evolve and build on the cowpaths. 3) The approach pollutes global name space with constructors. This had been voiced many times as unacceptable by developers. 4) How does build a custom element that uses name-card as its base element? What about div or any other HTML element? The last one remains to be the hardest. The tortured inheritance support is what killed element in the first place. We can't ignore the inheritance, since it is clearly present, in both DOM and JS. If we attempt to punt on supporting it, our decisions cut off the opportunities to evolve this right in the future, and will likely leave us with boogers like multiple syntaxes for inheritance vs. non-inheritance use cases. I recommend studying the work the WG had already done here
RE: [webcomponents] Proposal for Cross Origin Use Case and Declarative Syntax
Dimitri - yes, timeanddate.com agrees: 09:30 Shenzhen = 10:30 Tokyo = 17:30 San Francisco. The pin will be 9274# and we will use the #webapps channel. -TTYS, ArtB Sent from my Windows Phone From: ext Dimitri Glazkovmailto:dglaz...@chromium.org Sent: 11/12/2013 8:13 AM To: Barstow Art (Nokia-CIC/Boston)mailto:art.bars...@nokia.com Cc: ext Ryosuke Niwamailto:rn...@apple.com; Dominic Cooneymailto:domin...@chromium.org; public-webapps@w3.org WGmailto:public-webapps@w3.org; Elliott Sprehnmailto:espr...@gmail.com Subject: Re: [webcomponents] Proposal for Cross Origin Use Case and Declarative Syntax On Sun, Nov 10, 2013 at 6:49 PM, Arthur Barstow art.bars...@nokia.commailto:art.bars...@nokia.com wrote: Hi Dimitri, Dominic, Ryosuke is here in Shezhen at WebApps' f2f meeting. We would like to have one or both of you join us (via voice conference) on Tuesday morning to talk about Web Components and his comments below. Please look at the agenda page and let us know your availability for the one of the open slots before lunch (all times are local to Shenzhen): http://www.w3.org/wiki/Webapps/November2013Meeting#Agenda_Tuesday_November_12 I dropped something at 9:30am. I think that's 5:30pm Mountain View and 10:30am Tokyo, right? -Thanks, ArtB On 11/9/13 3:24 AM, ext Ryosuke Niwa wrote: Hi all, We have been discussing cross-orign use case and declarative syntax of web components internally at Apple, and here are our straw man proposal to amend the existing Web Components specifications to support it. *1. Modify HTML Imports to run scripts in the imported document itself* This allows the importee and the importer to not share the same script context, etc… This could be an option and shouldn’t be the default. By running scripts in a different context, we are ejecting the primary use case of enabling frameworks/libraries to better manage their assets and dependencies (aka the Bootstrap use case). Rob Dodson’s article has a nice progression explaining the use case: http://robdodson.me/blog/2013/08/20/exploring-html-imports/ Also, check out newly minted Eric Bidelman's article on imports (especially the use cases section at the bottom): http://www.html5rocks.com/en/tutorials/webcomponents/imports/ Re: Custom Elements LC, this is an issue to handle in HTML Imports specification, not related to Custom Elements. *2. Add “importcomponents content attribute on link element* It defines the list of custom element tag names to be imported from the imported HTML document. e.g. link rel=import href=~ importcomponents=tag-1 tag-2 will export custom elements of tag names tag-1 and tag-2 from ~. Any name that didn't have a definition in the import document is ignored (i.e. if tag-2 was not defined in ~, it would be skipped but tag-1 will be still imported). This mechanism prevents the imported document from defining arbitrary components in the host document. Re: Custom Elements LC, this should be handled in HTML Imports specification. HTML Imports can rely on Custom Elements specification. Any additional hooks that could be needed to facilitate this feature could be added in Custom Elements Level 2 specification. *3. Support static (write-once) binding of a HTML template* e.g. template id=cardTemplateName: {{name}}brEmail:{{email}}/template script document.body.appendChild(cardTemplate.instantiate({name: Ryosuke Niwa, email:rn...@webkit.orgmailto:rn...@webkit.org mailto:rn...@webkit.orgmailto:rn...@webkit.org})); /script This seems very similar to the Rafael Weinstein's MDV work. You guys should collaborate :) Re: Custom Elements LC, this is unrelated to specification. *4. Add “interface content attribute to template element* This content attribute specifies the name of the JavaScript constructor function to be created in the global scope. The UA creates one and will be used to instantiate a given custom element. The author can then setup the prototype chain as needed: template defines=name-card interface=NameCardElement Name: {{name}}brEmail:{{email}} /template script NameCardElement.prototype.namehttp://NameCardElement.prototype.name = function () {...} NameCardElement.prototype.email = function () {...} /script This is similar to doing: var NameCardElement = document.register(’name-card'); This is another take on the declarative custom elements (a variant of [1]). This particular approach has four problems that the WG was able to resolve (at least the first three) in previous iterations: 1) It is not friendly to ES6 classes. In fact, you can't use class syntax and this syntax together. 2) It couples templates, shadow DOM, and custom elements in a way that's highly opinionated and inflexible. Throughout this year, we've tried many various ways to get this right, and failed [2]. I highly recommend that we avoid putting this into a specification now. Instead, we should let the best practices evolve and build on the cowpaths
Re: [webcomponents] Proposal for Cross Origin Use Case and Declarative Syntax
Hi Dimitri, Dominic, Ryosuke is here in Shezhen at WebApps' f2f meeting. We would like to have one or both of you join us (via voice conference) on Tuesday morning to talk about Web Components and his comments below. Please look at the agenda page and let us know your availability for the one of the open slots before lunch (all times are local to Shenzhen): http://www.w3.org/wiki/Webapps/November2013Meeting#Agenda_Tuesday_November_12 -Thanks, ArtB On 11/9/13 3:24 AM, ext Ryosuke Niwa wrote: Hi all, We have been discussing cross-orign use case and declarative syntax of web components internally at Apple, and here are our straw man proposal to amend the existing Web Components specifications to support it. *1. Modify HTML Imports to run scripts in the imported document itself* This allows the importee and the importer to not share the same script context, etc… *2. Add “importcomponents content attribute on link element* It defines the list of custom element tag names to be imported from the imported HTML document. e.g. link rel=import href=~ importcomponents=tag-1 tag-2 will export custom elements of tag names tag-1 and tag-2 from ~. Any name that didn't have a definition in the import document is ignored (i.e. if tag-2 was not defined in ~, it would be skipped but tag-1 will be still imported). This mechanism prevents the imported document from defining arbitrary components in the host document. *3. Support static (write-once) binding of a HTML template* e.g. template id=cardTemplateName: {{name}}brEmail:{{email}}/template script document.body.appendChild(cardTemplate.instantiate({name: Ryosuke Niwa, email:rn...@webkit.org mailto:rn...@webkit.org})); /script *4. Add “interface content attribute to template element* This content attribute specifies the name of the JavaScript constructor function to be created in the global scope. The UA creates one and will be used to instantiate a given custom element. The author can then setup the prototype chain as needed: template defines=name-card interface=NameCardElement Name: {{name}}brEmail:{{email}} /template script NameCardElement.prototype.name = function () {...} NameCardElement.prototype.email = function () {...} /script This is similar to doing: var NameCardElement = document.register(’name-card'); *5. Add defines content attribute on HTML template element to define a custom element* This new attribute defines a custom element of the given name for the template content. e.g. template defines=nestedDivdivdiv/div/div/template will let you use nestedDiv/nestedDiv We didn’t think having a separate custom element was useful because we couldn’t think of a use case where you wanted to define a custom element declaratively and not use template by default, and having to associate the first template element with the custom element seemed unnecessary complexity. *5.1. When a custom element is instantiated, automatically instantiate template inside a shadow root after statically binding the template with dataset* This allows statically declaring arguments to a component. e.g. template defines=name-cardName: {{name}}brEmail:{{email}}/template name-card data-name=Ryosuke Niwa data-email=rn...@webkit.org mailto:rn...@webkit.org” *5.2. When a new custom element object is constructed, created callback is called with a shadow root* Unfortunately, we can't let the author define a constructor because the element hadn't been properly initialized with the right JS wrapper at the time of its construction. So just like we can't do new HTMLTitleElement, we're not going to let the author do an interesting things inside a custom element's constructor. Instead, we're going to call created function on its prototype chain: template defines=name-card interface=NameCardElement Name: {{name}}brEmail:{{email}} /template script NameCardElement.prototype.name = function () {...} NameCardElement.prototype.email = function () {...} NameCardElement.prototype.created = function (shadowRoot) { ... // Initialize the shadowRoot here. } /script This is similar to the way document.register works in that document.register creates a constructor automatically. *6. The cross-origin component does not have access to the shadow host element, and the host document doesn’t have access to the element object.* When member functions of the element is called, “this” object will be undefined. This is necessary because exposing the object to a cross-origin content will result in tricky security issues, forcing us to have proxy objects, etc… Inside the document that imported a component, the element doesn’t use the prototype defined by the component as that exposes JS objects cross-origin. e.g. even if LikeButtonElement was defined in facebook.com/~/like-button.html http://facebook.com/%7E/like-button.html, the document that uses this component wouldn’t see the prototype or the constructor. It’ll be HTMLUnknownElement. (We could create a
Re: [webcomponents] Proposal for Cross Origin Use Case and Declarative Syntax
Hi Ryosuke, Can you help me understand what security properties your proposal achieves and how it achieves them? I spent some time thinking about this problem a couple of years ago when this issue was discussed in depth, but I couldn't come up with a design that was simultaneously useful and secure. For example, your proposal seems to have the vulnerability described below: == Trusted container document == link rel=import href=https://untrusted.org/untrusted-components.html; importcomponents=name-card body name-card /name-card == untrusted-components.html == template defines=name-card interface=NameCardElement Name: {{name}}brEmail:{{email}} /template script NameCardElement.prototype.created = function (shadowRoot) { var victim = shadowRoot.ownerDocument; var script = victim.createElement(script); script.textContent = alert(/hacked/);; victim.body.appendChild(script); }; /script Maybe I'm not understanding your proposal correct? If this issue is indeed a vulnerability with your proposal, I have no doubt that you can modify your proposal to patch this hole, but iterating in that way isn't likely to lead to a secure design. Thanks, Adam On Fri, Nov 8, 2013 at 11:24 AM, Ryosuke Niwa rn...@apple.com wrote: Hi all, We have been discussing cross-orign use case and declarative syntax of web components internally at Apple, and here are our straw man proposal to amend the existing Web Components specifications to support it. 1. Modify HTML Imports to run scripts in the imported document itself This allows the importee and the importer to not share the same script context, etc… 2. Add “importcomponents content attribute on link element It defines the list of custom element tag names to be imported from the imported HTML document. e.g. link rel=import href=~ importcomponents=tag-1 tag-2 will export custom elements of tag names tag-1 and tag-2 from ~. Any name that didn't have a definition in the import document is ignored (i.e. if tag-2 was not defined in ~, it would be skipped but tag-1 will be still imported). This mechanism prevents the imported document from defining arbitrary components in the host document. 3. Support static (write-once) binding of a HTML template e.g. template id=cardTemplateName: {{name}}brEmail:{{email}}/template script document.body.appendChild(cardTemplate.instantiate({name: Ryosuke Niwa, email:rn...@webkit.org})); /script 4. Add “interface content attribute to template element This content attribute specifies the name of the JavaScript constructor function to be created in the global scope. The UA creates one and will be used to instantiate a given custom element. The author can then setup the prototype chain as needed: template defines=name-card interface=NameCardElement Name: {{name}}brEmail:{{email}} /template script NameCardElement.prototype.name = function () {...} NameCardElement.prototype.email = function () {...} /script This is similar to doing: var NameCardElement = document.register(’name-card'); 5. Add defines content attribute on HTML template element to define a custom element This new attribute defines a custom element of the given name for the template content. e.g. template defines=nestedDivdivdiv/div/div/template will let you use nestedDiv/nestedDiv We didn’t think having a separate custom element was useful because we couldn’t think of a use case where you wanted to define a custom element declaratively and not use template by default, and having to associate the first template element with the custom element seemed unnecessary complexity. 5.1. When a custom element is instantiated, automatically instantiate template inside a shadow root after statically binding the template with dataset This allows statically declaring arguments to a component. e.g. template defines=name-cardName: {{name}}brEmail:{{email}}/template name-card data-name=Ryosuke Niwa data-email=rn...@webkit.org” 5.2. When a new custom element object is constructed, created callback is called with a shadow root Unfortunately, we can't let the author define a constructor because the element hadn't been properly initialized with the right JS wrapper at the time of its construction. So just like we can't do new HTMLTitleElement, we're not going to let the author do an interesting things inside a custom element's constructor. Instead, we're going to call created function on its prototype chain: template defines=name-card interface=NameCardElement Name: {{name}}brEmail:{{email}} /template script NameCardElement.prototype.name = function () {...} NameCardElement.prototype.email = function () {...} NameCardElement.prototype.created = function (shadowRoot) { ... // Initialize the shadowRoot here. } /script This is similar to the way document.register works in that document.register creates a constructor automatically. 6. The cross-origin component does not have access to the shadow host