builtin_proxy_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  1. package goja
  2. import (
  3. "testing"
  4. )
  5. func TestProxy_Object_target_getPrototypeOf(t *testing.T) {
  6. const SCRIPT = `
  7. var proto = {};
  8. var obj = Object.create(proto);
  9. var proxy = new Proxy(obj, {});
  10. var p = Object.getPrototypeOf(proxy);
  11. assert.sameValue(proto, p);
  12. `
  13. testScript1(TESTLIB+SCRIPT, _undefined, t)
  14. }
  15. func TestProxy_Object_proxy_getPrototypeOf(t *testing.T) {
  16. const SCRIPT = `
  17. var proto = {};
  18. var proto2 = {};
  19. var obj = Object.create(proto);
  20. var proxy = new Proxy(obj, {
  21. getPrototypeOf: function(target) {
  22. return proto2;
  23. }
  24. });
  25. var p = Object.getPrototypeOf(proxy);
  26. assert.sameValue(proto2, p);
  27. `
  28. testScript1(TESTLIB+SCRIPT, _undefined, t)
  29. }
  30. func TestProxy_Object_native_proxy_getPrototypeOf(t *testing.T) {
  31. const SCRIPT = `
  32. var p = Object.getPrototypeOf(proxy);
  33. assert.sameValue(proto, p);
  34. `
  35. runtime := New()
  36. prototype := runtime.NewObject()
  37. runtime.Set("proto", prototype)
  38. target := runtime.NewObject()
  39. proxy := runtime.NewProxy(target, &ProxyTrapConfig{
  40. GetPrototypeOf: func(target *Object) *Object {
  41. return prototype
  42. },
  43. })
  44. runtime.Set("proxy", proxy)
  45. _, err := runtime.RunString(TESTLIB + SCRIPT)
  46. if err != nil {
  47. panic(err)
  48. }
  49. }
  50. func TestProxy_Object_target_setPrototypeOf(t *testing.T) {
  51. const SCRIPT = `
  52. var proto = {};
  53. var obj = {};
  54. Object.setPrototypeOf(obj, proto);
  55. var proxy = new Proxy(obj, {});
  56. var p = Object.getPrototypeOf(proxy);
  57. assert.sameValue(proto, p);
  58. `
  59. testScript1(TESTLIB+SCRIPT, _undefined, t)
  60. }
  61. func TestProxy_Object_proxy_setPrototypeOf(t *testing.T) {
  62. const SCRIPT = `
  63. var proto = {};
  64. var proto2 = {};
  65. var obj = {};
  66. Object.setPrototypeOf(obj, proto);
  67. var proxy = new Proxy(obj, {
  68. setPrototypeOf: function(target, prototype) {
  69. return Object.setPrototypeOf(target, proto2);
  70. }
  71. });
  72. Object.setPrototypeOf(proxy, null);
  73. var p = Object.getPrototypeOf(proxy);
  74. assert.sameValue(proto2, p);
  75. `
  76. testScript1(TESTLIB+SCRIPT, _undefined, t)
  77. }
  78. func TestProxy_Object_target_isExtensible(t *testing.T) {
  79. const SCRIPT = `
  80. var obj = {};
  81. Object.seal(obj);
  82. var proxy = new Proxy(obj, {});
  83. Object.isExtensible(proxy);
  84. `
  85. testScript1(SCRIPT, valueFalse, t)
  86. }
  87. func TestProxy_proxy_isExtensible(t *testing.T) {
  88. const SCRIPT = `
  89. var obj = {};
  90. Object.seal(obj);
  91. var proxy = new Proxy(obj, {
  92. isExtensible: function(target) {
  93. return false;
  94. }
  95. });
  96. Object.isExtensible(proxy);
  97. `
  98. testScript1(SCRIPT, valueFalse, t)
  99. }
  100. func TestProxy_native_proxy_isExtensible(t *testing.T) {
  101. const SCRIPT = `
  102. (function() {
  103. Object.preventExtensions(target);
  104. return Object.isExtensible(proxy);
  105. })();
  106. `
  107. runtime := New()
  108. target := runtime.NewObject()
  109. runtime.Set("target", target)
  110. proxy := runtime.NewProxy(target, &ProxyTrapConfig{
  111. IsExtensible: func(target *Object) (success bool) {
  112. return false
  113. },
  114. })
  115. runtime.Set("proxy", proxy)
  116. val, err := runtime.RunString(SCRIPT)
  117. if err != nil {
  118. panic(err)
  119. }
  120. if val.ToBoolean() {
  121. t.Fatal()
  122. }
  123. }
  124. func TestProxy_Object_target_preventExtensions(t *testing.T) {
  125. const SCRIPT = `
  126. var obj = {
  127. canEvolve: true
  128. };
  129. var proxy = new Proxy(obj, {});
  130. Object.preventExtensions(proxy);
  131. proxy.canEvolve
  132. `
  133. testScript1(SCRIPT, valueTrue, t)
  134. }
  135. func TestProxy_proxy_preventExtensions(t *testing.T) {
  136. const SCRIPT = `
  137. var obj = {
  138. canEvolve: true
  139. };
  140. var proxy = new Proxy(obj, {
  141. preventExtensions: function(target) {
  142. target.canEvolve = false;
  143. return false;
  144. }
  145. });
  146. Object.preventExtensions(proxy);
  147. proxy.canEvolve;
  148. `
  149. testScript1(SCRIPT, valueFalse, t)
  150. }
  151. func TestProxy_native_proxy_preventExtensions(t *testing.T) {
  152. const SCRIPT = `
  153. (function() {
  154. Object.preventExtensions(proxy);
  155. return proxy.canEvolve;
  156. })();
  157. `
  158. runtime := New()
  159. target := runtime.NewObject()
  160. target.Set("canEvolve", true)
  161. runtime.Set("target", target)
  162. proxy := runtime.NewProxy(target, &ProxyTrapConfig{
  163. PreventExtensions: func(target *Object) (success bool) {
  164. target.Set("canEvolve", false)
  165. return false
  166. },
  167. })
  168. runtime.Set("proxy", proxy)
  169. val, err := runtime.RunString(SCRIPT)
  170. if err != nil {
  171. panic(err)
  172. }
  173. if val.ToBoolean() {
  174. t.Fatal()
  175. }
  176. }
  177. func TestProxy_Object_target_getOwnPropertyDescriptor(t *testing.T) {
  178. const SCRIPT = `
  179. var desc = {
  180. configurable: false,
  181. enumerable: false,
  182. value: 42,
  183. writable: false
  184. };
  185. var obj = {};
  186. Object.defineProperty(obj, "foo", desc);
  187. var proxy = new Proxy(obj, {});
  188. var desc2 = Object.getOwnPropertyDescriptor(proxy, "foo");
  189. desc2.value
  190. `
  191. testScript1(SCRIPT, valueInt(42), t)
  192. }
  193. func TestProxy_proxy_getOwnPropertyDescriptor(t *testing.T) {
  194. const SCRIPT = `
  195. var desc = {
  196. configurable: false,
  197. enumerable: false,
  198. value: 42,
  199. writable: false
  200. };
  201. var proxy_desc = {
  202. configurable: false,
  203. enumerable: false,
  204. value: 24,
  205. writable: false
  206. };
  207. var obj = {};
  208. Object.defineProperty(obj, "foo", desc);
  209. var proxy = new Proxy(obj, {
  210. getOwnPropertyDescriptor: function(target, property) {
  211. return proxy_desc;
  212. }
  213. });
  214. assert.throws(TypeError, function() {
  215. Object.getOwnPropertyDescriptor(proxy, "foo");
  216. });
  217. undefined;
  218. `
  219. testScript1(TESTLIB+SCRIPT, _undefined, t)
  220. }
  221. func TestProxy_native_proxy_getOwnPropertyDescriptor(t *testing.T) {
  222. const SCRIPT = `
  223. (function() {
  224. var desc = {
  225. configurable: true,
  226. enumerable: false,
  227. value: 42,
  228. writable: false
  229. };
  230. var proxy_desc = {
  231. configurable: true,
  232. enumerable: false,
  233. value: 24,
  234. writable: false
  235. };
  236. var obj = {};
  237. Object.defineProperty(obj, "foo", desc);
  238. return function(constructor) {
  239. var proxy = constructor(obj, proxy_desc);
  240. var desc2 = Object.getOwnPropertyDescriptor(proxy, "foo");
  241. return desc2.value
  242. }
  243. })();
  244. `
  245. runtime := New()
  246. constructor := func(call FunctionCall) Value {
  247. target := call.Argument(0).(*Object)
  248. proxyDesc := call.Argument(1).(*Object)
  249. return runtime.NewProxy(target, &ProxyTrapConfig{
  250. GetOwnPropertyDescriptor: func(target *Object, prop string) PropertyDescriptor {
  251. return runtime.toPropertyDescriptor(proxyDesc)
  252. },
  253. }).proxy.val
  254. }
  255. val, err := runtime.RunString(SCRIPT)
  256. if err != nil {
  257. panic(err)
  258. }
  259. if c, ok := val.(*Object).self.assertCallable(); ok {
  260. val := c(FunctionCall{
  261. This: val,
  262. Arguments: []Value{runtime.ToValue(constructor)},
  263. })
  264. if i := val.ToInteger(); i != 24 {
  265. t.Fatalf("val: %d", i)
  266. }
  267. } else {
  268. t.Fatal("not a function")
  269. }
  270. }
  271. func TestProxy_Object_target_defineProperty(t *testing.T) {
  272. const SCRIPT = `
  273. var obj = {};
  274. var proxy = new Proxy(obj, {});
  275. Object.defineProperty(proxy, "foo", {
  276. value: "test123"
  277. });
  278. proxy.foo;
  279. `
  280. testScript1(SCRIPT, asciiString("test123"), t)
  281. }
  282. func TestProxy_proxy_defineProperty(t *testing.T) {
  283. const SCRIPT = `
  284. var obj = {};
  285. var proxy = new Proxy(obj, {
  286. defineProperty: function(target, prop, descriptor) {
  287. target.foo = "321tset";
  288. return true;
  289. }
  290. });
  291. Object.defineProperty(proxy, "foo", {
  292. value: "test123"
  293. });
  294. proxy.foo;
  295. `
  296. testScript1(SCRIPT, asciiString("321tset"), t)
  297. }
  298. func TestProxy_native_proxy_defineProperty(t *testing.T) {
  299. const SCRIPT = `
  300. Object.defineProperty(proxy, "foo", {
  301. value: "test123"
  302. });
  303. proxy.foo;
  304. `
  305. runtime := New()
  306. target := runtime.NewObject()
  307. proxy := runtime.NewProxy(target, &ProxyTrapConfig{
  308. DefineProperty: func(target *Object, key string, propertyDescriptor PropertyDescriptor) (success bool) {
  309. target.Set("foo", "321tset")
  310. return true
  311. },
  312. })
  313. runtime.Set("proxy", proxy)
  314. val, err := runtime.RunString(SCRIPT)
  315. if err != nil {
  316. panic(err)
  317. }
  318. if s := val.String(); s != "321tset" {
  319. t.Fatalf("val: %s", s)
  320. }
  321. }
  322. func TestProxy_target_has_in(t *testing.T) {
  323. const SCRIPT = `
  324. var obj = {
  325. secret: true
  326. };
  327. var proxy = new Proxy(obj, {});
  328. "secret" in proxy
  329. `
  330. testScript1(SCRIPT, valueTrue, t)
  331. }
  332. func TestProxy_proxy_has_in(t *testing.T) {
  333. const SCRIPT = `
  334. var obj = {
  335. secret: true
  336. };
  337. var proxy = new Proxy(obj, {
  338. has: function(target, key) {
  339. return key !== "secret";
  340. }
  341. });
  342. "secret" in proxy
  343. `
  344. testScript1(SCRIPT, valueFalse, t)
  345. }
  346. func TestProxy_target_has_with(t *testing.T) {
  347. const SCRIPT = `
  348. var obj = {
  349. secret: true
  350. };
  351. var proxy = new Proxy(obj, {});
  352. with(proxy) {
  353. (secret);
  354. }
  355. `
  356. testScript1(SCRIPT, valueTrue, t)
  357. }
  358. func TestProxy_proxy_has_with(t *testing.T) {
  359. const SCRIPT = `
  360. var obj = {
  361. secret: true
  362. };
  363. var proxy = new Proxy(obj, {
  364. has: function(target, key) {
  365. return key !== "secret";
  366. }
  367. });
  368. var thrown = false;
  369. try {
  370. with(proxy) {
  371. (secret);
  372. }
  373. } catch (e) {
  374. if (e instanceof ReferenceError) {
  375. thrown = true;
  376. } else {
  377. throw e;
  378. }
  379. }
  380. thrown;
  381. `
  382. testScript1(SCRIPT, valueTrue, t)
  383. }
  384. func TestProxy_target_get(t *testing.T) {
  385. const SCRIPT = `
  386. var obj = {};
  387. var proxy = new Proxy(obj, {});
  388. Object.defineProperty(proxy, "foo", {
  389. value: "test123"
  390. });
  391. proxy.foo;
  392. `
  393. testScript1(SCRIPT, asciiString("test123"), t)
  394. }
  395. func TestProxy_proxy_get(t *testing.T) {
  396. const SCRIPT = `
  397. var obj = {};
  398. var proxy = new Proxy(obj, {
  399. get: function(target, prop, receiver) {
  400. return "321tset"
  401. }
  402. });
  403. Object.defineProperty(proxy, "foo", {
  404. value: "test123",
  405. configurable: true,
  406. });
  407. proxy.foo;
  408. `
  409. testScript1(SCRIPT, asciiString("321tset"), t)
  410. }
  411. func TestProxy_proxy_get_json_stringify(t *testing.T) {
  412. const SCRIPT = `
  413. var obj = {};
  414. var propValue = "321tset";
  415. var _handler, _target, _prop, _receiver;
  416. var proxy = new Proxy(obj, {
  417. ownKeys: function() {
  418. return ["foo"];
  419. },
  420. getOwnPropertyDescriptor: function(target, prop) {
  421. if (prop === "foo") {
  422. return {
  423. value: propValue,
  424. enumerable: true,
  425. configurable: true
  426. }
  427. }
  428. },
  429. get: function(target, prop, receiver) {
  430. if (prop === "foo") {
  431. _prop = prop;
  432. _receiver = receiver;
  433. return propValue;
  434. }
  435. return obj[prop];
  436. }
  437. });
  438. var res = JSON.stringify(proxy);
  439. assert.sameValue(res, '{"foo":"321tset"}');
  440. assert.sameValue(_prop, "foo");
  441. assert.sameValue(_receiver, proxy);
  442. `
  443. testScript1(TESTLIB+SCRIPT, _undefined, t)
  444. }
  445. func TestProxy_native_proxy_get(t *testing.T) {
  446. vm := New()
  447. propValue := vm.ToValue("321tset")
  448. obj := vm.NewObject()
  449. proxy := vm.NewProxy(obj, &ProxyTrapConfig{
  450. OwnKeys: func(*Object) *Object {
  451. return vm.newArrayValues([]Value{vm.ToValue("foo")})
  452. },
  453. GetOwnPropertyDescriptor: func(target *Object, prop string) (propertyDescriptor PropertyDescriptor) {
  454. if prop == "foo" {
  455. return PropertyDescriptor{
  456. Value: propValue,
  457. Enumerable: FLAG_TRUE,
  458. Configurable: FLAG_TRUE,
  459. }
  460. }
  461. return PropertyDescriptor{}
  462. },
  463. Get: func(target *Object, property string, receiver *Object) (value Value) {
  464. if property == "foo" {
  465. return propValue
  466. }
  467. return obj.Get(property)
  468. },
  469. })
  470. vm.Set("proxy", proxy)
  471. res, err := vm.RunString(`JSON.stringify(proxy)`)
  472. if err != nil {
  473. t.Fatal(err)
  474. }
  475. if !res.SameAs(asciiString(`{"foo":"321tset"}`)) {
  476. t.Fatalf("res: %v", res)
  477. }
  478. res, err = vm.RunString(`proxy[Symbol.toPrimitive]`)
  479. if err != nil {
  480. t.Fatal(err)
  481. }
  482. if !IsUndefined(res) {
  483. t.Fatalf("res: %v", res)
  484. }
  485. res, err = vm.RunString(`proxy.hasOwnProperty(Symbol.toPrimitive)`)
  486. if err != nil {
  487. t.Fatal(err)
  488. }
  489. if !res.SameAs(valueFalse) {
  490. t.Fatalf("res: %v", res)
  491. }
  492. res, err = vm.RunString(`proxy.toString()`)
  493. if err != nil {
  494. t.Fatal(err)
  495. }
  496. if !res.SameAs(asciiString(`[object Object]`)) {
  497. t.Fatalf("res: %v", res)
  498. }
  499. }
  500. func TestProxy_target_set_prop(t *testing.T) {
  501. const SCRIPT = `
  502. var obj = {};
  503. var proxy = new Proxy(obj, {});
  504. proxy.foo = "test123";
  505. proxy.foo;
  506. `
  507. testScript1(SCRIPT, asciiString("test123"), t)
  508. }
  509. func TestProxy_proxy_set_prop(t *testing.T) {
  510. const SCRIPT = `
  511. var obj = {};
  512. var proxy = new Proxy(obj, {
  513. set: function(target, prop, receiver) {
  514. target.foo = "321tset";
  515. return true;
  516. }
  517. });
  518. proxy.foo = "test123";
  519. proxy.foo;
  520. `
  521. testScript1(SCRIPT, asciiString("321tset"), t)
  522. }
  523. func TestProxy_target_set_associative(t *testing.T) {
  524. const SCRIPT = `
  525. var obj = {};
  526. var proxy = new Proxy(obj, {});
  527. proxy["foo"] = "test123";
  528. proxy.foo;
  529. `
  530. testScript1(SCRIPT, asciiString("test123"), t)
  531. }
  532. func TestProxy_proxy_set_associative(t *testing.T) {
  533. const SCRIPT = `
  534. var obj = {};
  535. var proxy = new Proxy(obj, {
  536. set: function(target, property, value, receiver) {
  537. target["foo"] = "321tset";
  538. return true;
  539. }
  540. });
  541. proxy["foo"] = "test123";
  542. proxy.foo;
  543. `
  544. testScript1(SCRIPT, asciiString("321tset"), t)
  545. }
  546. func TestProxy_target_delete(t *testing.T) {
  547. const SCRIPT = `
  548. var obj = {
  549. foo: "test"
  550. };
  551. var proxy = new Proxy(obj, {});
  552. delete proxy.foo;
  553. proxy.foo;
  554. `
  555. testScript1(SCRIPT, _undefined, t)
  556. }
  557. func TestProxy_proxy_delete(t *testing.T) {
  558. const SCRIPT = `
  559. var obj = {
  560. foo: "test"
  561. };
  562. var proxy = new Proxy(obj, {
  563. deleteProperty: function(target, prop) {
  564. return true;
  565. }
  566. });
  567. delete proxy.foo;
  568. proxy.foo;
  569. `
  570. testScript1(SCRIPT, asciiString("test"), t)
  571. }
  572. func TestProxy_target_keys(t *testing.T) {
  573. const SCRIPT = `
  574. var obj = {
  575. foo: "test"
  576. };
  577. var proxy = new Proxy(obj, {});
  578. var keys = Object.keys(proxy);
  579. if (keys.length != 1) {
  580. throw new Error("assertion error");
  581. }
  582. `
  583. testScript1(SCRIPT, _undefined, t)
  584. }
  585. func TestProxy_proxy_keys(t *testing.T) {
  586. const SCRIPT = `
  587. var obj = {
  588. foo: "test"
  589. };
  590. var proxy = new Proxy(obj, {
  591. ownKeys: function(target) {
  592. return ["foo", "bar"];
  593. }
  594. });
  595. var keys = Object.keys(proxy);
  596. if (keys.length !== 1) {
  597. throw new Error("length is "+keys.length);
  598. }
  599. if (keys[0] !== "foo") {
  600. throw new Error("keys[0] is "+keys[0]);
  601. }
  602. `
  603. testScript1(SCRIPT, _undefined, t)
  604. }
  605. func TestProxy_target_call(t *testing.T) {
  606. const SCRIPT = `
  607. var obj = function() {
  608. return "test"
  609. }
  610. var proxy = new Proxy(obj, {});
  611. proxy();
  612. `
  613. testScript1(SCRIPT, asciiString("test"), t)
  614. }
  615. func TestProxy_proxy_call(t *testing.T) {
  616. const SCRIPT = `
  617. var obj = function() {
  618. return "test"
  619. }
  620. var proxy = new Proxy(obj, {
  621. apply: function(target, thisArg, args) {
  622. return "tset"
  623. }
  624. });
  625. proxy();
  626. `
  627. testScript1(SCRIPT, asciiString("tset"), t)
  628. }
  629. func TestProxy_target_func_apply(t *testing.T) {
  630. const SCRIPT = `
  631. var obj = function() {
  632. return "test"
  633. }
  634. var proxy = new Proxy(obj, {});
  635. proxy.apply();
  636. `
  637. testScript1(SCRIPT, asciiString("test"), t)
  638. }
  639. func TestProxy_proxy_func_apply(t *testing.T) {
  640. const SCRIPT = `
  641. var obj = function() {
  642. return "test"
  643. }
  644. var proxy = new Proxy(obj, {
  645. apply: function(target, thisArg, args) {
  646. return "tset"
  647. }
  648. });
  649. proxy.apply();
  650. `
  651. testScript1(SCRIPT, asciiString("tset"), t)
  652. }
  653. func TestProxy_target_func_call(t *testing.T) {
  654. const SCRIPT = `
  655. var obj = function() {
  656. return "test"
  657. }
  658. var proxy = new Proxy(obj, {});
  659. proxy.call();
  660. `
  661. testScript1(SCRIPT, asciiString("test"), t)
  662. }
  663. func TestProxy_proxy_func_call(t *testing.T) {
  664. const SCRIPT = `
  665. var obj = function() {
  666. return "test"
  667. }
  668. var proxy = new Proxy(obj, {
  669. apply: function(target, thisArg, args) {
  670. return "tset"
  671. }
  672. });
  673. proxy.call();
  674. `
  675. testScript1(SCRIPT, asciiString("tset"), t)
  676. }
  677. func TestProxy_target_new(t *testing.T) {
  678. const SCRIPT = `
  679. var obj = function(word) {
  680. this.foo = function() {
  681. return word;
  682. }
  683. }
  684. var proxy = new Proxy(obj, {});
  685. var instance = new proxy("test");
  686. instance.foo();
  687. `
  688. testScript1(SCRIPT, asciiString("test"), t)
  689. }
  690. func TestProxy_proxy_new(t *testing.T) {
  691. const SCRIPT = `
  692. var obj = function(word) {
  693. this.foo = function() {
  694. return word;
  695. }
  696. }
  697. var proxy = new Proxy(obj, {
  698. construct: function(target, args, newTarget) {
  699. var word = args[0];
  700. return {
  701. foo: function() {
  702. return "caught-" + word
  703. }
  704. }
  705. }
  706. });
  707. var instance = new proxy("test");
  708. instance.foo();
  709. `
  710. testScript1(SCRIPT, asciiString("caught-test"), t)
  711. }
  712. func TestProxy_Object_native_proxy_ownKeys(t *testing.T) {
  713. headers := map[string][]string{
  714. "k0": {},
  715. }
  716. vm := New()
  717. proxy := vm.NewProxy(vm.NewObject(), &ProxyTrapConfig{
  718. OwnKeys: func(target *Object) (object *Object) {
  719. keys := make([]interface{}, 0, len(headers))
  720. for k := range headers {
  721. keys = append(keys, k)
  722. }
  723. return vm.ToValue(keys).ToObject(vm)
  724. },
  725. GetOwnPropertyDescriptor: func(target *Object, prop string) PropertyDescriptor {
  726. v, exists := headers[prop]
  727. if exists {
  728. return PropertyDescriptor{
  729. Value: vm.ToValue(v),
  730. Enumerable: FLAG_TRUE,
  731. Configurable: FLAG_TRUE,
  732. }
  733. }
  734. return PropertyDescriptor{}
  735. },
  736. })
  737. vm.Set("headers", proxy)
  738. v, err := vm.RunString(`
  739. var keys = Object.keys(headers);
  740. keys.length === 1 && keys[0] === "k0";
  741. `)
  742. if err != nil {
  743. t.Fatal(err)
  744. }
  745. if v != valueTrue {
  746. t.Fatal("not true", v)
  747. }
  748. }
  749. func TestProxy_proxy_forIn(t *testing.T) {
  750. const SCRIPT = `
  751. var proto = {
  752. a: 2,
  753. protoProp: 1
  754. }
  755. Object.defineProperty(proto, "protoNonEnum", {
  756. value: 2,
  757. writable: true,
  758. configurable: true
  759. });
  760. var target = Object.create(proto);
  761. var proxy = new Proxy(target, {
  762. ownKeys: function() {
  763. return ["a", "b"];
  764. },
  765. getOwnPropertyDescriptor: function(target, p) {
  766. switch (p) {
  767. case "a":
  768. case "b":
  769. return {
  770. value: 42,
  771. enumerable: true,
  772. configurable: true
  773. }
  774. }
  775. },
  776. });
  777. var forInResult = [];
  778. for (var key in proxy) {
  779. if (forInResult.indexOf(key) !== -1) {
  780. throw new Error("Duplicate property "+key);
  781. }
  782. forInResult.push(key);
  783. }
  784. forInResult.length === 3 && forInResult[0] === "a" && forInResult[1] === "b" && forInResult[2] === "protoProp";
  785. `
  786. testScript1(SCRIPT, valueTrue, t)
  787. }
  788. func TestProxyExport(t *testing.T) {
  789. vm := New()
  790. v, err := vm.RunString(`
  791. new Proxy({}, {});
  792. `)
  793. if err != nil {
  794. t.Fatal(err)
  795. }
  796. v1 := v.Export()
  797. if _, ok := v1.(Proxy); !ok {
  798. t.Fatalf("Export returned unexpected type: %T", v1)
  799. }
  800. }