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)
delete
semantics (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 propertyP
in the original objectO
, and does not follow the prototype chain- In particular, an inherited property
P
which 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
CheckObjectCoercible
for the base value. In practice, throw aTypeError
if the base value isnull
orundefined
. - 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
O
isnull
orundefined
, 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
O
isnull
orundefined
, throw aTypeError
P
=ToString(P)
- If
O
is an object, call[[Delete]](O, P, currStrict)
, and return its result - Else
O
is 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, andThrow
isfalse
(ifThrow
istrue
, 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
delete
in 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
Boolean
instance: no own properties - a
Number
instance: no own properties - a
String
instance: haslength
and 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
O
isnull
orundefined
, throw aTypeError
P
=ToString(P)
- If
O
is an object, call[[Delete]](O, P, currStrict)
and return its result - Else
O
is primitive: a. IfO
is a boolean, returntrue
b. IfO
is a number, returntrue
c. IfO
is a string: 1. IfP
is length or an array index inside theO
string length: a. IfcurrStrict
istrue
, throw aTypeError
b. Else, returnfalse
2. Else, returntrue
d. Returntrue
(This step should never be reached, as the checks above are comprehensive.)
Step 4 can be simplified a bit:
- If
O
isnull
orundefined
, throw aTypeError
P
=ToString(P)
- If
O
is an object, call[[Delete]](O, P, currStrict)
and return its result - If
O
is a string: a. IfP
is length or an array index inside theO
string length: 1. IfcurrStrict
istrue
, throw aTypeError
2. 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.