proxy.go 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074
  1. package goja
  2. import (
  3. "fmt"
  4. "reflect"
  5. "github.com/dop251/goja/unistring"
  6. )
  7. // Proxy is a Go wrapper around ECMAScript Proxy. Calling Runtime.ToValue() on it
  8. // returns the underlying Proxy. Calling Export() on an ECMAScript Proxy returns a wrapper.
  9. // Use Runtime.NewProxy() to create one.
  10. type Proxy struct {
  11. proxy *proxyObject
  12. }
  13. var (
  14. proxyType = reflect.TypeOf(Proxy{})
  15. )
  16. type proxyPropIter struct {
  17. p *proxyObject
  18. names []Value
  19. idx int
  20. }
  21. func (i *proxyPropIter) next() (propIterItem, iterNextFunc) {
  22. for i.idx < len(i.names) {
  23. name := i.names[i.idx]
  24. i.idx++
  25. return propIterItem{name: name}, i.next
  26. }
  27. return propIterItem{}, nil
  28. }
  29. func (r *Runtime) newProxyObject(target, handler, proto *Object) *proxyObject {
  30. return r._newProxyObject(target, &jsProxyHandler{handler: handler}, proto)
  31. }
  32. func (r *Runtime) _newProxyObject(target *Object, handler proxyHandler, proto *Object) *proxyObject {
  33. v := &Object{runtime: r}
  34. p := &proxyObject{}
  35. v.self = p
  36. p.val = v
  37. p.class = classObject
  38. if proto == nil {
  39. p.prototype = r.global.ObjectPrototype
  40. } else {
  41. p.prototype = proto
  42. }
  43. p.extensible = false
  44. p.init()
  45. p.target = target
  46. p.handler = handler
  47. if call, ok := target.self.assertCallable(); ok {
  48. p.call = call
  49. }
  50. if ctor := target.self.assertConstructor(); ctor != nil {
  51. p.ctor = ctor
  52. }
  53. return p
  54. }
  55. func (p Proxy) Revoke() {
  56. p.proxy.revoke()
  57. }
  58. func (p Proxy) Handler() *Object {
  59. if handler := p.proxy.handler; handler != nil {
  60. return handler.toObject(p.proxy.val.runtime)
  61. }
  62. return nil
  63. }
  64. func (p Proxy) Target() *Object {
  65. return p.proxy.target
  66. }
  67. func (p Proxy) toValue(r *Runtime) Value {
  68. if p.proxy == nil {
  69. return _null
  70. }
  71. proxy := p.proxy.val
  72. if proxy.runtime != r {
  73. panic(r.NewTypeError("Illegal runtime transition of a Proxy"))
  74. }
  75. return proxy
  76. }
  77. type proxyTrap string
  78. const (
  79. proxy_trap_getPrototypeOf = "getPrototypeOf"
  80. proxy_trap_setPrototypeOf = "setPrototypeOf"
  81. proxy_trap_isExtensible = "isExtensible"
  82. proxy_trap_preventExtensions = "preventExtensions"
  83. proxy_trap_getOwnPropertyDescriptor = "getOwnPropertyDescriptor"
  84. proxy_trap_defineProperty = "defineProperty"
  85. proxy_trap_has = "has"
  86. proxy_trap_get = "get"
  87. proxy_trap_set = "set"
  88. proxy_trap_deleteProperty = "deleteProperty"
  89. proxy_trap_ownKeys = "ownKeys"
  90. proxy_trap_apply = "apply"
  91. proxy_trap_construct = "construct"
  92. )
  93. func (p proxyTrap) String() (name string) {
  94. return string(p)
  95. }
  96. type proxyHandler interface {
  97. getPrototypeOf(target *Object) (Value, bool)
  98. setPrototypeOf(target *Object, proto *Object) (bool, bool)
  99. isExtensible(target *Object) (bool, bool)
  100. preventExtensions(target *Object) (bool, bool)
  101. getOwnPropertyDescriptorStr(target *Object, prop unistring.String) (Value, bool)
  102. getOwnPropertyDescriptorIdx(target *Object, prop valueInt) (Value, bool)
  103. getOwnPropertyDescriptorSym(target *Object, prop *Symbol) (Value, bool)
  104. definePropertyStr(target *Object, prop unistring.String, desc PropertyDescriptor) (bool, bool)
  105. definePropertyIdx(target *Object, prop valueInt, desc PropertyDescriptor) (bool, bool)
  106. definePropertySym(target *Object, prop *Symbol, desc PropertyDescriptor) (bool, bool)
  107. hasStr(target *Object, prop unistring.String) (bool, bool)
  108. hasIdx(target *Object, prop valueInt) (bool, bool)
  109. hasSym(target *Object, prop *Symbol) (bool, bool)
  110. getStr(target *Object, prop unistring.String, receiver Value) (Value, bool)
  111. getIdx(target *Object, prop valueInt, receiver Value) (Value, bool)
  112. getSym(target *Object, prop *Symbol, receiver Value) (Value, bool)
  113. setStr(target *Object, prop unistring.String, value Value, receiver Value) (bool, bool)
  114. setIdx(target *Object, prop valueInt, value Value, receiver Value) (bool, bool)
  115. setSym(target *Object, prop *Symbol, value Value, receiver Value) (bool, bool)
  116. deleteStr(target *Object, prop unistring.String) (bool, bool)
  117. deleteIdx(target *Object, prop valueInt) (bool, bool)
  118. deleteSym(target *Object, prop *Symbol) (bool, bool)
  119. ownKeys(target *Object) (*Object, bool)
  120. apply(target *Object, this Value, args []Value) (Value, bool)
  121. construct(target *Object, args []Value, newTarget *Object) (Value, bool)
  122. toObject(*Runtime) *Object
  123. }
  124. type jsProxyHandler struct {
  125. handler *Object
  126. }
  127. func (h *jsProxyHandler) toObject(*Runtime) *Object {
  128. return h.handler
  129. }
  130. func (h *jsProxyHandler) proxyCall(trap proxyTrap, args ...Value) (Value, bool) {
  131. r := h.handler.runtime
  132. if m := toMethod(r.getVStr(h.handler, unistring.String(trap.String()))); m != nil {
  133. return m(FunctionCall{
  134. This: h.handler,
  135. Arguments: args,
  136. }), true
  137. }
  138. return nil, false
  139. }
  140. func (h *jsProxyHandler) boolProxyCall(trap proxyTrap, args ...Value) (bool, bool) {
  141. if v, ok := h.proxyCall(trap, args...); ok {
  142. return v.ToBoolean(), true
  143. }
  144. return false, false
  145. }
  146. func (h *jsProxyHandler) getPrototypeOf(target *Object) (Value, bool) {
  147. return h.proxyCall(proxy_trap_getPrototypeOf, target)
  148. }
  149. func (h *jsProxyHandler) setPrototypeOf(target *Object, proto *Object) (bool, bool) {
  150. var protoVal Value
  151. if proto != nil {
  152. protoVal = proto
  153. } else {
  154. protoVal = _null
  155. }
  156. return h.boolProxyCall(proxy_trap_setPrototypeOf, target, protoVal)
  157. }
  158. func (h *jsProxyHandler) isExtensible(target *Object) (bool, bool) {
  159. return h.boolProxyCall(proxy_trap_isExtensible, target)
  160. }
  161. func (h *jsProxyHandler) preventExtensions(target *Object) (bool, bool) {
  162. return h.boolProxyCall(proxy_trap_preventExtensions, target)
  163. }
  164. func (h *jsProxyHandler) getOwnPropertyDescriptorStr(target *Object, prop unistring.String) (Value, bool) {
  165. return h.proxyCall(proxy_trap_getOwnPropertyDescriptor, target, stringValueFromRaw(prop))
  166. }
  167. func (h *jsProxyHandler) getOwnPropertyDescriptorIdx(target *Object, prop valueInt) (Value, bool) {
  168. return h.proxyCall(proxy_trap_getOwnPropertyDescriptor, target, prop.toString())
  169. }
  170. func (h *jsProxyHandler) getOwnPropertyDescriptorSym(target *Object, prop *Symbol) (Value, bool) {
  171. return h.proxyCall(proxy_trap_getOwnPropertyDescriptor, target, prop)
  172. }
  173. func (h *jsProxyHandler) definePropertyStr(target *Object, prop unistring.String, desc PropertyDescriptor) (bool, bool) {
  174. return h.boolProxyCall(proxy_trap_defineProperty, target, stringValueFromRaw(prop), desc.toValue(h.handler.runtime))
  175. }
  176. func (h *jsProxyHandler) definePropertyIdx(target *Object, prop valueInt, desc PropertyDescriptor) (bool, bool) {
  177. return h.boolProxyCall(proxy_trap_defineProperty, target, prop.toString(), desc.toValue(h.handler.runtime))
  178. }
  179. func (h *jsProxyHandler) definePropertySym(target *Object, prop *Symbol, desc PropertyDescriptor) (bool, bool) {
  180. return h.boolProxyCall(proxy_trap_defineProperty, target, prop, desc.toValue(h.handler.runtime))
  181. }
  182. func (h *jsProxyHandler) hasStr(target *Object, prop unistring.String) (bool, bool) {
  183. return h.boolProxyCall(proxy_trap_has, target, stringValueFromRaw(prop))
  184. }
  185. func (h *jsProxyHandler) hasIdx(target *Object, prop valueInt) (bool, bool) {
  186. return h.boolProxyCall(proxy_trap_has, target, prop.toString())
  187. }
  188. func (h *jsProxyHandler) hasSym(target *Object, prop *Symbol) (bool, bool) {
  189. return h.boolProxyCall(proxy_trap_has, target, prop)
  190. }
  191. func (h *jsProxyHandler) getStr(target *Object, prop unistring.String, receiver Value) (Value, bool) {
  192. return h.proxyCall(proxy_trap_get, target, stringValueFromRaw(prop), receiver)
  193. }
  194. func (h *jsProxyHandler) getIdx(target *Object, prop valueInt, receiver Value) (Value, bool) {
  195. return h.proxyCall(proxy_trap_get, target, prop.toString(), receiver)
  196. }
  197. func (h *jsProxyHandler) getSym(target *Object, prop *Symbol, receiver Value) (Value, bool) {
  198. return h.proxyCall(proxy_trap_get, target, prop, receiver)
  199. }
  200. func (h *jsProxyHandler) setStr(target *Object, prop unistring.String, value Value, receiver Value) (bool, bool) {
  201. return h.boolProxyCall(proxy_trap_set, target, stringValueFromRaw(prop), value, receiver)
  202. }
  203. func (h *jsProxyHandler) setIdx(target *Object, prop valueInt, value Value, receiver Value) (bool, bool) {
  204. return h.boolProxyCall(proxy_trap_set, target, prop.toString(), value, receiver)
  205. }
  206. func (h *jsProxyHandler) setSym(target *Object, prop *Symbol, value Value, receiver Value) (bool, bool) {
  207. return h.boolProxyCall(proxy_trap_set, target, prop, value, receiver)
  208. }
  209. func (h *jsProxyHandler) deleteStr(target *Object, prop unistring.String) (bool, bool) {
  210. return h.boolProxyCall(proxy_trap_deleteProperty, target, stringValueFromRaw(prop))
  211. }
  212. func (h *jsProxyHandler) deleteIdx(target *Object, prop valueInt) (bool, bool) {
  213. return h.boolProxyCall(proxy_trap_deleteProperty, target, prop.toString())
  214. }
  215. func (h *jsProxyHandler) deleteSym(target *Object, prop *Symbol) (bool, bool) {
  216. return h.boolProxyCall(proxy_trap_deleteProperty, target, prop)
  217. }
  218. func (h *jsProxyHandler) ownKeys(target *Object) (*Object, bool) {
  219. if v, ok := h.proxyCall(proxy_trap_ownKeys, target); ok {
  220. return h.handler.runtime.toObject(v), true
  221. }
  222. return nil, false
  223. }
  224. func (h *jsProxyHandler) apply(target *Object, this Value, args []Value) (Value, bool) {
  225. return h.proxyCall(proxy_trap_apply, target, this, h.handler.runtime.newArrayValues(args))
  226. }
  227. func (h *jsProxyHandler) construct(target *Object, args []Value, newTarget *Object) (Value, bool) {
  228. return h.proxyCall(proxy_trap_construct, target, h.handler.runtime.newArrayValues(args), newTarget)
  229. }
  230. type proxyObject struct {
  231. baseObject
  232. target *Object
  233. handler proxyHandler
  234. call func(FunctionCall) Value
  235. ctor func(args []Value, newTarget *Object) *Object
  236. }
  237. func (p *proxyObject) checkHandler() proxyHandler {
  238. r := p.val.runtime
  239. if handler := p.handler; handler != nil {
  240. return handler
  241. }
  242. panic(r.NewTypeError("Proxy already revoked"))
  243. }
  244. func (p *proxyObject) proto() *Object {
  245. target := p.target
  246. if v, ok := p.checkHandler().getPrototypeOf(target); ok {
  247. var handlerProto *Object
  248. if v != _null {
  249. handlerProto = p.val.runtime.toObject(v)
  250. }
  251. if !target.self.isExtensible() && !p.__sameValue(handlerProto, target.self.proto()) {
  252. panic(p.val.runtime.NewTypeError("'getPrototypeOf' on proxy: proxy target is non-extensible but the trap did not return its actual prototype"))
  253. }
  254. return handlerProto
  255. }
  256. return target.self.proto()
  257. }
  258. func (p *proxyObject) setProto(proto *Object, throw bool) bool {
  259. target := p.target
  260. if v, ok := p.checkHandler().setPrototypeOf(target, proto); ok {
  261. if v {
  262. if !target.self.isExtensible() && !p.__sameValue(proto, target.self.proto()) {
  263. panic(p.val.runtime.NewTypeError("'setPrototypeOf' on proxy: trap returned truish for setting a new prototype on the non-extensible proxy target"))
  264. }
  265. return true
  266. } else {
  267. p.val.runtime.typeErrorResult(throw, "'setPrototypeOf' on proxy: trap returned falsish")
  268. return false
  269. }
  270. }
  271. return target.self.setProto(proto, throw)
  272. }
  273. func (p *proxyObject) isExtensible() bool {
  274. target := p.target
  275. if booleanTrapResult, ok := p.checkHandler().isExtensible(p.target); ok {
  276. if te := target.self.isExtensible(); booleanTrapResult != te {
  277. panic(p.val.runtime.NewTypeError("'isExtensible' on proxy: trap result does not reflect extensibility of proxy target (which is '%v')", te))
  278. }
  279. return booleanTrapResult
  280. }
  281. return target.self.isExtensible()
  282. }
  283. func (p *proxyObject) preventExtensions(throw bool) bool {
  284. target := p.target
  285. if booleanTrapResult, ok := p.checkHandler().preventExtensions(target); ok {
  286. if !booleanTrapResult {
  287. p.val.runtime.typeErrorResult(throw, "'preventExtensions' on proxy: trap returned falsish")
  288. return false
  289. }
  290. if te := target.self.isExtensible(); booleanTrapResult && te {
  291. panic(p.val.runtime.NewTypeError("'preventExtensions' on proxy: trap returned truish but the proxy target is extensible"))
  292. }
  293. }
  294. return target.self.preventExtensions(throw)
  295. }
  296. func propToValueProp(v Value) *valueProperty {
  297. if v == nil {
  298. return nil
  299. }
  300. if v, ok := v.(*valueProperty); ok {
  301. return v
  302. }
  303. return &valueProperty{
  304. value: v,
  305. writable: true,
  306. configurable: true,
  307. enumerable: true,
  308. }
  309. }
  310. func (p *proxyObject) proxyDefineOwnPropertyPreCheck(trapResult, throw bool) bool {
  311. if !trapResult {
  312. p.val.runtime.typeErrorResult(throw, "'defineProperty' on proxy: trap returned falsish")
  313. return false
  314. }
  315. return true
  316. }
  317. func (p *proxyObject) proxyDefineOwnPropertyPostCheck(prop Value, target *Object, descr PropertyDescriptor) {
  318. targetDesc := propToValueProp(prop)
  319. extensibleTarget := target.self.isExtensible()
  320. settingConfigFalse := descr.Configurable == FLAG_FALSE
  321. if targetDesc == nil {
  322. if !extensibleTarget {
  323. panic(p.val.runtime.NewTypeError())
  324. }
  325. if settingConfigFalse {
  326. panic(p.val.runtime.NewTypeError())
  327. }
  328. } else {
  329. if !p.__isCompatibleDescriptor(extensibleTarget, &descr, targetDesc) {
  330. panic(p.val.runtime.NewTypeError())
  331. }
  332. if settingConfigFalse && targetDesc.configurable {
  333. panic(p.val.runtime.NewTypeError())
  334. }
  335. if targetDesc.value != nil && !targetDesc.configurable && targetDesc.writable {
  336. if descr.Writable == FLAG_FALSE {
  337. panic(p.val.runtime.NewTypeError())
  338. }
  339. }
  340. }
  341. }
  342. func (p *proxyObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
  343. target := p.target
  344. if booleanTrapResult, ok := p.checkHandler().definePropertyStr(target, name, descr); ok {
  345. if !p.proxyDefineOwnPropertyPreCheck(booleanTrapResult, throw) {
  346. return false
  347. }
  348. p.proxyDefineOwnPropertyPostCheck(target.self.getOwnPropStr(name), target, descr)
  349. return true
  350. }
  351. return target.self.defineOwnPropertyStr(name, descr, throw)
  352. }
  353. func (p *proxyObject) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool {
  354. target := p.target
  355. if booleanTrapResult, ok := p.checkHandler().definePropertyIdx(target, idx, descr); ok {
  356. if !p.proxyDefineOwnPropertyPreCheck(booleanTrapResult, throw) {
  357. return false
  358. }
  359. p.proxyDefineOwnPropertyPostCheck(target.self.getOwnPropIdx(idx), target, descr)
  360. return true
  361. }
  362. return target.self.defineOwnPropertyIdx(idx, descr, throw)
  363. }
  364. func (p *proxyObject) defineOwnPropertySym(s *Symbol, descr PropertyDescriptor, throw bool) bool {
  365. target := p.target
  366. if booleanTrapResult, ok := p.checkHandler().definePropertySym(target, s, descr); ok {
  367. if !p.proxyDefineOwnPropertyPreCheck(booleanTrapResult, throw) {
  368. return false
  369. }
  370. p.proxyDefineOwnPropertyPostCheck(target.self.getOwnPropSym(s), target, descr)
  371. return true
  372. }
  373. return target.self.defineOwnPropertySym(s, descr, throw)
  374. }
  375. func (p *proxyObject) proxyHasChecks(targetProp Value, target *Object, name fmt.Stringer) {
  376. targetDesc := propToValueProp(targetProp)
  377. if targetDesc != nil {
  378. if !targetDesc.configurable {
  379. 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()))
  380. }
  381. if !target.self.isExtensible() {
  382. panic(p.val.runtime.NewTypeError("'has' on proxy: trap returned falsish for property '%s' but the proxy target is not extensible", name.String()))
  383. }
  384. }
  385. }
  386. func (p *proxyObject) hasPropertyStr(name unistring.String) bool {
  387. target := p.target
  388. if b, ok := p.checkHandler().hasStr(target, name); ok {
  389. if !b {
  390. p.proxyHasChecks(target.self.getOwnPropStr(name), target, name)
  391. }
  392. return b
  393. }
  394. return target.self.hasPropertyStr(name)
  395. }
  396. func (p *proxyObject) hasPropertyIdx(idx valueInt) bool {
  397. target := p.target
  398. if b, ok := p.checkHandler().hasIdx(target, idx); ok {
  399. if !b {
  400. p.proxyHasChecks(target.self.getOwnPropIdx(idx), target, idx)
  401. }
  402. return b
  403. }
  404. return target.self.hasPropertyIdx(idx)
  405. }
  406. func (p *proxyObject) hasPropertySym(s *Symbol) bool {
  407. target := p.target
  408. if b, ok := p.checkHandler().hasSym(target, s); ok {
  409. if !b {
  410. p.proxyHasChecks(target.self.getOwnPropSym(s), target, s)
  411. }
  412. return b
  413. }
  414. return target.self.hasPropertySym(s)
  415. }
  416. func (p *proxyObject) hasOwnPropertyStr(name unistring.String) bool {
  417. return p.getOwnPropStr(name) != nil
  418. }
  419. func (p *proxyObject) hasOwnPropertyIdx(idx valueInt) bool {
  420. return p.getOwnPropIdx(idx) != nil
  421. }
  422. func (p *proxyObject) hasOwnPropertySym(s *Symbol) bool {
  423. return p.getOwnPropSym(s) != nil
  424. }
  425. func (p *proxyObject) proxyGetOwnPropertyDescriptor(targetProp Value, target *Object, trapResult Value, name fmt.Stringer) Value {
  426. r := p.val.runtime
  427. targetDesc := propToValueProp(targetProp)
  428. var trapResultObj *Object
  429. if trapResult != nil && trapResult != _undefined {
  430. if obj, ok := trapResult.(*Object); ok {
  431. trapResultObj = obj
  432. } else {
  433. panic(r.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap returned neither object nor undefined for property '%s'", name.String()))
  434. }
  435. }
  436. if trapResultObj == nil {
  437. if targetDesc == nil {
  438. return nil
  439. }
  440. if !targetDesc.configurable {
  441. panic(r.NewTypeError())
  442. }
  443. if !target.self.isExtensible() {
  444. panic(r.NewTypeError())
  445. }
  446. return nil
  447. }
  448. extensibleTarget := target.self.isExtensible()
  449. resultDesc := r.toPropertyDescriptor(trapResultObj)
  450. resultDesc.complete()
  451. if !p.__isCompatibleDescriptor(extensibleTarget, &resultDesc, targetDesc) {
  452. 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()))
  453. }
  454. if resultDesc.Configurable == FLAG_FALSE {
  455. if targetDesc == nil {
  456. panic(r.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property '%s' which is non-existent in the proxy target", name.String()))
  457. }
  458. if targetDesc.configurable {
  459. panic(r.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property '%s' which is configurable in the proxy target", name.String()))
  460. }
  461. if resultDesc.Writable == FLAG_FALSE && targetDesc.writable {
  462. 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()))
  463. }
  464. }
  465. if resultDesc.Writable == FLAG_TRUE && resultDesc.Configurable == FLAG_TRUE &&
  466. resultDesc.Enumerable == FLAG_TRUE {
  467. return resultDesc.Value
  468. }
  469. return r.toValueProp(trapResultObj)
  470. }
  471. func (p *proxyObject) getOwnPropStr(name unistring.String) Value {
  472. target := p.target
  473. if v, ok := p.checkHandler().getOwnPropertyDescriptorStr(target, name); ok {
  474. return p.proxyGetOwnPropertyDescriptor(target.self.getOwnPropStr(name), target, v, name)
  475. }
  476. return target.self.getOwnPropStr(name)
  477. }
  478. func (p *proxyObject) getOwnPropIdx(idx valueInt) Value {
  479. target := p.target
  480. if v, ok := p.checkHandler().getOwnPropertyDescriptorIdx(target, idx); ok {
  481. return p.proxyGetOwnPropertyDescriptor(target.self.getOwnPropIdx(idx), target, v, idx)
  482. }
  483. return target.self.getOwnPropIdx(idx)
  484. }
  485. func (p *proxyObject) getOwnPropSym(s *Symbol) Value {
  486. target := p.target
  487. if v, ok := p.checkHandler().getOwnPropertyDescriptorSym(target, s); ok {
  488. return p.proxyGetOwnPropertyDescriptor(target.self.getOwnPropSym(s), target, v, s)
  489. }
  490. return target.self.getOwnPropSym(s)
  491. }
  492. func (p *proxyObject) proxyGetChecks(targetProp, trapResult Value, name fmt.Stringer) {
  493. if targetDesc, ok := targetProp.(*valueProperty); ok {
  494. if !targetDesc.accessor {
  495. if !targetDesc.writable && !targetDesc.configurable && !trapResult.SameAs(targetDesc.value) {
  496. 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))
  497. }
  498. } else {
  499. if !targetDesc.configurable && targetDesc.getterFunc == nil && trapResult != _undefined {
  500. 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))
  501. }
  502. }
  503. }
  504. }
  505. func (p *proxyObject) getStr(name unistring.String, receiver Value) Value {
  506. target := p.target
  507. if receiver == nil {
  508. receiver = p.val
  509. }
  510. if v, ok := p.checkHandler().getStr(target, name, receiver); ok {
  511. p.proxyGetChecks(target.self.getOwnPropStr(name), v, name)
  512. return v
  513. }
  514. return target.self.getStr(name, receiver)
  515. }
  516. func (p *proxyObject) getIdx(idx valueInt, receiver Value) Value {
  517. target := p.target
  518. if receiver == nil {
  519. receiver = p.val
  520. }
  521. if v, ok := p.checkHandler().getIdx(target, idx, receiver); ok {
  522. p.proxyGetChecks(target.self.getOwnPropIdx(idx), v, idx)
  523. return v
  524. }
  525. return target.self.getIdx(idx, receiver)
  526. }
  527. func (p *proxyObject) getSym(s *Symbol, receiver Value) Value {
  528. target := p.target
  529. if receiver == nil {
  530. receiver = p.val
  531. }
  532. if v, ok := p.checkHandler().getSym(target, s, receiver); ok {
  533. p.proxyGetChecks(target.self.getOwnPropSym(s), v, s)
  534. return v
  535. }
  536. return target.self.getSym(s, receiver)
  537. }
  538. func (p *proxyObject) proxySetPreCheck(trapResult, throw bool, name fmt.Stringer) bool {
  539. if !trapResult {
  540. p.val.runtime.typeErrorResult(throw, "'set' on proxy: trap returned falsish for property '%s'", name.String())
  541. }
  542. return trapResult
  543. }
  544. func (p *proxyObject) proxySetPostCheck(targetProp, value Value, name fmt.Stringer) {
  545. if prop, ok := targetProp.(*valueProperty); ok {
  546. if prop.accessor {
  547. if !prop.configurable && prop.setterFunc == nil {
  548. 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()))
  549. }
  550. } else if !prop.configurable && !prop.writable && !p.__sameValue(prop.value, value) {
  551. 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()))
  552. }
  553. }
  554. }
  555. func (p *proxyObject) proxySetStr(name unistring.String, value, receiver Value, throw bool) bool {
  556. target := p.target
  557. if v, ok := p.checkHandler().setStr(target, name, value, receiver); ok {
  558. if p.proxySetPreCheck(v, throw, name) {
  559. p.proxySetPostCheck(target.self.getOwnPropStr(name), value, name)
  560. return true
  561. }
  562. return false
  563. }
  564. return target.setStr(name, value, receiver, throw)
  565. }
  566. func (p *proxyObject) proxySetIdx(idx valueInt, value, receiver Value, throw bool) bool {
  567. target := p.target
  568. if v, ok := p.checkHandler().setIdx(target, idx, value, receiver); ok {
  569. if p.proxySetPreCheck(v, throw, idx) {
  570. p.proxySetPostCheck(target.self.getOwnPropIdx(idx), value, idx)
  571. return true
  572. }
  573. return false
  574. }
  575. return target.setIdx(idx, value, receiver, throw)
  576. }
  577. func (p *proxyObject) proxySetSym(s *Symbol, value, receiver Value, throw bool) bool {
  578. target := p.target
  579. if v, ok := p.checkHandler().setSym(target, s, value, receiver); ok {
  580. if p.proxySetPreCheck(v, throw, s) {
  581. p.proxySetPostCheck(target.self.getOwnPropSym(s), value, s)
  582. return true
  583. }
  584. return false
  585. }
  586. return target.setSym(s, value, receiver, throw)
  587. }
  588. func (p *proxyObject) setOwnStr(name unistring.String, v Value, throw bool) bool {
  589. return p.proxySetStr(name, v, p.val, throw)
  590. }
  591. func (p *proxyObject) setOwnIdx(idx valueInt, v Value, throw bool) bool {
  592. return p.proxySetIdx(idx, v, p.val, throw)
  593. }
  594. func (p *proxyObject) setOwnSym(s *Symbol, v Value, throw bool) bool {
  595. return p.proxySetSym(s, v, p.val, throw)
  596. }
  597. func (p *proxyObject) setForeignStr(name unistring.String, v, receiver Value, throw bool) (bool, bool) {
  598. return p.proxySetStr(name, v, receiver, throw), true
  599. }
  600. func (p *proxyObject) setForeignIdx(idx valueInt, v, receiver Value, throw bool) (bool, bool) {
  601. return p.proxySetIdx(idx, v, receiver, throw), true
  602. }
  603. func (p *proxyObject) setForeignSym(s *Symbol, v, receiver Value, throw bool) (bool, bool) {
  604. return p.proxySetSym(s, v, receiver, throw), true
  605. }
  606. func (p *proxyObject) proxyDeleteCheck(trapResult bool, targetProp Value, name fmt.Stringer, target *Object, throw bool) {
  607. if trapResult {
  608. if targetProp == nil {
  609. return
  610. }
  611. if targetDesc, ok := targetProp.(*valueProperty); ok {
  612. if !targetDesc.configurable {
  613. panic(p.val.runtime.NewTypeError("'deleteProperty' on proxy: property '%s' is a non-configurable property but the trap returned truish", name.String()))
  614. }
  615. }
  616. if !target.self.isExtensible() {
  617. panic(p.val.runtime.NewTypeError("'deleteProperty' on proxy: trap returned truish for property '%s' but the proxy target is non-extensible", name.String()))
  618. }
  619. } else {
  620. p.val.runtime.typeErrorResult(throw, "'deleteProperty' on proxy: trap returned falsish for property '%s'", name.String())
  621. }
  622. }
  623. func (p *proxyObject) deleteStr(name unistring.String, throw bool) bool {
  624. target := p.target
  625. if v, ok := p.checkHandler().deleteStr(target, name); ok {
  626. p.proxyDeleteCheck(v, target.self.getOwnPropStr(name), name, target, throw)
  627. return v
  628. }
  629. return target.self.deleteStr(name, throw)
  630. }
  631. func (p *proxyObject) deleteIdx(idx valueInt, throw bool) bool {
  632. target := p.target
  633. if v, ok := p.checkHandler().deleteIdx(target, idx); ok {
  634. p.proxyDeleteCheck(v, target.self.getOwnPropIdx(idx), idx, target, throw)
  635. return v
  636. }
  637. return target.self.deleteIdx(idx, throw)
  638. }
  639. func (p *proxyObject) deleteSym(s *Symbol, throw bool) bool {
  640. target := p.target
  641. if v, ok := p.checkHandler().deleteSym(target, s); ok {
  642. p.proxyDeleteCheck(v, target.self.getOwnPropSym(s), s, target, throw)
  643. return v
  644. }
  645. return target.self.deleteSym(s, throw)
  646. }
  647. func (p *proxyObject) keys(all bool, _ []Value) []Value {
  648. if v, ok := p.proxyOwnKeys(); ok {
  649. if !all {
  650. k := 0
  651. for i, key := range v {
  652. prop := p.val.getOwnProp(key)
  653. if prop == nil || prop == _undefined {
  654. continue
  655. }
  656. if prop, ok := prop.(*valueProperty); ok && !prop.enumerable {
  657. continue
  658. }
  659. if k != i {
  660. v[k] = v[i]
  661. }
  662. k++
  663. }
  664. v = v[:k]
  665. }
  666. return v
  667. }
  668. return p.target.self.keys(all, nil)
  669. }
  670. func (p *proxyObject) proxyOwnKeys() ([]Value, bool) {
  671. target := p.target
  672. if v, ok := p.checkHandler().ownKeys(target); ok {
  673. keys := p.val.runtime.toObject(v)
  674. var keyList []Value
  675. keySet := make(map[Value]struct{})
  676. l := toLength(keys.self.getStr("length", nil))
  677. for k := int64(0); k < l; k++ {
  678. item := keys.self.getIdx(valueInt(k), nil)
  679. if _, ok := item.(String); !ok {
  680. if _, ok := item.(*Symbol); !ok {
  681. panic(p.val.runtime.NewTypeError("%s is not a valid property name", item.String()))
  682. }
  683. }
  684. if _, exists := keySet[item]; exists {
  685. panic(p.val.runtime.NewTypeError("'ownKeys' on proxy: trap returned duplicate entries"))
  686. }
  687. keyList = append(keyList, item)
  688. keySet[item] = struct{}{}
  689. }
  690. ext := target.self.isExtensible()
  691. for item, next := target.self.iterateKeys()(); next != nil; item, next = next() {
  692. if _, exists := keySet[item.name]; exists {
  693. delete(keySet, item.name)
  694. } else {
  695. if !ext {
  696. panic(p.val.runtime.NewTypeError("'ownKeys' on proxy: trap result did not include '%s'", item.name.String()))
  697. }
  698. var prop Value
  699. if item.value == nil {
  700. prop = target.getOwnProp(item.name)
  701. } else {
  702. prop = item.value
  703. }
  704. if prop, ok := prop.(*valueProperty); ok && !prop.configurable {
  705. panic(p.val.runtime.NewTypeError("'ownKeys' on proxy: trap result did not include non-configurable '%s'", item.name.String()))
  706. }
  707. }
  708. }
  709. if !ext && len(keyList) > 0 && len(keySet) > 0 {
  710. panic(p.val.runtime.NewTypeError("'ownKeys' on proxy: trap returned extra keys but proxy target is non-extensible"))
  711. }
  712. return keyList, true
  713. }
  714. return nil, false
  715. }
  716. func (p *proxyObject) iterateStringKeys() iterNextFunc {
  717. return (&proxyPropIter{
  718. p: p,
  719. names: p.stringKeys(true, nil),
  720. }).next
  721. }
  722. func (p *proxyObject) iterateSymbols() iterNextFunc {
  723. return (&proxyPropIter{
  724. p: p,
  725. names: p.symbols(true, nil),
  726. }).next
  727. }
  728. func (p *proxyObject) iterateKeys() iterNextFunc {
  729. return (&proxyPropIter{
  730. p: p,
  731. names: p.keys(true, nil),
  732. }).next
  733. }
  734. func (p *proxyObject) assertCallable() (call func(FunctionCall) Value, ok bool) {
  735. if p.call != nil {
  736. return func(call FunctionCall) Value {
  737. return p.apply(call)
  738. }, true
  739. }
  740. return nil, false
  741. }
  742. func (p *proxyObject) vmCall(vm *vm, n int) {
  743. vm.pushCtx()
  744. vm.prg = nil
  745. vm.sb = vm.sp - n // so that [sb-1] points to the callee
  746. ret := p.apply(FunctionCall{This: vm.stack[vm.sp-n-2], Arguments: vm.stack[vm.sp-n : vm.sp]})
  747. if ret == nil {
  748. ret = _undefined
  749. }
  750. vm.stack[vm.sp-n-2] = ret
  751. vm.popCtx()
  752. vm.sp -= n + 1
  753. vm.pc++
  754. }
  755. func (p *proxyObject) assertConstructor() func(args []Value, newTarget *Object) *Object {
  756. if p.ctor != nil {
  757. return p.construct
  758. }
  759. return nil
  760. }
  761. func (p *proxyObject) apply(call FunctionCall) Value {
  762. if p.call == nil {
  763. panic(p.val.runtime.NewTypeError("proxy target is not a function"))
  764. }
  765. if v, ok := p.checkHandler().apply(p.target, nilSafe(call.This), call.Arguments); ok {
  766. return v
  767. }
  768. return p.call(call)
  769. }
  770. func (p *proxyObject) construct(args []Value, newTarget *Object) *Object {
  771. if p.ctor == nil {
  772. panic(p.val.runtime.NewTypeError("proxy target is not a constructor"))
  773. }
  774. if newTarget == nil {
  775. newTarget = p.val
  776. }
  777. if v, ok := p.checkHandler().construct(p.target, args, newTarget); ok {
  778. return p.val.runtime.toObject(v)
  779. }
  780. return p.ctor(args, newTarget)
  781. }
  782. func (p *proxyObject) __isCompatibleDescriptor(extensible bool, desc *PropertyDescriptor, current *valueProperty) bool {
  783. if current == nil {
  784. return extensible
  785. }
  786. if !current.configurable {
  787. if desc.Configurable == FLAG_TRUE {
  788. return false
  789. }
  790. if desc.Enumerable != FLAG_NOT_SET && desc.Enumerable.Bool() != current.enumerable {
  791. return false
  792. }
  793. if desc.IsGeneric() {
  794. return true
  795. }
  796. if desc.IsData() != !current.accessor {
  797. return desc.Configurable != FLAG_FALSE
  798. }
  799. if desc.IsData() && !current.accessor {
  800. if !current.configurable {
  801. if desc.Writable == FLAG_TRUE && !current.writable {
  802. return false
  803. }
  804. if !current.writable {
  805. if desc.Value != nil && !desc.Value.SameAs(current.value) {
  806. return false
  807. }
  808. }
  809. }
  810. return true
  811. }
  812. if desc.IsAccessor() && current.accessor {
  813. if !current.configurable {
  814. if desc.Setter != nil && desc.Setter.SameAs(current.setterFunc) {
  815. return false
  816. }
  817. if desc.Getter != nil && desc.Getter.SameAs(current.getterFunc) {
  818. return false
  819. }
  820. }
  821. }
  822. }
  823. return true
  824. }
  825. func (p *proxyObject) __sameValue(val1, val2 Value) bool {
  826. if val1 == nil && val2 == nil {
  827. return true
  828. }
  829. if val1 != nil {
  830. return val1.SameAs(val2)
  831. }
  832. return false
  833. }
  834. func (p *proxyObject) filterKeys(vals []Value, all, symbols bool) []Value {
  835. if !all {
  836. k := 0
  837. for i, val := range vals {
  838. var prop Value
  839. if symbols {
  840. if s, ok := val.(*Symbol); ok {
  841. prop = p.getOwnPropSym(s)
  842. } else {
  843. continue
  844. }
  845. } else {
  846. if _, ok := val.(*Symbol); !ok {
  847. prop = p.getOwnPropStr(val.string())
  848. } else {
  849. continue
  850. }
  851. }
  852. if prop == nil {
  853. continue
  854. }
  855. if prop, ok := prop.(*valueProperty); ok && !prop.enumerable {
  856. continue
  857. }
  858. if k != i {
  859. vals[k] = vals[i]
  860. }
  861. k++
  862. }
  863. vals = vals[:k]
  864. } else {
  865. k := 0
  866. for i, val := range vals {
  867. if _, ok := val.(*Symbol); ok != symbols {
  868. continue
  869. }
  870. if k != i {
  871. vals[k] = vals[i]
  872. }
  873. k++
  874. }
  875. vals = vals[:k]
  876. }
  877. return vals
  878. }
  879. func (p *proxyObject) stringKeys(all bool, _ []Value) []Value { // we can assume accum is empty
  880. var keys []Value
  881. if vals, ok := p.proxyOwnKeys(); ok {
  882. keys = vals
  883. } else {
  884. keys = p.target.self.stringKeys(true, nil)
  885. }
  886. return p.filterKeys(keys, all, false)
  887. }
  888. func (p *proxyObject) symbols(all bool, accum []Value) []Value {
  889. var symbols []Value
  890. if vals, ok := p.proxyOwnKeys(); ok {
  891. symbols = vals
  892. } else {
  893. symbols = p.target.self.symbols(true, nil)
  894. }
  895. symbols = p.filterKeys(symbols, all, true)
  896. if accum == nil {
  897. return symbols
  898. }
  899. accum = append(accum, symbols...)
  900. return accum
  901. }
  902. func (p *proxyObject) className() string {
  903. if p.target == nil {
  904. panic(p.val.runtime.NewTypeError("proxy has been revoked"))
  905. }
  906. if p.call != nil || p.ctor != nil {
  907. return classFunction
  908. }
  909. return classObject
  910. }
  911. func (p *proxyObject) typeOf() String {
  912. if p.call == nil {
  913. return stringObjectC
  914. }
  915. return stringFunction
  916. }
  917. func (p *proxyObject) exportType() reflect.Type {
  918. return proxyType
  919. }
  920. func (p *proxyObject) export(*objectExportCtx) interface{} {
  921. return Proxy{
  922. proxy: p,
  923. }
  924. }
  925. func (p *proxyObject) revoke() {
  926. p.handler = nil
  927. p.target = nil
  928. }