You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Differences between "normal" platform objects and "normal" JavaScript classesΒ #226
I believe in Gecko at least typeof will also be different.
No, typeof will always be object. You might be thinking about Object.prototype.toString.call(obj). But even there ES built-ins use Symbol.toStringTag to customize that. (But, normal JS classes do not.)
enumerable (Web IDL) vs. non-enumerable (conventional for ES)
There has been talk of adding something to IDL to control enumerability, so on a technical level we can "solve" this.
The more fundamental problem is the inconsistency in the platform and the lack of a credible plan to bridge it. :( ES classes are basically defined to look more like ES builtins here, while IDL standardized de-facto behavior of existing browser builtins like DOM. The web definitely depends on enumerability for some of the DOM APIs, but I don't know that anyone has a good list of which ones. Clearly we could make new ones non-enumerable, at the cost of even more confusion, but we could just as easily make new TC39 stuff enumerable, at the cost of even more confusion. Or maybe neither one is more confusing than what we have now, since most people have no clue which things are ES and which things are IDL-defined anyway. I don't see any non-sucky outcomes here, honestly...
statics being functions (Web IDL) vs. methods (conventional for ES)
In the sense that ES statics will examine their "this" object (the constructor object) for some state?
We could quite trivially change this on the IDL side in the sense of passing the "this" object to the spec prose defining the IDL static, which would allow it to use it if it wants. In practice, there's typically nothing the spec prose wants out of that object, so the distinction is moot in most cases. In the specific case of URLSearchParams there are no statics to start with, so the distinction is even more moot. ;)
I believe in Gecko at least typeof will also be different.
I'm not aware of anything like this.
having it clearly documented how "normal" platform objects differ from "normal" JavaScript classes
The most obvious difference is that platform objects have branding checks and JS classes normally don't [1]. JS builtins, which are somewhat like JS clases in some ways and different in others, sometimes do and sometimes don't.
[1] For the same reason they don't normally have interesting toString behavior: you can do it, but it takes some extra effort and most people wouldn't bother.
The statics-being-methods thing mostly impacts whether they work when extracted or not. E.g. const resolve = Promise.resolve will not work. But const cOU = URL.createObjectURL will work.
Ah. That's something that can be expressed in ES anyway using @@hasInstance (though typically is not, of course).
URL.createObjectURL and Promise.resolve are fundamentally different beasts: the former creates a string, while the latter creates a Promise. I agree that statics that create an object of the type being defined should be methods, to play nice with subclassing. With that in mind, we should change IDL to pass "this" to statics; if we don't have an existing issue on that, let's get one filed and just fix this. That will allow specs to do the right thing here. Whether we can change existing specs to the method semantics, I'm not sure. :(
But I'm pretty sure this mostly (only?) affects statics that create an object of the type they're defined on. I just looked (well, had our binding codegen look) through Gecko's IDL looking for such statics. The full list is:
IDBKeyRange.only
IDBKeyRange.lowerBound
IDBKeyRange.upperBound
IDBKeyRange.upperBound
IDBLocaleAwareKeyRange.bound
Response.error
Response.redirect
It's too bad no one raised this issue about statics when fetch's Response was being specified. :( IDB not raising it I'm not surprised by, of course; there weren't many ES-aware people involved in that.
Oh, and looks like IDBLocaleAwareKeyRange is not even on by default yet...
I can't speak to whether someone would want to subclass IDBKeyRange in practice, but subclassing Response seems like a totally reasonable thing to do. :(
It would be really great if the standards venue didn't affect the shape of the resulting API. Sounds like the three things raised in this thread have a path towards resolution. Would it be reasonable to start a policy of doing things in a more ES-type style when new APIs come up (sounds like enumerability is the big one here)? For enumerability on the JS side, there seems to be a strong feeling in TC39 that we couldn't add more enumerable methods to existing objects without breaking existing code.
It would be really great if the standards venue didn't affect the shape of the resulting API.
Yes, it would, though we have a huge legacy of it having done just that. We had this exact conversation 4-5 years ago (not you and I, but various people involved in ES and web specs) and absolutely nothing changed as a result. :(
Would it be reasonable to start a policy of doing things in a more ES-type style
Why not in a more IDL-type style? Honest question, not trolling.
For enumerability on the JS side, there seems to be a strong feeling in TC39 that we couldn't add more enumerable methods to existing objects without breaking existing code.
Oh, on the DOM side we can't remove enumerability from existing objects without breaking existing code. Or more precisely, we know there are some we can't remove it from, but we don't know which things are in that bucket, necessarily.
This is all be a discussion about new things that are added; for existing stuff we're stuck with what we have, I'm afraid.
@bzbarsky Definitely agree about not changing existing things.
Why not in a more IDL-type style? Honest question, not trolling.
The reason we don't make new things enumerable in ECMAScript (I believe) is that we're concerned about breaking the web. Maybe this claim that new enumerable properties the web would break isn't true, if other parts of the web platform have been getting away with it, but it makes me concerned.
I think this claim is perhaps true for new properties added on existing objects, and especially on Array.prototype and Object.prototype, because those two would break a lot of for-in loops.
I think adding enumerable stuff elsewhere would not have broken the web, and adding it on entirely new things is very unlikely to do so.
Activity
domenic commentedon Nov 7, 2016
No, typeof will always be object. You might be thinking about
Object.prototype.toString.call(obj). But even there ES built-ins useSymbol.toStringTagto customize that. (But, normal JS classes do not.)bzbarsky commentedon Nov 7, 2016
There has been talk of adding something to IDL to control enumerability, so on a technical level we can "solve" this.
The more fundamental problem is the inconsistency in the platform and the lack of a credible plan to bridge it. :( ES classes are basically defined to look more like ES builtins here, while IDL standardized de-facto behavior of existing browser builtins like DOM. The web definitely depends on enumerability for some of the DOM APIs, but I don't know that anyone has a good list of which ones. Clearly we could make new ones non-enumerable, at the cost of even more confusion, but we could just as easily make new TC39 stuff enumerable, at the cost of even more confusion. Or maybe neither one is more confusing than what we have now, since most people have no clue which things are ES and which things are IDL-defined anyway. I don't see any non-sucky outcomes here, honestly...
In the sense that ES statics will examine their "this" object (the constructor object) for some state?
We could quite trivially change this on the IDL side in the sense of passing the "this" object to the spec prose defining the IDL static, which would allow it to use it if it wants. In practice, there's typically nothing the spec prose wants out of that object, so the distinction is moot in most cases. In the specific case of URLSearchParams there are no statics to start with, so the distinction is even more moot. ;)
I'm not aware of anything like this.
The most obvious difference is that platform objects have branding checks and JS classes normally don't [1]. JS builtins, which are somewhat like JS clases in some ways and different in others, sometimes do and sometimes don't.
[1] For the same reason they don't normally have interesting toString behavior: you can do it, but it takes some extra effort and most people wouldn't bother.
annevk commentedon Nov 7, 2016
Sorry, I meant instanceof, not typeof.
annevk commentedon Nov 7, 2016
@bzbarsky the URL object has a static defined in the File API (createObjectURL).
domenic commentedon Nov 7, 2016
The statics-being-methods thing mostly impacts whether they work when extracted or not. E.g.
const resolve = Promise.resolvewill not work. Butconst cOU = URL.createObjectURLwill work.bzbarsky commentedon Nov 7, 2016
Ah. That's something that can be expressed in ES anyway using
@@hasInstance(though typically is not, of course).URL.createObjectURL and Promise.resolve are fundamentally different beasts: the former creates a string, while the latter creates a Promise. I agree that statics that create an object of the type being defined should be methods, to play nice with subclassing. With that in mind, we should change IDL to pass "this" to statics; if we don't have an existing issue on that, let's get one filed and just fix this. That will allow specs to do the right thing here. Whether we can change existing specs to the method semantics, I'm not sure. :(
But I'm pretty sure this mostly (only?) affects statics that create an object of the type they're defined on. I just looked (well, had our binding codegen look) through Gecko's IDL looking for such statics. The full list is:
It's too bad no one raised this issue about statics when fetch's Response was being specified. :( IDB not raising it I'm not surprised by, of course; there weren't many ES-aware people involved in that.
bzbarsky commentedon Nov 7, 2016
Oh, and looks like IDBLocaleAwareKeyRange is not even on by default yet...
I can't speak to whether someone would want to subclass IDBKeyRange in practice, but subclassing Response seems like a totally reasonable thing to do. :(
littledan commentedon Nov 7, 2016
It would be really great if the standards venue didn't affect the shape of the resulting API. Sounds like the three things raised in this thread have a path towards resolution. Would it be reasonable to start a policy of doing things in a more ES-type style when new APIs come up (sounds like enumerability is the big one here)? For enumerability on the JS side, there seems to be a strong feeling in TC39 that we couldn't add more enumerable methods to existing objects without breaking existing code.
bzbarsky commentedon Nov 7, 2016
Yes, it would, though we have a huge legacy of it having done just that. We had this exact conversation 4-5 years ago (not you and I, but various people involved in ES and web specs) and absolutely nothing changed as a result. :(
Why not in a more IDL-type style? Honest question, not trolling.
Oh, on the DOM side we can't remove enumerability from existing objects without breaking existing code. Or more precisely, we know there are some we can't remove it from, but we don't know which things are in that bucket, necessarily.
This is all be a discussion about new things that are added; for existing stuff we're stuck with what we have, I'm afraid.
littledan commentedon Nov 8, 2016
@bzbarsky Definitely agree about not changing existing things.
The reason we don't make new things enumerable in ECMAScript (I believe) is that we're concerned about breaking the web. Maybe this claim that new enumerable properties the web would break isn't true, if other parts of the web platform have been getting away with it, but it makes me concerned.
bzbarsky commentedon Nov 8, 2016
I think this claim is perhaps true for new properties added on existing objects, and especially on Array.prototype and Object.prototype, because those two would break a lot of for-in loops.
I think adding enumerable stuff elsewhere would not have broken the web, and adding it on entirely new things is very unlikely to do so.
Only install @@toStringTag on the prototype
littledan commentedon Dec 9, 2018
(This issue could use the jsidl tag.)
Only install @@toStringTag on interface prototype objects
Only install @@toStringTag on interface prototype objects
Only install @@toStringTag on interface prototype objects