| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- function print(x) { WScript.Echo(x); }
- print('\nTest 1: Simple case with single block-scoped function\n');
- (function ()
- {
- // with prior reference
- print(f);
- if (true)
- {
- function f() { }
- print(f);
- }
- print(f);
- // without prior reference
- if (true)
- {
- function g() { }
- print(g);
- }
- print(g);
- // without prior or in-block-scope reference
- if (true)
- {
- function h() { }
- }
- print(h);
- })();
- print('\nTest 2: Block-scoped function shadows outer let binding, but leaks into function scope\n');
- (function ()
- {
- print(f);
- if (true)
- {
- let f = 'let f';
- print(f);
- if (true)
- {
- function f() { }
- print(f);
- }
- print(f);
- }
- print(f);
- })();
- print('\nTest 3: Assignment to function in block behaves like assigning let variable; function still leaks out to function scope; assignment does not affect function scope binding\n');
- (function ()
- {
- print(f);
- if (true)
- {
- let f = 'let f';
- print(f);
- if (true)
- {
- function f() { }
- f = 'reassigned inner function declared "let" f';
- print(f);
- }
- print(f);
- f = 'reassigned outer let f';
- print(f);
- }
- print(f);
- })();
- print('\nTest 4: Last executed declaration wins; simple case\n');
- (function ()
- {
- if (true)
- {
- function f(one) { }
- print(f);
- }
- print(f);
- if (true)
- {
- function f(two) { }
- print(f);
- }
- print(f);
- })();
- print('\nTest 5: Inner shadows outer and last executed (inner) wins for function scope\n');
- (function ()
- {
- if (true)
- {
- function f(outer) { }
- print(f);
- if (true)
- {
- function f(inner) { }
- print(f);
- }
- print(f);
- }
- print(f);
- })();
- print('\nTest 6: Last declaration executed wins; loop and conditionals\n');
- (function ()
- {
- let x = 0;
- print(f);
- while (x < 3)
- {
- print(f);
- if (x === 0 || x === 2)
- {
- function f(one) { }
- print(f);
- }
- else if (x === 1)
- {
- function f(two) { }
- print(f);
- }
- print(f);
- x += 1;
- }
- print(f);
- })();
- print('\nTest 7: Make sure function scope binding is initialized even when it is an activation object (imposed by presence of eval)\n');
- (function ()
- {
- eval('print(f);');
- if (true)
- {
- function f() { }
- }
- eval('print(f);');
- print(f);
- })();
- print('\nTest 8: Function scope binding does not occur in strict mode\n');
- (function ()
- {
- for (var i = 0; i < 2; i += 1)
- {
- try
- {
- (function ()
- {
- "use strict";
- if (i == 0)
- print(f);
- if (true)
- {
- function f() { }
- print(f);
- }
- print(f);
- })();
- }
- catch (e)
- {
- print(e);
- }
- }
- })();
- print('\nTest 9: Overwriting user declared var\n');
- (function ()
- {
- var f = 'var f';
- print(f);
- if (true)
- {
- function f() { }
- print(f);
- }
- print(f);
- })();
- print('\nTest 10: inner functions before block scope function should bind to function scoped binding, not outer scope\n');
- (function ()
- {
- function f()
- {
- print('outer scope f()');
- }
- (function ()
- {
- function g ()
- {
- if (f === undefined)
- {
- print(f);
- }
- else
- {
- f();
- }
- }
- g();
- if (true)
- {
- function f ()
- {
- print('inner block-scope f()');
- }
- }
- g();
- })();
- })();
- print('\nTest 11: Function declarations shadow with object but also do not assign to with object properties\n');
- (function ()
- {
- print(f);
- print(g);
- with ({ f: 'with f', g: 'with g' })
- {
- function f() { }
- function h() { }
- print(f);
- if (true)
- {
- function g() { }
- print(g);
- }
- print(g);
- print(h);
- }
- print(f);
- print(g);
- print(h);
- })();
- print('\nTest 12: Ensure redeclaration errors do not occur with var binding of block scoped functions\n');
- (function ()
- {
- let f = 'let f';
- print(f);
- {
- function f() { }
- function g() { }
- print(f);
- print(g);
- }
- let g = 'let g';
- print(f);
- print(g);
- })();
- print('\nTest 13: Eval does not leak let and const bindings\n');
- (function ()
- {
- var f = 'var f';
- print(f);
- try { print(g); } catch (e) { print(e); }
- eval("var f = 'eval var f'; function g() { } let h = 'eval let h'; const i = 'eval const i'; if (true) { var j = 'eval blockscoped var j'; let k = 'eval blockscoped let k'; }");
- print(f);
- print(g);
- try { print(h); } catch (e) { print(e); }
- try { print(i); } catch (e) { print(e); }
- print(j);
- try { print(k); } catch (e) { print(e); }
- })();
- print('\nTest 14: Eval leaks vars, and var declarations bind to block scoped bindings for rhs initialization\n');
- (function ()
- {
- var f = 'var f';
- {
- let f = 'let f';
- eval("var f = 'eval var f'; var g = 'eval var g'; print(f); print(g);");
- print(f);
- print(g);
- }
- print(f);
- print(g);
- })();
- print('\nTest 15: Eval should have TDZ use before declaration error\n');
- (function ()
- {
- try
- {
- eval("f(); let x = 'let x'; function f() { print(x); }");
- }
- catch (e)
- {
- print(e);
- }
- })();
- print('\nTest 16: Eval function declarations create/assign to a var binding and assign to let binding, and create a let binding if not at eval global scope\n');
- (function ()
- {
- function f(notineval) { }
- if (true)
- {
- function g(notineval) { }
- function h(notineval) { }
- eval("function f(ineval) { }; function g(ineval) { }; if (true) { function h(ineval) { }; print(h); } print(h);");
- print(f); // this should be f(ineval)
- print(g); // this should be g(ineval)
- print(h); // this should be h(notineval)
- }
- print(f); // this should be f(ineval)
- print(g); // this should be g(ineval)
- print(h); // this should be h(ineval)
- })();
- print('\nTest 17: var initializations should find block scoped lets but still create properties at function scope\n');
- (function ()
- {
- var f = 'var f not in eval';
- if (true)
- {
- let g = 'let g not in eval';
- eval("var f = 'var f in eval'; if (true) { var g = 'var g in eval'; }");
- print(f); // this should be 'var f in eval'
- print(g); // this should be 'let g in eval'
- }
- print(f); // this should be 'var f in eval'
- print(g); // this should be 'undefined'
- })();
- print('\nTest 18: function declaration in eval should shadow variables declared outside eval (strict)\n');
- (function ()
- {
- // Only strict mode has this behavior
- "use strict";
- var f = 'var f';
- if (true)
- {
- let g = 'let g';
- eval("function f() { } function g() { } f(); g(); print(f); print(g);");
- print(g);
- }
- print(f);
- try
- {
- print(g);
- }
- catch (e)
- {
- print(e);
- }
- })();
- print('\nTest 19: function declaration var binding should be ignored when same named let/const variable is at function scope\n');
- (function ()
- {
- // Note: declared var's simply get overwritten instead of introducing shadowing
- // static
- (function () {
- let f = 'let f';
- {
- function f() { }
- print(f);
- }
- print(f);
- })();
- (function () {
- const g = 'const g';
- {
- function g() { }
- print(g);
- }
- print(g);
- })();
- (function () {
- var h = 'var h';
- {
- function h() { }
- print(h);
- }
- print(h);
- })();
- (function () {
- {
- function i() { }
- print(i);
- }
- let i = 'let i';
- print(i);
- })();
- (function () {
- {
- function j() { }
- print(j);
- }
- const j = 'const j';
- print(j);
- })();
- (function () {
- {
- function k() { }
- print(k);
- }
- var k = 'var k';
- print(k);
- })();
- // dynamic via eval
- (function () {
- let l = 'let l';
- {
- try { eval("function l(one) { }; print(l);"); } catch (e) { print(e); }
- print(l);
- }
- print(l);
- l = 'outer let l';
- {
- let l = 'inner let l';
- try { eval("function l(two) { }; print(l);"); } catch (e) { print(e); }
- print(l);
- }
- print(l);
- })();
- (function () {
- const m = 'const m';
- {
- try { eval("function m(one) { }; print(m);"); } catch (e) { print(e); }
- print(m);
- }
- print(m);
- {
- const m = 'inner const m';
- try { eval("function m(two) { }; print(m);"); } catch (e) { print(e); }
- print(m);
- }
- print(m);
- {
- let m = 'inner let m';
- try { eval("function m(three) { }; print(m);"); } catch (e) { print(e); }
- print(m);
- }
- print(m);
- })();
- (function () {
- var n = 'var n';
- {
- eval("function n() { }; print(n);");
- print(n);
- }
- print(n);
- })();
- (function () {
- {
- try { eval("function o() { }; print(o);"); } catch (e) { print(e); }
- }
- let o = 'let o';
- print(o);
- })();
- (function () {
- {
- try { eval("function p() { }; print(p);"); } catch (e) { print(e); }
- }
- const p = 'const p';
- print(p);
- })();
- (function () {
- {
- try { eval("function q() { }; print(q);"); } catch (e) { print(e); }
- }
- var q = 'var q';
- print(q);
- })();
- // function var binding should cause scope slot indices to be messed up;
- // see bug 513299.
- function test1() {
- eval('');
- a;
- {
- function b() { }
- }
- const b = 1;
- var a;
- }
- test1();
- })();
- print('\nTest 20: Function declaration in statement context without {}\n');
- (function() {
- if (1)
- function f1() { print('1'); }
- else
- function f1() { print('0'); }
- if (0)
- function f2() { print('1'); }
- else
- function f2() { print('0'); }
- if (1) {
- if (1)
- function f3() { print('1'); }
- else
- function f3() { print('0'); }
- if (0)
- function f4() { print('1'); }
- else
- function f4() { print('0'); }
- }
- while (false)
- function f5() {}
- for (;false;)
- function f6() {}
- for (var p in {a:'a'})
- function f7() {}
- for (var e of [1])
- function f8() {}
- with ({})
- function f9() {}
- f1();
- f2();
- f3();
- f4();
- f7();
- f8();
- f9();
- })();
- print('\nTest 21: Function declaration in statement context without {}, strict mode\n');
- (function() {
- "use strict";
- // The B.3.4 exceptions are not allowed in strict mode
- try {
- eval('if (true)' +
- ' function f() { return "not allowed in strict mode"; }' +
- 'else' +
- ' void 0;');
- }
- catch(ex) {
- print('21.1: ' + ex.message);
- }
- try {
- eval('if (true)' +
- ' void 0;' +
- 'else' +
- ' function f() { return "not allowed in strict mode"; }');
- }
- catch(ex) {
- print('21.2: ' + ex.message);
- }
- try {
- eval('if (true)' +
- ' function f() { return "not allowed in strict mode"; }' +
- 'else' +
- ' function f() { return "not allowed in strict mode"; }');
- }
- catch(ex) {
- print('21.3: ' + ex.message);
- }
- try {
- eval('if (true)' +
- ' function f() { return "not allowed in strict mode"; }');
- }
- catch(ex) {
- print('21.4: ' + ex.message);
- }
- })();
- print('\nTest 22: Function declaration in statement context without {}, illegal in sloppy mode\n');
- (function() {
- // Always illegal syntax regardless of strict mode
- // generator functions are GeneratorFunctionDeclaration, not FunctionDeclaration
- // so are also not allowed by the B.3.4 exception
- try {
- eval('if (true)' +
- ' function* f() { return "never allowed"; }' +
- 'else' +
- ' void 0;');
- }
- catch(ex) {
- print('22.1: ' + ex.message);
- }
- try {
- eval('if (true)' +
- ' void 0;' +
- 'else' +
- ' function* f() { return "never allowed"; }');
- }
- catch(ex) {
- print('22.2: ' + ex.message);
- }
- try {
- eval('if (true)' +
- ' function* f() { return "never allowed"; }' +
- 'else' +
- ' function* f() { return "never allowed"; }');
- }
- catch(ex) {
- print('22.3: ' + ex.message);
- }
- try {
- eval('if (true)' +
- ' function* f() { return "never allowed"; }');
- }
- catch(ex) {
- print('22.4: ' + ex.message);
- }
- // async is ES7 but presumably will also not be FunctionDeclaration in the grammar
- // and so are also not allowed by the B.3.4 exception
- try {
- eval('if (true)' +
- ' async function f() { return "never allowed"; }' +
- 'else' +
- ' void 0;');
- }
- catch(ex) {
- print('22.5: ' + ex.message);
- }
- try {
- eval('if (true)' +
- ' void 0;' +
- 'else' +
- ' async function f() { return "never allowed"; }');
- }
- catch(ex) {
- print('22.6: ' + ex.message);
- }
- try {
- eval('if (true)' +
- ' async function f() { return "never allowed"; }' +
- 'else' +
- ' async function f() { return "never allowed"; }');
- }
- catch(ex) {
- print('22.7: ' + ex.message);
- }
- try {
- eval('if (true)' +
- ' async function f() { return "never allowed"; }' +
- 'else' +
- ' async function f() { return "never allowed"; }');
- }
- catch(ex) {
- print('22.8: ' + ex.message);
- }
- try {
- eval('if (true)' +
- ' async function f() { return "never allowed"; }');
- }
- catch(ex) {
- print('22.8: ' + ex.message);
- }
- })();
- // Leave this test last since it is at global scope and would be awkward to place in the middle of the cleanly contained tests
- // above, and also so that it does not accidentally influence the previous tests.
- print('\nTest Global: Global scope has the same semantics for block-scoped function declarations\n');
- print(glo_f);
- if (true)
- {
- function glo_f() { }
- print(glo_f);
- }
- print(glo_f);
- function glo_g(globalscope) { }
- print(glo_g);
- if (true)
- {
- function glo_g(blockscope) { }
- print(glo_g);
- }
- print(glo_g);
- print(glo_h);
- if (true)
- {
- function glo_h(one) { }
- print(glo_h);
- }
- print(glo_h);
- if (true)
- {
- function glo_h(two) { }
- print(glo_h);
- }
- print(glo_h);
- print('\nGlobal version of Test 19: function declaration\'s var binding should be ignored when same named let/const variable is at global scope\n');
- // Note: declared var's simply get overwritten instead of introducing shadowing
- // static
- let glo_t19_f = 'let glo_t19_f';
- {
- function glo_t19_f() { }
- print(glo_t19_f);
- }
- print(glo_t19_f);
- const glo_t19_g = 'const glo_t19_g';
- {
- function glo_t19_g() { }
- print(glo_t19_g);
- }
- print(glo_t19_g);
- var glo_t19_h = 'var glo_t19_h';
- {
- function glo_t19_h() { }
- print(glo_t19_h);
- }
- print(glo_t19_h);
- {
- function glo_t19_i() { }
- print(glo_t19_i);
- }
- let glo_t19_i = 'let glo_t19_i';
- print(glo_t19_i);
- {
- function glo_t19_j() { }
- print(glo_t19_j);
- }
- const glo_t19_j = 'const glo_t19_j';
- print(glo_t19_j);
- {
- function glo_t19_k() { }
- print(glo_t19_k);
- }
- var glo_t19_k = 'var glo_t19_k';
- print(glo_t19_k);
- // dynamic via eval
- let glo_t19_l = 'let glo_t19_l';
- {
- try { eval("function glo_t19_l(one) { }; print(glo_t19_l);"); } catch (e) { print(e); }
- print(glo_t19_l);
- }
- print(glo_t19_l);
- print(this.glo_t19_l);
- {
- try { eval("function declaredLater(one) { }; print(declaredLater);"); } catch (e) { print(e); }
- }
- let declaredLater = 'let declaredLater';
- print(declaredLater);
- glo_t19_l = 'outer let glo_t19_l';
- {
- let glo_t19_l = 'inner let glo_t19_l';
- try { eval("function glo_t19_l(two) { }; print(glo_t19_l);"); } catch (e) { print(e); }
- print(glo_t19_l);
- }
- print(glo_t19_l);
- print(this.glo_t19_l);
- const glo_t19_m = 'const glo_t19_m';
- {
- try { eval("function glo_t19_m(one) { }; print(glo_t19_m);"); } catch (e) { print(e); }
- print(glo_t19_m);
- }
- print(glo_t19_m);
- print(this.glo_t19_m);
- {
- const glo_t19_m = 'inner const m';
- try { eval("function glo_t19_m(two) { }; print(glo_t19_m);"); } catch (e) { print(e); }
- print(glo_t19_m);
- }
- print(glo_t19_m);
- print(this.glo_t19_m);
- {
- let glo_t19_m = 'inner let m';
- try { eval("function glo_t19_m(three) { }; print(glo_t19_m);"); } catch (e) { print(e); }
- print(glo_t19_m);
- }
- print(glo_t19_m);
- print(this.glo_t19_m);
- var glo_t19_n = 'var glo_t19_n';
- {
- eval("function glo_t19_n() { }; print(glo_t19_n);");
- print(glo_t19_n);
- }
- print(glo_t19_n);
- {
- try { eval("function glo_t19_o() { }; print(glo_t19_o);"); } catch (e) { print(e); }
- }
- let glo_t19_o = 'let glo_t19_o';
- print(glo_t19_o);
- {
- try { eval("function glo_t19_p() { }; print(glo_t19_p);"); } catch (e) { print(e); }
- }
- const glo_t19_p = 'const glo_t19_p';
- print(glo_t19_p);
- {
- try { eval("function glo_t19_q() { }; print(glo_t19_q);"); } catch (e) { print(e); }
- }
- var glo_t19_q = 'var glo_t19_q';
- print(glo_t19_q);
- {
- function xxx(){}
- }
- try
- {
- eval('xxx()++');
- }
- catch(e)
- {
- print(e);
- }
- (function () {
- for (var ngjkfy = 0; ngjkfy < 16; ++ngjkfy) {
- if (ngjkfy % 5 == 2) {
- function y() {
- }
- } else {
- for (qvjjmr = 0; qvjjmr < 4; ++qvjjmr) {
- 'u{7cb6}';
- }
- }
- }
- var y = 0;
- }());
|