Closed Bug 797686 Opened 9 years ago Closed 1 year ago

Try making built-in constructor.prototype an Object instance for all built-ins

Categories

(Core :: JavaScript Engine, defect)

defect
Not set
normal

Tracking

()

RESOLVED WONTFIX

People

(Reporter: brendan, Assigned: jorendorff)

References

(Blocks 1 open bug)

Details

(Whiteboard: [js:t])

See the "Why DataView.prototype object's [[Class]] is "Object"?" thread from es-discuss, head post here:

https://mail.mozilla.org/pipermail/es-discuss/2012-September/025301.html

My late-thread attempt to summarize and propose action (namely this bug):

https://mail.mozilla.org/pipermail/es-discuss/2012-October/025432.html

The JS_InitClass API always made the prototype be firstborn of its class, yet not constructed (without JSCLASS_CONSTRUCT_PROTOTYPE, a late addition, now removed). This costs, and lies.

We hope no one counts on this misclassification. It's observable but not useful.

/be
Blocks: 656828
Several things are depending on it internally I imagine other API users depend on it also. JS_InitClass returns the prototype object, and it's convenient to stick references into reserved slots or the private slot of that object.

This would be a subtly breaking API change. It would go undetected at compile time and just cause things to assert or crash later.

So my inclination is not to try to fix things quite this way but instead to add yet another JSCLASS flag; I'll post the patch in bug 656828.
Whiteboard: [js:t]
Talked at the TC39 meeting happening now, some flies in the ointment:

1. Array.prototype needs to be an array instance, see

  var keys = concat.apply(ArrayProto, slice.call(arguments, 1));

from http://underscorejs.org/docs/underscore.html.

2. Function.prototype may need to be a no-op scripted function (_sans_ .prototype and [[Construct]] per spec, but otherwise as if self-hosted).

So plan B is to implement the change to Object for all but Array and Function.

/be
And I'm implementing plan B. Anyone see a larger set of exceptions from those in comment 2? Could be that RegExp, Boolean, Number, and String need exceptions (RegExp.prototype may need to be /(?:)/ and Boolean.prototype, Number.prototype, and String.prototype may need to convert to 0).

/be
What's the thing that requires Function.prototype to be a function?  I've seen the comments to that effect about making it a scripty thing and all in SpiderMonkey for a long time, but I've never managed to learn the underlying justification for it.  Just curious.  :-)
(And obviously that thing should be mentioned in those SpiderMonkey comments.)
(In reply to Jeff Walden [:Waldo] (remove +bmo to email) from comment #4)
> What's the thing that requires Function.prototype to be a function?  I've
> seen the comments to that effect about making it a scripty thing and all in
> SpiderMonkey for a long time, but I've never managed to learn the underlying
> justification for it.  Just curious.  :-)
I know jQuery defines a $.noop [1]. It is not Function.prototype, but I wouldn't be surprised if another library used Function.prototype for the same thing.

[1] https://github.com/jquery/jquery/blob/a5c33fe1f7872a20267ff69905561c8cc55fe3c1/src/core.js#L511
This is not yet fixed for Date.prototype nor WeakMap.prototype. Status?
I think till has had this in the back of his mind as a thing in need of doing.  At least wrt ClassSpec SpiderMonkey-internal changes.  He probably knows what's up here and could tackle this if it's worth prioritizing over other things.
Flags: needinfo?(till)
Correct. I'm using Date.prototype as a canary in bug 861219. Once the patch for that works, I'm planning to land it on Nightly and let it bake for a bit. If nothing breaks horribly, we can proceed with other builtins. (Or, I guess, independently from that, as the breakage might be different from builtin to builtin. In any case, Date.prototype will inform how to do this for the other builtins, too.)
Depends on: 861219
Flags: needinfo?(till)
Duplicate of this bug: 1133251
Blocks: es6
Depends on: 1055473
Depends on: 1189872
Depends on: 1192038
According to meeting notes, TC39 is backing off of this for Number, String, and Boolean.

> (Daniel Ehrenberg)
> 
> DE: This change breaks the web (specifically: mootools calls
> `Number.prototype.valueOf(Number.prototype)`)
> 
> https://esdiscuss.org/topic/number-prototype-not-being-an-instance-breaks-the-web-too
> https://github.com/mootools/mootools-core/issues/2711
> 
> Solution: roll back the change.
> 
> BE: Number, String, Boolean should be 
> 
> MM: To be clear: Date.prototype will be an object, not Date; RegExp.protototype will
> be an object, not RegExp. Every built-in constructor introduced after ES5 will have a
> plain object prototype.
> 
> MM: Prefer we do Number, Boolean, String together 
> 
> #### Conclusion/Resolution  
> 
> - Boolean.prototype, Number.prototype, String.prototype rolled back

Note that Array was already an exception, in ES6 as ratified:
  http://www.ecma-international.org/ecma-262/6.0/index.html#sec-properties-of-the-array-prototype-object

So was Function:
  http://www.ecma-international.org/ecma-262/6.0/index.html#sec-properties-of-the-function-prototype-object

I think the remaining prototypes that need to be changed to ordinary objects are:
* RegExp.prototype
* Error.prototype
* <NativeError>.prototype for all the various Error subclasses
> [...mentions Array, Function, Number, String, Boolean...]
> I think the remaining prototypes that need to be changed to ordinary objects are:
> * RegExp.prototype
> * Error.prototype
> * <NativeError>.prototype for all the various Error subclasses


I see that FF Nightly has already fixed Date.prototype. Thanks!
As a reminder to everyone else who might observe this bug:

Don't forget Date.prototype. There is a global communications channel lurking in there.

On platforms with this hole, we plug it but at considerable expense. See
https://github.com/google/caja/blob/master/src/com/google/caja/ses/repairES5.js#L1788
https://github.com/google/caja/blob/master/src/com/google/caja/ses/repairES5.js#L3847
and visit
https://rawgit.com/google/caja/master/src/com/google/caja/ses/explicit.html
Depends on: 1213341
Assignee: brendan → jorendorff
Depends on: 1315563
Depends on: 1318646

See bug 1318646 comment 1 why we can't make prototypes actual plain objects. This isn't actually observable outside error messages nowadays.

Status: ASSIGNED → RESOLVED
Closed: 1 year ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.