Comments on April ES5 final draft standard tc39-2009-025
2009/4/25 Mark S. Miller <erights at google.com>:
JSON to be covered separately.
15.5.4.21 String.prototype.toJSON ( key ) 15.6.4.4 Boolean.prototype.toJSON ( key ) 15.7.4.8 Number.prototype.toJSON ( key )
All three of these use the same boilerplate to a) typically unwrap a wrapped primitive, and b) in all cases ensure a primitive is returned. This seems largely redundant with ToPrimitive. How about for all of these just saying
1. Return the result of calling ToPrimitive on the this value.
Alternatively, all these are already almost redundant with logic within the JSON.stringify algorithm. But slightly repairing that logic (see below), we can simply remove these three methods; simplifying the spec.
15.12.1.2 The JSON Syntactic Grammar
defines a valid JSON text in terms of tokens from defined by the
delete "from"
15.12.2 parse ( text [ , reviver ] )
The JSON format is a restricted form of ECMAScript literal.
Not quite. \u2028 and \u2029 can appear in a JSONString unescaped. But ES5 considers these to be newline characters, and so they can only appear in ES5 literal strings if escaped. We need a note to that effect.
In abstract Walk operation, step 2, what's the purpose of the IsCallable test here? I think this test should be deleted.
2.a.iii.2 Let newElement be the result of calling the [[Put]] internal method ...
This binding of newElement is never used. Which is a good thing because [[Put]] doesn't return anything anyway. Also, it is not necessarily the case that this [[Put]] will succeed. Change to
Call the [[ThrowingPut]] internal method ... and true.
2.b.i. ... Object.key ...
Should be Object.keys. Likewise in step 6.a of JO.
15.12.3 stringify ( value [ , replacer [ , space ] ] )
The value parameter is a JavaScript value is usually an object or array, ...
Insert "that" between "value" and "is".
Step 7 of Str
The unwrapping here of Strings and Numbers is redundant with that in their toJSON methods as mentioned above. However, Boolean is left out here. I think it is better to have the unwrapping of primitive wrappers here, with Boolean repaired, and to remove the redundant toJSON methods on Number.prototype, String.prototype, and Boolean.prototype.
JO and JA refer to the abstract operation "str". Should be "Str".
JA step 10.b.iii. uses "{" and "}". Should be "[" and "]".
Several of the issues I've raised in this and my earlier message were first noticed by other Googlers and raised internally.
4.2.1 Objects
Javascript code does not express explicit allocation, so I suggest deleting "allocates storage for the objects and".
5.1.7 Grammar Notation
Since a nonterminal can expand into a sequence of terminals, this can be misread as including any terminal in any possible expansion, even if it can't be an initial terminal. In practice, I believe this shorthand is only used for one terminal deep nonterminals. Not sure what is the best way to clarify. Perhaps simply "... set of all initial terminals to ...".
7.1 Unicode Format Control Characters
regular expression literals.
I think someone else already pointed out that "in identifiers" should be deleted. Once it is, why not simply include format control characters in whitespace?
7.5.1 Reserved Words
Suggest "Identifiers" and using a distinguished font, in order to emphasize that we're talking about the Identifier production. This comes up several other places: 7.5.2, 10.2.1.2,
7.5.3 Future Reserved Words
At the last meeting, we had agreed to prohibit these in strict code, effectively reserving them, but I cannot find any text stating this prohibition.
7.6 Identifiers
Unicode standard
Suggest:
7.6 IdentifierNames
IdentifierNames are interpreted according to the grammar given in the "Identifiers" section of chapter 5 of the Unicode standard
"only required" sounds like they could do more if they like. How about "required to only do..."?
Note at end of 7.8.4 String Literals
Font change in middle of word "sequence".
7.8.5 Regular Expression Literals
Should "should" be "must"?
8.6.1 Property Attributes, Table 1
Not quite true, since a configurable non-writable property can still be changed by defineProperty. How about
"to change the property's [[Value]] by assignment will not succeed."
Not quite true, since a writable non-configurable property can still be made non-writable.
8.6.2 Object Internal Properties and Methods, Table 4
Doesn't the signature of [[DefineOwnProperty]] need a return type of "→ Boolean"? Likewise for the title of 8.12.10
8.6.2 Object Internal Properties and Methods, Table 5
should this be "SpecOp(thisArg, a List of any) → any or Reference"?
Conflicts with definitions elsewhere of "function". Based on previous conversations, I think this should be
"Objects that implement this internal method are callables. Only callables that are host objects may return Reference values."
The first sentence is wrong. [[HasInstance]] tests whether the argument delegates to this object's ".prototype".
"built-in" above should probably be "native", since it applies to all objects whose behavior is defined by this spec (i.e., not host objects). "built-in" objects are specifically those that exist before execution begins, which is not the distinction you intend. This problem comes up several places, such as the next 3 rows of table 5 , the [[Match]] row, and the first paragraph of 8.7.
However, the above paragraph is still wrong. Function.prototype is not an instance of the constructor Function, though presumably it does implement [[HasInstance]]. Also, Object.create(Function.prototype) would create an instance of the constructor Function that doesn't implement [[HasInstance]]. Perhaps the distinction is: Functions are objects whose [[Class]] is "Function".
8.7 The Reference Specification Type
This use of null implies that calling a strict function as a function will bind its this to "null". This is inconsistent with previous decisions as well as, for example, Annex D "called as a function, undefined as passed as the this value." This problem reappears several places: 10.2.1.1.7, 10.2.1.2.5, step 7 of 11.2.3,
If all of these were simply changed from "null" to "undefined", I believe the only observable difference would be to correct the "this" binding of strict functions called as functions.
Separately, it s not clear what the term "binding" means above. Likewise "binding values" in the table in 10.2.1.
Note at end of 8.7.2 PutValue (V, W)
I have no idea what this means.
8.12.9 [[DefaultValue]] (hint)
Throughout the spec, when speaking of hints, String and Number appear in normal font and without quotes. However, presumably, these are actually the strings "String" and "Number". To clarify, these should have quotes and perhaps be in code font.
9.2 ToPrimitive
Should this title include the signature? Perhaps "ToPrimitive(value, PreferredType) → primitive | undefined | null
9.4 ToInteger
I think this is always representable, but I'm not sure so I thought I'd ask.
10.2.2.3 NewObjectEnvironmentRecord(O, E)
Why not make ProvideThis another parameter of NewObjectEnvironmentRecord, rather than setting it after creation? I think it would make things simpler and clearer.
10.4.2 Eval Code
"If there is no calling context or" is unnecessary, since any such circumstance cannot be a direct call.
Note at end of 10.5 Arguments Object.
"caller" and "callee" are switched here. "callee" is the specified one.
11.1.1 The this Keyword
ThisBinding?
11.4.2 The void Operator
It is obscure why GetValue is being called when its value is ignore. Perhaps a note to clarify? Also 11.14.
11.5 Multiplicative Operators
The extra "MultiplicativeExpression" in step 3 should be deleted.
Shouldn't step 5 occur between steps 2 and 3?
11.5.1 Applying the * Operator
This boilerplate code occurs several places: 11.5.2, 11.6.3. Can't it simply be replaced with ToNumber, where this conversion is already covered?
11.8.7 The in operator
This seems less useful than either doing a ToObject or just returning false. I prefer doing ToObject.
11.13.1 Simple Assignment ( = )
Nor to an accessor property with attribute value {[[Setter]]: undefined}. Likewise in Annex C.
12 Statements
Even though these two conflicting uses of "empty" are distinguished by font, it is still confusing. Also, what kind of value is "the single element empty"? For example, could one read the spec as implying that
is legal, since
is legal, and "empty" is the implicit break label of the former. See also the "empty" at end of 12.12.
12.12 Labelled Statements
or "(continue, V, L)"?
13.1 Strict Mode Restrictions
FunctionDeclaration or FunctionExpression.
I don't remember for sure, but didn't we decide to prohibit bindings of "arguments" in strict code, just as we correctly do for "eval"?
13.2.3 The [[ThrowTypeError]] Function Object
The inclusion of steps 4, 5, and 6 here look like a copy paste error.
14 Program
This implies that
should return undefined. On FF 3.0.9 it returns 3, which I had understood was correct. I also don't think this is an intended change from ES3 to ES5.
15 Standard Built-in ECMAScript Objects
Is this what we decided on, or did we decide that "unless otherwise specified" extra arguments are ignored?
Also, what's the difference between "undefined" behavior and "implementation-dependent" behavior, as is used elsewhere in the spec?
Isn't, for example, the value of RangeError.prototype's [[Prototype]] property Error.prototype and not Object.prototype?
15.1 The Global Object
I suspect that we're currently confused about whether the global object should be considered a native or host object. A browser Window object is clearly a host object. Weird.
15.1.2.1 eval (x)
Chapter 16?
15.1.2.4 isNaN (number)
I got bit by believing the summary line. Instead, because of the ToNumber in the algorithm, isNaN("") returns true. Should say "Returns true if the arguments coerces to NaN..."
Also add Note to effect that a reliable test of whether x is a NaN is "x !== x".
15.1.3 URI Handling Function Properties
What about "#"?
15.2.3.4 Object.getOwnPropertyNames ( O )
Should add a note that (unlike keys) the result includes non-enumerable own property names.
15.2.3.5 Object.create ( O [, Properties] )
Probably too radical a change to consider at this late date, but should we have allowed O to be null?
15.2.3.8 Object.seal ( O ) and 15.2.3.9 Object.freeze ( O )
Ends with text explaining failure atomicity of these operations. However, I think neither of these operations can fail.
15.2.3.11 Object.isSealed ( O )
15.2.3.12 Object.isFrozen ( O )
The first steps 3 and 4 means the same thing as the second steps 3 and 4. Both are correct. They should use the same formulation.
15.2.4 Properties of the Object Prototype Object
Should be "the initial value..."
15.3.3 Properties of the Function Constructor
This is inconsistent with 13.2 step 16, which defines these as accessors using the thrower to throw. 13.2 is correct. 15.3.4.5 steps 18 and 19, the last paragraph of 15.3.5, and Annex C make the same mistake.
15.3.4.3 step 6
"Len" should be "Let".
15.3.5.3 [[HasInstance]] (V)
does not apply to functions created by bind.
15.4.2.2 new Array (len)
Since they're equal, the end of the sentence can be simplified from "ToUint32(len)" to "len".
15.4.4.16 Array.prototype.every ( callbackfn [ , thisArg ] )
I like this. But
15.4.4.17 Array.prototype.some ( callbackfn [ , thisArg ] )
has no such sentence. How about
'some acts like the "exists" quantifier in mathematics. In particular, for an empty array, it returns false."
15.4.5.1 (Array's) [[DefineOwnProperty]] ( P, Desc, Throw )
together with
15.4.5.2 length
I'm not sure what's being said here. How do non-deletable indexes affect setting length?
15.5.5.2 [[GetOwnProperty]] ( P )
Since these numeric pseudo-properties are not enumerated by for-in loops, we should describe them as non-enumerable.
15.7.4 Properties of the Number Prototype Object
typo. Should be "if Type(value) is Number".
15.8.2.14 (Math's) random ( )
Should add a note recommending that implementations provide high enough quality randomness as to make it infeasible to infer how many times random() was called between two calls to random(). If that is unacceptable, then should add the opposite note warning that programs may so infer, creating a covert channel hazard.
15.11.5 Properties of Error Instances
Shouldn't the "name" and "message" properties of 15.11.4.(2 & 3) instead be properties on Error instances? Likewise with 15.11.7.11.
Annex C
missing close paren after "Function.prototype.call".
Shouldn't this be an early error?
JSON to be covered separately.