This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 22808 (teetee) - Throw if object is constructed without new
Summary: Throw if object is constructed without new
Status: RESOLVED FIXED
Alias: teetee
Product: WebAppsWG
Classification: Unclassified
Component: WebIDL (show other bugs)
Version: unspecified
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: Cameron McCormack
QA Contact: public-webapps-bugzilla
URL:
Whiteboard: [v1]
Keywords:
Depends on:
Blocks:
 
Reported: 2013-07-25 22:27 UTC by Anne
Modified: 2016-11-03 21:15 UTC (History)
14 users (show)

See Also:


Attachments

Description Anne 2013-07-25 22:27:32 UTC
That way we can use [[Call]] for subclassing. It's the ES6 way.

We can hopefully still do this as Chrome/WebKit throw, whereas Gecko/Trident do not.
Comment 1 Boris Zbarsky 2013-07-28 18:11:26 UTC
Hmm.  We can try this; I'm a bit worried about compat impact.  :(
Comment 2 Jonas Sicking (Not reading bugmail) 2013-07-28 22:47:34 UTC
Same here. I'd add telemetry to Gecko before actually switching behavior.
Comment 3 Ms2ger 2013-09-03 07:25:49 UTC
Seems pretty pointless to break something that works.
Comment 4 Erik Arvidsson 2013-09-03 16:53:15 UTC
(In reply to comment #3)
> Seems pretty pointless to break something that works.

It doesn't work everywhere and it is future hostile.
Comment 5 Anne 2013-09-11 16:30:16 UTC
Also, at least for new objects we should no longer do this. So if we need this I suggest we call it out. E.g. by requiring LegacyConstructor or some such for those objects.
Comment 6 Anne 2013-09-16 06:40:50 UTC
Gecko: https://bugzilla.mozilla.org/show_bug.cgi?id=916644

Travis, Adrian, is this on your radar?
Comment 7 Travis Leithead [MSFT] 2013-09-16 17:15:54 UTC
I'm pretty hesitant to make this change without a web-compat analysis. I can very easily imagine lots and lots of sites that just blindly do:

var x = XMLHttpRequest();
x....

In the past, IE has run a lot of custom code on the web intended just for it. With IE11, we're starting to run much more of the Firefox/Chrome code, but in this case, not throwing is more compatible. Switching to a throwing behavior has generally made compat worse.

If you want to take on the burden of proof, that'd be great. I'm just saying that I don't think I'd want to be the one to guinea-pig this change.
Comment 8 Erik Arvidsson 2013-09-16 17:20:23 UTC
(In reply to Travis Leithead [MSFT] from comment #7)
> I'm pretty hesitant to make this change without a web-compat analysis. I can
> very easily imagine lots and lots of sites that just blindly do:
> 
> var x = XMLHttpRequest();
> x....

Remember that that throws in Safari and Chrome so it is unlikely that code on the open web would do that.
Comment 9 Boris Zbarsky 2013-09-16 17:32:44 UTC
Once I get Gecko to the point where our own code is not triggering this situation, I'll put in some telemetry to see how often this is hit in practice on the web for us....

> so it is unlikely that code on the open web would do that.

Methinks you underestimate the amount of UA-sniffing that happens "on the open web"....  I think it _very_ likely that code would do that; the only question is how common it is for users to run across that code in practice.
Comment 10 Anne 2014-12-16 12:56:12 UTC
https://bugzilla.mozilla.org/show_bug.cgi?id=916644 was fixed. Let's change IDL.
Comment 11 Boris Zbarsky 2015-01-13 03:42:16 UTC
I just looked at ES6 again, and I'd like to see the edits Allen is making to the whole [[Call]]/[[Construct]]/@@create setup right now land before we change things in IDL here.  Because we're going to need to override [[Construct]] to not invoke [[Call]] and whatnot, but the exact interaction will depend on exactly what ES looks like.
Comment 12 Erik Arvidsson 2015-02-09 17:04:25 UTC
(In reply to Boris Zbarsky from comment #11)
> I just looked at ES6 again, and I'd like to see the edits Allen is making to
> the whole [[Call]]/[[Construct]]/@@create setup right now land before we
> change things in IDL here.  Because we're going to need to override
> [[Construct]] to not invoke [[Call]] and whatnot, but the exact interaction
> will depend on exactly what ES looks like.

In ES6, constructor functions created using the class syntax gets marked with "classConstructor" and in the [[Call]] behavior,

http://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-function-objects-call-thisargument-argumentslist

we have

2. If F’s [[FunctionKind]] internal slot is "classConstructor", throw a TypeError exception.
Comment 13 Boris Zbarsky 2015-02-09 17:10:07 UTC
OK.  So it sounds like for Web IDL constructors we should make the following changes:

1)  [[Construct]] does what [[Call] does right now in the Web IDL spec.
2)  [[Call]] just throws a typeerror.

Or we could use the default [[Call]] and set the [[FunctionKind]] thing, but it seems simpler to just do the above, I think.
Comment 14 Domenic Denicola 2015-02-09 17:12:26 UTC
I'd rather do the default [[Call]] and set functionKind. functionKind might be used for other things (maybe it already is?) and in general uniformity with ES6 seems better.
Comment 15 Allen Wirfs-Brock 2015-02-09 17:20:26 UTC
(In reply to Domenic Denicola from comment #14)
> I'd rather do the default [[Call]] and set functionKind. functionKind might
> be used for other things (maybe it already is?) and in general uniformity
> with ES6 seems better.

the "default call" and the [[FunctionKind]] slots are specific to "ECMASCript Language functions".  In other words, functions whose body are implemented using ECMAScript code. 

You want to enable WebIDL methods to be implemented as ECMAScript functions but you don't want to require it.
Comment 16 Boris Zbarsky 2015-02-09 17:49:58 UTC
So I just looked through the ES6 spec.  The only other use of [[FunctionKind]] is to prevent subclassing a generator function.  This use assumes that anything without a [[FunctionKind]] slot is not a generator, so works fine with Web IDL.

What we _could_ consider is giving a [[FunctionKind]] slot to what the spec calls "Built-in Function objects" and checking it in http://people.mozilla.org/~jorendorff/es6-draft.html#sec-built-in-function-objects-call-thisargument-argumentslist (and modifying http://people.mozilla.org/~jorendorff/es6-draft.html#sec-built-in-function-objects-construct-argumentslist-newtarget to not check it, I guess).  That's assuming we don't want the existence of a [[FunctionKind]] slot to imply the function is an "ECMASCript Language function".
Comment 17 Allen Wirfs-Brock 2015-02-09 18:34:54 UTC
(In reply to Boris Zbarsky from comment #16)

The problem is that many of the ECMAScript library constructors, which are allspecified to be "Built-In Function objects", do support being "called as a function". So if we added [[FunctionKind]] to Built-in Function I would also have to specify it's setting for each ES built-in.  I might consider doing that if I wasn't within about a week of having to freeze the final ES6 draft.

As an alternative approach consider treating this similarly to what you do for parameter type checking. You can determine whether you are called by as function rather than via [[Construct]] by checking the value of NewTarget.  It has the value undefined if the function is being invoked via [[Call]]. 

So, in your WebIDL parameter checking also check NewTarget (for constructors).

This is essentially what the ES6 spec. does,  individually for each built-in constructor that is not callable.  For example see: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-map-iterable
Comment 18 Boris Zbarsky 2015-02-09 18:38:01 UTC
Ah, yes, that would work quite nicely.
Comment 19 Ms2ger 2016-04-13 16:06:31 UTC
Talked to bz on IRC; I believe he agrees that checking NewTarget is the best approach. This depends on <https://github.com/heycam/webidl/issues/106>.
Comment 20 Domenic Denicola 2016-10-22 16:05:40 UTC
https://github.com/heycam/webidl/issues/62