Ticket #281 (new defect)

Opened 1 year ago

Last modified 1 year ago

(Resolved) Compatibility fix: Automatic wrapping of primitive values that would otherwise escape

Reported by: lth Assigned to: lth
Type: defect Priority: trivial
Milestone: Component: Spec
Version: 4 Keywords:
Cc: brendan,jeffdyer,graydon,chrispi

Description

The use case here is code like this:

   var xs = []
   var label = 1
   String.prototype.capture =
       function () { this.label = label++; xs.push(this) }
   "abc".capture()
   "cde".capture()
   print(xs[0].label, xs[1].label)

The point is that in ES3 this prints 1, 2 but in ES4 (as of 2007-11-06) it prints undefined, undefined because of our non-wrapping behavior -- primitive values are true objects in ES4. This is a potential incompatibility that nobody has implemented and is therefore a little scary.

I propose the following compatible change to fix this.

If all these conditions hold:

  • we're inside a function that does not have a bound-this type
  • there is a reference to "this"
  • the value of "this" is an instance of string, int, uint, double, decimal, or boolean

then a wrapper is created and the value of "this" is replaced by the wrapper.

This is true even for the case when "this" is referenced implicitly in a function call that propagates "this".

Rationale: if the conditions hold then a method was called on a primitive value, and we want the wrapper if the method tries to observe it.

(It is certainly legal to wrap eagerly (at the point of function entry) if the conditions hold, since wrapping is not observable. In the same vein, propagation of "this" can defer wrapping if it can figure out how to do it reliably.)

The predefined methods on String.prototype will not want the wrapping to take place, and can circumvent it by putting a "this" binding on the method, eg with type AnyString?.

Attachments

Change History

follow-up: ↓ 2   Changed 1 year ago by waldemar

Clarification: I assume that "this" is wrapped eagerly, not once per reference.

It's a pity, but we may have to do this. Is there any way this wrapping could be accidentally triggered other than by putting functions on things like String.prototype?

in reply to: ↑ 1   Changed 1 year ago by lth

Replying to waldemar:

Clarification: I assume that "this" is wrapped eagerly, not once per reference.

That is correct. Wrapping may be delayed until the wrapper is first referenced but the wrapper has identity. At most one wrapper is created per activation of the wrapper-referencing function.

It's a pity, but we may have to do this. Is there any way this wrapping could be accidentally triggered other than by putting functions on things like String.prototype?

I don't think so, because the types for which wrapping occurs are explicitly enumerated, and those types are all final and immutable.

  Changed 1 year ago by lth

  • priority changed from major to trivial
  • component changed from Proposals to Spec
  • summary changed from Compatibility fix: Automatic wrapping of primitive values that would otherwise escape to (Resolved) Compatibility fix: Automatic wrapping of primitive values that would otherwise escape

Approved at the Jan 08 2008 meeting.

Note: See TracTickets for help on using tickets.