ES6Super.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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: "super in direct eval inside an object method",
  9. body: function () {
  10. var value;
  11. var obj = {
  12. m() { value = eval('super.value;'); }
  13. };
  14. assert.areEqual(undefined, value);
  15. obj.m();
  16. assert.areEqual(undefined, value);
  17. Object.setPrototypeOf(obj, { value: "super" });
  18. obj.m();
  19. assert.areEqual("super", value);
  20. }
  21. },
  22. {
  23. name: "home object's prototype is null",
  24. body: function () {
  25. var value;
  26. var obj = {
  27. m() {
  28. value = "identifier";
  29. super.prop;
  30. },
  31. n() {
  32. value = "expression";
  33. super["prop"];
  34. }
  35. };
  36. Object.setPrototypeOf(obj, null);
  37. assert.throws(obj.m, TypeError, "identifier", "Unable to get property 'prop' of undefined or null reference");
  38. assert.throws(obj.n, TypeError, "expression", "Unable to get property 'prop' of undefined or null reference");
  39. }
  40. },
  41. {
  42. name: "super in strict mode - object",
  43. body: function () {
  44. "use strict";
  45. var obj0 = {
  46. m() {
  47. super.prop = "identifier";
  48. Object.freeze(obj0);
  49. super.prop = "super";
  50. }
  51. };
  52. var obj1 = {
  53. m() {
  54. super['prop'] = "expression";
  55. Object.freeze(obj1);
  56. super['prop'] = "super";
  57. }
  58. };
  59. var base = {};
  60. Object.setPrototypeOf(obj0, base);
  61. Object.setPrototypeOf(obj1, base);
  62. assert.throws(()=>obj0.m(), TypeError, "identifier", "Assignment to read-only properties is not allowed in strict mode");
  63. assert.areEqual("identifier", obj0.prop);
  64. assert.throws(()=>obj1.m(), TypeError, "identifier", "Assignment to read-only properties is not allowed in strict mode");
  65. assert.areEqual("expression", obj1.prop);
  66. }
  67. },
  68. {
  69. name: "super in strict mode - class",
  70. body: function () {
  71. class A {
  72. m() {
  73. super.prop = "identifier";
  74. Object.freeze(A.prototype);
  75. super.prop = "super";
  76. }
  77. test() {
  78. assert.throws(()=>A.prototype.m(), TypeError, "identifier", "Assignment to read-only properties is not allowed in strict mode");
  79. assert.areEqual("identifier", A.prototype.prop);
  80. }
  81. }
  82. A.prototype.test();
  83. class B {
  84. m() {
  85. super['prop'] = "expression";
  86. Object.freeze(B.prototype);
  87. super['prop'] = "super";
  88. }
  89. test() {
  90. assert.throws(()=>B.prototype.m(), TypeError, "identifier", "Assignment to read-only properties is not allowed in strict mode");
  91. assert.areEqual("expression", B.prototype.prop);
  92. }
  93. }
  94. B.prototype.test();
  95. }
  96. },
  97. {
  98. name: "super property in eval",
  99. body: function () {
  100. var valuex, valuey, valuez, valuet;
  101. var a = { x: 'a', y: 'a', z: 'a', t: 'a' };
  102. var b = { y: 'b', t: 'b' };
  103. Object.setPrototypeOf(b, a);
  104. var obj = {
  105. x : 'obj',
  106. y : 'obj',
  107. z : 'obj',
  108. t : 'obj',
  109. m() {
  110. valuex = eval('super.x');
  111. valuey = eval('super.y');
  112. },
  113. n() {
  114. valuez = eval('super["z"]');
  115. valuet = eval('super["t"]');
  116. }
  117. };
  118. Object.setPrototypeOf(obj, b);
  119. obj.m();
  120. assert.areEqual("a", valuex, "value x == 'a'");
  121. assert.areEqual("b", valuey, "value y == 'b'");
  122. obj.n();
  123. assert.areEqual("a", valuez, "value z == 'a'");
  124. assert.areEqual("b", valuet, "value t == 'b'");
  125. }
  126. },
  127. {
  128. name: "evaluation of expression before making super property reference",
  129. body: function () {
  130. var value = undefined;
  131. assert.throws(function(){ eval('super[value = 0]'); }, ReferenceError, "super[value = 0]", "Missing or invalid 'super' binding");
  132. assert.areEqual(0, value);
  133. }
  134. },
  135. {
  136. name: "evaluation of argument list after getting super constructor",
  137. body: function () {
  138. var value = undefined;
  139. class A extends Object { constructor() { super(value = 1); } }
  140. Object.setPrototypeOf(A, toString);
  141. assert.throws(()=>new A(), TypeError, "Function is not a constructor", "Function is not a constructor");
  142. assert.areEqual(undefined, value);
  143. }
  144. },
  145. {
  146. name: "super reference may not be deleted",
  147. body: function () {
  148. assert.throws(
  149. function() {
  150. class A extends Object {
  151. constructor() { delete super.prop; }
  152. }
  153. new A();
  154. }, ReferenceError, "attempts to delete super property", "Unable to delete property with a super reference");
  155. }
  156. },
  157. {
  158. name: "attempts to call a null super constructor throws TypeError",
  159. body: function () {
  160. var value = 0;
  161. assert.throws(
  162. function() {
  163. class A extends null {
  164. constructor() { value++; super(); value++; }
  165. }
  166. new A();
  167. }, TypeError, "attempts to call a null super constructor", "Function is not a constructor");
  168. assert.areEqual(1, value);
  169. }
  170. },
  171. {
  172. name: "direct super calls from a class constructors",
  173. body: function () {
  174. var count = 0;
  175. assert.throws(function(){class A{constructor(){eval("count++; super();");}};new A();}, SyntaxError, "", "Invalid use of the 'super' keyword");
  176. assert.throws(function(){class A{constructor(){(()=>eval("count++; super();"))();}};new A();}, SyntaxError, "", "Invalid use of the 'super' keyword");
  177. assert.throws(function(){class A{constructor(){(()=>{(()=>eval("count++; super();"))();})();}};new A();}, SyntaxError, "", "Invalid use of the 'super' keyword");
  178. assert.throws(function(){class A{constructor(){eval("eval(\"count++; super();\");");}};new A();}, SyntaxError, "", "Invalid use of the 'super' keyword");
  179. assert.throws(function(){class A{constructor(){eval("(()=>{count++; super();})();");}};new A();}, SyntaxError, "", "Invalid use of the 'super' keyword");
  180. assert.throws(function(){class A{constructor(){eval("(()=>eval(\"count++; super();\"))();");}};new A();}, SyntaxError, "", "Invalid use of the 'super' keyword");
  181. assert.areEqual(0, count, "SyntaxError preempts side effects")
  182. assert.doesNotThrow(function(){class A extends Object{constructor(){eval("count++; super();");}};new A();}, "");
  183. assert.doesNotThrow(function(){class A extends Object{constructor(){(()=>eval("count++; super();"))();}};new A();}, "");
  184. assert.doesNotThrow(function(){class A extends Object{constructor(){(()=>{(()=>eval("count++; super();"))();})();}};new A();}, "");
  185. assert.doesNotThrow(function(){class A extends Object{constructor(){eval("eval(\"count++; super();\");");}};new A();}, "");
  186. assert.doesNotThrow(function(){class A extends Object{constructor(){eval("(()=>{count++; super();})();");}};new A();}, "");
  187. assert.doesNotThrow(function(){class A extends Object{constructor(){eval("(()=>eval(\"count++; super();\"))();");}};new A();}, "");
  188. assert.areEqual(6, count, "Side effects expected without SyntaxError");
  189. }
  190. },
  191. ];
  192. testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });