builtin_proxy.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. package goja
  2. import "fmt"
  3. func (r *Runtime) newNativeProxyHandler(nativeHandler *ProxyTrapConfig) *Object {
  4. handler := r.NewObject()
  5. r.proxyproto_nativehandler_gen_obj_obj(proxy_trap_getPrototypeOf, nativeHandler.GetPrototypeOf, handler)
  6. r.proxyproto_nativehandler_setPrototypeOf(nativeHandler.SetPrototypeOf, handler)
  7. r.proxyproto_nativehandler_gen_obj_bool(proxy_trap_isExtensible, nativeHandler.IsExtensible, handler)
  8. r.proxyproto_nativehandler_gen_obj_bool(proxy_trap_preventExtensions, nativeHandler.PreventExtensions, handler)
  9. r.proxyproto_nativehandler_getOwnPropertyDescriptor(nativeHandler.GetOwnPropertyDescriptor, handler)
  10. r.proxyproto_nativehandler_defineProperty(nativeHandler.DefineProperty, handler)
  11. r.proxyproto_nativehandler_gen_obj_string_bool(proxy_trap_has, nativeHandler.Has, handler)
  12. r.proxyproto_nativehandler_get(nativeHandler.Get, handler)
  13. r.proxyproto_nativehandler_set(nativeHandler.Set, handler)
  14. r.proxyproto_nativehandler_gen_obj_string_bool(proxy_trap_deleteProperty, nativeHandler.DeleteProperty, handler)
  15. r.proxyproto_nativehandler_gen_obj_obj(proxy_trap_ownKeys, nativeHandler.OwnKeys, handler)
  16. r.proxyproto_nativehandler_apply(nativeHandler.Apply, handler)
  17. r.proxyproto_nativehandler_construct(nativeHandler.Construct, handler)
  18. return handler
  19. }
  20. func (r *Runtime) proxyproto_nativehandler_gen_obj_obj(name proxyTrap, native func(*Object) *Object, handler *Object) {
  21. if native != nil {
  22. handler.self._putProp(string(name), r.newNativeFunc(func(call FunctionCall) Value {
  23. if len(call.Arguments) >= 1 {
  24. if t, ok := call.Argument(0).(*Object); ok {
  25. return native(t)
  26. }
  27. }
  28. panic(r.NewTypeError("%s needs to be called with target as Object", name))
  29. }, nil, fmt.Sprintf("[native %s]", name), nil, 1), true, true, true)
  30. }
  31. }
  32. func (r *Runtime) proxyproto_nativehandler_setPrototypeOf(native func(*Object, *Object) bool, handler *Object) {
  33. if native != nil {
  34. handler.self._putProp("setPrototypeOf", r.newNativeFunc(func(call FunctionCall) Value {
  35. if len(call.Arguments) >= 2 {
  36. if t, ok := call.Argument(0).(*Object); ok {
  37. if p, ok := call.Argument(1).(*Object); ok {
  38. s := native(t, p)
  39. return r.ToValue(s)
  40. }
  41. }
  42. }
  43. panic(r.NewTypeError("setPrototypeOf needs to be called with target and prototype as Object"))
  44. }, nil, "[native setPrototypeOf]", nil, 2), true, true, true)
  45. }
  46. }
  47. func (r *Runtime) proxyproto_nativehandler_gen_obj_bool(name proxyTrap, native func(*Object) bool, handler *Object) {
  48. if native != nil {
  49. handler.self._putProp(string(name), r.newNativeFunc(func(call FunctionCall) Value {
  50. if len(call.Arguments) >= 1 {
  51. if t, ok := call.Argument(0).(*Object); ok {
  52. s := native(t)
  53. return r.ToValue(s)
  54. }
  55. }
  56. panic(r.NewTypeError("%s needs to be called with target as Object", name))
  57. }, nil, fmt.Sprintf("[native %s]", name), nil, 1), true, true, true)
  58. }
  59. }
  60. func (r *Runtime) proxyproto_nativehandler_getOwnPropertyDescriptor(native func(*Object, string) PropertyDescriptor, handler *Object) {
  61. if native != nil {
  62. handler.self._putProp("getOwnPropertyDescriptor", r.newNativeFunc(func(call FunctionCall) Value {
  63. if len(call.Arguments) >= 2 {
  64. if t, ok := call.Argument(0).(*Object); ok {
  65. if p, ok := call.Argument(1).(valueString); ok {
  66. desc := native(t, p.String())
  67. return desc.toValue(r)
  68. }
  69. }
  70. }
  71. panic(r.NewTypeError("getOwnPropertyDescriptor needs to be called with target as Object and prop as string"))
  72. }, nil, "[native getOwnPropertyDescriptor]", nil, 2), true, true, true)
  73. }
  74. }
  75. func (r *Runtime) proxyproto_nativehandler_defineProperty(native func(*Object, string, PropertyDescriptor) bool, handler *Object) {
  76. if native != nil {
  77. handler.self._putProp("defineProperty", r.newNativeFunc(func(call FunctionCall) Value {
  78. if len(call.Arguments) >= 3 {
  79. if t, ok := call.Argument(0).(*Object); ok {
  80. if k, ok := call.Argument(1).(valueString); ok {
  81. propertyDescriptor := r.toPropertyDescriptor(call.Argument(2))
  82. s := native(t, k.String(), propertyDescriptor)
  83. return r.ToValue(s)
  84. }
  85. }
  86. }
  87. panic(r.NewTypeError("defineProperty needs to be called with target as Object and propertyDescriptor as string and key as string"))
  88. }, nil, "[native defineProperty]", nil, 3), true, true, true)
  89. }
  90. }
  91. func (r *Runtime) proxyproto_nativehandler_gen_obj_string_bool(name proxyTrap, native func(*Object, string) bool, handler *Object) {
  92. if native != nil {
  93. handler.self._putProp(string(name), r.newNativeFunc(func(call FunctionCall) Value {
  94. if len(call.Arguments) >= 2 {
  95. if t, ok := call.Argument(0).(*Object); ok {
  96. if p, ok := call.Argument(1).(valueString); ok {
  97. o := native(t, p.String())
  98. return r.ToValue(o)
  99. }
  100. }
  101. }
  102. panic(r.NewTypeError("%s needs to be called with target as Object and property as string", name))
  103. }, nil, fmt.Sprintf("[native %s]", name), nil, 2), true, true, true)
  104. }
  105. }
  106. func (r *Runtime) proxyproto_nativehandler_get(native func(*Object, string, *Object) Value, handler *Object) {
  107. if native != nil {
  108. handler.self._putProp("get", r.newNativeFunc(func(call FunctionCall) Value {
  109. if len(call.Arguments) >= 3 {
  110. if t, ok := call.Argument(0).(*Object); ok {
  111. if p, ok := call.Argument(1).(valueString); ok {
  112. if r, ok := call.Argument(2).(*Object); ok {
  113. return native(t, p.String(), r)
  114. }
  115. }
  116. }
  117. }
  118. panic(r.NewTypeError("get needs to be called with target and receiver as Object and property as string"))
  119. }, nil, "[native get]", nil, 3), true, true, true)
  120. }
  121. }
  122. func (r *Runtime) proxyproto_nativehandler_set(native func(*Object, string, Value, *Object) bool, handler *Object) {
  123. if native != nil {
  124. handler.self._putProp("set", r.newNativeFunc(func(call FunctionCall) Value {
  125. if len(call.Arguments) >= 4 {
  126. if t, ok := call.Argument(0).(*Object); ok {
  127. if p, ok := call.Argument(1).(valueString); ok {
  128. v := call.Argument(2)
  129. if re, ok := call.Argument(3).(*Object); ok {
  130. s := native(t, p.String(), v, re)
  131. return r.ToValue(s)
  132. }
  133. }
  134. }
  135. }
  136. panic(r.NewTypeError("set needs to be called with target and receiver as Object, property as string and value as a legal javascript value"))
  137. }, nil, "[native set]", nil, 4), true, true, true)
  138. }
  139. }
  140. func (r *Runtime) proxyproto_nativehandler_apply(native func(*Object, *Object, []Value) Value, handler *Object) {
  141. if native != nil {
  142. handler.self._putProp("apply", r.newNativeFunc(func(call FunctionCall) Value {
  143. if len(call.Arguments) >= 3 {
  144. if t, ok := call.Argument(0).(*Object); ok {
  145. if this, ok := call.Argument(1).(*Object); ok {
  146. if v, ok := call.Argument(2).(*Object); ok {
  147. if a, ok := v.self.(*arrayObject); ok {
  148. v := native(t, this, a.values)
  149. return r.ToValue(v)
  150. }
  151. }
  152. }
  153. }
  154. }
  155. panic(r.NewTypeError("apply needs to be called with target and this as Object and argumentsList as an array of legal javascript values"))
  156. }, nil, "[native apply]", nil, 3), true, true, true)
  157. }
  158. }
  159. func (r *Runtime) proxyproto_nativehandler_construct(native func(*Object, []Value, *Object) *Object, handler *Object) {
  160. if native != nil {
  161. handler.self._putProp("construct", r.newNativeFunc(func(call FunctionCall) Value {
  162. if len(call.Arguments) >= 3 {
  163. if t, ok := call.Argument(0).(*Object); ok {
  164. if v, ok := call.Argument(1).(*Object); ok {
  165. if newTarget, ok := call.Argument(2).(*Object); ok {
  166. if a, ok := v.self.(*arrayObject); ok {
  167. return native(t, a.values, newTarget)
  168. }
  169. }
  170. }
  171. }
  172. }
  173. panic(r.NewTypeError("construct needs to be called with target and newTarget as Object and argumentsList as an array of legal javascript values"))
  174. }, nil, "[native construct]", nil, 3), true, true, true)
  175. }
  176. }
  177. type ProxyTrapConfig struct {
  178. // A trap for Object.getPrototypeOf, Reflect.getPrototypeOf, __proto__, Object.prototype.isPrototypeOf, instanceof
  179. GetPrototypeOf func(target *Object) (prototype *Object)
  180. // A trap for Object.setPrototypeOf, Reflect.setPrototypeOf
  181. SetPrototypeOf func(target *Object, prototype *Object) (success bool)
  182. // A trap for Object.isExtensible, Reflect.isExtensible
  183. IsExtensible func(target *Object) (success bool)
  184. // A trap for Object.preventExtensions, Reflect.preventExtensions
  185. PreventExtensions func(target *Object) (success bool)
  186. // A trap for Object.getOwnPropertyDescriptor, Reflect.getOwnPropertyDescriptor
  187. GetOwnPropertyDescriptor func(target *Object, prop string) (propertyDescriptor PropertyDescriptor)
  188. // A trap for Object.defineProperty, Reflect.defineProperty
  189. DefineProperty func(target *Object, key string, propertyDescriptor PropertyDescriptor) (success bool)
  190. // A trap for the in operator, with operator, Reflect.has
  191. Has func(target *Object, property string) (available bool)
  192. // A trap for getting property values, Reflect.get
  193. Get func(target *Object, property string, receiver *Object) (value Value)
  194. // A trap for setting property values, Reflect.set
  195. Set func(target *Object, property string, value Value, receiver *Object) (success bool)
  196. // A trap for the delete operator, Reflect.deleteProperty
  197. DeleteProperty func(target *Object, property string) (success bool)
  198. // A trap for Object.getOwnPropertyNames, Object.getOwnPropertySymbols, Object.keys, Reflect.ownKeys
  199. OwnKeys func(target *Object) (object *Object)
  200. // A trap for a function call, Function.prototype.apply, Function.prototype.call, Reflect.apply
  201. Apply func(target *Object, this *Object, argumentsList []Value) (value Value)
  202. // A trap for the new operator, Reflect.construct
  203. Construct func(target *Object, argumentsList []Value, newTarget *Object) (value *Object)
  204. }
  205. func (r *Runtime) newProxy(args []Value, proto *Object) *Object {
  206. if len(args) >= 2 {
  207. if target, ok := args[0].(*Object); ok {
  208. if proxyHandler, ok := args[1].(*Object); ok {
  209. return r.newProxyObject(target, proxyHandler, proto).val
  210. }
  211. }
  212. }
  213. panic(r.NewTypeError("Cannot create proxy with a non-object as target or handler"))
  214. }
  215. func (r *Runtime) builtin_newProxy(args []Value, proto *Object) *Object {
  216. return r.newProxy(args, proto)
  217. }
  218. func (r *Runtime) NewProxy(target *Object, nativeHandler *ProxyTrapConfig) *Proxy {
  219. handler := r.newNativeProxyHandler(nativeHandler)
  220. proxy := r.newProxyObject(target, handler, r.global.Proxy)
  221. return &Proxy{proxy: proxy}
  222. }
  223. func (r *Runtime) builtin_proxy_revocable(call FunctionCall) Value {
  224. if len(call.Arguments) >= 2 {
  225. if target, ok := call.Argument(0).(*Object); ok {
  226. if proxyHandler, ok := call.Argument(1).(*Object); ok {
  227. proxy := r.newProxyObject(target, proxyHandler, nil)
  228. revoke := r.newNativeFunc(func(FunctionCall) Value {
  229. proxy.revoke()
  230. return _undefined
  231. }, nil, "", nil, 0)
  232. ret := r.NewObject()
  233. ret.self._putProp("proxy", proxy.val, true, true, true)
  234. ret.self._putProp("revoke", revoke, true, true, true)
  235. return ret
  236. }
  237. }
  238. }
  239. panic(r.NewTypeError("Cannot create proxy with a non-object as target or handler"))
  240. }
  241. func (r *Runtime) createProxy(val *Object) objectImpl {
  242. o := r.newNativeFuncObj(val, r.constructorThrower("Proxy"), r.builtin_newProxy, "Proxy", nil, 2)
  243. o._putProp("revocable", r.newNativeFunc(r.builtin_proxy_revocable, nil, "revocable", nil, 2), true, false, true)
  244. return o
  245. }
  246. func (r *Runtime) initProxy() {
  247. r.global.Proxy = r.newLazyObject(r.createProxy)
  248. r.addToGlobal("Proxy", r.global.Proxy)
  249. }