| //------------------------------------------------------------------------------------------------------- |
| // Copyright (C) Microsoft. All rights reserved. |
| // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. |
| //------------------------------------------------------------------------------------------------------- |
| |
| WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js"); |
| |
| var tests = [ |
| { |
| name: "Rest parsing and errors", |
| body: function () { |
| assert.throws(function () { eval("function foo(...a, ...b) {}")}, SyntaxError, "More than one rest parameter throws", "The rest parameter must be the last parameter in a formals list."); |
| assert.throws(function () { eval("function foo(a, ...b, c) => {}")}, SyntaxError, "Rest parameter not in the last position throws", "The rest parameter must be the last parameter in a formals list."); |
| assert.throws(function () { eval("var obj = class { method(a, b = 1, ...c = [2,3]) {} };")}, SyntaxError, "Rest parameter cannot have a default value"); |
| assert.throws(function () { eval("function f(c, a, ...a) { }")}, SyntaxError, "Duplicate parameters are not allowed for non-simple parameter list with only rest", "Duplicate formal parameter names not allowed in this context"); |
| assert.throws(function () { eval("function f(c = 10, a, ...a) { }")}, SyntaxError, "Duplicate parameters are not allowed for non-simple parameter list with both rest and default", "Duplicate formal parameter names not allowed in this context"); |
| assert.throws(function () { eval("function f(...a) { 'use strict'; }"); }, SyntaxError, "Strict mode cannot be applied to functions with rest parameter", "Cannot apply strict mode on functions with non-simple parameter list"); |
| assert.throws(function () { eval("function f(a, ...b) { 'use strict'; }"); }, SyntaxError, "Strict mode cannot be applied to functions with rest parameter", "Cannot apply strict mode on functions with non-simple parameter list"); |
| assert.throws(function () { eval("function f() { \"use strict\"; function g(a, b, c, ...a) { } }")}, SyntaxError, "Cannot have duplicate parameters for a function with non-simple parameter list, which is already in strict mode", "Duplicate formal parameter names not allowed in strict mode"); |
| assert.throws(function () { eval("function f() { \"use strict\"; function g(a, b, a, ...c) { } }")}, SyntaxError, "Cannot have duplicate parameters for a function with non-simple parameter list with rest, which is already in strict mode", "Duplicate formal parameter names not allowed in strict mode"); |
| |
| assert.throws(function () { eval("function foo(a = b, ...b) {}; foo();")}, ReferenceError, "Rest parameters cannot be referenced in default expressions (use before declaration)", "Use before declaration"); |
| |
| // Redeclaration errors - non-simple in this case means any parameter list with a rest parameter |
| assert.doesNotThrow(function () { eval("function foo(...a) { var a; }"); }, |
| "Var redeclaration does not throw with a non-simple parameter list"); |
| assert.doesNotThrow(function () { eval("function foo(a, ...b) { var a; }"); }, |
| "Var redeclaration does not throw with a non-simple parameter list on a non-rest parameter"); |
| assert.throws(function () { function foo(...a) { eval('var a;'); }; foo(); }, |
| ReferenceError, |
| "Var redeclaration throws with a non-simple parameter list inside an eval", |
| "Let/Const redeclaration"); |
| assert.throws(function () { function foo(a, ...b) { eval('var b;'); }; foo(); }, |
| ReferenceError, |
| "Var redeclaration throws with a non-simple parameter list inside an eval", |
| "Let/Const redeclaration"); |
| assert.throws(function () { function foo(a = 1, ...b) { eval('var b;'); }; foo(); }, |
| ReferenceError, |
| "Var redeclaration throws with a non-simple parameter list inside an eval", |
| "Let/Const redeclaration"); |
| assert.throws(function () { function foo(a, b = 1, ...c) { eval('var c;'); }; foo(); }, |
| ReferenceError, |
| "Var redeclaration throws with a non-simple parameter list inside an eval", |
| "Let/Const redeclaration"); |
| |
| assert.doesNotThrow(function () { function foo(...a) { eval('let a;'); }; foo(); }, "Let redeclaration inside an eval does not throw with a non-simple parameter list"); |
| assert.doesNotThrow(function () { function foo(...a) { eval('const a = "str";'); }; foo() }, "Const redeclaration inside an eval does not throw with a non-simple parameter list"); |
| assert.throws(function () { function foo(a, ...b) { eval('var a;'); }; foo(); }, |
| ReferenceError, |
| "Var redeclaration throws with a non-simple parameter list on a non-rest parameter inside eval", |
| "Let/Const redeclaration"); |
| assert.doesNotThrow(function () { function foo(...a) { eval('let a;'); }; foo(); }, "Let redeclaration of a non-default parameter inside an eval does not throw with a non-simple parameter list"); |
| assert.doesNotThrow(function () { function foo(...a) { eval('const a = 0;'); }; foo(); }, "Const redeclaration of a non-default parameter inside an eval does not throw with a non-simple parameter list"); |
| |
| assert.doesNotThrow(function () { eval("function foo(a, ...args) { function args() { } }"); }, "Nested function redeclaration of a rest parameter does not throw"); |
| |
| // Deferred spread/rest errors in lambda formals |
| assert.doesNotThrow(function () { (a, b = [...[1,2,3]], ...rest) => {}; }, "Correct spread and rest usage"); |
| assert.doesNotThrow(function () { (a, b = ([...[1,2,3]]), ...rest) => {}; }, "Correct spread and rest usage with added parens"); |
| assert.doesNotThrow(function () { (a, b = (([...[1,2,3]])), ...rest) => {}; }, "Correct spread and rest usage with added parens"); |
| assert.throws(function () { eval("(a = ...NaN, b = [...[1,2,3]], ...rest) => {};"); }, |
| SyntaxError, |
| "Invalid spread with valid rest throws on the first invalid spread", |
| "Unexpected ... operator"); |
| assert.throws(function () { eval("(a = (...NaN), ...b = [...[1,2,3]], ...rest) => {};"); }, |
| SyntaxError, |
| "Invalid spread in parens with invalid and valid rest throws on the first invalid spread", |
| "Invalid use of the ... operator. Spread can only be used in call arguments or an array literal."); |
| assert.throws(function () { eval("(a = (...NaN), ...b = [...[1,2,3]], rest) => {};"); }, |
| SyntaxError, |
| "Invalid spread in parens with invalid rest throws on the first invalid spread", |
| "Invalid use of the ... operator. Spread can only be used in call arguments or an array literal."); |
| assert.throws(function () { eval("(a = [...NaN], ...b = [...[1,2,3]], rest) => {};"); }, |
| SyntaxError, |
| "Invalid spread (runtime error) with invalid rest throws on the first invalid rest", |
| "Unexpected ... operator"); |
| assert.throws(function () { eval("(a, ...b, ...rest) => {};"); }, |
| SyntaxError, |
| "Invalid rest with valid rest throws on the first invalid rest", |
| "Unexpected ... operator"); |
| assert.throws(function () { eval("(...rest = ...NaN) => {};"); }, |
| SyntaxError, |
| "Invalid rest with invalid spread initializer throws on the invalid rest", |
| "The rest parameter cannot have a default initializer."); |
| |
| assert.throws(function () { eval("var x = { set setter(...x) {} }"); }, |
| SyntaxError, |
| "Setter methods cannot have a rest parameter", |
| "Unexpected ... operator"); |
| assert.throws(function () { eval("var x = class { set setter(...x) {} }"); }, |
| SyntaxError, |
| "Class setter methods cannot have a rest parameter", |
| "Unexpected ... operator"); |
| |
| // Default evaluation of 'this' should happen after the rest formal is assigned a register |
| assert.doesNotThrow(function () { eval("function foo(a = this, ...b) {}"); }, "'this' referenced in formal defaults should not affect rest parameter"); |
| |
| } |
| }, |
| { |
| name: "Rest basic uses and sanity checks", |
| body: function () { |
| function foo(a, b, c, ...rest) { return [a, b, c, ...rest]; } |
| |
| var bar = (a, b, c, ...rest) => [a, b, c, ...rest]; |
| |
| class restClass { |
| method(a, b, c, ...rest) { return [a, b, c, ...rest]; } |
| }; |
| var baz = new restClass(); |
| |
| var obj = { |
| method(a, b, c, ...rest) { return [a, b, c, ...rest]; }, |
| evalMethod(a, b, c, ...rest) { return eval("[a, b, c, ...rest]"); } |
| }; |
| |
| var funcObj = new Function("a, b, c, ...rest", "return [a, b, c, ...rest]"); |
| |
| function singleRest(...rest) { return rest; } |
| |
| assert.areEqual([1,2,undefined], foo(1,2), "Rest is an empty array with too few parameters to a function"); |
| assert.areEqual([1,2,3], foo(1,2,3), "Rest is an empty array with the exact number of parameters to a function"); |
| assert.areEqual([1,2,3,4,5,6], foo(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a function"); |
| |
| assert.areEqual([1,2,undefined], bar(1,2), "Rest is an empty array with too few parameters to a lambda"); |
| assert.areEqual([1,2,3], bar(1,2,3), "Rest is an empty array with the exact number of parameters to a lambda"); |
| assert.areEqual([1,2,3,4,5,6], bar(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a lambda"); |
| |
| assert.areEqual([1,2,undefined], baz.method(1,2), "Rest is an empty array with too few parameters to a class method"); |
| assert.areEqual([1,2,3], baz.method(1,2,3), "Rest is an empty array with the exact number of parameters to a class method"); |
| assert.areEqual([1,2,3,4,5,6], baz.method(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a class method"); |
| |
| assert.areEqual([1,2,undefined], obj.method(1,2), "Rest is an empty array with too few parameters to a method"); |
| assert.areEqual([1,2,3], obj.method(1,2,3), "Rest is an empty array with the exact number of parameters to a method"); |
| assert.areEqual([1,2,3,4,5,6], obj.method(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a method"); |
| |
| assert.areEqual([1,2,undefined], obj.method(1,2), "Rest is an empty array with too few parameters to a method with an eval"); |
| assert.areEqual([1,2,3], obj.method(1,2,3), "Rest is an empty array with the exact number of parameters to a method with an eval"); |
| assert.areEqual([1,2,3,4,5,6], obj.method(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a method with an eval"); |
| |
| assert.areEqual([1,2,undefined], funcObj(1,2), "Rest is an empty array with too few parameters to a function object"); |
| assert.areEqual([1,2,3], funcObj(1,2,3), "Rest is an empty array with the exact number of parameters to a function object"); |
| assert.areEqual([1,2,3,4,5,6], funcObj(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a method with a function object"); |
| |
| // The following takes a different path in the JIT |
| assert.areEqual([1,2,3,4,5,6], singleRest(1,2,3,4,5,6), "Rest is a non-empty array with any parameters to a function with only a rest parameter"); |
| } |
| }, |
| { |
| name: "Rest basic uses and sanity checks with an arguments reference", |
| body: function () { |
| function fooArgs(a, b, c, ...rest) { arguments; return [a, b, c, ...rest]; } |
| |
| var barArgs = (a, b, c, ...rest) => { arguments; return [a, b, c, ...rest]; } |
| |
| class restClass { |
| methodArgs(a, b, c, ...rest) { arguments; return [a, b, c, ...rest]; } |
| }; |
| var baz = new restClass(); |
| |
| var obj = { |
| methodArgs(a, b, c, ...rest) { arguments; return [a, b, c, ...rest]; }, |
| evalMethodArgs(a, b, c, ...rest) { arguments; return eval("[a, b, c, ...rest]"); } |
| }; |
| |
| function testScopeSlots(a, b, c, ...rest) { |
| function sub() { |
| return [a, b, c, ...rest]; |
| } |
| arguments; |
| return sub(); |
| } |
| |
| assert.areEqual([1,2,undefined], fooArgs(1,2), "Rest is an empty array with too few parameters to a function with a reference to arguments"); |
| assert.areEqual([1,2,3], fooArgs(1,2,3), "Rest is an empty array with the exact number of parameters to a function with a reference to arguments"); |
| assert.areEqual([1,2,3,4,5,6], fooArgs(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a function with a reference to arguments"); |
| |
| assert.areEqual([1,2,undefined], barArgs(1,2), "Rest is an empty array with too few parameters to a lambda with a reference to arguments"); |
| assert.areEqual([1,2,3], barArgs(1,2,3), "Rest is an empty array with the exact number of parameters to a lambda with a reference to arguments"); |
| assert.areEqual([1,2,3,4,5,6], barArgs(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a lambda with a reference to arguments"); |
| |
| assert.areEqual([1,2,undefined], baz.methodArgs(1,2), "Rest is an empty array with too few parameters to a class method with a reference to arguments"); |
| assert.areEqual([1,2,3], baz.methodArgs(1,2,3), "Rest is an empty array with the exact number of parameters to a class method with a reference to arguments"); |
| assert.areEqual([1,2,3,4,5,6], baz.methodArgs(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a class method with a reference to arguments"); |
| |
| assert.areEqual([1,2,undefined], obj.methodArgs(1,2), "Rest is an empty array with too few parameters to a method with a reference to arguments"); |
| assert.areEqual([1,2,3], obj.methodArgs(1,2,3), "Rest is an empty array with the exact number of parameters to a method with a reference to arguments"); |
| assert.areEqual([1,2,3,4,5,6], obj.methodArgs(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a method with a reference to arguments"); |
| |
| assert.areEqual([1,2,undefined], obj.methodArgs(1,2), "Rest is an empty array with too few parameters to a method with eval and a reference to arguments"); |
| assert.areEqual([1,2,3], obj.methodArgs(1,2,3), "Rest is an empty array with the exact number of parameters to a method with eval and a reference to arguments"); |
| assert.areEqual([1,2,3,4,5,6], obj.methodArgs(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a method with eval and a reference to arguments"); |
| |
| assert.areEqual([1,2,undefined], testScopeSlots(1,2), "Rest is an empty array with too few parameters to a function with a reference to arguments using a sub function"); |
| assert.areEqual([1,2,3], testScopeSlots(1,2,3), "Rest is an empty array with the exact number of parameters to a function with a reference to arguments using a sub function"); |
| assert.areEqual([1,2,3,4,5,6], testScopeSlots(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a function with a reference to arguments using a sub function"); |
| } |
| }, |
| { |
| name: "Rest basic uses and sanity checks with a this reference", |
| body: function () { |
| function fooArgs(a, b, c, ...rest) { this; return [a, b, c, ...rest]; } |
| |
| var barArgs = (a, b, c, ...rest) => { this; return [a, b, c, ...rest]; } |
| |
| class restClass { |
| methodArgs(a, b, c, ...rest) { this; return [a, b, c, ...rest]; } |
| }; |
| var baz = new restClass(); |
| |
| var obj = { |
| methodArgs(a, b, c, ...rest) { this; return [a, b, c, ...rest]; }, |
| evalMethodArgs(a, b, c, ...rest) { this; return eval("[a, b, c, ...rest]"); } |
| }; |
| |
| assert.areEqual([1,2,undefined], fooArgs(1,2), "Rest is an empty array with too few parameters to a function with a reference to this"); |
| assert.areEqual([1,2,3], fooArgs(1,2,3), "Rest is an empty array with the exact number of parameters to a function with a reference to this"); |
| assert.areEqual([1,2,3,4,5,6], fooArgs(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a function with a reference to this"); |
| |
| assert.areEqual([1,2,undefined], barArgs(1,2), "Rest is an empty array with too few parameters to a lambda with a reference to this"); |
| assert.areEqual([1,2,3], barArgs(1,2,3), "Rest is an empty array with the exact number of parameters to a lambda with a reference to this"); |
| assert.areEqual([1,2,3,4,5,6], barArgs(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a lambda with a reference to this"); |
| |
| assert.areEqual([1,2,undefined], baz.methodArgs(1,2), "Rest is an empty array with too few parameters to a class method with a reference to this"); |
| assert.areEqual([1,2,3], baz.methodArgs(1,2,3), "Rest is an empty array with the exact number of parameters to a class method with a reference to this"); |
| assert.areEqual([1,2,3,4,5,6], baz.methodArgs(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a class method with a reference to this"); |
| |
| assert.areEqual([1,2,undefined], obj.methodArgs(1,2), "Rest is an empty array with too few parameters to a method with a reference to this"); |
| assert.areEqual([1,2,3], obj.methodArgs(1,2,3), "Rest is an empty array with the exact number of parameters to a method with a reference to this"); |
| assert.areEqual([1,2,3,4,5,6], obj.methodArgs(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a method with a reference to this"); |
| |
| assert.areEqual([1,2,undefined], obj.methodArgs(1,2), "Rest is an empty array with too few parameters to a method with eval and a reference to this"); |
| assert.areEqual([1,2,3], obj.methodArgs(1,2,3), "Rest is an empty array with the exact number of parameters to a method with eval and a reference to this"); |
| assert.areEqual([1,2,3,4,5,6], obj.methodArgs(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a method with eval and a reference to this"); |
| } |
| }, |
| { |
| name: "Rest basic uses and sanity checks with eval", |
| body: function () { |
| function fooArgs(a, b, c, ...rest) { eval(""); return [a, b, c, ...rest]; } |
| |
| var barArgs = (a, b, c, ...rest) => { eval(""); return [a, b, c, ...rest]; } |
| |
| class restClass { |
| methodArgs(a, b, c, ...rest) { eval(""); return [a, b, c, ...rest]; } |
| }; |
| var baz = new restClass(); |
| |
| var obj = { |
| methodArgs(a, b, c, ...rest) { eval(""); return [a, b, c, ...rest]; }, |
| evalMethodArgs(a, b, c, ...rest) { eval(""); return eval("[a, b, c, ...rest]"); } |
| }; |
| |
| assert.areEqual([1,2,undefined], fooArgs(1,2), "Rest is an empty array with too few parameters to a function with an eval"); |
| assert.areEqual([1,2,3], fooArgs(1,2,3), "Rest is an empty array with the exact number of parameters to a function with an eval"); |
| assert.areEqual([1,2,3,4,5,6], fooArgs(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a function with an eval"); |
| |
| assert.areEqual([1,2,undefined], barArgs(1,2), "Rest is an empty array with too few parameters to a lambda with an eval"); |
| assert.areEqual([1,2,3], barArgs(1,2,3), "Rest is an empty array with the exact number of parameters to a lambda with an eval"); |
| assert.areEqual([1,2,3,4,5,6], barArgs(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a lambda with an eval"); |
| |
| assert.areEqual([1,2,undefined], baz.methodArgs(1,2), "Rest is an empty array with too few parameters to a class method with an eval"); |
| assert.areEqual([1,2,3], baz.methodArgs(1,2,3), "Rest is an empty array with the exact number of parameters to a class method with an eval"); |
| assert.areEqual([1,2,3,4,5,6], baz.methodArgs(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a class method with an eval"); |
| |
| assert.areEqual([1,2,undefined], obj.methodArgs(1,2), "Rest is an empty array with too few parameters to a method with an eval"); |
| assert.areEqual([1,2,3], obj.methodArgs(1,2,3), "Rest is an empty array with the exact number of parameters to a method with an eval"); |
| assert.areEqual([1,2,3,4,5,6], obj.methodArgs(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a method with an eval"); |
| |
| assert.areEqual([1,2,undefined], obj.methodArgs(1,2), "Rest is an empty array with too few parameters to a method with eval and an eval"); |
| assert.areEqual([1,2,3], obj.methodArgs(1,2,3), "Rest is an empty array with the exact number of parameters to a method with eval and an eval"); |
| assert.areEqual([1,2,3,4,5,6], obj.methodArgs(1,2,3,4,5,6), "Rest is a non-empty array with too many parameters to a method with eval and an eval"); |
| } |
| }, |
| { |
| name: "Rest inlining", |
| body: function () { |
| function inlineTest() { |
| function fooInline(a, b, c, ...rest) { arguments; this; return [a, b, c, ...rest]; } |
| |
| fooInline(1,2); |
| assert.areEqual([1,2,undefined], fooInline(1,2), "Inlined rest handles less actuals than formals correctly"); |
| assert.areEqual([1,2,undefined], fooInline(...[1,2]), "Inlined rest handles less spread actuals than formals correctly"); |
| |
| fooInline(1,2,3); |
| assert.areEqual([1,2,3], fooInline(1,2,3), "Inlined rest handles the same amount of actuals and formals correctly"); |
| assert.areEqual([1,2,3], fooInline(...[1,2,3]), "Inlined rest handles the same amount of spread actuals and formals correctly"); |
| |
| fooInline(1,2,3,4,5,6); |
| assert.areEqual([1,2,3,4,5,6], fooInline(1,2,3,4,5,6), "Inlined rest handles the more actuals than formals correctly"); |
| assert.areEqual([1,2,3,4,5,6], fooInline(...[1,2,3,4,5,6]), "Inlined rest handles the more actuals than formals correctly"); |
| } |
| inlineTest(); |
| inlineTest(); |
| inlineTest(); |
| } |
| }, |
| { |
| name: "OS 264962: Deferred nested function causes an assert", |
| body: function () { |
| var func4 = function (...argArr13) { |
| function foo() { |
| eval(); |
| } |
| }; |
| } |
| }, |
| { |
| name: "OS 265363: ArgIn_Rest is emitted in loop bodies", |
| body: function () { |
| var func4 = function (argArrObj9, ...argArr11) { |
| while (false) { |
| } |
| }; |
| func4(); |
| } |
| }, |
| { |
| name: "OS 266421: Rest does not create a frame object properly", |
| body: function () { |
| var func4 = function (...argArr6) { |
| for (var _i in arguments) { |
| } |
| }; |
| } |
| }, |
| { |
| name: "OS 645508: Nested function reference to parent rest parameter fails", |
| body: function () { |
| function foo(...bar) { |
| function child() { |
| bar; |
| } |
| child(); |
| } |
| foo(); |
| } |
| }, |
| { |
| name: "Rest parameter is incorrectly assumed to be in a scope slot", |
| body: function () { |
| function test0() { |
| var func1 = function (...argArr5) { |
| arguments[1]; |
| }; |
| do { |
| func1(); |
| _oo2obj2.func1(); |
| } while (false); |
| } |
| } |
| }, |
| { |
| name: "OSG 5737917: Create arguments object when the only formal is a rest argument", |
| body: function () { |
| var func1 = function (...argArr0) { |
| eval(''); |
| return (Object({ |
| get: function () { |
| } |
| })); |
| } |
| } |
| }, |
| { |
| name: "OS 7249217: Rest is able to be in a slot in arguments optimization case", |
| body: function () { |
| function foo(...argArr9) { |
| var protoObj0 = {}; |
| with (protoObj0) { |
| arguments; |
| var f = function () { assert.areEqual([1,2,3], argArr9, "Arguments scope object optimization allows rest to function correctly inside with"); }; |
| f(); |
| } |
| assert.areEqual([1,2,3], argArr9, "Arguments scope object optimization allows rest to function correctly"); |
| } |
| foo(1,2,3); |
| } |
| } |
| ]; |
| |
| testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" }); |
| |
| // OS: Bug 269660: [ES6][Rest] ASSERTION 14444: (inetcore\jscript\lib\backend\irbuilder.cpp, line 792) Tried to use an undefined stacksym? |
| // Serialization bug that needs to be at global scope. |
| function test0() { |
| var func1 = function (...argArr2) { |
| if (false) { |
| var strvar9 = argArr2; |
| } |
| }; |
| func1(); |
| } |
| test0(); |
| test0(); |