Re: [webcomponents] Binding Custom Element without Polluting Global Scope (Was Proposal for Cross Origin Use Case and Declarative Syntax)

2014-02-06 Thread Ryosuke Niwa
On Dec 7, 2013, at 3:25 PM, Dominic Cooney domin...@google.com wrote:
 On Sat, Dec 7, 2013 at 10:06 AM, Ryosuke Niwa rn...@apple.com wrote:
 On Dec 6, 2013, at 5:01 PM, Ryosuke Niwa rn...@apple.com wrote:
 On Dec 6, 2013, at 1:20 AM, Brian Di Palma off...@gmail.com wrote:
 On Fri, Dec 6, 2013 at 3:24 AM, Ryosuke Niwa rn...@apple.com wrote:
 On Nov 12, 2013, at 12:45 AM, Ryosuke Niwa rn...@apple.com wrote:
 
 On Nov 12, 2013, at 8:12 AM, Dimitri Glazkov dglaz...@chromium.org wrote:
 
 1) It is not friendly to ES6 classes. In fact, you can't use class syntax
 and this syntax together.
 
 
 Okay, let the author define the constructor.
 
 3) The approach pollutes global name space with constructors. This had been
 voiced many times as unacceptable by developers.
 
 
 We can solve this problem by using JavaScript object path as opposed to a
 variable name.
 
 So instead of:
 template register=my-button interface=MyButton
 /template
 
 We allow:
 script
 var my = {views:{MyButton: ~}};
 /script
 template register=my-button interface=my.views.MyButton
 /template
 
 While this requires some variable to be exposed on the global scope,
 libraries and frameworks do this already,
 
 Hopefully though they won't do that any longer in the ES6 module world.
 They had to be exposed on the global scope in some way otherwise they
 couldn't be used, in future that will no longer be the case.
 
 Are you proposing to provide some mechanism to declaratively define a custom 
 element inside a module?
 How does a ES6 module end up having markup?
 
 I'll also point out that with our proposal to add an optional template 
 argument, we could do:
 
 template id=myButton
 ...
 /template
 script
 (function () {
 class MyButton extends HTMLElement {
 ...
 }
 document.register('my-button', MyButton, 
 document.getElementById('myButton'));
 )();
 /script
 
 so authors DO have an option to hide the class entirely from the global 
 scope. It's just not declarative.
 
 I don't think this proposal is an improvement over the document.register in 
 the spec today.

It is an improvement in that it reduces the boilerplate code that we expect 
many custom elements to have.

 The existing spec for document.register does not add a binding to the 
 JavaScript scope. So it does not suffer the problem discussed in this thread.

Sorry, I don't really understand what you mean by this.  Could you clarify?

 Given that we don't want to change this or the global object per previous 
 discussion in the working group,
 
 I don't know what discussion you are specifically referring to so my next 
 statement is not agreeing or disagreeing with the preceding clause of this 
 sentence.


See Erik's inline comment in 
http://lists.w3.org/Archives/Public/public-webapps/2013AprJun/0122.html

Unfortunately NodeJS broke this invariant already. `this` inside a module that 
has been required is a not the [[Global]] object. This has caused me a lot of 
personal porting pain so I agree we must not break this invariant on the web.


 I don't see how we can refer to a JS class/constructor declaratively.
 
 Yes. I can't think of an example where DOM attributes do this. onclick, etc. 
 handlers relate to script, but they do not refer to specific objects.
 
 This is a problem with your proposal.

I don't think this is an issue with our proposal.  I don't think any proposal 
for declarative syntax can simultaneously satisfy requirements to not change 
the meaning of this inside the element definition and not pollute the global 
namespace at all.

 I think a proposal for declarative Custom Elements must also deal with the 
 problems the group discovered when it last tried. They are summarized here:
 http://lists.w3.org/Archives/Public/public-webapps/2013JulSep/0287.html

A lot of problems listed there appears to stem from an implicit assumption that 
the declarative syntax should have the same expressiveness as imperative API.  
I disagree with that proposition.  Any moderately complicated Web apps will 
inevitably involve scripts.  The existing Web APIs are designed around this 
principle; they address common use cases with declarative syntax and provide 
imperative APIs for more complicated use cases.

- R. Niwa




Re: [webcomponents] Binding Custom Element without Polluting Global Scope (Was Proposal for Cross Origin Use Case and Declarative Syntax)

2013-12-07 Thread Brian Di Palma
On Sat, Dec 7, 2013 at 1:01 AM, Ryosuke Niwa rn...@apple.com wrote:
 On Dec 6, 2013, at 1:20 AM, Brian Di Palma off...@gmail.com wrote:
 On Fri, Dec 6, 2013 at 3:24 AM, Ryosuke Niwa rn...@apple.com wrote:
 On Nov 12, 2013, at 12:45 AM, Ryosuke Niwa rn...@apple.com wrote:

 On Nov 12, 2013, at 8:12 AM, Dimitri Glazkov dglaz...@chromium.org wrote:

 1) It is not friendly to ES6 classes. In fact, you can't use class syntax
 and this syntax together.


 Okay, let the author define the constructor.

 3) The approach pollutes global name space with constructors. This had been
 voiced many times as unacceptable by developers.


 We can solve this problem by using JavaScript object path as opposed to a
 variable name.

 So instead of:
 template register=my-button interface=MyButton
 /template

 We allow:
 script
 var my = {views:{MyButton: ~}};
 /script
 template register=my-button interface=my.views.MyButton
 /template

 While this requires some variable to be exposed on the global scope,
 libraries and frameworks do this already,

 Hopefully though they won't do that any longer in the ES6 module world.
 They had to be exposed on the global scope in some way otherwise they
 couldn't be used, in future that will no longer be the case.

 Are you proposing to provide some mechanism to declaratively define a custom 
 element inside a module?

 How does a ES6 module end up having markup?


It doesn't. I don't like mixing the different resource types inside one file.
Whether that is a HTML file with JS inside it or a JS file with HTML inside it.
I feel they should be kept separate from each other as much as possible.
Especially since I have no need for the HTML markup in my ES6 module.

The current document.register signature requires,

TYPE, the custom element type of the element being registered

PROTOTYPE, the custom element prototype, optional

So I don't see what use the HTML markup would be to me.

If we look at the proposal we are talking about here the signature has
one extra parameter added,

TEMPLATEELEMENT, HTMLTemplateElement used as template for custom element.

again I'm not sure what I'd need the HTML markup for.

You may point out that I need the HTMLTemplateElement, which is true
and for that I'd really like
to use a mechanism that as a proficient ES6+ developer I'd be quite
familiar with.

javascript

import { myCustomElement } from my-customelement.html;

class MyCustomElement extends HTMLElement {
...
}

document.register('my-customelement', MyCustomElement, myCustomElement);


I think in fact that the import line can be made to work with the some
tweaks to the standard module loader.
I'd much prefer this over having a HTML file containing my code and
business logic stuck inside an antiquated IIFE.

With HTTP2.0/SPDY you can have your server push the CSS files related
to the custom element so they are in cache
when the element is created if browsers don't natively support the above code.

I'd build a dependency tree by using the module loader imports so that
any dependent custom elements are available.

Actually I'm not sure I'd use HTML imports at all if I had this...I'm
sure I'm missing some benefit they would provide?

P.S.

For extra fun you could import CSS in the same way and have it apply
in scoped fashion to different elements.

javascript

import CSSStyleSheetObject from my-customelement.css apply to myCustomElement;
import anotherCSSStyleSheetObject from my-application-styles.css
apply to document;



Once you have ES modules implemented this might be a quick addition
for a browser maker.

 - R. Niwa




Re: [webcomponents] Binding Custom Element without Polluting Global Scope (Was Proposal for Cross Origin Use Case and Declarative Syntax)

2013-12-07 Thread Dominic Cooney
On Sat, Dec 7, 2013 at 10:06 AM, Ryosuke Niwa rn...@apple.com wrote:

 On Dec 6, 2013, at 5:01 PM, Ryosuke Niwa rn...@apple.com wrote:

 On Dec 6, 2013, at 1:20 AM, Brian Di Palma off...@gmail.com wrote:

 On Fri, Dec 6, 2013 at 3:24 AM, Ryosuke Niwa rn...@apple.com wrote:

 On Nov 12, 2013, at 12:45 AM, Ryosuke Niwa rn...@apple.com wrote:

 On Nov 12, 2013, at 8:12 AM, Dimitri Glazkov dglaz...@chromium.org
 wrote:

 1) It is not friendly to ES6 classes. In fact, you can't use class syntax
 and this syntax together.


 Okay, let the author define the constructor.

 3) The approach pollutes global name space with constructors. This had been
 voiced many times as unacceptable by developers.


 We can solve this problem by using JavaScript object path as opposed to a
 variable name.

 So instead of:
 template register=my-button interface=MyButton
 /template

 We allow:
 script
 var my = {views:{MyButton: ~}};
 /script
 template register=my-button interface=my.views.MyButton
 /template

 While this requires some variable to be exposed on the global scope,
 libraries and frameworks do this already,


 Hopefully though they won't do that any longer in the ES6 module world.
 They had to be exposed on the global scope in some way otherwise they
 couldn't be used, in future that will no longer be the case.


 Are you proposing to provide some mechanism to declaratively define a
 custom element inside a module?
 How does a ES6 module end up having markup?


 I'll also point out that with our proposal to add an optional template
 argument, we could do:

 template id=myButton
 ...
 /template
 script
 (function () {
 class MyButton extends HTMLElement {
 ...
 }
 document.register('my-button', MyButton,
 document.getElementById('myButton'));
 )();
 /script

 so authors DO have an option to hide the class entirely from the global
 scope. It's just not declarative.


I don't think this proposal is an improvement over the document.register in
the spec today. Whether there is an argument for a template element is
orthogonal to adding a binding to the JavaScript scope.

The existing spec for document.register does not add a binding to the
JavaScript scope. So it does not suffer the problem discussed in this
thread.


 Given that we don't want to change this or the global object per
 previous discussion in the working group,


I don't know what discussion you are specifically referring to so my next
statement is not agreeing or disagreeing with the preceding clause of this
sentence.


 I don't see how we can refer to a JS class/constructor declaratively.


Yes. I can't think of an example where DOM attributes do this. onclick,
etc. handlers relate to script, but they do not refer to specific objects.

This is a problem with your proposal.

I think a proposal for declarative Custom Elements must also deal with the
problems the group discovered when it last tried. They are summarized here:

http://lists.w3.org/Archives/Public/public-webapps/2013JulSep/0287.html

Link provided for convenience, as you are no doubt aware of these.

-- 
http://goto.google.com/dc-email-sla


Re: [webcomponents] Binding Custom Element without Polluting Global Scope (Was Proposal for Cross Origin Use Case and Declarative Syntax)

2013-12-06 Thread Brian Di Palma
On Fri, Dec 6, 2013 at 3:24 AM, Ryosuke Niwa rn...@apple.com wrote:
 On Nov 12, 2013, at 12:45 AM, Ryosuke Niwa rn...@apple.com wrote:

 On Nov 12, 2013, at 8:12 AM, Dimitri Glazkov dglaz...@chromium.org wrote:

 1) It is not friendly to ES6 classes. In fact, you can't use class syntax
 and this syntax together.


 Okay, let the author define the constructor.

 3) The approach pollutes global name space with constructors. This had been
 voiced many times as unacceptable by developers.


 We can solve this problem by using JavaScript object path as opposed to a
 variable name.

 So instead of:
 template register=my-button interface=MyButton
 /template

 We allow:
 script
 var my = {views:{MyButton: ~}};
 /script
 template register=my-button interface=my.views.MyButton
 /template

 While this requires some variable to be exposed on the global scope,
 libraries and frameworks do this already,

Hopefully though they won't do that any longer in the ES6 module world.
They had to be exposed on the global scope in some way otherwise they
couldn't be used, in future that will no longer be the case.

 and authors could use
 document.register to avoid that altogether if they really wanted.

 - R. Niwa




Re: [webcomponents] Binding Custom Element without Polluting Global Scope (Was Proposal for Cross Origin Use Case and Declarative Syntax)

2013-12-06 Thread Ryosuke Niwa
On Dec 6, 2013, at 1:20 AM, Brian Di Palma off...@gmail.com wrote:
 On Fri, Dec 6, 2013 at 3:24 AM, Ryosuke Niwa rn...@apple.com wrote:
 On Nov 12, 2013, at 12:45 AM, Ryosuke Niwa rn...@apple.com wrote:
 
 On Nov 12, 2013, at 8:12 AM, Dimitri Glazkov dglaz...@chromium.org wrote:
 
 1) It is not friendly to ES6 classes. In fact, you can't use class syntax
 and this syntax together.
 
 
 Okay, let the author define the constructor.
 
 3) The approach pollutes global name space with constructors. This had been
 voiced many times as unacceptable by developers.
 
 
 We can solve this problem by using JavaScript object path as opposed to a
 variable name.
 
 So instead of:
 template register=my-button interface=MyButton
 /template
 
 We allow:
 script
 var my = {views:{MyButton: ~}};
 /script
 template register=my-button interface=my.views.MyButton
 /template
 
 While this requires some variable to be exposed on the global scope,
 libraries and frameworks do this already,
 
 Hopefully though they won't do that any longer in the ES6 module world.
 They had to be exposed on the global scope in some way otherwise they
 couldn't be used, in future that will no longer be the case.

Are you proposing to provide some mechanism to declaratively define a custom 
element inside a module?

How does a ES6 module end up having markup?

- R. Niwa




Re: [webcomponents] Binding Custom Element without Polluting Global Scope (Was Proposal for Cross Origin Use Case and Declarative Syntax)

2013-12-06 Thread Ryosuke Niwa
On Dec 6, 2013, at 5:01 PM, Ryosuke Niwa rn...@apple.com wrote:

 On Dec 6, 2013, at 1:20 AM, Brian Di Palma off...@gmail.com wrote:
 On Fri, Dec 6, 2013 at 3:24 AM, Ryosuke Niwa rn...@apple.com wrote:
 On Nov 12, 2013, at 12:45 AM, Ryosuke Niwa rn...@apple.com wrote:
 
 On Nov 12, 2013, at 8:12 AM, Dimitri Glazkov dglaz...@chromium.org wrote:
 
 1) It is not friendly to ES6 classes. In fact, you can't use class syntax
 and this syntax together.
 
 
 Okay, let the author define the constructor.
 
 3) The approach pollutes global name space with constructors. This had been
 voiced many times as unacceptable by developers.
 
 
 We can solve this problem by using JavaScript object path as opposed to a
 variable name.
 
 So instead of:
 template register=my-button interface=MyButton
 /template
 
 We allow:
 script
 var my = {views:{MyButton: ~}};
 /script
 template register=my-button interface=my.views.MyButton
 /template
 
 While this requires some variable to be exposed on the global scope,
 libraries and frameworks do this already,
 
 Hopefully though they won't do that any longer in the ES6 module world.
 They had to be exposed on the global scope in some way otherwise they
 couldn't be used, in future that will no longer be the case.
 
 Are you proposing to provide some mechanism to declaratively define a custom 
 element inside a module?
 How does a ES6 module end up having markup?

I'll also point out that with our proposal to add an optional template 
argument, we could do:

template id=myButton
...
/template
script
(function () {
class MyButton extends HTMLElement {
...
}
document.register('my-button', MyButton, 
document.getElementById('myButton'));
)();
/script

so authors DO have an option to hide the class entirely from the global scope. 
It's just not declarative.

Given that we don't want to change this or the global object per previous 
discussion in the working group,
I don't see how we can refer to a JS class/constructor declaratively.

- R. Niwa



[webcomponents] Binding Custom Element without Polluting Global Scope (Was Proposal for Cross Origin Use Case and Declarative Syntax)

2013-12-05 Thread Ryosuke Niwa
On Nov 12, 2013, at 12:45 AM, Ryosuke Niwa rn...@apple.com wrote:
 On Nov 12, 2013, at 8:12 AM, Dimitri Glazkov dglaz...@chromium.org wrote:
 1) It is not friendly to ES6 classes. In fact, you can't use class syntax 
 and this syntax together.

Okay, let the author define the constructor.

 3) The approach pollutes global name space with constructors. This had been 
 voiced many times as unacceptable by developers.

We can solve this problem by using JavaScript object path as opposed to a 
variable name.

So instead of:
template register=my-button interface=MyButton
/template

We allow:
script
var my = {views:{MyButton: ~}};
/script
template register=my-button interface=my.views.MyButton
/template

While this requires some variable to be exposed on the global scope, libraries 
and frameworks do this already, and authors could use document.register to 
avoid that altogether if they really wanted.

- R. Niwa