proxybugs.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
  6. var tests = [
  7. {
  8. name: "Setting proxy object on Map and WeakMap",
  9. body() {
  10. [WeakMap, Map].forEach(function(ctor) {
  11. var target = {};
  12. let p = new Proxy(target, {});
  13. let map = new ctor();
  14. map.set(p, 101);
  15. assert.areEqual(map.get(p), 101, ctor.name + " map should be able to set and get the proxy object");
  16. p.x = 20;
  17. assert.areEqual(target.x, 20, "target object should work as expected even after proxy object is added to map");
  18. });
  19. }
  20. },
  21. {
  22. name: "Setting proxy object on Map and WeakMap - multiple sets and delete",
  23. body() {
  24. [WeakMap, Map].forEach(function(ctor) {
  25. var target = {};
  26. let p = new Proxy(target, {});
  27. let map = new ctor();
  28. map.set(p, 101);
  29. assert.areEqual(map.get(p), 101);
  30. map.delete(p);
  31. assert.areEqual(map.get(p), undefined, ctor.name + " map can remove the proxy object properly");
  32. map.set(p, 102);
  33. assert.areEqual(map.get(p), 102, ctor.name + " proxy object can be set again and it returns 102");
  34. p.x = 20;
  35. assert.areEqual(target.x, 20, "target object should work as expected even after proxy object is added to map");
  36. });
  37. }
  38. },
  39. {
  40. name: "Assertion validation : returning descriptor during getOwnPropertyDescriptor should not pollute the descriptor",
  41. body() {
  42. var target = {};
  43. var handler = {};
  44. var getOwnPropertyDescriptorCalled = false;
  45. handler['defineProperty'] = function () {
  46. assert.fail("This function will not be called as 'getOwnPropertyDescriptor' will add accessor");
  47. };
  48. handler['getOwnPropertyDescriptor'] = function (t, property) {
  49. getOwnPropertyDescriptorCalled = true;
  50. Object.defineProperty(t, 'abc', { set: function () { } });
  51. return Reflect.getOwnPropertyDescriptor(t, property);
  52. };
  53. var proxy = new Proxy(target, handler);
  54. proxy.abc = undefined;
  55. assert.isTrue(getOwnPropertyDescriptorCalled);
  56. }
  57. },
  58. {
  59. name: "Assertion validation : returning descriptor with writable false should not defineProperty again.",
  60. body() {
  61. var target = {};
  62. var handler = {};
  63. var getOwnPropertyDescriptorCalled = false;
  64. handler['defineProperty'] = function () {
  65. assert.fail("This function will not be called as 'getOwnPropertyDescriptor' will add property with writable false");
  66. };
  67. handler['getOwnPropertyDescriptor'] = function (t, property) {
  68. getOwnPropertyDescriptorCalled = true;
  69. Object.defineProperty(t, 'abc', { value : 1, writable : false });
  70. return Reflect.getOwnPropertyDescriptor(t, property);
  71. };
  72. var proxy = new Proxy(target, handler);
  73. proxy.abc = undefined;
  74. assert.isTrue(getOwnPropertyDescriptorCalled);
  75. }
  76. },
  77. {
  78. name: "No property found at getOwnPropertyDescriptor will call defineProperty",
  79. body() {
  80. var target = {};
  81. var handler = {};
  82. var definePropertyCalled = false;
  83. var getOwnPropertyDescriptorCalled = false;
  84. handler['defineProperty'] = function () {
  85. definePropertyCalled = true;
  86. };
  87. handler['getOwnPropertyDescriptor'] = function (t, property) {
  88. getOwnPropertyDescriptorCalled = true;
  89. return Reflect.getOwnPropertyDescriptor(t, property);
  90. };
  91. var proxy = new Proxy(target, handler);
  92. proxy.abc = undefined;
  93. assert.isTrue(definePropertyCalled);
  94. assert.isTrue(getOwnPropertyDescriptorCalled);
  95. }
  96. },
  97. {
  98. name: "Cross-site on proxy exercising function trap - no function handler provided",
  99. body() {
  100. var targetCalled = false;
  101. var func4 = function () { targetCalled = true; };
  102. var v0 = new Proxy(func4, {});
  103. var anotherScript = `function foo() {
  104. var a = undefined;
  105. v0(a) > 1;
  106. }`;
  107. var sc0 = WScript.LoadScript(anotherScript, 'samethread');
  108. sc0.v0 = v0;
  109. sc0.foo();
  110. assert.isTrue(targetCalled);
  111. }
  112. },
  113. {
  114. name: "Type confusion in JavascriptProxy::SetPropertyTrap when using a Symbol",
  115. body: function () {
  116. try{ Reflect.set((new Proxy({}, {has: function(){ return true; }})), 'abc', 0x44444444, new Uint32Array); } catch(e){}
  117. try{ Reflect.set((new Proxy({}, {has: function(){ return true; }})), 'abc', 0x44444444, new Uint32Array); } catch(e){}
  118. var obj1 = Object.create(new Proxy({}, {}));
  119. obj1[Symbol.species] = 0;
  120. }
  121. },
  122. {
  123. name: "Cross-site on proxy exercising function trap - with 'apply' function trap",
  124. body() {
  125. var trapCalled = false;
  126. var func4 = function () {};
  127. var handler = {
  128. apply : function(a, b, c) {
  129. trapCalled = true;
  130. }
  131. };
  132. var v0 = new Proxy(func4, handler);
  133. var anotherScript = `function foo() {
  134. var a = undefined;
  135. v0(a) > 1;
  136. }`;
  137. var sc0 = WScript.LoadScript(anotherScript, 'samethread');
  138. sc0.v0 = v0;
  139. sc0.foo();
  140. assert.isTrue(trapCalled);
  141. }
  142. },
  143. {
  144. name: "Assertion validation : revoking the proxy in getPrototypeOf trap",
  145. body() {
  146. var trapCalled = false;
  147. var handler = {
  148. getPrototypeOf : function(a, b) {
  149. trapCalled = true;
  150. obj.revoke();
  151. return {};
  152. }
  153. };
  154. var obj = Proxy.revocable({}, handler);
  155. Object.getPrototypeOf(obj.proxy);
  156. assert.isTrue(trapCalled);
  157. }
  158. },
  159. {
  160. name: "Assertion validation : revoking the proxy in setPrototypeOf trap",
  161. body() {
  162. var trapCalled = false;
  163. var handler = {
  164. setPrototypeOf : function(a, b) {
  165. trapCalled = true;
  166. obj.revoke();
  167. return true;
  168. }
  169. };
  170. var obj = Proxy.revocable({}, handler);
  171. var ret = Object.setPrototypeOf(obj.proxy, {});
  172. assert.isTrue(trapCalled);
  173. }
  174. },
  175. {
  176. name: "Assertion validation : revoking the proxy in isExtensible trap",
  177. body() {
  178. var trapCalled = false;
  179. var handler = {
  180. isExtensible : function(a, b) {
  181. trapCalled = true;
  182. obj.revoke();
  183. return true;
  184. }
  185. };
  186. var obj = Proxy.revocable({}, handler);
  187. var ret = Object.isExtensible(obj.proxy);
  188. assert.isTrue(trapCalled);
  189. }
  190. },
  191. {
  192. name: "Assertion validation : revoking the proxy in preventExtensions trap",
  193. body() {
  194. var trapCalled = false;
  195. var handler = {
  196. preventExtensions : function(a, b) {
  197. trapCalled = true;
  198. obj.revoke();
  199. }
  200. };
  201. var obj = Proxy.revocable({}, handler);
  202. Object.preventExtensions(obj.proxy);
  203. assert.isTrue(trapCalled);
  204. }
  205. },
  206. {
  207. name: "Assertion validation : revoking the proxy in getOwnPropertyDescriptor trap",
  208. body() {
  209. var trapCalled = false;
  210. var handler = {
  211. getOwnPropertyDescriptor : function(a, b, c) {
  212. trapCalled = true;
  213. obj.revoke();
  214. }
  215. };
  216. var obj = Proxy.revocable({}, handler);
  217. assert.throws( () => { Object.getOwnPropertyDescriptor(obj.proxy, 'a'); }, TypeError);
  218. assert.isTrue(trapCalled);
  219. }
  220. },
  221. {
  222. name: "Assertion validation : revoking the proxy by invoking getOwnPropertyDescriptor trap but no handler present",
  223. body() {
  224. var trapCalled = false;
  225. var handler = {
  226. get(t, propertyKey) {
  227. trapCalled = true;
  228. if (propertyKey === "getOwnPropertyDescriptor")
  229. obj.revoke();
  230. }
  231. };
  232. var obj = Proxy.revocable({a:0}, new Proxy({}, handler));
  233. Object.getOwnPropertyDescriptor(obj.proxy, 'a');
  234. assert.isTrue(trapCalled);
  235. }
  236. },
  237. {
  238. name: "Assertion validation : revoking the proxy in has trap",
  239. body() {
  240. var trapCalled = false;
  241. var handler = {
  242. has : function(a, b, c) {
  243. trapCalled = true;
  244. obj.revoke();
  245. return false;
  246. }
  247. };
  248. var obj = Proxy.revocable({}, handler);
  249. 'a' in obj.proxy;
  250. assert.isTrue(trapCalled);
  251. }
  252. },
  253. {
  254. name: "Assertion validation : revoking the proxy in get trap",
  255. body() {
  256. var trapCalled = false;
  257. var handler = {
  258. get : function (a, b, c) {
  259. trapCalled = true;
  260. obj.revoke();
  261. return {};
  262. }
  263. };
  264. var obj = Proxy.revocable({}, handler);
  265. var ret = obj.proxy.a;
  266. assert.isTrue(trapCalled);
  267. }
  268. },
  269. {
  270. name: "Assertion validation : revoking the proxy in set trap",
  271. body() {
  272. var trapCalled = false;
  273. var handler = {
  274. set : function (a, b, c) {
  275. trapCalled = true;
  276. obj.revoke();
  277. return {};
  278. }
  279. };
  280. var obj = Proxy.revocable({}, handler);
  281. obj.proxy.a = 10;
  282. assert.isTrue(trapCalled);
  283. }
  284. },
  285. {
  286. name: "Assertion validation : revoking the proxy in deleteProperty trap",
  287. body() {
  288. var trapCalled = false;
  289. var handler = {
  290. deleteProperty : function (a, b, c) {
  291. trapCalled = true;
  292. obj.revoke();
  293. return {};
  294. }
  295. };
  296. var obj = Proxy.revocable({}, handler);
  297. delete obj.proxy.a;
  298. assert.isTrue(trapCalled);
  299. }
  300. },
  301. {
  302. name: "Assertion validation : revoking the proxy in ownKeys trap",
  303. body() {
  304. var trapCalled = false;
  305. var handler = {
  306. ownKeys : function (a, b, c) {
  307. trapCalled = true;
  308. obj.revoke();
  309. return {};
  310. }
  311. };
  312. var obj = Proxy.revocable({}, handler);
  313. Object.keys(obj.proxy);
  314. assert.isTrue(trapCalled);
  315. }
  316. },
  317. {
  318. name: "Assertion validation : revoking the proxy in apply trap",
  319. body() {
  320. var trapCalled = false;
  321. var handler = {
  322. get apply () {
  323. trapCalled = true;
  324. obj.revoke();
  325. }
  326. };
  327. var obj = Proxy.revocable(() => {}, handler);
  328. obj.proxy();
  329. assert.isTrue(trapCalled);
  330. }
  331. },
  332. {
  333. name: "Assertion validation : revoking the proxy in construct trap",
  334. body() {
  335. var trapCalled = false;
  336. var handler = {
  337. get construct () {
  338. trapCalled = true;
  339. obj.revoke();
  340. return () => { return {}; };
  341. }
  342. };
  343. var obj = Proxy.revocable(() => {}, handler);
  344. new obj.proxy();
  345. assert.isTrue(trapCalled);
  346. }
  347. },
  348. ];
  349. testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });