10.5 Proxy Object Internal Methods and Internal Slots
A proxy object is an
An object is a Proxy exotic object if its essential internal methods (including [[Call]] and [[Construct]], if applicable) use the definitions in this section. These internal methods are installed in
Internal Method | Handler Method |
---|---|
[[GetPrototypeOf]] |
getPrototypeOf
|
[[SetPrototypeOf]] |
setPrototypeOf
|
[[IsExtensible]] |
isExtensible
|
[[PreventExtensions]] |
preventExtensions
|
[[GetOwnProperty]] |
getOwnPropertyDescriptor
|
[[DefineOwnProperty]] |
defineProperty
|
[[HasProperty]] |
has
|
[[Get]] |
get
|
[[Set]] |
set
|
[[Delete]] |
deleteProperty
|
[[OwnPropertyKeys]] |
ownKeys
|
[[Call]] |
apply
|
[[Construct]] |
construct
|
When a handler method is called to provide the implementation of a proxy object internal method, the handler method is passed the proxy's target object as a parameter. A proxy's handler object does not necessarily have a method corresponding to every essential internal method. Invoking an internal method on the proxy results in the invocation of the corresponding internal method on the proxy's target object if the handler object does not have a method corresponding to the internal trap.
The [[ProxyHandler]] and [[ProxyTarget]] internal slots of a proxy object are always initialized when the object is created and typically may not be modified. Some proxy objects are created in a manner that permits them to be subsequently revoked. When a proxy is revoked, its [[ProxyHandler]] and [[ProxyTarget]] internal slots are set to
Because proxy objects permit the implementation of internal methods to be provided by arbitrary ECMAScript code, it is possible to define a proxy object whose handler methods violates the invariants defined in
In the following algorithm descriptions, assume O is an ECMAScript proxy object, P is a property key value, V is any
10.5.1 [[GetPrototypeOf]] ( )
The [[GetPrototypeOf]] internal method of a
- Let handler be O.[[ProxyHandler]].
- If handler is
null , throw aTypeError exception. Assert :Type (handler) is Object.- Let target be O.[[ProxyTarget]].
- Let trap be ?
GetMethod (handler,"getPrototypeOf" ). - If trap is
undefined , then- Return ? target.[[GetPrototypeOf]]().
- Let handlerProto be ?
Call (trap, handler, « target »). - If
Type (handlerProto) is neither Object nor Null, throw aTypeError exception. - Let extensibleTarget be ?
IsExtensible (target). - If extensibleTarget is
true , return handlerProto. - Let targetProto be ? target.[[GetPrototypeOf]]().
- If
SameValue (handlerProto, targetProto) isfalse , throw aTypeError exception. - Return handlerProto.
[[GetPrototypeOf]] for proxy objects enforces the following invariants:
-
The result of [[GetPrototypeOf]] must be either an Object or
null . - If the target object is not extensible, [[GetPrototypeOf]] applied to the proxy object must return the same value as [[GetPrototypeOf]] applied to the proxy object's target object.
10.5.2 [[SetPrototypeOf]] ( V )
The [[SetPrototypeOf]] internal method of a
Assert : EitherType (V) is Object orType (V) is Null.- Let handler be O.[[ProxyHandler]].
- If handler is
null , throw aTypeError exception. Assert :Type (handler) is Object.- Let target be O.[[ProxyTarget]].
- Let trap be ?
GetMethod (handler,"setPrototypeOf" ). - If trap is
undefined , then- Return ? target.[[SetPrototypeOf]](V).
- Let booleanTrapResult be !
ToBoolean (?Call (trap, handler, « target, V »)). - If booleanTrapResult is
false , returnfalse . - Let extensibleTarget be ?
IsExtensible (target). - If extensibleTarget is
true , returntrue . - Let targetProto be ? target.[[GetPrototypeOf]]().
- If
SameValue (V, targetProto) isfalse , throw aTypeError exception. - Return
true .
[[SetPrototypeOf]] for proxy objects enforces the following invariants:
- The result of [[SetPrototypeOf]] is a Boolean value.
- If the target object is not extensible, the argument value must be the same as the result of [[GetPrototypeOf]] applied to target object.
10.5.3 [[IsExtensible]] ( )
The [[IsExtensible]] internal method of a
- Let handler be O.[[ProxyHandler]].
- If handler is
null , throw aTypeError exception. Assert :Type (handler) is Object.- Let target be O.[[ProxyTarget]].
- Let trap be ?
GetMethod (handler,"isExtensible" ). - If trap is
undefined , then- Return ?
IsExtensible (target).
- Return ?
- Let booleanTrapResult be !
ToBoolean (?Call (trap, handler, « target »)). - Let targetResult be ?
IsExtensible (target). - If
SameValue (booleanTrapResult, targetResult) isfalse , throw aTypeError exception. - Return booleanTrapResult.
[[IsExtensible]] for proxy objects enforces the following invariants:
- The result of [[IsExtensible]] is a Boolean value.
- [[IsExtensible]] applied to the proxy object must return the same value as [[IsExtensible]] applied to the proxy object's target object with the same argument.
10.5.4 [[PreventExtensions]] ( )
The [[PreventExtensions]] internal method of a
- Let handler be O.[[ProxyHandler]].
- If handler is
null , throw aTypeError exception. Assert :Type (handler) is Object.- Let target be O.[[ProxyTarget]].
- Let trap be ?
GetMethod (handler,"preventExtensions" ). - If trap is
undefined , then- Return ? target.[[PreventExtensions]]().
- Let booleanTrapResult be !
ToBoolean (?Call (trap, handler, « target »)). - If booleanTrapResult is
true , then- Let extensibleTarget be ?
IsExtensible (target). - If extensibleTarget is
true , throw aTypeError exception.
- Let extensibleTarget be ?
- Return booleanTrapResult.
[[PreventExtensions]] for proxy objects enforces the following invariants:
- The result of [[PreventExtensions]] is a Boolean value.
-
[[PreventExtensions]] applied to the proxy object only returns
true if [[IsExtensible]] applied to the proxy object's target object isfalse .
10.5.5 [[GetOwnProperty]] ( P )
The [[GetOwnProperty]] internal method of a
Assert :IsPropertyKey (P) istrue .- Let handler be O.[[ProxyHandler]].
- If handler is
null , throw aTypeError exception. Assert :Type (handler) is Object.- Let target be O.[[ProxyTarget]].
- Let trap be ?
GetMethod (handler,"getOwnPropertyDescriptor" ). - If trap is
undefined , then- Return ? target.[[GetOwnProperty]](P).
- Let trapResultObj be ?
Call (trap, handler, « target, P »). - If
Type (trapResultObj) is neither Object nor Undefined, throw aTypeError exception. - Let targetDesc be ? target.[[GetOwnProperty]](P).
- If trapResultObj is
undefined , then- If targetDesc is
undefined , returnundefined . - If targetDesc.[[Configurable]] is
false , throw aTypeError exception. - Let extensibleTarget be ?
IsExtensible (target). - If extensibleTarget is
false , throw aTypeError exception. - Return
undefined .
- If targetDesc is
- Let extensibleTarget be ?
IsExtensible (target). - Let resultDesc be ?
ToPropertyDescriptor (trapResultObj). - Call
CompletePropertyDescriptor (resultDesc). - Let valid be
IsCompatiblePropertyDescriptor (extensibleTarget, resultDesc, targetDesc). - If valid is
false , throw aTypeError exception. - If resultDesc.[[Configurable]] is
false , then- If targetDesc is
undefined or targetDesc.[[Configurable]] istrue , then- Throw a
TypeError exception.
- Throw a
- If resultDesc has a [[Writable]] field and resultDesc.[[Writable]] is
false , then- If targetDesc.[[Writable]] is
true , throw aTypeError exception.
- If targetDesc.[[Writable]] is
- If targetDesc is
- Return resultDesc.
[[GetOwnProperty]] for proxy objects enforces the following invariants:
-
The result of [[GetOwnProperty]] must be either an Object or
undefined . - A property cannot be reported as non-existent, if it exists as a non-configurable own property of the target object.
- A property cannot be reported as non-existent, if the target object is not extensible, unless it does not exist as an own property of the target object.
- A property cannot be reported as existent, if the target object is not extensible, unless it exists as an own property of the target object.
- A property cannot be reported as non-configurable, unless it exists as a non-configurable own property of the target object.
- A property cannot be reported as both non-configurable and non-writable, unless it exists as a non-configurable, non-writable own property of the target object.
10.5.6 [[DefineOwnProperty]] ( P, Desc )
The [[DefineOwnProperty]] internal method of a
Assert :IsPropertyKey (P) istrue .- Let handler be O.[[ProxyHandler]].
- If handler is
null , throw aTypeError exception. Assert :Type (handler) is Object.- Let target be O.[[ProxyTarget]].
- Let trap be ?
GetMethod (handler,"defineProperty" ). - If trap is
undefined , then- Return ? target.[[DefineOwnProperty]](P, Desc).
- Let descObj be
FromPropertyDescriptor (Desc). - Let booleanTrapResult be !
ToBoolean (?Call (trap, handler, « target, P, descObj »)). - If booleanTrapResult is
false , returnfalse . - Let targetDesc be ? target.[[GetOwnProperty]](P).
- Let extensibleTarget be ?
IsExtensible (target). - If Desc has a [[Configurable]] field and if Desc.[[Configurable]] is
false , then- Let settingConfigFalse be
true .
- Let settingConfigFalse be
- Else, let settingConfigFalse be
false . - If targetDesc is
undefined , then- If extensibleTarget is
false , throw aTypeError exception. - If settingConfigFalse is
true , throw aTypeError exception.
- If extensibleTarget is
- Else,
- If
IsCompatiblePropertyDescriptor (extensibleTarget, Desc, targetDesc) isfalse , throw aTypeError exception. - If settingConfigFalse is
true and targetDesc.[[Configurable]] istrue , throw aTypeError exception. - If
IsDataDescriptor (targetDesc) istrue , targetDesc.[[Configurable]] isfalse , and targetDesc.[[Writable]] istrue , then- If Desc has a [[Writable]] field and Desc.[[Writable]] is
false , throw aTypeError exception.
- If Desc has a [[Writable]] field and Desc.[[Writable]] is
- If
- Return
true .
[[DefineOwnProperty]] for proxy objects enforces the following invariants:
- The result of [[DefineOwnProperty]] is a Boolean value.
- A property cannot be added, if the target object is not extensible.
- A property cannot be non-configurable, unless there exists a corresponding non-configurable own property of the target object.
- A non-configurable property cannot be non-writable, unless there exists a corresponding non-configurable, non-writable own property of the target object.
-
If a property has a corresponding target object property then applying the
Property Descriptor of the property to the target object using [[DefineOwnProperty]] will not throw an exception.
10.5.7 [[HasProperty]] ( P )
The [[HasProperty]] internal method of a
Assert :IsPropertyKey (P) istrue .- Let handler be O.[[ProxyHandler]].
- If handler is
null , throw aTypeError exception. Assert :Type (handler) is Object.- Let target be O.[[ProxyTarget]].
- Let trap be ?
GetMethod (handler,"has" ). - If trap is
undefined , then- Return ? target.[[HasProperty]](P).
- Let booleanTrapResult be !
ToBoolean (?Call (trap, handler, « target, P »)). - If booleanTrapResult is
false , then- Let targetDesc be ? target.[[GetOwnProperty]](P).
- If targetDesc is not
undefined , then- If targetDesc.[[Configurable]] is
false , throw aTypeError exception. - Let extensibleTarget be ?
IsExtensible (target). - If extensibleTarget is
false , throw aTypeError exception.
- If targetDesc.[[Configurable]] is
- Return booleanTrapResult.
[[HasProperty]] for proxy objects enforces the following invariants:
- The result of [[HasProperty]] is a Boolean value.
- A property cannot be reported as non-existent, if it exists as a non-configurable own property of the target object.
- A property cannot be reported as non-existent, if it exists as an own property of the target object and the target object is not extensible.
10.5.8 [[Get]] ( P, Receiver )
The [[Get]] internal method of a
Assert :IsPropertyKey (P) istrue .- Let handler be O.[[ProxyHandler]].
- If handler is
null , throw aTypeError exception. Assert :Type (handler) is Object.- Let target be O.[[ProxyTarget]].
- Let trap be ?
GetMethod (handler,"get" ). - If trap is
undefined , then- Return ? target.[[Get]](P, Receiver).
- Let trapResult be ?
Call (trap, handler, « target, P, Receiver »). - Let targetDesc be ? target.[[GetOwnProperty]](P).
- If targetDesc is not
undefined and targetDesc.[[Configurable]] isfalse , then- If
IsDataDescriptor (targetDesc) istrue and targetDesc.[[Writable]] isfalse , then- If
SameValue (trapResult, targetDesc.[[Value]]) isfalse , throw aTypeError exception.
- If
- If
IsAccessorDescriptor (targetDesc) istrue and targetDesc.[[Get]] isundefined , then- If trapResult is not
undefined , throw aTypeError exception.
- If trapResult is not
- If
- Return trapResult.
[[Get]] for proxy objects enforces the following invariants:
-
The value reported for a property must be the same as the value of the corresponding target object property if the target object property is a non-writable, non-configurable own
data property . -
The value reported for a property must be
undefined if the corresponding target object property is a non-configurable ownaccessor property that hasundefined as its [[Get]] attribute.
10.5.9 [[Set]] ( P, V, Receiver )
The [[Set]] internal method of a
Assert :IsPropertyKey (P) istrue .- Let handler be O.[[ProxyHandler]].
- If handler is
null , throw aTypeError exception. Assert :Type (handler) is Object.- Let target be O.[[ProxyTarget]].
- Let trap be ?
GetMethod (handler,"set" ). - If trap is
undefined , then- Return ? target.[[Set]](P, V, Receiver).
- Let booleanTrapResult be !
ToBoolean (?Call (trap, handler, « target, P, V, Receiver »)). - If booleanTrapResult is
false , returnfalse . - Let targetDesc be ? target.[[GetOwnProperty]](P).
- If targetDesc is not
undefined and targetDesc.[[Configurable]] isfalse , then- If
IsDataDescriptor (targetDesc) istrue and targetDesc.[[Writable]] isfalse , then- If
SameValue (V, targetDesc.[[Value]]) isfalse , throw aTypeError exception.
- If
- If
IsAccessorDescriptor (targetDesc) istrue , then- If targetDesc.[[Set]] is
undefined , throw aTypeError exception.
- If targetDesc.[[Set]] is
- If
- Return
true .
[[Set]] for proxy objects enforces the following invariants:
- The result of [[Set]] is a Boolean value.
-
Cannot change the value of a property to be different from the value of the corresponding target object property if the corresponding target object property is a non-writable, non-configurable own
data property . -
Cannot set the value of a property if the corresponding target object property is a non-configurable own
accessor property that hasundefined as its [[Set]] attribute.
10.5.10 [[Delete]] ( P )
The [[Delete]] internal method of a
Assert :IsPropertyKey (P) istrue .- Let handler be O.[[ProxyHandler]].
- If handler is
null , throw aTypeError exception. Assert :Type (handler) is Object.- Let target be O.[[ProxyTarget]].
- Let trap be ?
GetMethod (handler,"deleteProperty" ). - If trap is
undefined , then- Return ? target.[[Delete]](P).
- Let booleanTrapResult be !
ToBoolean (?Call (trap, handler, « target, P »)). - If booleanTrapResult is
false , returnfalse . - Let targetDesc be ? target.[[GetOwnProperty]](P).
- If targetDesc is
undefined , returntrue . - If targetDesc.[[Configurable]] is
false , throw aTypeError exception. - Let extensibleTarget be ?
IsExtensible (target). - If extensibleTarget is
false , throw aTypeError exception. - Return
true .
[[Delete]] for proxy objects enforces the following invariants:
- The result of [[Delete]] is a Boolean value.
- A property cannot be reported as deleted, if it exists as a non-configurable own property of the target object.
- A property cannot be reported as deleted, if it exists as an own property of the target object and the target object is non-extensible.
10.5.11 [[OwnPropertyKeys]] ( )
The [[OwnPropertyKeys]] internal method of a
- Let handler be O.[[ProxyHandler]].
- If handler is
null , throw aTypeError exception. Assert :Type (handler) is Object.- Let target be O.[[ProxyTarget]].
- Let trap be ?
GetMethod (handler,"ownKeys" ). - If trap is
undefined , then- Return ? target.[[OwnPropertyKeys]]().
- Let trapResultArray be ?
Call (trap, handler, « target »). - Let trapResult be ?
CreateListFromArrayLike (trapResultArray, « String, Symbol »). - If trapResult contains any duplicate entries, throw a
TypeError exception. - Let extensibleTarget be ?
IsExtensible (target). - Let targetKeys be ? target.[[OwnPropertyKeys]]().
Assert : targetKeys is aList whose elements are only String and Symbol values.Assert : targetKeys contains no duplicate entries.- Let targetConfigurableKeys be a new empty
List . - Let targetNonconfigurableKeys be a new empty
List . - For each element key of targetKeys, do
- Let desc be ? target.[[GetOwnProperty]](key).
- If desc is not
undefined and desc.[[Configurable]] isfalse , then- Append key as an element of targetNonconfigurableKeys.
- Else,
- Append key as an element of targetConfigurableKeys.
- If extensibleTarget is
true and targetNonconfigurableKeys is empty, then- Return trapResult.
- Let uncheckedResultKeys be a
List whose elements are the elements of trapResult. - For each element key of targetNonconfigurableKeys, do
- If key is not an element of uncheckedResultKeys, throw a
TypeError exception. - Remove key from uncheckedResultKeys.
- If key is not an element of uncheckedResultKeys, throw a
- If extensibleTarget is
true , return trapResult. - For each element key of targetConfigurableKeys, do
- If key is not an element of uncheckedResultKeys, throw a
TypeError exception. - Remove key from uncheckedResultKeys.
- If key is not an element of uncheckedResultKeys, throw a
- If uncheckedResultKeys is not empty, throw a
TypeError exception. - Return trapResult.
[[OwnPropertyKeys]] for proxy objects enforces the following invariants:
-
The result of [[OwnPropertyKeys]] is a
List . -
The returned
List contains no duplicate entries. -
The Type of each result
List element is either String or Symbol. -
The result
List must contain the keys of all non-configurable own properties of the target object. -
If the target object is not extensible, then the result
List must contain all the keys of the own properties of the target object and no other values.
10.5.12 [[Call]] ( thisArgument, argumentsList )
The [[Call]] internal method of a
- Let handler be O.[[ProxyHandler]].
- If handler is
null , throw aTypeError exception. Assert :Type (handler) is Object.- Let target be O.[[ProxyTarget]].
- Let trap be ?
GetMethod (handler,"apply" ). - If trap is
undefined , then- Return ?
Call (target, thisArgument, argumentsList).
- Return ?
- Let argArray be !
CreateArrayFromList (argumentsList). - Return ?
Call (trap, handler, « target, thisArgument, argArray »).
A
10.5.13 [[Construct]] ( argumentsList, newTarget )
The [[Construct]] internal method of a
- Let handler be O.[[ProxyHandler]].
- If handler is
null , throw aTypeError exception. Assert :Type (handler) is Object.- Let target be O.[[ProxyTarget]].
Assert :IsConstructor (target) istrue .- Let trap be ?
GetMethod (handler,"construct" ). - If trap is
undefined , then- Return ?
Construct (target, argumentsList, newTarget).
- Return ?
- Let argArray be !
CreateArrayFromList (argumentsList). - Let newObj be ?
Call (trap, handler, « target, argArray, newTarget »). - If
Type (newObj) is not Object, throw aTypeError exception. - Return newObj.
A
[[Construct]] for proxy objects enforces the following invariants:
- The result of [[Construct]] must be an Object.
10.5.14 ProxyCreate ( target, handler )
The abstract operation ProxyCreate takes arguments target and handler. It is used to specify the creation of new Proxy exotic objects. It performs the following steps when called:
- If
Type (target) is not Object, throw aTypeError exception. - If
Type (handler) is not Object, throw aTypeError exception. - Let P be !
MakeBasicObject (« [[ProxyHandler]], [[ProxyTarget]] »). - Set P's essential internal methods, except for [[Call]] and [[Construct]], to the definitions specified in
10.5 . - If
IsCallable (target) istrue , then- Set P.[[Call]] as specified in
10.5.12 . - If
IsConstructor (target) istrue , then- Set P.[[Construct]] as specified in
10.5.13 .
- Set P.[[Construct]] as specified in
- Set P.[[Call]] as specified in
- Set P.[[ProxyTarget]] to target.
- Set P.[[ProxyHandler]] to handler.
- Return P.