builtin_proxy_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  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. var p = Object.getPrototypeOf(proxy);
  73. assert.sameValue(proto2, p);
  74. `
  75. testScript1(TESTLIB+SCRIPT, _undefined, t)
  76. }*/
  77. func TestProxy_Object_target_isExtensible(t *testing.T) {
  78. const SCRIPT = `
  79. var obj = {};
  80. Object.seal(obj);
  81. var proxy = new Proxy(obj, {});
  82. Object.isExtensible(proxy);
  83. `
  84. testScript1(SCRIPT, valueFalse, t)
  85. }
  86. func TestProxy_proxy_isExtensible(t *testing.T) {
  87. const SCRIPT = `
  88. var obj = {};
  89. Object.seal(obj);
  90. var proxy = new Proxy(obj, {
  91. isExtensible: function(target) {
  92. return false;
  93. }
  94. });
  95. Object.isExtensible(proxy);
  96. `
  97. testScript1(SCRIPT, valueFalse, t)
  98. }
  99. func TestProxy_native_proxy_isExtensible(t *testing.T) {
  100. const SCRIPT = `
  101. (function() {
  102. Object.preventExtensions(target);
  103. return Object.isExtensible(proxy);
  104. })();
  105. `
  106. runtime := New()
  107. target := runtime.NewObject()
  108. runtime.Set("target", target)
  109. proxy := runtime.NewProxy(target, &ProxyTrapConfig{
  110. IsExtensible: func(target *Object) (success bool) {
  111. return false
  112. },
  113. })
  114. runtime.Set("proxy", proxy)
  115. val, err := runtime.RunString(SCRIPT)
  116. if err != nil {
  117. panic(err)
  118. }
  119. if val.ToBoolean() {
  120. t.Fatal()
  121. }
  122. }
  123. func TestProxy_Object_target_preventExtensions(t *testing.T) {
  124. const SCRIPT = `
  125. var obj = {
  126. canEvolve: true
  127. };
  128. var proxy = new Proxy(obj, {});
  129. Object.preventExtensions(proxy);
  130. proxy.canEvolve
  131. `
  132. testScript1(SCRIPT, valueTrue, t)
  133. }
  134. func TestProxy_proxy_preventExtensions(t *testing.T) {
  135. const SCRIPT = `
  136. var obj = {
  137. canEvolve: true
  138. };
  139. var proxy = new Proxy(obj, {
  140. preventExtensions: function(target) {
  141. target.canEvolve = false;
  142. return false;
  143. }
  144. });
  145. Object.preventExtensions(proxy);
  146. proxy.canEvolve;
  147. `
  148. testScript1(SCRIPT, valueFalse, t)
  149. }
  150. func TestProxy_native_proxy_preventExtensions(t *testing.T) {
  151. const SCRIPT = `
  152. (function() {
  153. Object.preventExtensions(proxy);
  154. return proxy.canEvolve;
  155. })();
  156. `
  157. runtime := New()
  158. target := runtime.NewObject()
  159. target.Set("canEvolve", true)
  160. runtime.Set("target", target)
  161. proxy := runtime.NewProxy(target, &ProxyTrapConfig{
  162. PreventExtensions: func(target *Object) (success bool) {
  163. target.Set("canEvolve", false)
  164. return false
  165. },
  166. })
  167. runtime.Set("proxy", proxy)
  168. val, err := runtime.RunString(SCRIPT)
  169. if err != nil {
  170. panic(err)
  171. }
  172. if val.ToBoolean() {
  173. t.Fatal()
  174. }
  175. }
  176. func TestProxy_Object_target_getOwnPropertyDescriptor(t *testing.T) {
  177. const SCRIPT = `
  178. var desc = {
  179. configurable: false,
  180. enumerable: false,
  181. value: 42,
  182. writable: false
  183. };
  184. var obj = {};
  185. Object.defineProperty(obj, "foo", desc);
  186. var proxy = new Proxy(obj, {});
  187. var desc2 = Object.getOwnPropertyDescriptor(proxy, "foo");
  188. desc2.value
  189. `
  190. testScript1(SCRIPT, valueInt(42), t)
  191. }
  192. func TestProxy_proxy_getOwnPropertyDescriptor(t *testing.T) {
  193. const SCRIPT = `
  194. var desc = {
  195. configurable: false,
  196. enumerable: false,
  197. value: 42,
  198. writable: false
  199. };
  200. var proxy_desc = {
  201. configurable: false,
  202. enumerable: false,
  203. value: 24,
  204. writable: false
  205. };
  206. var obj = {};
  207. Object.defineProperty(obj, "foo", desc);
  208. var proxy = new Proxy(obj, {
  209. getOwnPropertyDescriptor: function(target, property) {
  210. return proxy_desc;
  211. }
  212. });
  213. assert.throws(TypeError, function() {
  214. Object.getOwnPropertyDescriptor(proxy, "foo");
  215. });
  216. undefined;
  217. `
  218. testScript1(TESTLIB+SCRIPT, _undefined, t)
  219. }
  220. func TestProxy_native_proxy_getOwnPropertyDescriptor(t *testing.T) {
  221. const SCRIPT = `
  222. (function() {
  223. var desc = {
  224. configurable: true,
  225. enumerable: false,
  226. value: 42,
  227. writable: false
  228. };
  229. var proxy_desc = {
  230. configurable: true,
  231. enumerable: false,
  232. value: 24,
  233. writable: false
  234. };
  235. var obj = {};
  236. Object.defineProperty(obj, "foo", desc);
  237. return function(constructor) {
  238. var proxy = constructor(obj, proxy_desc);
  239. var desc2 = Object.getOwnPropertyDescriptor(proxy, "foo");
  240. return desc2.value
  241. }
  242. })();
  243. `
  244. runtime := New()
  245. constructor := func(call FunctionCall) Value {
  246. target := call.Argument(0).(*Object)
  247. proxyDesc := call.Argument(1).(*Object)
  248. return runtime.NewProxy(target, &ProxyTrapConfig{
  249. GetOwnPropertyDescriptor: func(target *Object, prop string) PropertyDescriptor {
  250. return runtime.toPropertyDescriptor(proxyDesc)
  251. },
  252. }).proxy.val
  253. }
  254. val, err := runtime.RunString(SCRIPT)
  255. if err != nil {
  256. panic(err)
  257. }
  258. if c, ok := val.(*Object).self.assertCallable(); ok {
  259. val := c(FunctionCall{
  260. This: val,
  261. Arguments: []Value{runtime.ToValue(constructor)},
  262. })
  263. if i := val.ToInteger(); i != 24 {
  264. t.Fatalf("val: %d", i)
  265. }
  266. } else {
  267. t.Fatal("not a function")
  268. }
  269. }
  270. func TestProxy_Object_target_defineProperty(t *testing.T) {
  271. const SCRIPT = `
  272. var obj = {};
  273. var proxy = new Proxy(obj, {});
  274. Object.defineProperty(proxy, "foo", {
  275. value: "test123"
  276. });
  277. proxy.foo;
  278. `
  279. testScript1(SCRIPT, asciiString("test123"), t)
  280. }
  281. func TestProxy_proxy_defineProperty(t *testing.T) {
  282. const SCRIPT = `
  283. var obj = {};
  284. var proxy = new Proxy(obj, {
  285. defineProperty: function(target, prop, descriptor) {
  286. target.foo = "321tset";
  287. return true;
  288. }
  289. });
  290. Object.defineProperty(proxy, "foo", {
  291. value: "test123"
  292. });
  293. proxy.foo;
  294. `
  295. testScript1(SCRIPT, asciiString("321tset"), t)
  296. }
  297. func TestProxy_native_proxy_defineProperty(t *testing.T) {
  298. const SCRIPT = `
  299. Object.defineProperty(proxy, "foo", {
  300. value: "test123"
  301. });
  302. proxy.foo;
  303. `
  304. runtime := New()
  305. target := runtime.NewObject()
  306. proxy := runtime.NewProxy(target, &ProxyTrapConfig{
  307. DefineProperty: func(target *Object, key string, propertyDescriptor PropertyDescriptor) (success bool) {
  308. target.Set("foo", "321tset")
  309. return true
  310. },
  311. })
  312. runtime.Set("proxy", proxy)
  313. val, err := runtime.RunString(SCRIPT)
  314. if err != nil {
  315. panic(err)
  316. }
  317. if s := val.String(); s != "321tset" {
  318. t.Fatalf("val: %s", s)
  319. }
  320. }
  321. func TestProxy_target_has_in(t *testing.T) {
  322. const SCRIPT = `
  323. var obj = {
  324. secret: true
  325. };
  326. var proxy = new Proxy(obj, {});
  327. "secret" in proxy
  328. `
  329. testScript1(SCRIPT, valueTrue, t)
  330. }
  331. func TestProxy_proxy_has_in(t *testing.T) {
  332. const SCRIPT = `
  333. var obj = {
  334. secret: true
  335. };
  336. var proxy = new Proxy(obj, {
  337. has: function(target, key) {
  338. return key !== "secret";
  339. }
  340. });
  341. "secret" in proxy
  342. `
  343. testScript1(SCRIPT, valueFalse, t)
  344. }
  345. func TestProxy_target_has_with(t *testing.T) {
  346. const SCRIPT = `
  347. var obj = {
  348. secret: true
  349. };
  350. var proxy = new Proxy(obj, {});
  351. with(proxy) {
  352. (secret);
  353. }
  354. `
  355. testScript1(SCRIPT, valueTrue, t)
  356. }
  357. func TestProxy_proxy_has_with(t *testing.T) {
  358. const SCRIPT = `
  359. var obj = {
  360. secret: true
  361. };
  362. var proxy = new Proxy(obj, {
  363. has: function(target, key) {
  364. return key !== "secret";
  365. }
  366. });
  367. var thrown = false;
  368. try {
  369. with(proxy) {
  370. (secret);
  371. }
  372. } catch (e) {
  373. if (e instanceof ReferenceError) {
  374. thrown = true;
  375. } else {
  376. throw e;
  377. }
  378. }
  379. thrown;
  380. `
  381. testScript1(SCRIPT, valueTrue, t)
  382. }
  383. func TestProxy_target_get(t *testing.T) {
  384. const SCRIPT = `
  385. var obj = {};
  386. var proxy = new Proxy(obj, {});
  387. Object.defineProperty(proxy, "foo", {
  388. value: "test123"
  389. });
  390. proxy.foo;
  391. `
  392. testScript1(SCRIPT, asciiString("test123"), t)
  393. }
  394. func TestProxy_proxy_get(t *testing.T) {
  395. const SCRIPT = `
  396. var obj = {};
  397. var proxy = new Proxy(obj, {
  398. get: function(target, prop, receiver) {
  399. return "321tset"
  400. }
  401. });
  402. Object.defineProperty(proxy, "foo", {
  403. value: "test123",
  404. configurable: true,
  405. });
  406. proxy.foo;
  407. `
  408. testScript1(SCRIPT, asciiString("321tset"), t)
  409. }
  410. func TestProxy_target_set_prop(t *testing.T) {
  411. const SCRIPT = `
  412. var obj = {};
  413. var proxy = new Proxy(obj, {});
  414. proxy.foo = "test123";
  415. proxy.foo;
  416. `
  417. testScript1(SCRIPT, asciiString("test123"), t)
  418. }
  419. func TestProxy_proxy_set_prop(t *testing.T) {
  420. const SCRIPT = `
  421. var obj = {};
  422. var proxy = new Proxy(obj, {
  423. set: function(target, prop, receiver) {
  424. target.foo = "321tset";
  425. return true;
  426. }
  427. });
  428. proxy.foo = "test123";
  429. proxy.foo;
  430. `
  431. testScript1(SCRIPT, asciiString("321tset"), t)
  432. }
  433. func TestProxy_target_set_associative(t *testing.T) {
  434. const SCRIPT = `
  435. var obj = {};
  436. var proxy = new Proxy(obj, {});
  437. proxy["foo"] = "test123";
  438. proxy.foo;
  439. `
  440. testScript1(SCRIPT, asciiString("test123"), t)
  441. }
  442. func TestProxy_proxy_set_associative(t *testing.T) {
  443. const SCRIPT = `
  444. var obj = {};
  445. var proxy = new Proxy(obj, {
  446. set: function(target, property, value, receiver) {
  447. target["foo"] = "321tset";
  448. return true;
  449. }
  450. });
  451. proxy["foo"] = "test123";
  452. proxy.foo;
  453. `
  454. testScript1(SCRIPT, asciiString("321tset"), t)
  455. }
  456. func TestProxy_target_delete(t *testing.T) {
  457. const SCRIPT = `
  458. var obj = {
  459. foo: "test"
  460. };
  461. var proxy = new Proxy(obj, {});
  462. delete proxy.foo;
  463. proxy.foo;
  464. `
  465. testScript1(SCRIPT, _undefined, t)
  466. }
  467. func TestProxy_proxy_delete(t *testing.T) {
  468. const SCRIPT = `
  469. var obj = {
  470. foo: "test"
  471. };
  472. var proxy = new Proxy(obj, {
  473. deleteProperty: function(target, prop) {
  474. return true;
  475. }
  476. });
  477. delete proxy.foo;
  478. proxy.foo;
  479. `
  480. testScript1(SCRIPT, asciiString("test"), t)
  481. }
  482. func TestProxy_target_keys(t *testing.T) {
  483. const SCRIPT = `
  484. var obj = {
  485. foo: "test"
  486. };
  487. var proxy = new Proxy(obj, {});
  488. var keys = Object.keys(proxy);
  489. if (keys.length != 1) {
  490. throw new Error("assertion error");
  491. }
  492. `
  493. testScript1(SCRIPT, _undefined, t)
  494. }
  495. func TestProxy_proxy_keys(t *testing.T) {
  496. const SCRIPT = `
  497. var obj = {
  498. foo: "test"
  499. };
  500. var proxy = new Proxy(obj, {
  501. ownKeys: function(target) {
  502. return ["foo", "bar"];
  503. }
  504. });
  505. var keys = Object.keys(proxy);
  506. if (keys.length !== 1) {
  507. throw new Error("length is "+keys.length);
  508. }
  509. if (keys[0] !== "foo") {
  510. throw new Error("keys[0] is "+keys[0]);
  511. }
  512. `
  513. testScript1(SCRIPT, _undefined, t)
  514. }
  515. func TestProxy_target_call(t *testing.T) {
  516. const SCRIPT = `
  517. var obj = function() {
  518. return "test"
  519. }
  520. var proxy = new Proxy(obj, {});
  521. proxy();
  522. `
  523. testScript1(SCRIPT, asciiString("test"), t)
  524. }
  525. func TestProxy_proxy_call(t *testing.T) {
  526. const SCRIPT = `
  527. var obj = function() {
  528. return "test"
  529. }
  530. var proxy = new Proxy(obj, {
  531. apply: function(target, thisArg, args) {
  532. return "tset"
  533. }
  534. });
  535. proxy();
  536. `
  537. testScript1(SCRIPT, asciiString("tset"), t)
  538. }
  539. func TestProxy_target_func_apply(t *testing.T) {
  540. const SCRIPT = `
  541. var obj = function() {
  542. return "test"
  543. }
  544. var proxy = new Proxy(obj, {});
  545. proxy.apply();
  546. `
  547. testScript1(SCRIPT, asciiString("test"), t)
  548. }
  549. func TestProxy_proxy_func_apply(t *testing.T) {
  550. const SCRIPT = `
  551. var obj = function() {
  552. return "test"
  553. }
  554. var proxy = new Proxy(obj, {
  555. apply: function(target, thisArg, args) {
  556. return "tset"
  557. }
  558. });
  559. proxy.apply();
  560. `
  561. testScript1(SCRIPT, asciiString("tset"), t)
  562. }
  563. func TestProxy_target_func_call(t *testing.T) {
  564. const SCRIPT = `
  565. var obj = function() {
  566. return "test"
  567. }
  568. var proxy = new Proxy(obj, {});
  569. proxy.call();
  570. `
  571. testScript1(SCRIPT, asciiString("test"), t)
  572. }
  573. func TestProxy_proxy_func_call(t *testing.T) {
  574. const SCRIPT = `
  575. var obj = function() {
  576. return "test"
  577. }
  578. var proxy = new Proxy(obj, {
  579. apply: function(target, thisArg, args) {
  580. return "tset"
  581. }
  582. });
  583. proxy.call();
  584. `
  585. testScript1(SCRIPT, asciiString("tset"), t)
  586. }
  587. func TestProxy_target_new(t *testing.T) {
  588. const SCRIPT = `
  589. var obj = function(word) {
  590. this.foo = function() {
  591. return word;
  592. }
  593. }
  594. var proxy = new Proxy(obj, {});
  595. var instance = new proxy("test");
  596. instance.foo();
  597. `
  598. testScript1(SCRIPT, asciiString("test"), t)
  599. }
  600. func TestProxy_proxy_new(t *testing.T) {
  601. const SCRIPT = `
  602. var obj = function(word) {
  603. this.foo = function() {
  604. return word;
  605. }
  606. }
  607. var proxy = new Proxy(obj, {
  608. construct: function(target, args, newTarget) {
  609. var word = args[0];
  610. return {
  611. foo: function() {
  612. return "caught-" + word
  613. }
  614. }
  615. }
  616. });
  617. var instance = new proxy("test");
  618. instance.foo();
  619. `
  620. testScript1(SCRIPT, asciiString("caught-test"), t)
  621. }
  622. func TestProxy_Object_native_proxy_ownKeys(t *testing.T) {
  623. headers := map[string][]string{
  624. "k0": {},
  625. }
  626. vm := New()
  627. proxy := vm.NewProxy(vm.NewObject(), &ProxyTrapConfig{
  628. OwnKeys: func(target *Object) (object *Object) {
  629. keys := make([]interface{}, 0, len(headers))
  630. for k := range headers {
  631. keys = append(keys, k)
  632. }
  633. return vm.ToValue(keys).ToObject(vm)
  634. },
  635. GetOwnPropertyDescriptor: func(target *Object, prop string) PropertyDescriptor {
  636. v, exists := headers[prop]
  637. if exists {
  638. return PropertyDescriptor{
  639. Value: vm.ToValue(v),
  640. Enumerable: FLAG_TRUE,
  641. Configurable: FLAG_TRUE,
  642. }
  643. }
  644. return PropertyDescriptor{}
  645. },
  646. })
  647. vm.Set("headers", proxy)
  648. v, err := vm.RunString(`
  649. var keys = Object.keys(headers);
  650. keys.length === 1 && keys[0] === "k0";
  651. `)
  652. if err != nil {
  653. t.Fatal(err)
  654. }
  655. if v != valueTrue {
  656. t.Fatal("not true", v)
  657. }
  658. }
  659. func TestProxy_proxy_forIn(t *testing.T) {
  660. const SCRIPT = `
  661. var proto = {
  662. a: 2,
  663. protoProp: 1
  664. }
  665. Object.defineProperty(proto, "protoNonEnum", {
  666. value: 2,
  667. writable: true,
  668. configurable: true
  669. });
  670. var target = Object.create(proto);
  671. var proxy = new Proxy(target, {
  672. ownKeys: function() {
  673. return ["a", "b"];
  674. },
  675. getOwnPropertyDescriptor: function(target, p) {
  676. switch (p) {
  677. case "a":
  678. case "b":
  679. return {
  680. value: 42,
  681. enumerable: true,
  682. configurable: true
  683. }
  684. }
  685. },
  686. });
  687. var forInResult = [];
  688. for (var key in proxy) {
  689. if (forInResult.indexOf(key) !== -1) {
  690. throw new Error("Duplicate property "+key);
  691. }
  692. forInResult.push(key);
  693. }
  694. forInResult.length === 3 && forInResult[0] === "a" && forInResult[1] === "b" && forInResult[2] === "protoProp";
  695. `
  696. testScript1(SCRIPT, valueTrue, t)
  697. }