package goja import "fmt" func (r *Runtime) newNativeProxyHandler(nativeHandler *ProxyTrapConfig) *Object { handler := r.NewObject() r.proxyproto_nativehandler_gen_obj_obj(proxy_trap_getPrototypeOf, nativeHandler.GetPrototypeOf, handler) r.proxyproto_nativehandler_setPrototypeOf(nativeHandler.SetPrototypeOf, handler) r.proxyproto_nativehandler_gen_obj_bool(proxy_trap_isExtensible, nativeHandler.IsExtensible, handler) r.proxyproto_nativehandler_gen_obj_bool(proxy_trap_preventExtensions, nativeHandler.PreventExtensions, handler) r.proxyproto_nativehandler_getOwnPropertyDescriptor(nativeHandler.GetOwnPropertyDescriptor, handler) r.proxyproto_nativehandler_defineProperty(nativeHandler.DefineProperty, handler) r.proxyproto_nativehandler_gen_obj_string_bool(proxy_trap_has, nativeHandler.Has, handler) r.proxyproto_nativehandler_get(nativeHandler.Get, handler) r.proxyproto_nativehandler_set(nativeHandler.Set, handler) r.proxyproto_nativehandler_gen_obj_string_bool(proxy_trap_deleteProperty, nativeHandler.DeleteProperty, handler) r.proxyproto_nativehandler_gen_obj_obj(proxy_trap_ownKeys, nativeHandler.OwnKeys, handler) r.proxyproto_nativehandler_apply(nativeHandler.Apply, handler) r.proxyproto_nativehandler_construct(nativeHandler.Construct, handler) return handler } func (r *Runtime) proxyproto_nativehandler_gen_obj_obj(name proxyTrap, native func(*Object) *Object, handler *Object) { if native != nil { handler.self._putProp(string(name), r.newNativeFunc(func(call FunctionCall) Value { if len(call.Arguments) >= 1 { if t, ok := call.Argument(0).(*Object); ok { return native(t) } } panic(r.NewTypeError("%s needs to be called with target as Object", name)) }, nil, fmt.Sprintf("[native %s]", name), nil, 1), true, true, true) } } func (r *Runtime) proxyproto_nativehandler_setPrototypeOf(native func(*Object, *Object) bool, handler *Object) { if native != nil { handler.self._putProp("setPrototypeOf", r.newNativeFunc(func(call FunctionCall) Value { if len(call.Arguments) >= 2 { if t, ok := call.Argument(0).(*Object); ok { if p, ok := call.Argument(1).(*Object); ok { s := native(t, p) return r.ToValue(s) } } } panic(r.NewTypeError("setPrototypeOf needs to be called with target and prototype as Object")) }, nil, "[native setPrototypeOf]", nil, 2), true, true, true) } } func (r *Runtime) proxyproto_nativehandler_gen_obj_bool(name proxyTrap, native func(*Object) bool, handler *Object) { if native != nil { handler.self._putProp(string(name), r.newNativeFunc(func(call FunctionCall) Value { if len(call.Arguments) >= 1 { if t, ok := call.Argument(0).(*Object); ok { s := native(t) return r.ToValue(s) } } panic(r.NewTypeError("%s needs to be called with target as Object", name)) }, nil, fmt.Sprintf("[native %s]", name), nil, 1), true, true, true) } } func (r *Runtime) proxyproto_nativehandler_getOwnPropertyDescriptor(native func(*Object, string) PropertyDescriptor, handler *Object) { if native != nil { handler.self._putProp("getOwnPropertyDescriptor", r.newNativeFunc(func(call FunctionCall) Value { if len(call.Arguments) >= 2 { if t, ok := call.Argument(0).(*Object); ok { if p, ok := call.Argument(1).(valueString); ok { desc := native(t, p.String()) return desc.toValue(r) } } } panic(r.NewTypeError("getOwnPropertyDescriptor needs to be called with target as Object and prop as string")) }, nil, "[native getOwnPropertyDescriptor]", nil, 2), true, true, true) } } func (r *Runtime) proxyproto_nativehandler_defineProperty(native func(*Object, string, PropertyDescriptor) bool, handler *Object) { if native != nil { handler.self._putProp("defineProperty", r.newNativeFunc(func(call FunctionCall) Value { if len(call.Arguments) >= 3 { if t, ok := call.Argument(0).(*Object); ok { if k, ok := call.Argument(1).(valueString); ok { propertyDescriptor := r.toPropertyDescriptor(call.Argument(2)) s := native(t, k.String(), propertyDescriptor) return r.ToValue(s) } } } panic(r.NewTypeError("defineProperty needs to be called with target as Object and propertyDescriptor as string and key as string")) }, nil, "[native defineProperty]", nil, 3), true, true, true) } } func (r *Runtime) proxyproto_nativehandler_gen_obj_string_bool(name proxyTrap, native func(*Object, string) bool, handler *Object) { if native != nil { handler.self._putProp(string(name), r.newNativeFunc(func(call FunctionCall) Value { if len(call.Arguments) >= 2 { if t, ok := call.Argument(0).(*Object); ok { if p, ok := call.Argument(1).(valueString); ok { o := native(t, p.String()) return r.ToValue(o) } } } panic(r.NewTypeError("%s needs to be called with target as Object and property as string", name)) }, nil, fmt.Sprintf("[native %s]", name), nil, 2), true, true, true) } } func (r *Runtime) proxyproto_nativehandler_get(native func(*Object, string, *Object) Value, handler *Object) { if native != nil { handler.self._putProp("get", r.newNativeFunc(func(call FunctionCall) Value { if len(call.Arguments) >= 3 { if t, ok := call.Argument(0).(*Object); ok { if p, ok := call.Argument(1).(valueString); ok { if r, ok := call.Argument(2).(*Object); ok { return native(t, p.String(), r) } } } } panic(r.NewTypeError("get needs to be called with target and receiver as Object and property as string")) }, nil, "[native get]", nil, 3), true, true, true) } } func (r *Runtime) proxyproto_nativehandler_set(native func(*Object, string, Value, *Object) bool, handler *Object) { if native != nil { handler.self._putProp("set", r.newNativeFunc(func(call FunctionCall) Value { if len(call.Arguments) >= 4 { if t, ok := call.Argument(0).(*Object); ok { if p, ok := call.Argument(1).(valueString); ok { v := call.Argument(2) if re, ok := call.Argument(3).(*Object); ok { s := native(t, p.String(), v, re) return r.ToValue(s) } } } } panic(r.NewTypeError("set needs to be called with target and receiver as Object, property as string and value as a legal javascript value")) }, nil, "[native set]", nil, 4), true, true, true) } } func (r *Runtime) proxyproto_nativehandler_apply(native func(*Object, *Object, []Value) Value, handler *Object) { if native != nil { handler.self._putProp("apply", r.newNativeFunc(func(call FunctionCall) Value { if len(call.Arguments) >= 3 { if t, ok := call.Argument(0).(*Object); ok { if this, ok := call.Argument(1).(*Object); ok { if v, ok := call.Argument(2).(*Object); ok { if a, ok := v.self.(*arrayObject); ok { v := native(t, this, a.values) return r.ToValue(v) } } } } } panic(r.NewTypeError("apply needs to be called with target and this as Object and argumentsList as an array of legal javascript values")) }, nil, "[native apply]", nil, 3), true, true, true) } } func (r *Runtime) proxyproto_nativehandler_construct(native func(*Object, []Value, *Object) *Object, handler *Object) { if native != nil { handler.self._putProp("construct", r.newNativeFunc(func(call FunctionCall) Value { if len(call.Arguments) >= 3 { if t, ok := call.Argument(0).(*Object); ok { if v, ok := call.Argument(1).(*Object); ok { if newTarget, ok := call.Argument(2).(*Object); ok { if a, ok := v.self.(*arrayObject); ok { return native(t, a.values, newTarget) } } } } } panic(r.NewTypeError("construct needs to be called with target and newTarget as Object and argumentsList as an array of legal javascript values")) }, nil, "[native construct]", nil, 3), true, true, true) } } type ProxyTrapConfig struct { // A trap for Object.getPrototypeOf, Reflect.getPrototypeOf, __proto__, Object.prototype.isPrototypeOf, instanceof GetPrototypeOf func(target *Object) (prototype *Object) // A trap for Object.setPrototypeOf, Reflect.setPrototypeOf SetPrototypeOf func(target *Object, prototype *Object) (success bool) // A trap for Object.isExtensible, Reflect.isExtensible IsExtensible func(target *Object) (success bool) // A trap for Object.preventExtensions, Reflect.preventExtensions PreventExtensions func(target *Object) (success bool) // A trap for Object.getOwnPropertyDescriptor, Reflect.getOwnPropertyDescriptor GetOwnPropertyDescriptor func(target *Object, prop string) (propertyDescriptor PropertyDescriptor) // A trap for Object.defineProperty, Reflect.defineProperty DefineProperty func(target *Object, key string, propertyDescriptor PropertyDescriptor) (success bool) // A trap for the in operator, with operator, Reflect.has Has func(target *Object, property string) (available bool) // A trap for getting property values, Reflect.get Get func(target *Object, property string, receiver *Object) (value Value) // A trap for setting property values, Reflect.set Set func(target *Object, property string, value Value, receiver *Object) (success bool) // A trap for the delete operator, Reflect.deleteProperty DeleteProperty func(target *Object, property string) (success bool) // A trap for Object.getOwnPropertyNames, Object.getOwnPropertySymbols, Object.keys, Reflect.ownKeys OwnKeys func(target *Object) (object *Object) // A trap for a function call, Function.prototype.apply, Function.prototype.call, Reflect.apply Apply func(target *Object, this *Object, argumentsList []Value) (value Value) // A trap for the new operator, Reflect.construct Construct func(target *Object, argumentsList []Value, newTarget *Object) (value *Object) } func (r *Runtime) newProxy(args []Value, proto *Object) *Object { if len(args) >= 2 { if target, ok := args[0].(*Object); ok { if proxyHandler, ok := args[1].(*Object); ok { return r.newProxyObject(target, proxyHandler, proto).val } } } panic(r.NewTypeError("Cannot create proxy with a non-object as target or handler")) } func (r *Runtime) builtin_newProxy(args []Value, proto *Object) *Object { return r.newProxy(args, proto) } func (r *Runtime) NewProxy(target *Object, nativeHandler *ProxyTrapConfig) *Proxy { handler := r.newNativeProxyHandler(nativeHandler) proxy := r.newProxyObject(target, handler, r.global.Proxy) return &Proxy{proxy: proxy} } func (r *Runtime) builtin_proxy_revocable(call FunctionCall) Value { if len(call.Arguments) >= 2 { if target, ok := call.Argument(0).(*Object); ok { if proxyHandler, ok := call.Argument(1).(*Object); ok { proxy := r.newProxyObject(target, proxyHandler, nil) revoke := r.newNativeFunc(func(FunctionCall) Value { proxy.revoke() return _undefined }, nil, "", nil, 0) ret := r.NewObject() ret.self._putProp("proxy", proxy.val, true, true, true) ret.self._putProp("revoke", revoke, true, true, true) return ret } } } panic(r.NewTypeError("Cannot create proxy with a non-object as target or handler")) } func (r *Runtime) createProxy(val *Object) objectImpl { o := r.newNativeFuncObj(val, r.constructorThrower("Proxy"), r.builtin_newProxy, "Proxy", nil, 2) o._putProp("revocable", r.newNativeFunc(r.builtin_proxy_revocable, nil, "revocable", nil, 2), true, false, true) return o } func (r *Runtime) initProxy() { r.global.Proxy = r.newLazyObject(r.createProxy) r.addToGlobal("Proxy", r.global.Proxy) }