-
Notifications
You must be signed in to change notification settings - Fork 371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ES5 consideration for custom elements #423
Comments
@domenic is it worth adding a note somewhere? I don't really care either way. |
I don't really think so. As @rniwa notes, every browser that implements custom elements also implements class syntax. We can close. Using issue tracker for PSAs is a good idea though. |
Does this mean that custom elements v1 will not be compatible with ES5 style "classes"? For example the custom tag example could NOT be written as the following with custom elements v1:
If it is the case that custom elements v1 will not support ES5 style classes I am concerned that it will make it unnecessarily difficult for many applications that want to begin the process of migrating to custom elements. Assuming a developer wants to incrementally support modern browser features (using tools like transpilers and polyfills), the following scenarios come to mind:
As a developer who wants to support custom elements in a way that is forward looking and yet compatible with modern browsers, I can choose to write in ES6 classes against the custom elements v1 api. For deployment, I transpile ES6 classes to ES5 style "classes" and include a custom element v1 polyfill. In the ideal situation, browsers that support custom element v1 natively will not utilize the custom element v1 polyfill and consume the ES5 style "classes" with the native custom element v1 api. However, if ES6 style classes are required, then deployment becomes much more complex. One option would be to use feature detection to selectively serve two versions of all elements (one version with ES6 classes to the bleeding edge browsers and one version with ES5 style "classes" to the broad-base). Or even worse, create a single build that utilizes the polyfill in browsers that do not support custom element v1 and force the polyfill on bleeding edge browsers as well. The later scenario seems to be the more likely outcome because of the significantly reduced difficulty of distributing a single build while simultaneously adopting a larger user base. If the idea is that requiring ES6 classes is an acceptable migration burden for early adopters utilizing custom elements v0 and for new users of the platform, I believe this decision will unnecessarily punish new adopters and encourage non-native and non-spec compliant polyfill implementations. Considering that custom elements behavior is so foundational to the whole idea of api interoperability between web components and frameworks consuming web components, encouraging adoption of spec compliant implementations should be a high priority. Alternatively, I am completely off the rails and have misinterpreted both the current drafts of the custom element v1 specification and this Github issue. If that is the case and ES5 style "classes" are to be supported then some of the phrasing such as:
is a bit unclear and I can file a separate issue for those cases. If you made it this far, thank you for taking the time to read this post and I look forward to your thoughts. |
All browsers that support custom elements v1 API would support So, you can write a wrapper around it which calls |
Thank you for the quick reply! To take it a step further, the pattern of using Reflect.construct would be required for all ES5 style derived "classes" that want to extend base constructors that create exotic objects. This is probably not unique to HTMLElement, but also to Array, etc. Does that seem fair? If that is the case, the spec makes the following note:
Is this note implying that:
Side note: I found the Exploring JS: Classes chapter very helpful for this discussion |
I don't believe that note is implying either of those things. What about it do you find unclear? |
The spec doesn't imply either.
This is certainly not the case.
All browsers that do support custom elements will support In other browsers that don't support custom elements or Perhaps the spec could be updated to also mention |
Maybe it is more of a phrasing issue. By saying:
It seems to imply that something will be changing in the future, but it is not very clear what would change. |
What can change is that we might allow something like |
@domenic Mentioning that reason would be clearer about what is being implied
@rniwa I think it would be appreciated if a reference to calling the HTMLElement constructor via either super() or Reflect.construct was included.
Either that or just loosening the language a bit
|
That's probably a good change. @domenic : could you make that spec change for us? |
I think it's less accurate than what we have now. If you're looking for precision it should be something along the lines of "the HTMLElemwnt constructor cannot be invoked unless NewTarget is set to a custom element constructor." Saying that it can be invoked "inside", " for example by super()", is just incorrect. I'd like further clarity on exactly what is wrong with the current phrasing. |
I think the problem is that the current spec specifically says we must use |
I didn't read the whole thread, but currently, Custom Elements are compatible with ES5 constructor-pattern classes like this: function MyElement() {
// The only caveat: just don't do anything in this constructor.
}
MyElement.prototype = Object.create(HTMLElement.prototype)
MyElement.prototype.createdCallback = function createdCallback() {
// Instead, do your "constructor" logic here.
}
MyElement = document.registerElement('my-element', )
// ^ This assignment is required if you'd like to use `new MyElement` directly
// instead of document.createElement('my-element')
export default MyElement This also works with ES6 classes: class MyElement extends HTMLElement {
createdCallback() {
// Do your "constructor" logic here.
}
}
MyElement = document.registerElement('my-element', )
// ^ This assignment is required if you'd like to use `new MyElement` directly
// instead of document.createElement('my-element')
export default MyElement then in another file import MyElement from './my-element'
let el = document.createElement('my-element')
// or
let el = new MyElement It'd be cool if it just worked properly with (at least) ES6 classes: class MyElement extends HTMLElement {
constructor() {
// Do your actual constructor logic here.
}
}
document.registerElement('my-element', MyElement)
// ^ With no assignment needed.
export default MyElement then just import MyElement from './my-element'
let el = new MyElement
// document.createElement() not needed, but can exist for backwards compatibility. I don't see why this can't work with any constructor (ES5 constructor-pattern classes for example). Anything's possible! |
@trusktr this is exactly what's happening. This thread is only about purely ES5 style constructors which call their super constructor with Function.call. In this case I think this is mainly a concern for output of compilers and code that aims to be compatible with both native implementations and polyfills on browsers without |
FYI, |
@rniwa yes, that's what the shim I have does. |
For anyone stumbling across this, newer discussion on this topic can be found here: #587 In particular: #587 (comment) |
Everyone, the strict enforcement of using This is a bad because not everyone is off of IE 10 or 11 yet, and there's no way to transpile this to a format that doesn't use What this means is that people transpiling this to ES5 and using a Custom Elements v1 and Reflect polyfill will get lucky that it works in IE10, but then they'll get this error in new browsers like Chrome:
|
For example, see how bad this is with Buble output. Run the output code in Chrome. This is not good! It makes things very difficult, especially in a time when many people still have to support non-native-ES2015+ environments. |
We think this is okay but I'll note that the new constructor based custom elements API is incompatible with ES5 because there is no mechanism to set new.target in ES5 without use of
Reflect.construct
.This is probably non-issue though because by the time custom elements API will be implemented by all browsers,
Reflect.construct
would certainly be available everywhere.This is just FYI.
The text was updated successfully, but these errors were encountered: