proto_initializer.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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. /// <reference path="protolib.js" />
  6. if (this.WScript && this.WScript.LoadScriptFile) {
  7. WScript.LoadScriptFile("protolib.js");
  8. }
  9. // Test __proto__ (object literal) initializer in a new engine:
  10. // Run "enabled" function, disable__proto__, then run "disabled" (or by default "enabled" again).
  11. function test_init(enabled, /*optional*/disabled) {
  12. var eng = make_engine();
  13. eng.run(enabled);
  14. eng.disable__proto__();
  15. eng.run(disabled || enabled);
  16. }
  17. var tests = [
  18. {
  19. name: "init to an object",
  20. body: function () {
  21. test_init(
  22. function () { // enabled: [[prototype]]
  23. var p = { p: 123 };
  24. var o = { __proto__: p };
  25. assert.areEqual(p, Object.getPrototypeOf(o));
  26. assert.isTrue(!o.hasOwnProperty("__proto__"));
  27. assert.areEqual(123, o.p);
  28. assert.areEqual(p, Object.getPrototypeOf(o));
  29. });
  30. }
  31. },
  32. {
  33. name: "init to null",
  34. body: function () {
  35. test_init(
  36. function () { // enabled: [[prototype]]
  37. var o = { __proto__: null };
  38. assert.areEqual(null, Object.getPrototypeOf(o));
  39. assert.isFalse({}.hasOwnProperty.apply(o, ["__proto__"]));
  40. assert.areEqual(undefined, o.__proto__); // o's [[prototype]] is null, so doesn't have a __proto__ property
  41. });
  42. }
  43. },
  44. {
  45. name: "init to neither object nor null",
  46. body: function () {
  47. test_init(
  48. function () { // enabled: throw
  49. function test(value) {
  50. var o = { __proto__: value };
  51. assert.areEqual(Object.prototype, Object.getPrototypeOf(o));
  52. assert.isFalse(o.hasOwnProperty("__proto__"));
  53. }
  54. [undefined, 0, 123, Infinity, true, false, "string value"].forEach(function (value) {
  55. test(value);
  56. });
  57. });
  58. }
  59. },
  60. {
  61. name: "init to accessor",
  62. body: function () {
  63. test_init(
  64. function () { // same for enabled/disabled: local property
  65. var o = {
  66. get __proto__() { return "proto"; },
  67. set __proto__(value) { this.__proto__value = value; }
  68. };
  69. assert.areEqual(Object.prototype, Object.getPrototypeOf(o));
  70. assert.isTrue(o.hasOwnProperty("__proto__"));
  71. assert.areEqual("proto", o.__proto__);
  72. o.__proto__ = "a value";
  73. assert.areEqual("a value", o.__proto__value);
  74. });
  75. }
  76. },
  77. {
  78. name: "verify no incorrectly shared type",
  79. body: function () {
  80. function foo(p) {
  81. return {
  82. a: 100,
  83. __proto__: p,
  84. };
  85. }
  86. // If we incorrectly shared Type, we'll have wrong [[prototype]].
  87. var o1 = foo({ b: 1 });
  88. var o2 = foo({ b: 2 });
  89. var o3 = foo({ b: 3 });
  90. assert.areEqual(1, o1.b);
  91. assert.areEqual(2, o2.b);
  92. assert.areEqual(3, o3.b);
  93. }
  94. },
  95. {
  96. name: "verify not accidentally enables it for function parameters",
  97. body: function () {
  98. function foo(a, b, __proto__) {
  99. var o = arguments;
  100. assert.areEqual(Object.prototype, Object.getPrototypeOf(o));
  101. assert.areEqual(Object.prototype, o.__proto__);
  102. assert.isTrue(!o.hasOwnProperty("__proto__"));
  103. assert.areEqual(1, o[0]);
  104. assert.areEqual(3, o[2].a);
  105. assert.areEqual(4, __proto__.b);
  106. }
  107. foo(1, 2, { a: 3, b: 4, c: 5 });
  108. }
  109. },
  110. {
  111. name: "verify not accidentally enables it for JSON",
  112. body: function () {
  113. var o = JSON.parse('{ "a": 1, "b": 2, "__proto__": {"c": 3, "d": 4} }');
  114. assert.areEqual(Object.prototype, Object.getPrototypeOf(o));
  115. assert.isTrue(o.hasOwnProperty("__proto__"));
  116. assert.areEqual(3, o.__proto__.c);
  117. }
  118. },
  119. {
  120. name: "Verify not accidentally share code with global InitFld",
  121. body: function () {
  122. // Check if we accidentally changed global's [[prototype]] to a function when declaring a global
  123. // function with name __proto__ (see bottom of this file). If yes, we'd have "length" property.
  124. assert.areEqual(undefined, this.length);
  125. }
  126. },
  127. {
  128. name: "Run the same initializer with __proto__ enabled, run it again with __proto__ disabled",
  129. body: function () {
  130. var eng = make_engine();
  131. // inject global g_p and foo into eng
  132. eng.eval("var g_p = { p: 123 }");
  133. eng.eval("var foo = " + function() {
  134. return { a: 0, __proto__: g_p, b: 1 };
  135. });
  136. var test = function () { // enabled: [[prototype]]
  137. var o = foo();
  138. assert.areEqual(g_p, Object.getPrototypeOf(o));
  139. assert.areEqual("a,b", Object.keys(o).toString());
  140. assert.areEqual(123, o.p);
  141. };
  142. eng.run(test);
  143. eng.disable__proto__();
  144. eng.run(test);
  145. }
  146. },
  147. {
  148. name: "Enumeration order should be unaffected",
  149. body: function () {
  150. test_init(
  151. function () {
  152. var o = {
  153. a: 100,
  154. __proto__: new Number(200),
  155. b: 300,
  156. };
  157. assert.areEqual("a,b", Object.keys(o).toString());
  158. });
  159. test_init(
  160. function () { // enabled: [[prototype]]
  161. var o = {
  162. a: 100,
  163. __proto__: { c: "p0", d: "p1" },
  164. b: 300,
  165. };
  166. var names = [];
  167. for (var name in o) {
  168. names.push(name);
  169. }
  170. assert.areEqual("a,b", Object.keys(o).toString());
  171. assert.areEqual("a,b,c,d", names.toString());
  172. });
  173. }
  174. },
  175. {
  176. name: "Verify bytecode serialization",
  177. body: function () { // Test in current engine to use switch -ForceSerialized
  178. var o = {
  179. a: 100,
  180. __proto__: { c: "p0", d: "p1" },
  181. b: 300,
  182. };
  183. // Serialized bytecode should correctly mark if initializer has__proto__
  184. assert.areEqual("a,b", Object.keys(o).toString());
  185. }
  186. },
  187. ];
  188. testRunner.run(tests);
  189. // Used by: Verify not accidentally share code with global InitFld
  190. function __proto__() { }