DELPROP: exposed property deletion algorithm ("delete" operator)
Background
Properties are deleted in ECMAScript code with the delete operator, e.g.:
delete foo.bar;
This involves:
- A property accessor reference (E5 Section 11.2.1)
deletesemantics (E5 Section 11.4.1)- A call to
[[Delete]]
The property accessor coercions are the same as for GetValue:
- The base reference is checked with
CheckObjectCoercible() - The property name is coerced to a string
The delete expression will then:
- Coerce the base value to an object
- Call the
[[Delete]]algorithm
Note that if the base value is not an object, a temporary object will be created by coercion. Since a deletion always operates on the "own properties" of an object, the deletion can only have side effects (error throwing) side effects. Any other effects will be lost with the temporary object. This is discussed in more detail below, for the deletion algorithm.
Notes:
[[Delete]]only checks for the propertyPin the original objectO, and does not follow the prototype chain- In particular, an inherited property
Pwhich would prevent a[[Put]]does not affect the outcome of[[Delete]]
First draft
Starting from the property accessor, then applying delete (and skipping any unused steps):
- Call
CheckObjectCoerciblefor the base value. In practice, throw aTypeErrorif the base value isnullorundefined. - Coerce property name to string using
ToString(). - Coerce base value to object using
ToObject()and call[[Delete]]with the coerced object, the coerced key, and a "Throw" flag set if the property reference is contained in strict mode code.
More formally, suppose O is the base value, P is the property name value, and currStrict is true if the property deletion expression occurred in strict code:
- If
Oisnullorundefined, throw aTypeError P=ToString(P)O=ToObject(O)- Call
O.[[Delete]](P, currStrict), and return its result
Avoiding object coercion
We want to avoid the object coercion; let's first make it more explicit:
- If
Oisnullorundefined, throw aTypeError P=ToString(P)- If
Ois an object, call[[Delete]](O, P, currStrict), and return its result - Else
Ois primitive: a.O=ToObject(O)(create temporary object) b. CallO.[[Delete]](P, currStrict), and return its result
Avoiding temporary objects
Note that a [[Delete]] only operates on the "own properties" of the target object. When the base value is not an object, the deletion operates only on the temporary object. Since the temporary object is immediately discarded, there are only two possible user visible effects:
- The return value of
[[Delete]], which is:true, if the property does not existtrue, if the property exists and could be deletedfalse, if the property exists, cannot be deleted, andThrowisfalse(ifThrowistrue, an error is thrown instead)
- Errors thrown by
[[Delete]], which happens if:- The (own) property exists, the property is non-configurable, and the Throw flag is set, i.e. we're evaluating
deletein strict code
- The (own) property exists, the property is non-configurable, and the Throw flag is set, i.e. we're evaluating
The coerced temporary object can be:
- a
Booleaninstance: no own properties - a
Numberinstance: no own properties - a
Stringinstance: haslengthand array indices (inside string length) as own properties, all non-configurable
Given these, the algorithm can be changed to avoid creation of temporaries entirely:
- If
Oisnullorundefined, throw aTypeError P=ToString(P)- If
Ois an object, call[[Delete]](O, P, currStrict)and return its result - Else
Ois primitive: a. IfOis a boolean, returntrueb. IfOis a number, returntruec. IfOis a string: 1. IfPis length or an array index inside theOstring length: a. IfcurrStrictistrue, throw aTypeErrorb. Else, returnfalse2. Else, returntrued. Returntrue(This step should never be reached, as the checks above are comprehensive.)
Step 4 can be simplified a bit:
- If
Oisnullorundefined, throw aTypeError P=ToString(P)- If
Ois an object, call[[Delete]](O, P, currStrict)and return its result - If
Ois a string: a. IfPis length or an array index inside theOstring length: 1. IfcurrStrictistrue, throw aTypeError2. Else, returnfalse - Return
true
Fast path for array indices
It would be straightforward to add a fast path for array indices, but there is no fast path in the current implementation for array index deletion. The index is always string coerced and interned.