Removing String, Number and Boolean
On Sun, May 9, 2010 at 2:41 PM, Erik Arvidsson <erik.arvidsson at gmail.com>wrote:
We have previously discussed removing the object wrappers of string, number and boolean, referred to as String, Number and Boolean. It is too bad we forgot about these when we introduced strict mode in ES5. I hope we can remove them from Harmony?
We didn't forget. (In fact, we spent a long time working this out.) ES5/strict removes these wrappers as much as it can given the constraints. Remember that strict vs non-strict is per code, not per heap. Strict and non-strict code must co-exist in the same heap with access to the same objects. Thus, we can't actually remove the wrappers without breaking compatibility. What ES5/strict did instead is to remove from strict code the case that causes implicit wrapping -- the coercion of "this" to an object. An example is at < google-caja.googlecode.com/svn/trunk/doc/html/es5-talk/img38.html>.
As shown by this example, the net effect is that booleans still act like they inherit from Boolean.prototype, but without the wrapping confusion. Likewise of course for all primitive types.
Together, if a whole program
- only contains strict code
- never explicitly calls a wrapper constructor then it should never encounter any wrappers.
2010/5/9 Mark S. Miller <erights at google.com>:
On Sun, May 9, 2010 at 2:41 PM, Erik Arvidsson <erik.arvidsson at gmail.com> wrote:
We have previously discussed removing the object wrappers of string, number and boolean, referred to as String, Number and Boolean. It is too bad we forgot about these when we introduced strict mode in ES5. I hope we can remove them from Harmony?
We didn't forget. (In fact, we spent a long time working this out.) ES5/strict removes these wrappers as much as it can given the constraints. Remember that strict vs non-strict is per code, not per heap. Strict and non-strict code must co-exist in the same heap with access to the same objects. Thus, we can't actually remove the wrappers without breaking compatibility. What ES5/strict did instead is to remove from strict code the case that causes implicit wrapping -- the coercion of "this" to an object. An example is at google-caja.googlecode.com/svn/trunk/doc/html/es5-talk/img38.html. As shown by this example, the net effect is that booleans still act like they inherit from Boolean.prototype, but without the wrapping confusion. Likewise of course for all primitive types. Together, if a whole program
- only contains strict code
- never explicitly calls a wrapper constructor
- never explicitly calls Object(...)
- never attaches a non-strict method to a wrapper or Object prototype that returns this
On Sun, May 9, 2010 at 3:08 PM, Mike Samuel <mikesamuel at gmail.com> wrote:
2010/5/9 Mark S. Miller <erights at google.com>:
On Sun, May 9, 2010 at 2:41 PM, Erik Arvidsson <erik.arvidsson at gmail.com
wrote:
We have previously discussed removing the object wrappers of string, number and boolean, referred to as String, Number and Boolean. It is too bad we forgot about these when we introduced strict mode in ES5. I hope we can remove them from Harmony?
We didn't forget. (In fact, we spent a long time working this out.) ES5/strict removes these wrappers as much as it can given the constraints. Remember that strict vs non-strict is per code, not per heap. Strict and non-strict code must co-exist in the same heap with access to the same objects. Thus, we can't actually remove the wrappers without breaking compatibility. What ES5/strict did instead is to remove from strict code the case that causes implicit wrapping -- the coercion of "this" to an object. An example is at < google-caja.googlecode.com/svn/trunk/doc/html/es5-talk/img38.html>. As shown by this example, the net effect is that booleans still act like they inherit from Boolean.prototype, but without the wrapping confusion. Likewise of course for all primitive types.
Together, if a whole program
- only contains strict code
- never explicitly calls a wrapper constructor
- never explicitly calls Object(...)
Yes. Good catch.
- never attaches a non-strict method to a wrapper or Object prototype that returns this
The existence for a non-strict method anywhere within the whole program violates my first condition.
I was thinking about prohibiting [[Construct]] for String, Number and Boolean in strict context?
- never attaches a non-strict method to a wrapper or Object prototype that returns this
The existence for a non-strict method anywhere within the whole program violates my first condition.
On this note are builtin functions considered to be strict or non-strict? Take the following stupid example: String.prototype.toString = function() { return "Boo!"; }
"Test".charAt(0); // If builtins are strict then the result is "T" if the builtin is not strict the result should be "B"
Quick testing of this case would imply the browsers already skip the [[ToObject]] conversion, at least for string |this| to a string proto function
There are neither strict or non-strict, they are their own thing. The definitions in 10.1 and 10.4.3 relating to "function code" ("source code that is parsed as part of a FunctionBody") are not intended to apply to them. I believe tha the last time this was discussed on this list the conclusion was to think of each of the functions specifications in Chapter 15 as the specification of a unique [[Call]] or [[Construct]] abstract method for its applicable built-in function object.
Because 10.4.3 does not apply to built-in methods, its steps 2&3 (that does null/undefined to the global object and wrappering of primitive this values) also do not apply to calling them. That means that built-in methods are supposed to received their this value exactly as passed without any conversions applied. That is why , in the ES5 spec, the definition of all built-in methods were updated to cover what to do will such this values (if it hadn't already been specified in ES3).
Steps 1&2 of String.prototpe.charAt (and most other string methods) are now:
- Call CheckObjectCoercible pass the this value as its argument.
- Let S be the result of calling ToString, give it the this value as its arugment.
Step 1 will throw a TypeError for null or undefined this values. (conversion to the global object now never happens for built-ins, so in that sense you can think of them as being "strict") Step 2 was already there in ES3 as step 1.
CheckObjectCoercible is like ToObject in the exceptions its throws but does not does not create new wrapper objects like ToObject. As your experiments suggest, this seems to match what implementation were actually doing rather than what the ES3 spec. said.
Allen
From: es-discuss-bounces at mozilla.org [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Oliver Hunt Sent: Sunday, May 09, 2010 4:14 PM To: Mark S.Miller Cc: Erik Arvidsson; es-discuss at mozilla.org Subject: Re: Removing String, Number and Boolean
- never attaches a non-strict method to a wrapper or Object prototype that returns this
The existence for a non-strict method anywhere within the whole program violates my first condition.
On this note are builtin functions considered to be strict or non-strict? Take the following stupid example: String.prototype.toString = function() { return "Boo!"; }
"Test".charAt(0); // If builtins are strict then the result is "T" if the builtin is not strict the result should be "B"
Quick testing of this case would imply the browsers already skip the [[ToObject]] conversion, at least for string |this| to a string proto function
We have previously discussed removing the object wrappers of string, number and boolean, referred to as String, Number and Boolean. It is too bad we forgot about these when we introduced strict mode in ES5. I hope we can remove them from Harmony?
-- erik