default.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  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: "Default argument parsing",
  9. body: function () {
  10. // Incomplete expressions
  11. assert.throws(function () { eval("function foo(a =) { return a; }"); }, SyntaxError, "Incomplete default expression throws in a function", "Syntax error");
  12. assert.throws(function () { eval("var x = function(a =) { return a; }"); }, SyntaxError, "Incomplete default expression throws in a function expression", "Syntax error");
  13. assert.throws(function () { eval("(a =) => a"); }, SyntaxError, "Incomplete default expression throws in a lambda", "Syntax error");
  14. assert.throws(function () { eval("var x = { foo(a =) { return a; } }"); }, SyntaxError, "Incomplete default expression throws in an object method", "Syntax error");
  15. assert.throws(function () { eval("var x = class { foo(a =) { return a; } }"); }, SyntaxError, "Incomplete default expression throws in a class method", "Syntax error");
  16. assert.throws(function () { eval("var x = { foo: function (a =) { return a; } }"); }, SyntaxError, "Incomplete default expression throws in an object member function", "Syntax error");
  17. assert.throws(function () { eval("function * foo(a =) { return a; }"); }, SyntaxError, "Incomplete default expression throws in a generator function", "Syntax error");
  18. assert.throws(function () { eval("var x = function*(a =) { return a; }"); }, SyntaxError, "Incomplete default expression throws in a generator function", "Syntax error");
  19. assert.throws(function () { eval("var x = class { * foo(a =) { return a; } }"); }, SyntaxError, "Incomplete default expression throws in a class generator method", "Syntax error");
  20. // Duplicate parameters
  21. assert.throws(function () { eval("function f(a, b, a, c = 10) { }"); }, SyntaxError, "Duplicate parameters are not allowed before the default argument", "Duplicate formal parameter names not allowed in this context");
  22. assert.throws(function () { eval("function f(a, b = 10, a) { }"); }, SyntaxError, "Duplicate parameters are not allolwed after the default argument", "Duplicate formal parameter names not allowed in this context");
  23. assert.throws(function () { eval("function f(a, b, a, c) { \"use strict\"; }"); }, SyntaxError, "When function is in strict mode duplicate parameters are not allowed for simple parameter list", "Duplicate formal parameter names not allowed in strict mode");
  24. assert.throws(function () { eval("function f(a, b = 1) { \"use strict\"; }"); }, SyntaxError, "Strict mode cannot be applied to functions with default parameters", "Cannot apply strict mode on functions with non-simple parameter list");
  25. assert.throws(function () { eval("function f() { \"use strict\"; function g(a, b, a) { } }"); }, SyntaxError, "When a function is already in strict mode duplicate parameters are not allowed for simple parameter list", "Duplicate formal parameter names not allowed in strict mode");
  26. assert.throws(function () { eval("function f() { \"use strict\"; function g(a, b, a = 10) { } }"); }, SyntaxError, "When a function is already in strict mode duplicate parameters are not allowed for formal parameter list", "Duplicate formal parameter names not allowed in strict mode");
  27. assert.doesNotThrow(function f() { "use strict"; function g(a, b = 10) { } }, "Default arguments are allowed for functions which are already in strict mode");
  28. assert.doesNotThrow(function f(a, b, a, c) { return a + b + c; }, "In non-strict mode duplicate parameters are allowed");
  29. assert.doesNotThrow(function () { var obj = { set f(a = 1) {} }; }, "Default parameters can be used with setters inside an object literal");
  30. assert.doesNotThrow(function () { class c { set f(a = 1) {} }; }, "Default parameters can be used with setters inside a class");
  31. assert.doesNotThrow(function () { var obj = { set f({a}) {} }; }, "Setter can have destructured param list");
  32. assert.doesNotThrow(function () { var obj = { set f({a, b}) {} }; }, "Setter can have destructured param list with more than one parameter");
  33. assert.doesNotThrow(function () { var obj = { set f([a, b]) {} }; }, "Setter can have destructured array pattern with more than one parameter");
  34. assert.doesNotThrow(function () { var obj = { set f([a, ...b]) {} }; }, "Setter can have destructured array pattern with rest");
  35. assert.throws(function () { eval("var obj = { set f(...a) {} };"); }, SyntaxError, "Rest parameter cannot be used with setters inside an object literal", "Unexpected ... operator");
  36. assert.throws(function () { eval("var obj = { set f(a, b = 1) {} };"); }, SyntaxError, "Setters can have only one parameter even if one of them is default parameter", "Setter functions must have exactly one parameter");
  37. assert.throws(function () { eval("var obj = { set f(a = 1, b) {} };"); }, SyntaxError, "Setters can have only one parameter even if one of them is default parameter", "Setter functions must have exactly one parameter");
  38. assert.throws(function () { eval("var obj = { set f(a = 1, ...b) {} };") }, SyntaxError, "Setters can have only one parameter even if one of them is rest parameter", "Setter functions must have exactly one parameter");
  39. assert.throws(function () { eval("var obj = { set f(a = 1, {b}) {} };"); }, SyntaxError, "Setters can have only one parameter even if one of them is destructured parameter", "Setter functions must have exactly one parameter");
  40. assert.throws(function () { eval("var obj = { set f({a}, b = 1) {} };"); }, SyntaxError, "Setters can have only one parameter even if one of them is default parameter", "Setter functions must have exactly one parameter");
  41. assert.throws(function () { eval("var obj = { get f(a = 1) {} };"); }, SyntaxError, "Getter cannnot have any parameter even if it is default parameter", "Getter functions must have no parameters");
  42. assert.throws(function () { eval("var obj = { get f(...a) {} };"); }, SyntaxError, "Getter cannot have any parameter even if it is rest parameter", "Getter functions must have no parameters");
  43. assert.throws(function () { eval("var obj = { get f({a}) {} };"); }, SyntaxError, "Getter cannot have any parameter even if it is destructured parameter", "Getter functions must have no parameters");
  44. assert.throws(function () { eval("function foo(a *= 5)"); }, SyntaxError, "Other assignment operators do not work");
  45. // Redeclaration errors - non-simple in this case means any parameter list with a default expression
  46. assert.doesNotThrow(function () { eval("function foo(a = 1) { var a; }"); }, "Var redeclaration with a non-simple parameter list");
  47. assert.doesNotThrow(function () { eval("function foo(a = 1, b) { var b; }"); }, "Var redeclaration does not throw with a non-simple parameter list on a non-default parameter");
  48. assert.throws(function () { function foo(a = 1) { eval('var a;'); }; foo() }, ReferenceError, "Var redeclaration throws with a non-simple parameter list inside an eval", "Let/Const redeclaration");
  49. assert.throws(function () { function foo(a = 1, b) { eval('var b;'); }; foo(); }, ReferenceError, "Var redeclaration throws with a non-simple parameter list on a non-default parameter inside eval", "Let/Const redeclaration");
  50. assert.doesNotThrow(function () { function foo(a = 1) { eval('let a;'); }; foo() }, "Let redeclaration inside an eval does not throw with a non-simple parameter list");
  51. assert.doesNotThrow(function () { function foo(a = 1) { eval('const a = "str";'); }; foo() }, "Const redeclaration inside an eval does not throw with a non-simple parameter list");
  52. assert.doesNotThrow(function () { function foo(a = 1) { eval('let a;'); }; foo() }, "Let redeclaration of a non-default parameter inside an eval does not throw with a non-simple parameter list");
  53. assert.doesNotThrow(function () { function foo(a = 1) { eval('const a = 0;'); }; foo() }, "Const redeclaration of a non-default parameter inside an eval does not throw with a non-simple parameter list");
  54. assert.throws(function () { eval("x = 3 => x"); }, SyntaxError, "Lambda formals without parentheses cannot have default expressions", "Expected \'(\'");
  55. assert.throws(function () { eval("var a = 0, b = 0; (x = ++a,++b) => x"); }, SyntaxError, "Default expressions cannot have comma separated expressions", "Expected identifier");
  56. assert.doesNotThrow(function f(a = 1, b = class c { f() { return 2; }}) { }, "Class methods that do not refer to a formal are allowed in the param scope");
  57. }
  58. },
  59. {
  60. name: "Default argument sanity checks and expressions",
  61. body: function () {
  62. function foo(a, b = 2, c = 1, d = a + b + c, e) { return d; }
  63. assert.areEqual(foo(), foo(undefined, undefined, undefined, undefined, undefined), "Passing undefined has the same behavior as a default expression");
  64. assert.areEqual(foo(1), foo(1, 2), "Passing some arguments leaves default values for the rest");
  65. assert.areEqual(foo(1, 2), foo(1, 2, 1), "Passing some arguments leaves default values for the rest");
  66. assert.areEqual(foo(3, 5), foo(3, 5, 1), "Overriding default values leaves other default values in tact");
  67. function sideEffects(a = 1, b = ++a, c = ++b, d = ++c) { return [a,b,c,d]; }
  68. assert.areEqual([2,3,4,4], sideEffects(), "Side effects chain properly");
  69. assert.areEqual([1,1,1,1], sideEffects(0,undefined,0), "Side effects chain properly with some arguments passed");
  70. function argsObj1(a = 15, b = arguments[1], c = arguments[0]) { return [a,b,c]; }
  71. assert.areEqual([15,undefined,undefined], argsObj1(), "Arguments object uses original parameters passed");
  72. function argsObj2(a, b = 5 * arguments[0]) { return arguments[1]; }
  73. assert.areEqual(undefined, argsObj2(5), "Arguments object does not return default expression");
  74. this.val = { test : "test" };
  75. function thisTest(a = this.val, b = this.val = 1.1, c = this.val, d = this.val2 = 2, e = this.val2) { return [a,b,c,d,e]; }
  76. assert.areEqual([{test:"test"}, 1.1, 1.1, 2, 2], thisTest(), "'this' is able to be referenced and modified");
  77. var expAValue, expBValue, expCValue;
  78. function f(a = 10, b = 20, c) {
  79. assert.areEqual(a, expAValue, "First argument");
  80. assert.areEqual(b, expBValue, "Second argument");
  81. assert.areEqual(c, expCValue, "Third argument");
  82. }
  83. expAValue = null, expBValue = 20, expCValue = 1;
  84. f(null, undefined, 1);
  85. expAValue = null, expBValue = null, expCValue = null;
  86. f(null, null, null);
  87. expAValue = 10, expBValue = null, expCValue = 3;
  88. f(undefined, null, 3);
  89. function lambdaCapture() {
  90. this.propA = 1;
  91. var lambda = (a = this.propA++) => {
  92. assert.areEqual(a, 1, "Lambda default parameters use 'this' correctly");
  93. assert.areEqual(this.propA, 2, "Lambda default parameters using 'this' support side effects");
  94. };
  95. lambda();
  96. }
  97. lambdaCapture();
  98. // Function length with and without default
  99. function length1(a, b, c) {}
  100. function length2(a, b, c = 1) {}
  101. function length3(a, b = 1, c = 1) {}
  102. function length4(a, b = 1, c) {}
  103. function length5(a = 2, b, c) {}
  104. function length6(a = 2, b = 5, c = "str") {}
  105. assert.areEqual(3, length1.length, "No default parameters gives correct length");
  106. assert.areEqual(2, length2.length, "One trailing default parameter gives correct length");
  107. assert.areEqual(1, length3.length, "Two trailing default parameters gives correct length");
  108. assert.areEqual(1, length4.length, "One default parameter with following non-default gives correct length");
  109. assert.areEqual(0, length5.length, "One default parameter with two following non-defaults gives correct length");
  110. assert.areEqual(0, length6.length, "All default parameters gives correct length");
  111. }
  112. },
  113. {
  114. name: "Use before declaration in parameter lists",
  115. body: function () {
  116. assert.throws(function () { eval("function foo(a = b, b = a) {}; foo();"); }, ReferenceError, "Unevaluated parameters cannot be referenced in a default initializer", "Use before declaration");
  117. assert.throws(function () { eval("function foo(a = a, b = b) {}; foo();"); }, ReferenceError, "Unevaluated parameters cannot be referenced in a default initializer", "Use before declaration");
  118. assert.throws(function () { eval("function foo(a = (b = 5), b) {}; foo();"); }, ReferenceError, "Unevaluated parameters cannot be modified in a default initializer", "Use before declaration");
  119. function argsFoo(a = (arguments[1] = 5), b) { return b };
  120. assert.areEqual(undefined, argsFoo(), "Unevaluated parameters are referenceable using the arguments object");
  121. assert.areEqual(undefined, argsFoo(1), "Side effects on the arguments object are allowed but has no effect on default parameter initialization");
  122. assert.areEqual(2, argsFoo(1, 2), "Side effects on the arguments object are allowed but has no effect on default parameter initialization");
  123. }
  124. },
  125. {
  126. name: "Parameter scope does not have visibility of body declarations",
  127. body: function () {
  128. function foo1(a = x) { var x = 1; return a; }
  129. assert.throws(function() { foo1(); },
  130. ReferenceError,
  131. "Shadowed var in parameter scope is not affected by body initialization when setting the default value",
  132. "'x' is not defined");
  133. function foo2(a = () => x) { var x = 1; return a(); }
  134. assert.throws(function () { foo2(); },
  135. ReferenceError,
  136. "Arrow function capturing var at parameter scope is not affected by body declaration",
  137. "'x' is not defined");
  138. function foo3(a = () => x) { var x = 1; return a; } // a() undefined
  139. assert.throws(function () { foo3()(); },
  140. ReferenceError,
  141. "Attempted closure capture of body scoped var throws in an arrow function default expression",
  142. "'x' is not defined");
  143. function foo4(a = function() { return x; }) { var x = 1; return a(); }
  144. assert.throws(function () { foo4(); },
  145. ReferenceError,
  146. "Attempted closure capture of body scoped var throws in an anonymous function default expression",
  147. "'x' is not defined");
  148. function foo5(a = function bar() { return 1; }, b = bar()) { return [a(), b]; }
  149. assert.throws(function () { foo5(); },
  150. ReferenceError,
  151. "Named function expression does not leak name into subsequent default expressions",
  152. "'bar' is not defined");
  153. function foo6(a = b1) {
  154. {
  155. function b1() {
  156. return 2;
  157. }
  158. }
  159. assert.areEqual(1, a, "First argument should get the initial value from outer variable");
  160. assert.areEqual(2, b1(), "Block scoped function should be visible in the body also");
  161. }
  162. var b1 = 1;
  163. foo6();
  164. var a1 = 10;
  165. function foo7(b = function () { return a1; }) {
  166. assert.areEqual(undefined, a1, "Inside the function body the assignment hasn't happened yet");
  167. var a1 = 20;
  168. assert.areEqual(20, a1, "Assignment to the symbol inside the function changes the value");
  169. return b;
  170. }
  171. assert.areEqual(10, foo7()(), "Function in the param scope correctly binds to the outer variable");
  172. function foo8(a = x1, b = function g() {
  173. return function h() {
  174. assert.areEqual(10, x1, "x1 is captured from the outer scope");
  175. };
  176. }) {
  177. var x1 = 100;
  178. b()();
  179. };
  180. var x1 = 10;
  181. foo8();
  182. var x2 = 1;
  183. function foo9(a = x2, b = function() { return x2; }) {
  184. {
  185. function x2() {
  186. }
  187. }
  188. var x2 = 2;
  189. return b;
  190. }
  191. assert.areEqual(1, foo9()(), "Symbol capture at the param scope is unaffected by the inner definitions");
  192. var x3 = 1;
  193. function foo10(a = x3, b = function(_x) { return x3; }) {
  194. var x3 = 2;
  195. return b;
  196. }
  197. assert.areEqual(1, foo10()(), "Symbol capture at the param scope is unaffected by other references in the body and param");
  198. }
  199. },
  200. {
  201. name: "Parameter scope shadowing tests",
  202. body: function () {
  203. // These tests exercise logic in FindOrAddPidRef for when we need to look at parameter scope
  204. // Original sym in parameter scope
  205. var test0 = function(arg1 = _strvar0) {
  206. for (var _strvar0 in f32) {
  207. for (var _strvar0 in obj1) {
  208. }
  209. }
  210. }
  211. // False positive PidRef (no decl) at parameter scope
  212. function test1() {
  213. for (var _strvar0 in a) {
  214. var f = function(b = _strvar0) {
  215. for (var _strvar0 in c) {}
  216. };
  217. }
  218. }
  219. function test2() {
  220. let l = (z) => {
  221. let w = { z };
  222. assert.areEqual(10, w.z, "Identifier reference in object literal should get the correct reference from the arguments");
  223. var z;
  224. }
  225. l(10);
  226. };
  227. test2();
  228. }
  229. },
  230. {
  231. name: "Arrow function bodies in parameter scope",
  232. body: function () {
  233. // Nested parameter scopes
  234. function arrow(a = ((x = 1) => x)()) { return a; }
  235. assert.areEqual(1, arrow(), "Arrow function with default value works at parameter scope");
  236. function nestedArrow(a = (b = (x = () => 1)) => 1) { return a; }
  237. assert.areEqual(1, nestedArrow()(), "Nested arrow function with default value works at parameter scope");
  238. }
  239. },
  240. {
  241. name: "OS 1583694: Arguments sym is not set correctly on undo defer",
  242. body: function () {
  243. eval();
  244. var arguments;
  245. }
  246. },
  247. {
  248. name: "Unmapped arguments - Non simple parameter list",
  249. body: function () {
  250. function f1 (x = 10, y = 20, z) {
  251. x += 2;
  252. y += 2;
  253. z += 2;
  254. assert.areEqual(arguments[0], undefined, "arguments[0] is not mapped with first formal and did not change when the first formal changed");
  255. assert.areEqual(arguments[1], undefined, "arguments[1] is not mapped with second formal and did not change when the second formal changed");
  256. assert.areEqual(arguments[2], 30, "arguments[2] is not mapped with third formal and did not change when the third formal changed");
  257. arguments[0] = 1;
  258. arguments[1] = 2;
  259. arguments[2] = 3;
  260. assert.areEqual(x, 12, "Changing arguments[0], did not change the first formal");
  261. assert.areEqual(y, 22, "Changing arguments[1], did not change the second formal");
  262. assert.areEqual(z, 32, "Changing arguments[2], did not change the third formal");
  263. }
  264. f1(undefined, undefined, 30);
  265. function f2 (x = 10, y = 20, z) {
  266. eval('');
  267. x += 2;
  268. y += 2;
  269. z += 2;
  270. assert.areEqual(arguments[0], undefined, "Function has eval - arguments[0] is not mapped with first formal and did not change when the first formal changed");
  271. assert.areEqual(arguments[1], undefined, "Function has eval - arguments[1] is not mapped with second formal and did not change when the second formal changed");
  272. assert.areEqual(arguments[2], 30, "Function has eval - arguments[2] is not mapped with third formal and did not change when the third formal changed");
  273. arguments[0] = 1;
  274. arguments[1] = 2;
  275. arguments[2] = 3;
  276. assert.areEqual(x, 12, "Function has eval - Changing arguments[0], did not change the first formal");
  277. assert.areEqual(y, 22, "Function has eval - Changing arguments[1], did not change the second formal");
  278. assert.areEqual(z, 32, "Function has eval - Changing arguments[2], did not change the third formal");
  279. }
  280. f2(undefined, undefined, 30);
  281. function f3 (x = 10, y = 20, z) {
  282. (function () {
  283. eval('');
  284. })();
  285. x += 2;
  286. y += 2;
  287. z += 2;
  288. assert.areEqual(arguments[0], undefined, "Function's inner function has eval - arguments[0] is not mapped with first formal and did not change when the first formal changed");
  289. assert.areEqual(arguments[1], undefined, "Function's inner function has eval - arguments[1] is not mapped with second formal and did not change when the second formal changed");
  290. assert.areEqual(arguments[2], 30, "Function's inner function has eval - arguments[2] is not mapped with third formal and did not change when the third formal changed");
  291. arguments[0] = 1;
  292. arguments[1] = 2;
  293. arguments[2] = 3;
  294. assert.areEqual(x, 12, "Function's inner function has eval - Changing arguments[0], did not change the first formal");
  295. assert.areEqual(y, 22, "Function's inner function has eval - Changing arguments[1], did not change the second formal");
  296. assert.areEqual(z, 32, "Function's inner function has eval - Changing arguments[2], did not change the third formal");
  297. }
  298. f3(undefined, undefined, 30);
  299. function f4 (a, b, c, d = 1) {
  300. var e = 10;
  301. assert.areEqual(2, arguments[0], "Unmapped arguments value has the expected value in the body");
  302. (function () {
  303. eval('');
  304. }());
  305. };
  306. f4.call(1, 2);
  307. function f5 (a, b, c, d = 1) {
  308. var e = 10;
  309. var d = 11;
  310. assert.areEqual(2, arguments[0], "Unmapped arguments value has the expected value, even with duplicate symbol in the body");
  311. (function () {
  312. eval('');
  313. }());
  314. };
  315. f5.call(1, 2);
  316. function f6() {
  317. return ((a, b = (c = arguments) => c) => b)(2);
  318. };
  319. assert.areEqual(1, f6(1)()[0], "Nested lambda should capture the arguments from the outer function");
  320. }
  321. },
  322. {
  323. name: "Param of lambda has default as function",
  324. body: function () {
  325. assert.doesNotThrow(function () { eval("[ (a = function () { }) => {} ];"); }, "Lambda defined, inside an array literal, has a default as a function should not assert");
  326. }
  327. },
  328. {
  329. name: "Shadowing arguments symbol",
  330. body: function () {
  331. function f1(a, b = arguments[0]) {
  332. assert.areEqual(1, arguments[0], "Initial value of arguments symbol in the body should be same as the arguments from the param scope");
  333. var arguments = [10, 20];
  334. assert.areEqual(1, b, "Arguments value is the initial value in the param scope too");
  335. assert.areEqual(10, arguments[0], "Arguments value is updated in the body");
  336. }
  337. f1(1);
  338. function f2(a = 1, arguments) {
  339. assert.areEqual(2, arguments, "Initial value of arguments symbol in the body should be same as the arguments from the param scope");
  340. var arguments = [10, 20];
  341. assert.areEqual(10, arguments[0], "Arguments value is updated in the body");
  342. }
  343. f2(undefined, 2);
  344. function f3(a, b = arguments[0]) {
  345. assert.areEqual(10, arguments(), "Arguments symbol is overwritten by the the function definition");
  346. function arguments() {
  347. return 10;
  348. }
  349. assert.areEqual(1, b, "Arguments value is the initial value in the param scope too");
  350. }
  351. f3(1);
  352. function f4(a = 1, arguments, c = arguments) {
  353. assert.areEqual(10, arguments(), "In the body function definition shadows the formal");
  354. assert.areEqual(2, c, "Value of the formal is assigned properly");
  355. function arguments() {
  356. return 10;
  357. }
  358. }
  359. f4(undefined, 2);
  360. function f5(a, b = arguments) {
  361. function arguments(c) {
  362. return arguments;
  363. }
  364. assert.areEqual(30, arguments(10, 20, 30)[2], "Inside the arguments function the arguments symbol should points to the passed in values");
  365. assert.areEqual(4, b[3], "In the param scope arguments symbol referes to the passed in values");
  366. }
  367. f5(1, undefined, 3, 4, 5);
  368. function f6(a, b = arguments) {
  369. function arguments(c) {
  370. if (!arguments.length) {
  371. return arguments.callee(10, 20, 30);
  372. }
  373. return arguments;
  374. }
  375. assert.areEqual(20, arguments()[1], "In the function body arguments refers to the inner function");
  376. assert.areEqual(3, b[2], "In the param scope arguments symbol referes to the passed in values");
  377. }
  378. f6(1, undefined, 3, 4);
  379. function f7(a, b = function arguments(c) {
  380. if (!c) {
  381. return arguments.callee(10, 20);
  382. }
  383. return c + arguments[1];
  384. }) {
  385. assert.areEqual(30, b(), "Function defined in the param scope can be called recursively");
  386. assert.areEqual(1, arguments[0], "Arguments symbol is unaffected by the function expression");
  387. }
  388. f7(1);
  389. function f8(a, b = arguments) {
  390. var c = function arguments(c) {
  391. if (!arguments.length) {
  392. return arguments.callee(10, 20, 30);
  393. }
  394. return arguments;
  395. }
  396. assert.areEqual(30, c()[2], "In the function body the arguments function expression with name is not visible");
  397. assert.areEqual(1, b[0], "In the param scope arguments symbol referes to the passed in values");
  398. }
  399. f8(1);
  400. assert.throws(function () { eval("function f(a, b = arguments) { class arguments { } }"); }, SyntaxError, "Class cannot be named arguments", "Invalid usage of 'arguments' in strict mode");
  401. assert.throws(function () { eval("function f(a, arguments) { class arguments { } }"); }, SyntaxError, "Class cannot be named arguments even when one of the formal is named arguments", "Let/Const redeclaration");
  402. function f9( a = 0, b = {
  403. arguments() {
  404. return 10;
  405. }
  406. }, c = arguments) {
  407. with (b) {
  408. assert.areEqual(10, arguments(), "Inside with the right the arguments function inside the object is used in the body also");
  409. }
  410. assert.areEqual(1, arguments[0], "Arguments symbol should be unaffected after with construct");
  411. assert.areEqual(1, c[0], "Arguments symbol from param scope should be unaffected after with construct");
  412. }
  413. f9(1);
  414. function f10(a = 1, b = () => {
  415. assert.areEqual(undefined, arguments, "Due to the decalration in the body arguments symbol is shadowed inside the lambda");
  416. var arguments = 100;
  417. assert.areEqual(100, arguments, "After the assignment value of arguments is updated inside the lambda");
  418. }, c = arguments) {
  419. assert.areEqual(10, arguments[0], "In the body the value of arguments is retained");
  420. assert.areEqual(10, c[0], "Arguments symbol is not affected in the param scope");
  421. b();
  422. }
  423. f10(10);
  424. function f11(a = 1, b = () => {
  425. assert.areEqual(100, arguments(), "Inside the lambda the function definition shadows the parent's arguments symbol");
  426. function arguments() {
  427. return 100;
  428. }
  429. }, c = arguments) {
  430. assert.areEqual(10, arguments[0], "In the body the value of arguments is retained");
  431. b();
  432. assert.areEqual(10, c[0], "Arguments symbol is not affected in the param scope");
  433. }
  434. f11(10);
  435. function f12({a = 1, arguments}) {
  436. assert.areEqual(2, arguments, "Initial value of arguments symbol in the body should be same as the arguments from the param scope's destructured pattern");
  437. var arguments = [10, 20];
  438. assert.areEqual(10, arguments[0], "Arguments value is updated in the body");
  439. }
  440. f12({arguments : 2});
  441. function f13(a = 1, {arguments, c = arguments}) {
  442. assert.areEqual(10, arguments(), "In the body function definition shadows the destructured formal");
  443. assert.areEqual(2, c, "Value of the formal is assigned properly");
  444. function arguments() {
  445. return 10;
  446. }
  447. }
  448. f13(undefined, { arguments: 2 });
  449. function f14(a, b = arguments[0]) {
  450. assert.areEqual(1, arguments[0], "Function in block causes a var declaration to be hoisted and the initial value should be same as the arguments symbol");
  451. {
  452. {
  453. function arguments() {
  454. return 10;
  455. }
  456. }
  457. }
  458. assert.areEqual(1, b, "Arguments value is the initial value in the param scope too");
  459. assert.areEqual(10, arguments(), "Hoisted var binding is updated after the block is exected");
  460. }
  461. f14(1);
  462. function f15() {
  463. function f16() {
  464. eval("");
  465. this.arguments = 1;
  466. }
  467. var obj = new f16();
  468. function arguments() {
  469. return 10;
  470. }
  471. assert.areEqual(1, obj.arguments, "Child function having eval should work fine with a duplicate arguments definition in the parent body");
  472. };
  473. f15();
  474. }
  475. },
  476. {
  477. name: "Shadowing arguments symbol - Eval",
  478. body: function () {
  479. function f1(a, b = arguments[0]) {
  480. assert.areEqual(1, arguments[0], "Initial value of arguments symbol in the body should be same as the arguments from the param scope");
  481. var arguments = [10, 20];
  482. assert.areEqual(1, b, "Arguments value is the initial value in the param scope too");
  483. assert.areEqual(10, eval("arguments[0]"), "Arguments value is updated in the body");
  484. }
  485. f1(1);
  486. function f2(a = 1, arguments) {
  487. assert.areEqual(2, eval("arguments"), "Initial value of arguments symbol in the body should be same as the arguments from the param scope");
  488. var arguments = [10, 20];
  489. assert.areEqual(10, arguments[0], "Arguments value is updated in the body");
  490. }
  491. f2(undefined, 2);
  492. function f3(a, b = arguments[0]) {
  493. assert.areEqual(10, eval("arguments()"), "Arguments symbol is overwritten by the the function definition");
  494. function arguments() {
  495. return 10;
  496. }
  497. assert.areEqual(1, b, "Arguments value is the initial value in the param scope too");
  498. }
  499. f3(1);
  500. function f4(a = 1, arguments, c = arguments) {
  501. assert.areEqual(10, arguments(), "In the body function definition shadows the formal");
  502. assert.areEqual(2, eval("c"), "Value of the formal is assigned properly");
  503. function arguments() {
  504. return 10;
  505. }
  506. }
  507. f4(undefined, 2);
  508. function f5(a, b, c = arguments) {
  509. function arguments(c) {
  510. return eval("arguments");
  511. }
  512. assert.areEqual(30, arguments(10, 20, 30)[2], "In the function body arguments refers to the inner function");
  513. assert.areEqual(2, c[1], "In the param scope arguments symbol referes to the passed in values");
  514. }
  515. f5(1, 2, undefined, 4);
  516. function f6(a, b = function arguments(c) {
  517. if (!c) {
  518. return arguments.callee(10, 20);
  519. }
  520. return c + arguments[1];
  521. }) {
  522. assert.areEqual(30, eval("b()"), "Function defined in the param scope can be called recursively");
  523. assert.areEqual(1, arguments[0], "Arguments symbol is unaffected by the function expression");
  524. }
  525. f6(1);
  526. function f7(a, b = arguments) {
  527. var c = function arguments(c) {
  528. if (!arguments.length) {
  529. return arguments.callee(10, 20, 30);
  530. }
  531. return arguments;
  532. }
  533. assert.areEqual(10, eval("c()[0]"), "In the function body the arguments function expression with name is not visible");
  534. assert.areEqual(4, b[3], "In the param scope arguments symbol referes to the passed in values");
  535. }
  536. f7(1, undefined, 3, 4);
  537. }
  538. }
  539. ];
  540. testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });