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
Define that interface objects are constructors #698
Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function.
We don't normatively identify the interface object as a constructor, even if it has a [Constructor]. I guess we should.
A less obvious question is what we should do if there's no [Constructor]. Right now, I think we're aiming to install a [[Construct]] internal method that always throws, but that makes the interface object pass IsConstructor().
If the [Constructor] extended attribute appears on an interface, it indicates that the interface object for this interface will have an [[Construct]] internal method
So I think we're good here: thing with a [Constructor] have [[Construct]] and things without do not, as desired.
Though I guess that leaves open the question of the no-[Constructor] case. I just checked Gecko, and it does have a [[Constructor]] in that case, albeit one that always throws. I wonder whether the output of IsConstructor() is observable, other than by the exceptions that get thrown.
On that testcase, Chrome and Firefox log "constructing"; Safari does not (and the exception it throws is about p not being a constructor). Yay interop. ;)
But OK, if we want to spec Chrome/Firefox behavior here then we need to change something in the idl spec.
I've always assumed they had constructors (and [[Construct]] methods), just throwing ones.
I think it'd be very strange to have callable interface objects exist at all, and be reachable via the .constructor property, if they are not also [[Construct]]able.
In practice it doesn't matter much, but I do prefer keeping [[Construct]] and just saying that it throws for things without a constructor in the IDL.
There was an interesting question about feature detection that was raised the other day: how to detect a change from "no [Constructor]" to "no-arg [Constructor]". Right now, I think "call the constructor and see if it throws" is the only way in Firefox and Chrome. The Proxy thing above could be used if we changed whether [[Construct]] happens...
But maybe this is enough of an edge case that it's not an issue.
@rniwa would Safari be open to changing its behavior here, or do you know whom I should be asking about it?
FWIW, it seems there’s a number of ways to observe this distinction beyond just Proxy — pretty much anywhere IsConstructor is used, I guess. In addition to peeking out through various programmatic APIs, it can also impact evaluation of ‘bare’ syntax (third example below). Each of the following statements will throw a TypeError if Foo[[Construct]] is absent, but will not throw if it’s present:
Usually it’s throw vs don’t throw, but sometimes potentially neither throws but they still do other different things:
// If Foo[[Construct]] is present, (attempts) returning new Foo.// If Foo[[Construct]] is absent, returns new Array.Array.from.call(Foo,[]);// In practice here, the first case throws for the specific Web IDL issue under discussion,// though it’s the reverse of the other cases (i.e. throw when [[Construct]] _is_ present).
I think it'd be very strange to have callable interface objects exist at all, and be reachable via the .constructor property, if they are not also [[Construct]]able.
Thanks @shvaikalesh! Do you know if there are web platform tests for this?
I looked into how we would update the Web IDL spec to be explicit about this, and it's still kinda unclear to me, largely because the ES spec is unclear. I will open an issue on tc39/ecma262 asking for guidance.
Activity
bzbarsky commentedon Mar 26, 2019
This is the key, no? https://heycam.github.io/webidl/#Constructor specifies otherwise:
So I think we're good here: thing with a
[Constructor]have[[Construct]]and things without do not, as desired.bzbarsky commentedon Mar 26, 2019
Though I guess that leaves open the question of the no-
[Constructor]case. I just checked Gecko, and it does have a[[Constructor]]in that case, albeit one that always throws. I wonder whether the output ofIsConstructor()is observable, other than by the exceptions that get thrown.bzbarsky commentedon Mar 26, 2019
I guess you could do something where you use a DOM interface object as the
.constructorof an array and see what happens in https://tc39.github.io/ecma262/#sec-arrayspeciescreate step 6.bzbarsky commentedon Mar 26, 2019
And also whether a proxy for a DOM interface object ends up with a construct trap being called. So simple testcase:
bzbarsky commentedon Mar 26, 2019
On that testcase, Chrome and Firefox log "constructing"; Safari does not (and the exception it throws is about
pnot being a constructor). Yay interop. ;)But OK, if we want to spec Chrome/Firefox behavior here then we need to change something in the idl spec.
bzbarsky commentedon Mar 26, 2019
And admittedly it would be good if the "is a constructor" bit was near the bit that defines the steps, not way off somewhere else...
domenic commentedon Apr 3, 2019
I've always assumed they had constructors (and [[Construct]] methods), just throwing ones.
I think it'd be very strange to have callable interface objects exist at all, and be reachable via the
.constructorproperty, if they are not also [[Construct]]able.In practice it doesn't matter much, but I do prefer keeping [[Construct]] and just saying that it throws for things without a constructor in the IDL.
bzbarsky commentedon Apr 3, 2019
There was an interesting question about feature detection that was raised the other day: how to detect a change from "no [Constructor]" to "no-arg [Constructor]". Right now, I think "call the constructor and see if it throws" is the only way in Firefox and Chrome. The Proxy thing above could be used if we changed whether [[Construct]] happens...
But maybe this is enough of an edge case that it's not an issue.
@rniwa would Safari be open to changing its behavior here, or do you know whom I should be asking about it?
rniwa commentedon Apr 3, 2019
What's the benefit of implementing Chrome/Firefox behavior here?
bathos commentedon Oct 3, 2019
FWIW, it seems there’s a number of ways to observe this distinction beyond just Proxy — pretty much anywhere IsConstructor is used, I guess. In addition to peeking out through various programmatic APIs, it can also impact evaluation of ‘bare’ syntax (third example below). Each of the following statements will throw a TypeError if
Foo[[Construct]]is absent, but will not throw if it’s present:Usually it’s throw vs don’t throw, but sometimes potentially neither throws but they still do other different things:
I agree.
shvaikalesh commentedon Oct 20, 2020
This behavior was changed in
JSDOMConstructorNotConstructableshould be a constructor, aligning Safari with Chrome/Firefox.domenic commentedon Oct 20, 2020
Thanks @shvaikalesh! Do you know if there are web platform tests for this?
I looked into how we would update the Web IDL spec to be explicit about this, and it's still kinda unclear to me, largely because the ES spec is unclear. I will open an issue on tc39/ecma262 asking for guidance.
shvaikalesh commentedon Oct 20, 2020
There are tests asserting that
(class extends HTML___Element {})doesn't throw, and that's it.idlharness.jshas aFIXMEfor implementing[[Construct]]check.Test IsConstructor for all interfaces
Test IsConstructor for all interfaces
Bug 1698657 [wpt PR 28089] - Test IsConstructor for all interfaces, a…
Bug 1698657 [wpt PR 28089] - Test IsConstructor for all interfaces, a…