proxy.go 31 KB

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