|
@@ -1,6 +1,7 @@
|
|
package goja
|
|
package goja
|
|
|
|
|
|
import (
|
|
import (
|
|
|
|
+ "fmt"
|
|
"reflect"
|
|
"reflect"
|
|
|
|
|
|
"github.com/dop251/goja/unistring"
|
|
"github.com/dop251/goja/unistring"
|
|
@@ -45,6 +46,10 @@ func (r *Runtime) newProxyObject(target, handler, proto *Object) *proxyObject {
|
|
panic(r.NewTypeError("Cannot create proxy with a revoked proxy as handler"))
|
|
panic(r.NewTypeError("Cannot create proxy with a revoked proxy as handler"))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ return r._newProxyObject(target, &jsProxyHandler{handler: handler}, proto)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (r *Runtime) _newProxyObject(target *Object, handler proxyHandler, proto *Object) *proxyObject {
|
|
v := &Object{runtime: r}
|
|
v := &Object{runtime: r}
|
|
p := &proxyObject{}
|
|
p := &proxyObject{}
|
|
v.self = p
|
|
v.self = p
|
|
@@ -73,7 +78,10 @@ func (p Proxy) Revoke() {
|
|
}
|
|
}
|
|
|
|
|
|
func (p Proxy) Handler() *Object {
|
|
func (p Proxy) Handler() *Object {
|
|
- return p.proxy.handler
|
|
|
|
|
|
+ if handler := p.proxy.handler; handler != nil {
|
|
|
|
+ return handler.toObject(p.proxy.val.runtime)
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
}
|
|
}
|
|
|
|
|
|
func (p Proxy) Target() *Object {
|
|
func (p Proxy) Target() *Object {
|
|
@@ -113,23 +121,57 @@ func (p proxyTrap) String() (name string) {
|
|
return string(p)
|
|
return string(p)
|
|
}
|
|
}
|
|
|
|
|
|
-type proxyObject struct {
|
|
|
|
- baseObject
|
|
|
|
- target *Object
|
|
|
|
|
|
+type proxyHandler interface {
|
|
|
|
+ getPrototypeOf(target *Object) (Value, bool)
|
|
|
|
+ setPrototypeOf(target *Object, proto *Object) (bool, bool)
|
|
|
|
+ isExtensible(target *Object) (bool, bool)
|
|
|
|
+ preventExtensions(target *Object) (bool, bool)
|
|
|
|
+
|
|
|
|
+ getOwnPropertyDescriptorStr(target *Object, prop unistring.String) (Value, bool)
|
|
|
|
+ getOwnPropertyDescriptorIdx(target *Object, prop valueInt) (Value, bool)
|
|
|
|
+ getOwnPropertyDescriptorSym(target *Object, prop *Symbol) (Value, bool)
|
|
|
|
+
|
|
|
|
+ definePropertyStr(target *Object, prop unistring.String, desc PropertyDescriptor) (bool, bool)
|
|
|
|
+ definePropertyIdx(target *Object, prop valueInt, desc PropertyDescriptor) (bool, bool)
|
|
|
|
+ definePropertySym(target *Object, prop *Symbol, desc PropertyDescriptor) (bool, bool)
|
|
|
|
+
|
|
|
|
+ hasStr(target *Object, prop unistring.String) (bool, bool)
|
|
|
|
+ hasIdx(target *Object, prop valueInt) (bool, bool)
|
|
|
|
+ hasSym(target *Object, prop *Symbol) (bool, bool)
|
|
|
|
+
|
|
|
|
+ getStr(target *Object, prop unistring.String, receiver Value) (Value, bool)
|
|
|
|
+ getIdx(target *Object, prop valueInt, receiver Value) (Value, bool)
|
|
|
|
+ getSym(target *Object, prop *Symbol, receiver Value) (Value, bool)
|
|
|
|
+
|
|
|
|
+ setStr(target *Object, prop unistring.String, value Value, receiver Value) (bool, bool)
|
|
|
|
+ setIdx(target *Object, prop valueInt, value Value, receiver Value) (bool, bool)
|
|
|
|
+ setSym(target *Object, prop *Symbol, value Value, receiver Value) (bool, bool)
|
|
|
|
+
|
|
|
|
+ deleteStr(target *Object, prop unistring.String) (bool, bool)
|
|
|
|
+ deleteIdx(target *Object, prop valueInt) (bool, bool)
|
|
|
|
+ deleteSym(target *Object, prop *Symbol) (bool, bool)
|
|
|
|
+
|
|
|
|
+ ownKeys(target *Object) (*Object, bool)
|
|
|
|
+ apply(target *Object, this Value, args []Value) (Value, bool)
|
|
|
|
+ construct(target *Object, args []Value, newTarget *Object) (Value, bool)
|
|
|
|
+
|
|
|
|
+ toObject(*Runtime) *Object
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type jsProxyHandler struct {
|
|
handler *Object
|
|
handler *Object
|
|
- call func(FunctionCall) Value
|
|
|
|
- ctor func(args []Value, newTarget *Object) *Object
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-func (p *proxyObject) proxyCall(trap proxyTrap, args ...Value) (Value, bool) {
|
|
|
|
- r := p.val.runtime
|
|
|
|
- if p.handler == nil {
|
|
|
|
- panic(r.NewTypeError("Proxy already revoked"))
|
|
|
|
- }
|
|
|
|
|
|
+func (h *jsProxyHandler) toObject(*Runtime) *Object {
|
|
|
|
+ return h.handler
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) proxyCall(trap proxyTrap, args ...Value) (Value, bool) {
|
|
|
|
+ r := h.handler.runtime
|
|
|
|
|
|
- if m := toMethod(r.getVStr(p.handler, unistring.String(trap.String()))); m != nil {
|
|
|
|
|
|
+ if m := toMethod(r.getVStr(h.handler, unistring.String(trap.String()))); m != nil {
|
|
return m(FunctionCall{
|
|
return m(FunctionCall{
|
|
- This: p.handler,
|
|
|
|
|
|
+ This: h.handler,
|
|
Arguments: args,
|
|
Arguments: args,
|
|
}), true
|
|
}), true
|
|
}
|
|
}
|
|
@@ -137,61 +179,196 @@ func (p *proxyObject) proxyCall(trap proxyTrap, args ...Value) (Value, bool) {
|
|
return nil, false
|
|
return nil, false
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func (h *jsProxyHandler) boolProxyCall(trap proxyTrap, args ...Value) (bool, bool) {
|
|
|
|
+ if v, ok := h.proxyCall(trap, args...); ok {
|
|
|
|
+ return v.ToBoolean(), true
|
|
|
|
+ }
|
|
|
|
+ return false, false
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) getPrototypeOf(target *Object) (Value, bool) {
|
|
|
|
+ return h.proxyCall(proxy_trap_getPrototypeOf, target)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) setPrototypeOf(target *Object, proto *Object) (bool, bool) {
|
|
|
|
+ var protoVal Value
|
|
|
|
+ if proto != nil {
|
|
|
|
+ protoVal = proto
|
|
|
|
+ } else {
|
|
|
|
+ protoVal = _null
|
|
|
|
+ }
|
|
|
|
+ return h.boolProxyCall(proxy_trap_setPrototypeOf, target, protoVal)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) isExtensible(target *Object) (bool, bool) {
|
|
|
|
+ return h.boolProxyCall(proxy_trap_isExtensible, target)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) preventExtensions(target *Object) (bool, bool) {
|
|
|
|
+ return h.boolProxyCall(proxy_trap_preventExtensions, target)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) getOwnPropertyDescriptorStr(target *Object, prop unistring.String) (Value, bool) {
|
|
|
|
+ return h.proxyCall(proxy_trap_getOwnPropertyDescriptor, target, stringValueFromRaw(prop))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) getOwnPropertyDescriptorIdx(target *Object, prop valueInt) (Value, bool) {
|
|
|
|
+ return h.proxyCall(proxy_trap_getOwnPropertyDescriptor, target, prop.toString())
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) getOwnPropertyDescriptorSym(target *Object, prop *Symbol) (Value, bool) {
|
|
|
|
+ return h.proxyCall(proxy_trap_getOwnPropertyDescriptor, target, prop)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) definePropertyStr(target *Object, prop unistring.String, desc PropertyDescriptor) (bool, bool) {
|
|
|
|
+ return h.boolProxyCall(proxy_trap_defineProperty, target, stringValueFromRaw(prop), desc.toValue(h.handler.runtime))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) definePropertyIdx(target *Object, prop valueInt, desc PropertyDescriptor) (bool, bool) {
|
|
|
|
+ return h.boolProxyCall(proxy_trap_defineProperty, target, prop.toString(), desc.toValue(h.handler.runtime))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) definePropertySym(target *Object, prop *Symbol, desc PropertyDescriptor) (bool, bool) {
|
|
|
|
+ return h.boolProxyCall(proxy_trap_defineProperty, target, prop, desc.toValue(h.handler.runtime))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) hasStr(target *Object, prop unistring.String) (bool, bool) {
|
|
|
|
+ return h.boolProxyCall(proxy_trap_has, target, stringValueFromRaw(prop))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) hasIdx(target *Object, prop valueInt) (bool, bool) {
|
|
|
|
+ return h.boolProxyCall(proxy_trap_has, target, prop.toString())
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) hasSym(target *Object, prop *Symbol) (bool, bool) {
|
|
|
|
+ return h.boolProxyCall(proxy_trap_has, target, prop)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) getStr(target *Object, prop unistring.String, receiver Value) (Value, bool) {
|
|
|
|
+ return h.proxyCall(proxy_trap_get, target, stringValueFromRaw(prop), receiver)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) getIdx(target *Object, prop valueInt, receiver Value) (Value, bool) {
|
|
|
|
+ return h.proxyCall(proxy_trap_get, target, prop.toString(), receiver)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) getSym(target *Object, prop *Symbol, receiver Value) (Value, bool) {
|
|
|
|
+ return h.proxyCall(proxy_trap_get, target, prop, receiver)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) setStr(target *Object, prop unistring.String, value Value, receiver Value) (bool, bool) {
|
|
|
|
+ return h.boolProxyCall(proxy_trap_set, target, stringValueFromRaw(prop), value, receiver)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) setIdx(target *Object, prop valueInt, value Value, receiver Value) (bool, bool) {
|
|
|
|
+ return h.boolProxyCall(proxy_trap_set, target, prop.toString(), value, receiver)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) setSym(target *Object, prop *Symbol, value Value, receiver Value) (bool, bool) {
|
|
|
|
+ return h.boolProxyCall(proxy_trap_set, target, prop, value, receiver)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) deleteStr(target *Object, prop unistring.String) (bool, bool) {
|
|
|
|
+ return h.boolProxyCall(proxy_trap_deleteProperty, target, stringValueFromRaw(prop))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) deleteIdx(target *Object, prop valueInt) (bool, bool) {
|
|
|
|
+ return h.boolProxyCall(proxy_trap_deleteProperty, target, prop.toString())
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) deleteSym(target *Object, prop *Symbol) (bool, bool) {
|
|
|
|
+ return h.boolProxyCall(proxy_trap_deleteProperty, target, prop)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) ownKeys(target *Object) (*Object, bool) {
|
|
|
|
+ if v, ok := h.proxyCall(proxy_trap_ownKeys, target); ok {
|
|
|
|
+ return h.handler.runtime.toObject(v), true
|
|
|
|
+ }
|
|
|
|
+ return nil, false
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) apply(target *Object, this Value, args []Value) (Value, bool) {
|
|
|
|
+ return h.proxyCall(proxy_trap_apply, target, this, h.handler.runtime.newArrayValues(args))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *jsProxyHandler) construct(target *Object, args []Value, newTarget *Object) (Value, bool) {
|
|
|
|
+ return h.proxyCall(proxy_trap_construct, target, h.handler.runtime.newArrayValues(args), newTarget)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type proxyObject struct {
|
|
|
|
+ baseObject
|
|
|
|
+ target *Object
|
|
|
|
+ handler proxyHandler
|
|
|
|
+ call func(FunctionCall) Value
|
|
|
|
+ ctor func(args []Value, newTarget *Object) *Object
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (p *proxyObject) checkHandler() proxyHandler {
|
|
|
|
+ r := p.val.runtime
|
|
|
|
+ if handler := p.handler; handler != nil {
|
|
|
|
+ return handler
|
|
|
|
+ }
|
|
|
|
+ panic(r.NewTypeError("Proxy already revoked"))
|
|
|
|
+}
|
|
|
|
+
|
|
func (p *proxyObject) proto() *Object {
|
|
func (p *proxyObject) proto() *Object {
|
|
- if v, ok := p.proxyCall(proxy_trap_getPrototypeOf, p.target); ok {
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if v, ok := p.checkHandler().getPrototypeOf(target); ok {
|
|
var handlerProto *Object
|
|
var handlerProto *Object
|
|
if v != _null {
|
|
if v != _null {
|
|
handlerProto = p.val.runtime.toObject(v)
|
|
handlerProto = p.val.runtime.toObject(v)
|
|
}
|
|
}
|
|
- if !p.target.self.isExtensible() && !p.__sameValue(handlerProto, p.target.self.proto()) {
|
|
|
|
|
|
+ if !target.self.isExtensible() && !p.__sameValue(handlerProto, target.self.proto()) {
|
|
panic(p.val.runtime.NewTypeError("'getPrototypeOf' on proxy: proxy target is non-extensible but the trap did not return its actual prototype"))
|
|
panic(p.val.runtime.NewTypeError("'getPrototypeOf' on proxy: proxy target is non-extensible but the trap did not return its actual prototype"))
|
|
}
|
|
}
|
|
return handlerProto
|
|
return handlerProto
|
|
}
|
|
}
|
|
|
|
|
|
- return p.target.self.proto()
|
|
|
|
|
|
+ return target.self.proto()
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) setProto(proto *Object, throw bool) bool {
|
|
func (p *proxyObject) setProto(proto *Object, throw bool) bool {
|
|
- if v, ok := p.proxyCall(proxy_trap_setPrototypeOf, p.target, proto); ok {
|
|
|
|
- if v.ToBoolean() {
|
|
|
|
- if !p.target.self.isExtensible() && !p.__sameValue(proto, p.target.self.proto()) {
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if v, ok := p.checkHandler().setPrototypeOf(target, proto); ok {
|
|
|
|
+ if v {
|
|
|
|
+ if !target.self.isExtensible() && !p.__sameValue(proto, target.self.proto()) {
|
|
panic(p.val.runtime.NewTypeError("'setPrototypeOf' on proxy: trap returned truish for setting a new prototype on the non-extensible proxy target"))
|
|
panic(p.val.runtime.NewTypeError("'setPrototypeOf' on proxy: trap returned truish for setting a new prototype on the non-extensible proxy target"))
|
|
}
|
|
}
|
|
return true
|
|
return true
|
|
} else {
|
|
} else {
|
|
p.val.runtime.typeErrorResult(throw, "'setPrototypeOf' on proxy: trap returned falsish")
|
|
p.val.runtime.typeErrorResult(throw, "'setPrototypeOf' on proxy: trap returned falsish")
|
|
|
|
+ return false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- return p.target.self.setProto(proto, throw)
|
|
|
|
|
|
+ return target.self.setProto(proto, throw)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) isExtensible() bool {
|
|
func (p *proxyObject) isExtensible() bool {
|
|
- if v, ok := p.proxyCall(proxy_trap_isExtensible, p.target); ok {
|
|
|
|
- booleanTrapResult := v.ToBoolean()
|
|
|
|
- if te := p.target.self.isExtensible(); booleanTrapResult != te {
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if booleanTrapResult, ok := p.checkHandler().isExtensible(p.target); ok {
|
|
|
|
+ if te := target.self.isExtensible(); booleanTrapResult != te {
|
|
panic(p.val.runtime.NewTypeError("'isExtensible' on proxy: trap result does not reflect extensibility of proxy target (which is '%v')", te))
|
|
panic(p.val.runtime.NewTypeError("'isExtensible' on proxy: trap result does not reflect extensibility of proxy target (which is '%v')", te))
|
|
}
|
|
}
|
|
return booleanTrapResult
|
|
return booleanTrapResult
|
|
}
|
|
}
|
|
|
|
|
|
- return p.target.self.isExtensible()
|
|
|
|
|
|
+ return target.self.isExtensible()
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) preventExtensions(throw bool) bool {
|
|
func (p *proxyObject) preventExtensions(throw bool) bool {
|
|
- if v, ok := p.proxyCall(proxy_trap_preventExtensions, p.target); ok {
|
|
|
|
- booleanTrapResult := v.ToBoolean()
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if booleanTrapResult, ok := p.checkHandler().preventExtensions(target); ok {
|
|
if !booleanTrapResult {
|
|
if !booleanTrapResult {
|
|
p.val.runtime.typeErrorResult(throw, "'preventExtensions' on proxy: trap returned falsish")
|
|
p.val.runtime.typeErrorResult(throw, "'preventExtensions' on proxy: trap returned falsish")
|
|
return false
|
|
return false
|
|
}
|
|
}
|
|
- if te := p.target.self.isExtensible(); booleanTrapResult && te {
|
|
|
|
|
|
+ if te := target.self.isExtensible(); booleanTrapResult && te {
|
|
panic(p.val.runtime.NewTypeError("'preventExtensions' on proxy: trap returned truish but the proxy target is extensible"))
|
|
panic(p.val.runtime.NewTypeError("'preventExtensions' on proxy: trap returned truish but the proxy target is extensible"))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- return p.target.self.preventExtensions(throw)
|
|
|
|
|
|
+ return target.self.preventExtensions(throw)
|
|
}
|
|
}
|
|
|
|
|
|
func propToValueProp(v Value) *valueProperty {
|
|
func propToValueProp(v Value) *valueProperty {
|
|
@@ -209,99 +386,124 @@ func propToValueProp(v Value) *valueProperty {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-func (p *proxyObject) proxyDefineOwnProperty(name Value, descr PropertyDescriptor, throw bool) (bool, bool) {
|
|
|
|
- if v, ok := p.proxyCall(proxy_trap_defineProperty, p.target, name, descr.toValue(p.val.runtime)); ok {
|
|
|
|
- booleanTrapResult := v.ToBoolean()
|
|
|
|
- if !booleanTrapResult {
|
|
|
|
- p.val.runtime.typeErrorResult(throw, "'defineProperty' on proxy: trap returned falsish")
|
|
|
|
- return false, true
|
|
|
|
|
|
+func (p *proxyObject) proxyDefineOwnPropertyPreCheck(trapResult, throw bool) bool {
|
|
|
|
+ if !trapResult {
|
|
|
|
+ p.val.runtime.typeErrorResult(throw, "'defineProperty' on proxy: trap returned falsish")
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ return true
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (p *proxyObject) proxyDefineOwnPropertyPostCheck(prop Value, target *Object, descr PropertyDescriptor) {
|
|
|
|
+ targetDesc := propToValueProp(prop)
|
|
|
|
+ extensibleTarget := target.self.isExtensible()
|
|
|
|
+ settingConfigFalse := descr.Configurable == FLAG_FALSE
|
|
|
|
+ if targetDesc == nil {
|
|
|
|
+ if !extensibleTarget {
|
|
|
|
+ panic(p.val.runtime.NewTypeError())
|
|
}
|
|
}
|
|
- targetDesc := propToValueProp(p.target.getOwnProp(name))
|
|
|
|
- extensibleTarget := p.target.self.isExtensible()
|
|
|
|
- settingConfigFalse := descr.Configurable == FLAG_FALSE
|
|
|
|
- if targetDesc == nil {
|
|
|
|
- if !extensibleTarget {
|
|
|
|
- panic(p.val.runtime.NewTypeError())
|
|
|
|
- }
|
|
|
|
- if settingConfigFalse {
|
|
|
|
- panic(p.val.runtime.NewTypeError())
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- if !p.__isCompatibleDescriptor(extensibleTarget, &descr, targetDesc) {
|
|
|
|
- panic(p.val.runtime.NewTypeError())
|
|
|
|
- }
|
|
|
|
- if settingConfigFalse && targetDesc.configurable {
|
|
|
|
|
|
+ if settingConfigFalse {
|
|
|
|
+ panic(p.val.runtime.NewTypeError())
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ if !p.__isCompatibleDescriptor(extensibleTarget, &descr, targetDesc) {
|
|
|
|
+ panic(p.val.runtime.NewTypeError())
|
|
|
|
+ }
|
|
|
|
+ if settingConfigFalse && targetDesc.configurable {
|
|
|
|
+ panic(p.val.runtime.NewTypeError())
|
|
|
|
+ }
|
|
|
|
+ if targetDesc.value != nil && !targetDesc.configurable && targetDesc.writable {
|
|
|
|
+ if descr.Writable == FLAG_FALSE {
|
|
panic(p.val.runtime.NewTypeError())
|
|
panic(p.val.runtime.NewTypeError())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- return booleanTrapResult, true
|
|
|
|
}
|
|
}
|
|
- return false, false
|
|
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
|
|
func (p *proxyObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
|
|
- if v, ok := p.proxyDefineOwnProperty(stringValueFromRaw(name), descr, throw); ok {
|
|
|
|
- return v
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if booleanTrapResult, ok := p.checkHandler().definePropertyStr(target, name, descr); ok {
|
|
|
|
+ if !p.proxyDefineOwnPropertyPreCheck(booleanTrapResult, throw) {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ p.proxyDefineOwnPropertyPostCheck(target.self.getOwnPropStr(name), target, descr)
|
|
|
|
+ return true
|
|
}
|
|
}
|
|
- return p.target.self.defineOwnPropertyStr(name, descr, throw)
|
|
|
|
|
|
+ return target.self.defineOwnPropertyStr(name, descr, throw)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool {
|
|
func (p *proxyObject) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool {
|
|
- if v, ok := p.proxyDefineOwnProperty(idx, descr, throw); ok {
|
|
|
|
- return v
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if booleanTrapResult, ok := p.checkHandler().definePropertyIdx(target, idx, descr); ok {
|
|
|
|
+ if !p.proxyDefineOwnPropertyPreCheck(booleanTrapResult, throw) {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ p.proxyDefineOwnPropertyPostCheck(target.self.getOwnPropIdx(idx), target, descr)
|
|
|
|
+ return true
|
|
}
|
|
}
|
|
- return p.target.self.defineOwnPropertyIdx(idx, descr, throw)
|
|
|
|
|
|
+
|
|
|
|
+ return target.self.defineOwnPropertyIdx(idx, descr, throw)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) defineOwnPropertySym(s *Symbol, descr PropertyDescriptor, throw bool) bool {
|
|
func (p *proxyObject) defineOwnPropertySym(s *Symbol, descr PropertyDescriptor, throw bool) bool {
|
|
- if v, ok := p.proxyDefineOwnProperty(s, descr, throw); ok {
|
|
|
|
- return v
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if booleanTrapResult, ok := p.checkHandler().definePropertySym(target, s, descr); ok {
|
|
|
|
+ if !p.proxyDefineOwnPropertyPreCheck(booleanTrapResult, throw) {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ p.proxyDefineOwnPropertyPostCheck(target.self.getOwnPropSym(s), target, descr)
|
|
|
|
+ return true
|
|
}
|
|
}
|
|
- return p.target.self.defineOwnPropertySym(s, descr, throw)
|
|
|
|
|
|
+
|
|
|
|
+ return target.self.defineOwnPropertySym(s, descr, throw)
|
|
}
|
|
}
|
|
|
|
|
|
-func (p *proxyObject) proxyHas(name Value) (bool, bool) {
|
|
|
|
- if v, ok := p.proxyCall(proxy_trap_has, p.target, name); ok {
|
|
|
|
- booleanTrapResult := v.ToBoolean()
|
|
|
|
- if !booleanTrapResult {
|
|
|
|
- targetDesc := propToValueProp(p.target.getOwnProp(name))
|
|
|
|
- if targetDesc != nil {
|
|
|
|
- if !targetDesc.configurable {
|
|
|
|
- panic(p.val.runtime.NewTypeError("'has' on proxy: trap returned falsish for property '%s' which exists in the proxy target as non-configurable", name.String()))
|
|
|
|
- }
|
|
|
|
- if !p.target.self.isExtensible() {
|
|
|
|
- panic(p.val.runtime.NewTypeError("'has' on proxy: trap returned falsish for property '%s' but the proxy target is not extensible", name.String()))
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+func (p *proxyObject) proxyHasChecks(targetProp Value, target *Object, name fmt.Stringer) {
|
|
|
|
+ targetDesc := propToValueProp(targetProp)
|
|
|
|
+ if targetDesc != nil {
|
|
|
|
+ if !targetDesc.configurable {
|
|
|
|
+ panic(p.val.runtime.NewTypeError("'has' on proxy: trap returned falsish for property '%s' which exists in the proxy target as non-configurable", name.String()))
|
|
|
|
+ }
|
|
|
|
+ if !target.self.isExtensible() {
|
|
|
|
+ panic(p.val.runtime.NewTypeError("'has' on proxy: trap returned falsish for property '%s' but the proxy target is not extensible", name.String()))
|
|
}
|
|
}
|
|
- return booleanTrapResult, true
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
- return false, false
|
|
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) hasPropertyStr(name unistring.String) bool {
|
|
func (p *proxyObject) hasPropertyStr(name unistring.String) bool {
|
|
- if b, ok := p.proxyHas(stringValueFromRaw(name)); ok {
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if b, ok := p.checkHandler().hasStr(target, name); ok {
|
|
|
|
+ if !b {
|
|
|
|
+ p.proxyHasChecks(target.self.getOwnPropStr(name), target, name)
|
|
|
|
+ }
|
|
return b
|
|
return b
|
|
}
|
|
}
|
|
|
|
|
|
- return p.target.self.hasPropertyStr(name)
|
|
|
|
|
|
+ return target.self.hasPropertyStr(name)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) hasPropertyIdx(idx valueInt) bool {
|
|
func (p *proxyObject) hasPropertyIdx(idx valueInt) bool {
|
|
- if b, ok := p.proxyHas(idx); ok {
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if b, ok := p.checkHandler().hasIdx(target, idx); ok {
|
|
|
|
+ if !b {
|
|
|
|
+ p.proxyHasChecks(target.self.getOwnPropIdx(idx), target, idx)
|
|
|
|
+ }
|
|
return b
|
|
return b
|
|
}
|
|
}
|
|
|
|
|
|
- return p.target.self.hasPropertyIdx(idx)
|
|
|
|
|
|
+ return target.self.hasPropertyIdx(idx)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) hasPropertySym(s *Symbol) bool {
|
|
func (p *proxyObject) hasPropertySym(s *Symbol) bool {
|
|
- if b, ok := p.proxyHas(s); ok {
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if b, ok := p.checkHandler().hasSym(target, s); ok {
|
|
|
|
+ if !b {
|
|
|
|
+ p.proxyHasChecks(target.self.getOwnPropSym(s), target, s)
|
|
|
|
+ }
|
|
return b
|
|
return b
|
|
}
|
|
}
|
|
|
|
|
|
- return p.target.self.hasPropertySym(s)
|
|
|
|
|
|
+ return target.self.hasPropertySym(s)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) hasOwnPropertyStr(name unistring.String) bool {
|
|
func (p *proxyObject) hasOwnPropertyStr(name unistring.String) bool {
|
|
@@ -316,233 +518,258 @@ func (p *proxyObject) hasOwnPropertySym(s *Symbol) bool {
|
|
return p.getOwnPropSym(s) != nil
|
|
return p.getOwnPropSym(s) != nil
|
|
}
|
|
}
|
|
|
|
|
|
-func (p *proxyObject) proxyGetOwnPropertyDescriptor(name Value) (Value, bool) {
|
|
|
|
- target := p.target
|
|
|
|
- if v, ok := p.proxyCall(proxy_trap_getOwnPropertyDescriptor, target, name); ok {
|
|
|
|
- r := p.val.runtime
|
|
|
|
-
|
|
|
|
- targetDesc := propToValueProp(target.getOwnProp(name))
|
|
|
|
-
|
|
|
|
- var trapResultObj *Object
|
|
|
|
- if v != nil && v != _undefined {
|
|
|
|
- if obj, ok := v.(*Object); ok {
|
|
|
|
- trapResultObj = obj
|
|
|
|
- } else {
|
|
|
|
- panic(r.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap returned neither object nor undefined for property '%s'", name.String()))
|
|
|
|
- }
|
|
|
|
|
|
+func (p *proxyObject) proxyGetOwnPropertyDescriptor(targetProp Value, target *Object, trapResult Value, name fmt.Stringer) Value {
|
|
|
|
+ r := p.val.runtime
|
|
|
|
+ targetDesc := propToValueProp(targetProp)
|
|
|
|
+ var trapResultObj *Object
|
|
|
|
+ if trapResult != nil && trapResult != _undefined {
|
|
|
|
+ if obj, ok := trapResult.(*Object); ok {
|
|
|
|
+ trapResultObj = obj
|
|
|
|
+ } else {
|
|
|
|
+ panic(r.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap returned neither object nor undefined for property '%s'", name.String()))
|
|
}
|
|
}
|
|
- if trapResultObj == nil {
|
|
|
|
- if targetDesc == nil {
|
|
|
|
- return nil, true
|
|
|
|
- }
|
|
|
|
- if !targetDesc.configurable {
|
|
|
|
- panic(r.NewTypeError())
|
|
|
|
- }
|
|
|
|
- if !target.self.isExtensible() {
|
|
|
|
- panic(r.NewTypeError())
|
|
|
|
- }
|
|
|
|
- return nil, true
|
|
|
|
|
|
+ }
|
|
|
|
+ if trapResultObj == nil {
|
|
|
|
+ if targetDesc == nil {
|
|
|
|
+ return nil
|
|
}
|
|
}
|
|
- extensibleTarget := target.self.isExtensible()
|
|
|
|
- resultDesc := r.toPropertyDescriptor(trapResultObj)
|
|
|
|
- resultDesc.complete()
|
|
|
|
- if !p.__isCompatibleDescriptor(extensibleTarget, &resultDesc, targetDesc) {
|
|
|
|
- panic(r.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap returned descriptor for property '%s' that is incompatible with the existing property in the proxy target", name.String()))
|
|
|
|
|
|
+ if !targetDesc.configurable {
|
|
|
|
+ panic(r.NewTypeError())
|
|
}
|
|
}
|
|
|
|
+ if !target.self.isExtensible() {
|
|
|
|
+ panic(r.NewTypeError())
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ extensibleTarget := target.self.isExtensible()
|
|
|
|
+ resultDesc := r.toPropertyDescriptor(trapResultObj)
|
|
|
|
+ resultDesc.complete()
|
|
|
|
+ if !p.__isCompatibleDescriptor(extensibleTarget, &resultDesc, targetDesc) {
|
|
|
|
+ panic(r.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap returned descriptor for property '%s' that is incompatible with the existing property in the proxy target", name.String()))
|
|
|
|
+ }
|
|
|
|
|
|
- if resultDesc.Configurable == FLAG_FALSE {
|
|
|
|
- if targetDesc == nil {
|
|
|
|
- panic(r.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property '%s' which is non-existent in the proxy target", name.String()))
|
|
|
|
- }
|
|
|
|
|
|
+ if resultDesc.Configurable == FLAG_FALSE {
|
|
|
|
+ if targetDesc == nil {
|
|
|
|
+ panic(r.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property '%s' which is non-existent in the proxy target", name.String()))
|
|
|
|
+ }
|
|
|
|
|
|
- if targetDesc.configurable {
|
|
|
|
- panic(r.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property '%s' which is configurable in the proxy target", name.String()))
|
|
|
|
- }
|
|
|
|
|
|
+ if targetDesc.configurable {
|
|
|
|
+ panic(r.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property '%s' which is configurable in the proxy target", name.String()))
|
|
}
|
|
}
|
|
|
|
|
|
- if resultDesc.Writable == FLAG_TRUE && resultDesc.Configurable == FLAG_TRUE &&
|
|
|
|
- resultDesc.Enumerable == FLAG_TRUE {
|
|
|
|
- return resultDesc.Value, true
|
|
|
|
|
|
+ if resultDesc.Writable == FLAG_FALSE && targetDesc.writable {
|
|
|
|
+ panic(r.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap reported non-configurable and writable for property '%s' which is non-configurable, non-writable in the proxy target", name.String()))
|
|
}
|
|
}
|
|
- return r.toValueProp(trapResultObj), true
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- return nil, false
|
|
|
|
|
|
+ if resultDesc.Writable == FLAG_TRUE && resultDesc.Configurable == FLAG_TRUE &&
|
|
|
|
+ resultDesc.Enumerable == FLAG_TRUE {
|
|
|
|
+ return resultDesc.Value
|
|
|
|
+ }
|
|
|
|
+ return r.toValueProp(trapResultObj)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) getOwnPropStr(name unistring.String) Value {
|
|
func (p *proxyObject) getOwnPropStr(name unistring.String) Value {
|
|
- if v, ok := p.proxyGetOwnPropertyDescriptor(stringValueFromRaw(name)); ok {
|
|
|
|
- return v
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if v, ok := p.checkHandler().getOwnPropertyDescriptorStr(target, name); ok {
|
|
|
|
+ return p.proxyGetOwnPropertyDescriptor(target.self.getOwnPropStr(name), target, v, name)
|
|
}
|
|
}
|
|
|
|
|
|
- return p.target.self.getOwnPropStr(name)
|
|
|
|
|
|
+ return target.self.getOwnPropStr(name)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) getOwnPropIdx(idx valueInt) Value {
|
|
func (p *proxyObject) getOwnPropIdx(idx valueInt) Value {
|
|
- if v, ok := p.proxyGetOwnPropertyDescriptor(idx.toString()); ok {
|
|
|
|
- return v
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if v, ok := p.checkHandler().getOwnPropertyDescriptorIdx(target, idx); ok {
|
|
|
|
+ return p.proxyGetOwnPropertyDescriptor(target.self.getOwnPropIdx(idx), target, v, idx)
|
|
}
|
|
}
|
|
|
|
|
|
- return p.target.self.getOwnPropIdx(idx)
|
|
|
|
|
|
+ return target.self.getOwnPropIdx(idx)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) getOwnPropSym(s *Symbol) Value {
|
|
func (p *proxyObject) getOwnPropSym(s *Symbol) Value {
|
|
- if v, ok := p.proxyGetOwnPropertyDescriptor(s); ok {
|
|
|
|
- return v
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if v, ok := p.checkHandler().getOwnPropertyDescriptorSym(target, s); ok {
|
|
|
|
+ return p.proxyGetOwnPropertyDescriptor(target.self.getOwnPropSym(s), target, v, s)
|
|
}
|
|
}
|
|
|
|
|
|
- return p.target.self.getOwnPropSym(s)
|
|
|
|
|
|
+ return target.self.getOwnPropSym(s)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (p *proxyObject) proxyGetChecks(targetProp, trapResult Value, name fmt.Stringer) {
|
|
|
|
+ if targetDesc, ok := targetProp.(*valueProperty); ok {
|
|
|
|
+ if !targetDesc.accessor {
|
|
|
|
+ if !targetDesc.writable && !targetDesc.configurable && !trapResult.SameAs(targetDesc.value) {
|
|
|
|
+ panic(p.val.runtime.NewTypeError("'get' on proxy: property '%s' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '%s' but got '%s')", name.String(), nilSafe(targetDesc.value), ret))
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ if !targetDesc.configurable && targetDesc.getterFunc == nil && trapResult != _undefined {
|
|
|
|
+ panic(p.val.runtime.NewTypeError("'get' on proxy: property '%s' is a non-configurable accessor property on the proxy target and does not have a getter function, but the trap did not return 'undefined' (got '%s')", name.String(), ret))
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) getStr(name unistring.String, receiver Value) Value {
|
|
func (p *proxyObject) getStr(name unistring.String, receiver Value) Value {
|
|
- if v, ok := p.proxyGet(stringValueFromRaw(name), receiver); ok {
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if receiver == nil {
|
|
|
|
+ receiver = p.val
|
|
|
|
+ }
|
|
|
|
+ if v, ok := p.checkHandler().getStr(target, name, receiver); ok {
|
|
|
|
+ p.proxyGetChecks(target.self.getOwnPropStr(name), v, name)
|
|
return v
|
|
return v
|
|
}
|
|
}
|
|
- return p.target.self.getStr(name, receiver)
|
|
|
|
|
|
+ return target.self.getStr(name, receiver)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) getIdx(idx valueInt, receiver Value) Value {
|
|
func (p *proxyObject) getIdx(idx valueInt, receiver Value) Value {
|
|
- if v, ok := p.proxyGet(idx.toString(), receiver); ok {
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if receiver == nil {
|
|
|
|
+ receiver = p.val
|
|
|
|
+ }
|
|
|
|
+ if v, ok := p.checkHandler().getIdx(target, idx, receiver); ok {
|
|
|
|
+ p.proxyGetChecks(target.self.getOwnPropIdx(idx), v, idx)
|
|
return v
|
|
return v
|
|
}
|
|
}
|
|
- return p.target.self.getIdx(idx, receiver)
|
|
|
|
|
|
+ return target.self.getIdx(idx, receiver)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) getSym(s *Symbol, receiver Value) Value {
|
|
func (p *proxyObject) getSym(s *Symbol, receiver Value) Value {
|
|
- if v, ok := p.proxyGet(s, receiver); ok {
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if receiver == nil {
|
|
|
|
+ receiver = p.val
|
|
|
|
+ }
|
|
|
|
+ if v, ok := p.checkHandler().getSym(target, s, receiver); ok {
|
|
|
|
+ p.proxyGetChecks(target.self.getOwnPropSym(s), v, s)
|
|
return v
|
|
return v
|
|
}
|
|
}
|
|
- return p.target.self.getSym(s, receiver)
|
|
|
|
|
|
|
|
|
|
+ return target.self.getSym(s, receiver)
|
|
}
|
|
}
|
|
|
|
|
|
-func (p *proxyObject) proxyGet(name, receiver Value) (Value, bool) {
|
|
|
|
- target := p.target
|
|
|
|
- if receiver == nil {
|
|
|
|
- receiver = p.val
|
|
|
|
|
|
+func (p *proxyObject) proxySetPreCheck(trapResult, throw bool, name fmt.Stringer) bool {
|
|
|
|
+ if !trapResult {
|
|
|
|
+ p.val.runtime.typeErrorResult(throw, "'set' on proxy: trap returned falsish for property '%s'", name.String())
|
|
}
|
|
}
|
|
- if v, ok := p.proxyCall(proxy_trap_get, target, name, receiver); ok {
|
|
|
|
- if targetDesc, ok := target.getOwnProp(name).(*valueProperty); ok {
|
|
|
|
- if !targetDesc.accessor {
|
|
|
|
- if !targetDesc.writable && !targetDesc.configurable && !v.SameAs(targetDesc.value) {
|
|
|
|
- panic(p.val.runtime.NewTypeError("'get' on proxy: property '%s' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '%s' but got '%s')", name.String(), nilSafe(targetDesc.value), ret))
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- if !targetDesc.configurable && targetDesc.getterFunc == nil && v != _undefined {
|
|
|
|
- panic(p.val.runtime.NewTypeError("'get' on proxy: property '%s' is a non-configurable accessor property on the proxy target and does not have a getter function, but the trap did not return 'undefined' (got '%s')", name.String(), ret))
|
|
|
|
- }
|
|
|
|
|
|
+ return trapResult
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (p *proxyObject) proxySetPostCheck(targetProp, value Value, name fmt.Stringer) {
|
|
|
|
+ if prop, ok := targetProp.(*valueProperty); ok {
|
|
|
|
+ if prop.accessor {
|
|
|
|
+ if !prop.configurable && prop.setterFunc == nil {
|
|
|
|
+ panic(p.val.runtime.NewTypeError("'set' on proxy: trap returned truish for property '%s' which exists in the proxy target as a non-configurable and non-writable accessor property without a setter", name.String()))
|
|
}
|
|
}
|
|
|
|
+ } else if !prop.configurable && !prop.writable && !p.__sameValue(prop.value, value) {
|
|
|
|
+ panic(p.val.runtime.NewTypeError("'set' on proxy: trap returned truish for property '%s' which exists in the proxy target as a non-configurable and non-writable data property with a different value", name.String()))
|
|
}
|
|
}
|
|
- return v, true
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
- return nil, false
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-func (p *proxyObject) proxySet(name, value, receiver Value, throw bool) (bool, bool) {
|
|
|
|
|
|
+func (p *proxyObject) proxySetStr(name unistring.String, value, receiver Value, throw bool) bool {
|
|
target := p.target
|
|
target := p.target
|
|
- if v, ok := p.proxyCall(proxy_trap_set, target, name, value, receiver); ok {
|
|
|
|
- if v.ToBoolean() {
|
|
|
|
- if prop, ok := target.getOwnProp(name).(*valueProperty); ok {
|
|
|
|
- if prop.accessor {
|
|
|
|
- if !prop.configurable && prop.setterFunc == nil {
|
|
|
|
- panic(p.val.runtime.NewTypeError("'set' on proxy: trap returned truish for property '%s' which exists in the proxy target as a non-configurable and non-writable accessor property without a setter", name.String()))
|
|
|
|
- }
|
|
|
|
- } else if !prop.configurable && !prop.writable && !p.__sameValue(prop.value, value) {
|
|
|
|
- panic(p.val.runtime.NewTypeError("'set' on proxy: trap returned truish for property '%s' which exists in the proxy target as a non-configurable and non-writable data property with a different value", name.String()))
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return true, true
|
|
|
|
|
|
+ if v, ok := p.checkHandler().setStr(target, name, value, receiver); ok {
|
|
|
|
+ if p.proxySetPreCheck(v, throw, name) {
|
|
|
|
+ p.proxySetPostCheck(target.self.getOwnPropStr(name), value, name)
|
|
|
|
+ return true
|
|
}
|
|
}
|
|
- if throw {
|
|
|
|
- panic(p.val.runtime.NewTypeError("'set' on proxy: trap returned falsish for property '%s'", name.String()))
|
|
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ return target.setStr(name, value, receiver, throw)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (p *proxyObject) proxySetIdx(idx valueInt, value, receiver Value, throw bool) bool {
|
|
|
|
+ target := p.target
|
|
|
|
+ if v, ok := p.checkHandler().setIdx(target, idx, value, receiver); ok {
|
|
|
|
+ if p.proxySetPreCheck(v, throw, idx) {
|
|
|
|
+ p.proxySetPostCheck(target.self.getOwnPropIdx(idx), value, idx)
|
|
|
|
+ return true
|
|
}
|
|
}
|
|
- return false, true
|
|
|
|
|
|
+ return false
|
|
}
|
|
}
|
|
|
|
+ return target.setIdx(idx, value, receiver, throw)
|
|
|
|
+}
|
|
|
|
|
|
- return false, false
|
|
|
|
|
|
+func (p *proxyObject) proxySetSym(s *Symbol, value, receiver Value, throw bool) bool {
|
|
|
|
+ target := p.target
|
|
|
|
+ if v, ok := p.checkHandler().setSym(target, s, value, receiver); ok {
|
|
|
|
+ if p.proxySetPreCheck(v, throw, s) {
|
|
|
|
+ p.proxySetPostCheck(target.self.getOwnPropSym(s), value, s)
|
|
|
|
+ return true
|
|
|
|
+ }
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ return target.setSym(s, value, receiver, throw)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) setOwnStr(name unistring.String, v Value, throw bool) bool {
|
|
func (p *proxyObject) setOwnStr(name unistring.String, v Value, throw bool) bool {
|
|
- if res, ok := p.proxySet(stringValueFromRaw(name), v, p.val, throw); ok {
|
|
|
|
- return res
|
|
|
|
- }
|
|
|
|
- return p.target.setStr(name, v, p.val, throw)
|
|
|
|
|
|
+ return p.proxySetStr(name, v, p.val, throw)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) setOwnIdx(idx valueInt, v Value, throw bool) bool {
|
|
func (p *proxyObject) setOwnIdx(idx valueInt, v Value, throw bool) bool {
|
|
- if res, ok := p.proxySet(idx.toString(), v, p.val, throw); ok {
|
|
|
|
- return res
|
|
|
|
- }
|
|
|
|
- return p.target.setIdx(idx, v, p.val, throw)
|
|
|
|
|
|
+ return p.proxySetIdx(idx, v, p.val, throw)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) setOwnSym(s *Symbol, v Value, throw bool) bool {
|
|
func (p *proxyObject) setOwnSym(s *Symbol, v Value, throw bool) bool {
|
|
- if res, ok := p.proxySet(s, v, p.val, throw); ok {
|
|
|
|
- return res
|
|
|
|
- }
|
|
|
|
- return p.target.setSym(s, v, p.val, throw)
|
|
|
|
|
|
+ return p.proxySetSym(s, v, p.val, throw)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) setForeignStr(name unistring.String, v, receiver Value, throw bool) (bool, bool) {
|
|
func (p *proxyObject) setForeignStr(name unistring.String, v, receiver Value, throw bool) (bool, bool) {
|
|
- if res, ok := p.proxySet(stringValueFromRaw(name), v, receiver, throw); ok {
|
|
|
|
- return res, true
|
|
|
|
- }
|
|
|
|
- return p.target.setStr(name, v, receiver, throw), true
|
|
|
|
|
|
+ return p.proxySetStr(name, v, receiver, throw), true
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) setForeignIdx(idx valueInt, v, receiver Value, throw bool) (bool, bool) {
|
|
func (p *proxyObject) setForeignIdx(idx valueInt, v, receiver Value, throw bool) (bool, bool) {
|
|
- if res, ok := p.proxySet(idx.toString(), v, receiver, throw); ok {
|
|
|
|
- return res, true
|
|
|
|
- }
|
|
|
|
- return p.target.setIdx(idx, v, receiver, throw), true
|
|
|
|
|
|
+ return p.proxySetIdx(idx, v, receiver, throw), true
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) setForeignSym(s *Symbol, v, receiver Value, throw bool) (bool, bool) {
|
|
func (p *proxyObject) setForeignSym(s *Symbol, v, receiver Value, throw bool) (bool, bool) {
|
|
- if res, ok := p.proxySet(s, v, receiver, throw); ok {
|
|
|
|
- return res, true
|
|
|
|
- }
|
|
|
|
- return p.target.setSym(s, v, receiver, throw), true
|
|
|
|
|
|
+ return p.proxySetSym(s, v, receiver, throw), true
|
|
}
|
|
}
|
|
|
|
|
|
-func (p *proxyObject) proxyDelete(n Value) (bool, bool) {
|
|
|
|
- target := p.target
|
|
|
|
- if v, ok := p.proxyCall(proxy_trap_deleteProperty, target, n); ok {
|
|
|
|
- if v.ToBoolean() {
|
|
|
|
- if targetDesc, ok := target.getOwnProp(n).(*valueProperty); ok {
|
|
|
|
- if !targetDesc.configurable {
|
|
|
|
- panic(p.val.runtime.NewTypeError("'deleteProperty' on proxy: property '%s' is a non-configurable property but the trap returned truish", n.String()))
|
|
|
|
- }
|
|
|
|
|
|
+func (p *proxyObject) proxyDeleteCheck(trapResult bool, targetProp Value, name fmt.Stringer, target *Object) {
|
|
|
|
+ if trapResult {
|
|
|
|
+ if targetProp == nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if targetDesc, ok := targetProp.(*valueProperty); ok {
|
|
|
|
+ if !targetDesc.configurable {
|
|
|
|
+ panic(p.val.runtime.NewTypeError("'deleteProperty' on proxy: property '%s' is a non-configurable property but the trap returned truish", name.String()))
|
|
}
|
|
}
|
|
- return true, true
|
|
|
|
}
|
|
}
|
|
- return false, true
|
|
|
|
|
|
+ if !target.self.isExtensible() {
|
|
|
|
+ panic(p.val.runtime.NewTypeError("'deleteProperty' on proxy: trap returned truish for property '%s' but the proxy target is non-extensible", name.String()))
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- return false, false
|
|
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) deleteStr(name unistring.String, throw bool) bool {
|
|
func (p *proxyObject) deleteStr(name unistring.String, throw bool) bool {
|
|
- if ret, ok := p.proxyDelete(stringValueFromRaw(name)); ok {
|
|
|
|
- return ret
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if v, ok := p.checkHandler().deleteStr(target, name); ok {
|
|
|
|
+ p.proxyDeleteCheck(v, target.self.getOwnPropStr(name), name, target)
|
|
|
|
+ return v
|
|
}
|
|
}
|
|
|
|
|
|
- return p.target.self.deleteStr(name, throw)
|
|
|
|
|
|
+ return target.self.deleteStr(name, throw)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) deleteIdx(idx valueInt, throw bool) bool {
|
|
func (p *proxyObject) deleteIdx(idx valueInt, throw bool) bool {
|
|
- if ret, ok := p.proxyDelete(idx.toString()); ok {
|
|
|
|
- return ret
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if v, ok := p.checkHandler().deleteIdx(target, idx); ok {
|
|
|
|
+ p.proxyDeleteCheck(v, target.self.getOwnPropIdx(idx), idx, target)
|
|
|
|
+ return v
|
|
}
|
|
}
|
|
|
|
|
|
- return p.target.self.deleteIdx(idx, throw)
|
|
|
|
|
|
+ return target.self.deleteIdx(idx, throw)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) deleteSym(s *Symbol, throw bool) bool {
|
|
func (p *proxyObject) deleteSym(s *Symbol, throw bool) bool {
|
|
- if ret, ok := p.proxyDelete(s); ok {
|
|
|
|
- return ret
|
|
|
|
|
|
+ target := p.target
|
|
|
|
+ if v, ok := p.checkHandler().deleteSym(target, s); ok {
|
|
|
|
+ p.proxyDeleteCheck(v, target.self.getOwnPropSym(s), s, target)
|
|
|
|
+ return v
|
|
}
|
|
}
|
|
|
|
|
|
- return p.target.self.deleteSym(s, throw)
|
|
|
|
|
|
+ return target.self.deleteSym(s, throw)
|
|
}
|
|
}
|
|
|
|
|
|
func (p *proxyObject) ownPropertyKeys(all bool, _ []Value) []Value {
|
|
func (p *proxyObject) ownPropertyKeys(all bool, _ []Value) []Value {
|
|
@@ -554,7 +781,7 @@ func (p *proxyObject) ownPropertyKeys(all bool, _ []Value) []Value {
|
|
|
|
|
|
func (p *proxyObject) proxyOwnKeys() ([]Value, bool) {
|
|
func (p *proxyObject) proxyOwnKeys() ([]Value, bool) {
|
|
target := p.target
|
|
target := p.target
|
|
- if v, ok := p.proxyCall(proxy_trap_ownKeys, p.target); ok {
|
|
|
|
|
|
+ if v, ok := p.checkHandler().ownKeys(target); ok {
|
|
keys := p.val.runtime.toObject(v)
|
|
keys := p.val.runtime.toObject(v)
|
|
var keyList []Value
|
|
var keyList []Value
|
|
keySet := make(map[Value]struct{})
|
|
keySet := make(map[Value]struct{})
|
|
@@ -623,7 +850,7 @@ func (p *proxyObject) apply(call FunctionCall) Value {
|
|
if p.call == nil {
|
|
if p.call == nil {
|
|
p.val.runtime.NewTypeError("proxy target is not a function")
|
|
p.val.runtime.NewTypeError("proxy target is not a function")
|
|
}
|
|
}
|
|
- if v, ok := p.proxyCall(proxy_trap_apply, p.target, nilSafe(call.This), p.val.runtime.newArrayValues(call.Arguments)); ok {
|
|
|
|
|
|
+ if v, ok := p.checkHandler().apply(p.target, nilSafe(call.This), call.Arguments); ok {
|
|
return v
|
|
return v
|
|
}
|
|
}
|
|
return p.call(call)
|
|
return p.call(call)
|
|
@@ -636,7 +863,7 @@ func (p *proxyObject) construct(args []Value, newTarget *Object) *Object {
|
|
if newTarget == nil {
|
|
if newTarget == nil {
|
|
newTarget = p.val
|
|
newTarget = p.val
|
|
}
|
|
}
|
|
- if v, ok := p.proxyCall(proxy_trap_construct, p.target, p.val.runtime.newArrayValues(args), newTarget); ok {
|
|
|
|
|
|
+ if v, ok := p.checkHandler().construct(p.target, args, newTarget); ok {
|
|
return p.val.runtime.toObject(v)
|
|
return p.val.runtime.toObject(v)
|
|
}
|
|
}
|
|
return p.ctor(args, newTarget)
|
|
return p.ctor(args, newTarget)
|