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?.