ai_old/goja/builtin_proxy.go

397 lines
14 KiB
Go
Raw Normal View History

2024-09-20 16:50:35 +08:00
package goja
import (
"apigo.cc/ai/ai/goja/unistring"
2024-09-20 16:50:35 +08:00
)
type nativeProxyHandler struct {
handler *ProxyTrapConfig
}
func (h *nativeProxyHandler) getPrototypeOf(target *Object) (Value, bool) {
if trap := h.handler.GetPrototypeOf; trap != nil {
return trap(target), true
}
return nil, false
}
func (h *nativeProxyHandler) setPrototypeOf(target *Object, proto *Object) (bool, bool) {
if trap := h.handler.SetPrototypeOf; trap != nil {
return trap(target, proto), true
}
return false, false
}
func (h *nativeProxyHandler) isExtensible(target *Object) (bool, bool) {
if trap := h.handler.IsExtensible; trap != nil {
return trap(target), true
}
return false, false
}
func (h *nativeProxyHandler) preventExtensions(target *Object) (bool, bool) {
if trap := h.handler.PreventExtensions; trap != nil {
return trap(target), true
}
return false, false
}
func (h *nativeProxyHandler) getOwnPropertyDescriptorStr(target *Object, prop unistring.String) (Value, bool) {
if trap := h.handler.GetOwnPropertyDescriptorIdx; trap != nil {
if idx, ok := strToInt(prop); ok {
desc := trap(target, idx)
return desc.toValue(target.runtime), true
}
}
if trap := h.handler.GetOwnPropertyDescriptor; trap != nil {
desc := trap(target, prop.String())
return desc.toValue(target.runtime), true
}
return nil, false
}
func (h *nativeProxyHandler) getOwnPropertyDescriptorIdx(target *Object, prop valueInt) (Value, bool) {
if trap := h.handler.GetOwnPropertyDescriptorIdx; trap != nil {
desc := trap(target, toIntStrict(int64(prop)))
return desc.toValue(target.runtime), true
}
if trap := h.handler.GetOwnPropertyDescriptor; trap != nil {
desc := trap(target, prop.String())
return desc.toValue(target.runtime), true
}
return nil, false
}
func (h *nativeProxyHandler) getOwnPropertyDescriptorSym(target *Object, prop *Symbol) (Value, bool) {
if trap := h.handler.GetOwnPropertyDescriptorSym; trap != nil {
desc := trap(target, prop)
return desc.toValue(target.runtime), true
}
return nil, false
}
func (h *nativeProxyHandler) definePropertyStr(target *Object, prop unistring.String, desc PropertyDescriptor) (bool, bool) {
if trap := h.handler.DefinePropertyIdx; trap != nil {
if idx, ok := strToInt(prop); ok {
return trap(target, idx, desc), true
}
}
if trap := h.handler.DefineProperty; trap != nil {
return trap(target, prop.String(), desc), true
}
return false, false
}
func (h *nativeProxyHandler) definePropertyIdx(target *Object, prop valueInt, desc PropertyDescriptor) (bool, bool) {
if trap := h.handler.DefinePropertyIdx; trap != nil {
return trap(target, toIntStrict(int64(prop)), desc), true
}
if trap := h.handler.DefineProperty; trap != nil {
return trap(target, prop.String(), desc), true
}
return false, false
}
func (h *nativeProxyHandler) definePropertySym(target *Object, prop *Symbol, desc PropertyDescriptor) (bool, bool) {
if trap := h.handler.DefinePropertySym; trap != nil {
return trap(target, prop, desc), true
}
return false, false
}
func (h *nativeProxyHandler) hasStr(target *Object, prop unistring.String) (bool, bool) {
if trap := h.handler.HasIdx; trap != nil {
if idx, ok := strToInt(prop); ok {
return trap(target, idx), true
}
}
if trap := h.handler.Has; trap != nil {
return trap(target, prop.String()), true
}
return false, false
}
func (h *nativeProxyHandler) hasIdx(target *Object, prop valueInt) (bool, bool) {
if trap := h.handler.HasIdx; trap != nil {
return trap(target, toIntStrict(int64(prop))), true
}
if trap := h.handler.Has; trap != nil {
return trap(target, prop.String()), true
}
return false, false
}
func (h *nativeProxyHandler) hasSym(target *Object, prop *Symbol) (bool, bool) {
if trap := h.handler.HasSym; trap != nil {
return trap(target, prop), true
}
return false, false
}
func (h *nativeProxyHandler) getStr(target *Object, prop unistring.String, receiver Value) (Value, bool) {
if trap := h.handler.GetIdx; trap != nil {
if idx, ok := strToInt(prop); ok {
return trap(target, idx, receiver), true
}
}
if trap := h.handler.Get; trap != nil {
return trap(target, prop.String(), receiver), true
}
return nil, false
}
func (h *nativeProxyHandler) getIdx(target *Object, prop valueInt, receiver Value) (Value, bool) {
if trap := h.handler.GetIdx; trap != nil {
return trap(target, toIntStrict(int64(prop)), receiver), true
}
if trap := h.handler.Get; trap != nil {
return trap(target, prop.String(), receiver), true
}
return nil, false
}
func (h *nativeProxyHandler) getSym(target *Object, prop *Symbol, receiver Value) (Value, bool) {
if trap := h.handler.GetSym; trap != nil {
return trap(target, prop, receiver), true
}
return nil, false
}
func (h *nativeProxyHandler) setStr(target *Object, prop unistring.String, value Value, receiver Value) (bool, bool) {
if trap := h.handler.SetIdx; trap != nil {
if idx, ok := strToInt(prop); ok {
return trap(target, idx, value, receiver), true
}
}
if trap := h.handler.Set; trap != nil {
return trap(target, prop.String(), value, receiver), true
}
return false, false
}
func (h *nativeProxyHandler) setIdx(target *Object, prop valueInt, value Value, receiver Value) (bool, bool) {
if trap := h.handler.SetIdx; trap != nil {
return trap(target, toIntStrict(int64(prop)), value, receiver), true
}
if trap := h.handler.Set; trap != nil {
return trap(target, prop.String(), value, receiver), true
}
return false, false
}
func (h *nativeProxyHandler) setSym(target *Object, prop *Symbol, value Value, receiver Value) (bool, bool) {
if trap := h.handler.SetSym; trap != nil {
return trap(target, prop, value, receiver), true
}
return false, false
}
func (h *nativeProxyHandler) deleteStr(target *Object, prop unistring.String) (bool, bool) {
if trap := h.handler.DeletePropertyIdx; trap != nil {
if idx, ok := strToInt(prop); ok {
return trap(target, idx), true
}
}
if trap := h.handler.DeleteProperty; trap != nil {
return trap(target, prop.String()), true
}
return false, false
}
func (h *nativeProxyHandler) deleteIdx(target *Object, prop valueInt) (bool, bool) {
if trap := h.handler.DeletePropertyIdx; trap != nil {
return trap(target, toIntStrict(int64(prop))), true
}
if trap := h.handler.DeleteProperty; trap != nil {
return trap(target, prop.String()), true
}
return false, false
}
func (h *nativeProxyHandler) deleteSym(target *Object, prop *Symbol) (bool, bool) {
if trap := h.handler.DeletePropertySym; trap != nil {
return trap(target, prop), true
}
return false, false
}
func (h *nativeProxyHandler) ownKeys(target *Object) (*Object, bool) {
if trap := h.handler.OwnKeys; trap != nil {
return trap(target), true
}
return nil, false
}
func (h *nativeProxyHandler) apply(target *Object, this Value, args []Value) (Value, bool) {
if trap := h.handler.Apply; trap != nil {
return trap(target, this, args), true
}
return nil, false
}
func (h *nativeProxyHandler) construct(target *Object, args []Value, newTarget *Object) (Value, bool) {
if trap := h.handler.Construct; trap != nil {
return trap(target, args, newTarget), true
}
return nil, false
}
func (h *nativeProxyHandler) toObject(runtime *Runtime) *Object {
return runtime.ToValue(h.handler).ToObject(runtime)
}
func (r *Runtime) newNativeProxyHandler(nativeHandler *ProxyTrapConfig) proxyHandler {
return &nativeProxyHandler{handler: nativeHandler}
}
// ProxyTrapConfig provides a simplified Go-friendly API for implementing Proxy traps.
// If an *Idx trap is defined it gets called for integer property keys, including negative ones. Note that
// this only includes string property keys that represent a canonical integer
// (i.e. "0", "123", but not "00", "01", " 1" or "-0").
// For efficiency strings representing integers exceeding 2^53 are not checked to see if they are canonical,
// i.e. the *Idx traps will receive "9007199254740993" as well as "9007199254740994", even though the former is not
// a canonical representation in ECMAScript (Number("9007199254740993") === 9007199254740992).
// See https://262.ecma-international.org/#sec-canonicalnumericindexstring
// If an *Idx trap is not set, the corresponding string one is used.
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 (string properties)
GetOwnPropertyDescriptor func(target *Object, prop string) (propertyDescriptor PropertyDescriptor)
// A trap for Object.getOwnPropertyDescriptor, Reflect.getOwnPropertyDescriptor (integer properties)
GetOwnPropertyDescriptorIdx func(target *Object, prop int) (propertyDescriptor PropertyDescriptor)
// A trap for Object.getOwnPropertyDescriptor, Reflect.getOwnPropertyDescriptor (Symbol properties)
GetOwnPropertyDescriptorSym func(target *Object, prop *Symbol) (propertyDescriptor PropertyDescriptor)
// A trap for Object.defineProperty, Reflect.defineProperty (string properties)
DefineProperty func(target *Object, key string, propertyDescriptor PropertyDescriptor) (success bool)
// A trap for Object.defineProperty, Reflect.defineProperty (integer properties)
DefinePropertyIdx func(target *Object, key int, propertyDescriptor PropertyDescriptor) (success bool)
// A trap for Object.defineProperty, Reflect.defineProperty (Symbol properties)
DefinePropertySym func(target *Object, key *Symbol, propertyDescriptor PropertyDescriptor) (success bool)
// A trap for the in operator, with operator, Reflect.has (string properties)
Has func(target *Object, property string) (available bool)
// A trap for the in operator, with operator, Reflect.has (integer properties)
HasIdx func(target *Object, property int) (available bool)
// A trap for the in operator, with operator, Reflect.has (Symbol properties)
HasSym func(target *Object, property *Symbol) (available bool)
// A trap for getting property values, Reflect.get (string properties)
Get func(target *Object, property string, receiver Value) (value Value)
// A trap for getting property values, Reflect.get (integer properties)
GetIdx func(target *Object, property int, receiver Value) (value Value)
// A trap for getting property values, Reflect.get (Symbol properties)
GetSym func(target *Object, property *Symbol, receiver Value) (value Value)
// A trap for setting property values, Reflect.set (string properties)
Set func(target *Object, property string, value Value, receiver Value) (success bool)
// A trap for setting property values, Reflect.set (integer properties)
SetIdx func(target *Object, property int, value Value, receiver Value) (success bool)
// A trap for setting property values, Reflect.set (Symbol properties)
SetSym func(target *Object, property *Symbol, value Value, receiver Value) (success bool)
// A trap for the delete operator, Reflect.deleteProperty (string properties)
DeleteProperty func(target *Object, property string) (success bool)
// A trap for the delete operator, Reflect.deleteProperty (integer properties)
DeletePropertyIdx func(target *Object, property int) (success bool)
// A trap for the delete operator, Reflect.deleteProperty (Symbol properties)
DeletePropertySym func(target *Object, property *Symbol) (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 Value, 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, newTarget *Object) *Object {
if newTarget == nil {
panic(r.needNew("Proxy"))
}
return r.newProxy(args, r.getPrototypeFromCtor(newTarget, r.getProxy(), r.global.ObjectPrototype))
}
func (r *Runtime) NewProxy(target *Object, nativeHandler *ProxyTrapConfig) Proxy {
if p, ok := target.self.(*proxyObject); ok {
if p.handler == nil {
panic(r.NewTypeError("Cannot create proxy with a revoked proxy as target"))
}
}
handler := r.newNativeProxyHandler(nativeHandler)
proxy := r._newProxyObject(target, handler, nil)
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
}, "", 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.newNativeConstructOnly(val, r.builtin_newProxy, nil, "Proxy", 2)
o._putProp("revocable", r.newNativeFunc(r.builtin_proxy_revocable, "revocable", 2), true, false, true)
return o
}
func (r *Runtime) getProxy() *Object {
ret := r.global.Proxy
if ret == nil {
ret = &Object{runtime: r}
r.global.Proxy = ret
r.createProxy(ret)
}
return ret
}