Comments on April ES5 final draft standard tc39-2009-025
Mark S. Miller
erights at google.com
Sat Apr 25 20:38:16 PDT 2009
4.2.1 Objects
> ... constructors which create objects by executing code that allocates storage for the objects and initializes ...
Javascript code does not express explicit allocation, so I suggest
deleting "allocates storage for the objects and".
5.1.7 Grammar Notation
> For convenience, the set can also be written as a nonterminal, in which case it represents the set of all terminals to which that nonterminal could expand.
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
> The format control characters may be used in identifiers, within comments, and within string literals and
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
> Reserved words cannot be used as identifiers.
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
> NOTE
> The identifiers 'let‘, and 'yield‘ may be used in a future version of this standard.
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
> Identifiers are interpreted according to the grammar given in the "Identifiers" section of chapter 5 of the
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
> (in other words, conforming ECMAScript implementations are only required to do bitwise comparison on identifiers)
"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
> An implementation may extend the regular expression constructor's grammar, but it should not extend the RegularExpressionBody and RegularExpressionFlags productions or the productions used by these productions.
Should "should" be "must"?
8.6.1 Property Attributes, Table 1
> [[Writable]] Boolean
> If false, attempts by ECMAScript code to change the property‘s [[Value]] attribute will not succeed.
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."
> [[Configurable]] Boolean
> If false, attempts to delete the property, change the property to be an accessor property, or change its attributes (other than [[Value]]) will fail.
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
> [[Call]]
> SpecOp(a List of any) → any or Reference
should this be "SpecOp(thisArg, a List of any) → any or Reference"?
> Executes code associated with the object. Invoked via a function call expression. The arguments to the SpecOp are the arguments passed to the function call expression.
> Objects that implement this internal method are functions. Only functions that are host objects may return Reference values.
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."
> [[HasInstance]]
> SpecOp(any) → Boolean
> Returns a Boolean value indicating whether the argument is an Object that delegates behaviour to this object. Of the standard built-in ECMAScript objects, only Objects that are instances of the standard built-in constructor Function implement [[HasInstance]].
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
> The base value is either null, an Object, a Boolean, a String, a Number, or an environment record (10.2.1). A base value of null indicates that the reference could not be resolved to a binding.
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)
> or is in violation of a Throw conditioned error check
I have no idea what this means.
8.12.9 [[DefaultValue]] (hint)
> When the [[DefaultValue]] internal method of O is called with hint String,
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
> 1. Let number be the result of calling ToNumber on the input argument.
> ...
> 4. Return the result of computing sign(number) * floor(abs(number)).
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
> 1. If there is no calling context or if the eval code is not being evaluated by a direct call
"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.
> The "caller" property has a more specific meaning for non-strict mode functions and a "callee" property has historically been provided as an implementation-defined extension by some ECMAScript implementations.
"caller" and "callee" are switched here. "callee" is the specified one.
11.1.1 The this Keyword
> The this keyword evaluates to the value of the ThisBind of the current execution context.
ThisBinding?
11.4.2 The void Operator
> 2. Call GetValue(expr).
> 3. Return undefined.
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
> 1. Let left be the result of evaluating MultiplicativeExpression.
> 2. Let leftValue be GetValue(left).
> 3. Let right be the result of evaluating MultiplicativeExpression UnaryExpression.
> 4. Let rightValue be GetValue(right).
> 5. Let leftNum be ToNumber(leftValue).
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
> If the magnitude is too large to represent, the result is then an infinity of appropriate sign. If the magnitude is too small to represent, the result is then a zero of appropriate sign. The ECMAScript language requires support of gradual underflow as defined by IEEE 754.
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
> 5. If Type(rval) is not Object, throw a TypeError exception.
This seems less useful than either doing a ToObject or just returning
false. I prefer doing ToObject.
11.13.1 Simple Assignment ( = )
> The LeftHandSide also may not be a reference to a property with the attribute value {[[Writable]]:false} nor to a non-existent property of an object whose [[Extensible]] internal property has the value false.
Nor to an accessor property with attribute value {[[Setter]]:
undefined}. Likewise in Annex C.
12 Statements
> The label set of an IterationStatement or a SwitchStatement initially contains the single element empty. The label set of any other statement is initially empty.
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
empty: { break; }
is legal, since
empty: { break empty; }
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
> If the result of evaluating Statement is (break, V, L) where L is equal to Identifier, the production results in (normal, V, empty).
or "(continue, V, L)"?
13.1 Strict Mode Restrictions
> ... if the Identifier "eval" appears within a FormalParameterList of a strict mode
FunctionDeclaration or FunctionExpression.
> ... if the Identifier "eval" appears as the Identifier of a strict mode FunctionDeclaration.
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
> 4. Set the [[Call]] internal property of F as described in 13.2.1.
> 5. Set the [[Scope]] internal property of F to the Global Environment.
> 6. Let names be a List containing, in left to right textual order, the strings corresponding to the identifiers of FormalParameterList.
The inclusion of steps 4, 5, and 6 here look like a copy paste error.
14 Program
> The production SourceElement : FunctionDeclaration is evaluated as follows:
> 1. Return (normal, empty, empty).
This implies that
eval("3; function foo(){}")
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
> Unless otherwise specified in the description of a particular function, if a function or constructor described in this section is given more arguments than the function is specified to allow, the behaviour of the function or constructor is undefined.
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?
> Every built-in prototype object has the Object prototype object, which is the initial value of the expression Object.prototype (15.2.4), as the value of its [[Prototype]] internal property, except the Object prototype object itself.
Isn't, for example, the value of RangeError.prototype's [[Prototype]]
property Error.prototype and not Object.prototype?
15.1 The Global Object
> The values of the [[Prototype]] and [[Class]] internal properties of the global object are implementation-dependent.
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)
> 2. Let prog be the ECMAScript code that is the result of parsing x as a Program. If the parse fails, throw a SyntaxError exception (but see also clause 16).
Chapter 16?
15.1.2.4 isNaN (number)
> Returns true if the argument is NaN, and otherwise returns false.
> 1. If ToNumber(number) is NaN, return true.
> 2. Otherwise, return false.
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
> uriReserved ::: one of
> ; / ? : @ & = + $ ,
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] )
> 1. If Type(O) is not Object throw a TypeError exception.
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 )
> 3. If the [[Extensible]] internal property of O is false, then return true.
> 4. Otherwise, return false.
15.2.3.12 Object.isFrozen ( O )
> 3. If the [[Extensible]] internal property of O is true, then return false.
> 4. Otherwise, return true.
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
> and the value of the [[Extensible]] internal property is true.
Should be "the initial value..."
15.3.3 Properties of the Function Constructor
> The Function constructor has properties named "caller" and "arguments" whose initial value is null. These properties have attributes: attribute {[[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false}. An ECMAScript implementation must not associate any implementation specific behaviour with access of these properties.
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)
> If the argument len is a Number and ToUint32(len) is equal to len, then the length property of the newly constructed object is set to ToUint32(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 ] )
> every acts like the "for all" quantifier in mathematics. In particular, for an empty array, it returns true.
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 )
> step 3.a.vi.2 Let cantDelete be the result of calling the [[Delete]] internal method of A passing ToString(oldLen) and false as arguments.
together with
15.4.5.2 length
> The length property of this Array object is a data property whose value is always numerically greater than the name of every deletable property whose name is an array index.
I'm not sure what's being said here. How do non-deletable indexes
affect setting length?
15.5.5.2 [[GetOwnProperty]] ( P )
> 9. Return a Property Descriptor { [[Value]]: resultStr, [[Enumerable]]: true, [[Writable]]: false, [[Configurable]]: false }
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
> if Type(this value) is Number
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
> Error instances have no special properties beyond those inherited from the Error prototype object.
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".
> When a delete operator occurs within strict mode code, a ReferenceException is thrown if its UnaryExpression is a direct reference to a variable, function argument, or function name.
Shouldn't this be an early error?
JSON to be covered separately.
--
Cheers,
--MarkM
More information about the es-discuss
mailing list