123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- const noHoistLexTopLevel = false;
- let canCallNonHoisted = 0;
- expect(basicHoistTopLevel()).toEqual("basicHoistTopLevel");
- function basicHoistTopLevel() {
- return "basicHoistTopLevel";
- }
- expect(typeof noHoistLexTopLevel).toBe("boolean");
- expect(typeof hoistInBlockTopLevel).toBe("undefined");
- {
- expect(noHoistLexTopLevel()).toEqual("noHoistLexTopLevel");
- ++canCallNonHoisted;
- expect(basicHoistTopLevel()).toEqual("basicHoistTopLevelInBlock");
- ++canCallNonHoisted;
- expect(hoistInBlockTopLevel()).toEqual("hoistInBlockTopLevel");
- function hoistInBlockTopLevel() {
- return "hoistInBlockTopLevel";
- }
- function noHoistLexTopLevel() {
- return "noHoistLexTopLevel";
- }
- function basicHoistTopLevel() {
- return "basicHoistTopLevelInBlock";
- }
- }
- expect(canCallNonHoisted).toBe(2);
- expect(hoistInBlockTopLevel()).toEqual("hoistInBlockTopLevel");
- {
- {
- expect(nestedBlocksTopLevel()).toEqual("nestedBlocksTopLevel");
- function nestedBlocksTopLevel() {
- return "nestedBlocksTopLevel";
- }
- }
- expect(nestedBlocksTopLevel()).toEqual("nestedBlocksTopLevel");
- }
- expect(nestedBlocksTopLevel()).toEqual("nestedBlocksTopLevel");
- expect(hoistInBlockTopLevel()).toEqual("hoistInBlockTopLevel");
- expect(typeof hoistSecondOneTopLevel).toBe("undefined");
- {
- expect(typeof hoistSecondOneTopLevel).toBe("undefined");
- {
- expect(hoistSecondOneTopLevel()).toEqual("hoistSecondOneTopLevel");
- function hoistSecondOneTopLevel() {
- return "hoistFirstOneTopLevel";
- }
- expect(hoistSecondOneTopLevel()).toEqual("hoistSecondOneTopLevel");
- function hoistSecondOneTopLevel() {
- return "hoistSecondOneTopLevel";
- }
- expect(hoistSecondOneTopLevel()).toEqual("hoistSecondOneTopLevel");
- {
- expect(hoistSecondOneTopLevel()).toEqual("hoistThirdOneTopLevel");
- function hoistSecondOneTopLevel() {
- return "hoistThirdOneTopLevel";
- }
- expect(hoistSecondOneTopLevel()).toEqual("hoistThirdOneTopLevel");
- }
- expect(hoistSecondOneTopLevel()).toEqual("hoistSecondOneTopLevel");
- }
- expect(hoistSecondOneTopLevel()).toEqual("hoistSecondOneTopLevel");
- }
- expect(hoistSecondOneTopLevel()).toEqual("hoistSecondOneTopLevel");
- test("Non-strict function does hoist", () => {
- const noHoistLexFunction = false;
- let canCallNonHoisted = 0;
- expect(basicHoistFunction()).toEqual("basicHoistFunction");
- function basicHoistFunction() {
- return "basicHoistFunction";
- }
- expect(typeof noHoistLexFunction).toBe("boolean");
- expect(typeof hoistInBlockFunction).toBe("undefined");
- {
- expect(noHoistLexFunction()).toEqual("noHoistLexFunction");
- ++canCallNonHoisted;
- expect(basicHoistFunction()).toEqual("basicHoistFunctionInBlock");
- ++canCallNonHoisted;
- expect(hoistInBlockFunction()).toEqual("hoistInBlockFunction");
- function hoistInBlockFunction() {
- return "hoistInBlockFunction";
- }
- function noHoistLexFunction() {
- return "noHoistLexFunction";
- }
- function basicHoistFunction() {
- return "basicHoistFunctionInBlock";
- }
- }
- expect(canCallNonHoisted).toBe(2);
- expect(hoistInBlockFunction()).toEqual("hoistInBlockFunction");
- {
- {
- expect(nestedBlocksFunction()).toEqual("nestedBlocksFunction");
- function nestedBlocksFunction() {
- return "nestedBlocksFunction";
- }
- }
- expect(nestedBlocksFunction()).toEqual("nestedBlocksFunction");
- }
- expect(nestedBlocksFunction()).toEqual("nestedBlocksFunction");
- expect(hoistInBlockFunction()).toEqual("hoistInBlockFunction");
- expect(typeof hoistSecondOneFunction).toBe("undefined");
- {
- expect(typeof hoistSecondOneFunction).toBe("undefined");
- {
- expect(hoistSecondOneFunction()).toEqual("hoistSecondOneFunction");
- function hoistSecondOneFunction() {
- return "hoistFirstOneFunction";
- }
- expect(hoistSecondOneFunction()).toEqual("hoistSecondOneFunction");
- function hoistSecondOneFunction() {
- return "hoistSecondOneFunction";
- }
- expect(hoistSecondOneFunction()).toEqual("hoistSecondOneFunction");
- {
- expect(hoistSecondOneFunction()).toEqual("hoistThirdOneFunction");
- function hoistSecondOneFunction() {
- return "hoistThirdOneFunction";
- }
- expect(hoistSecondOneFunction()).toEqual("hoistThirdOneFunction");
- }
- expect(hoistSecondOneFunction()).toEqual("hoistSecondOneFunction");
- }
- expect(hoistSecondOneFunction()).toEqual("hoistSecondOneFunction");
- }
- expect(hoistSecondOneFunction()).toEqual("hoistSecondOneFunction");
- expect(notBlockFunctionTopLevel()).toBe("second");
- function notBlockFunctionTopLevel() {
- return "first";
- }
- expect(notBlockFunctionTopLevel()).toBe("second");
- function notBlockFunctionTopLevel() {
- return "second";
- }
- expect(notBlockFunctionTopLevel()).toBe("second");
- });
- test("Strict function does not hoist", () => {
- "use strict";
- const noHoistLexStrictFunction = false;
- let canCallNonHoisted = 0;
- expect(basicHoistStrictFunction()).toEqual("basicHoistStrictFunction");
- function basicHoistStrictFunction() {
- return "basicHoistStrictFunction";
- }
- expect(typeof noHoistLexStrictFunction).toBe("boolean");
- // We cannot use expect(() => ).toThrow because that introduces extra scoping
- try {
- hoistInBlockStrictFunction;
- expect().fail();
- } catch (e) {
- expect(e).toBeInstanceOf(ReferenceError);
- expect(e.message).toEqual("'hoistInBlockStrictFunction' is not defined");
- }
- {
- expect(noHoistLexStrictFunction()).toEqual("noHoistLexStrictFunction");
- ++canCallNonHoisted;
- expect(basicHoistStrictFunction()).toEqual("basicHoistStrictFunctionInBlock");
- ++canCallNonHoisted;
- expect(hoistInBlockStrictFunction()).toEqual("hoistInBlockStrictFunction");
- function hoistInBlockStrictFunction() {
- return "hoistInBlockStrictFunction";
- }
- function noHoistLexStrictFunction() {
- return "noHoistLexStrictFunction";
- }
- function basicHoistStrictFunction() {
- return "basicHoistStrictFunctionInBlock";
- }
- }
- expect(canCallNonHoisted).toBe(2);
- try {
- hoistInBlockStrictFunction;
- expect().fail();
- } catch (e) {
- expect(e).toBeInstanceOf(ReferenceError);
- expect(e.message).toEqual("'hoistInBlockStrictFunction' is not defined");
- }
- {
- try {
- nestedBlocksStrictFunction;
- expect().fail();
- } catch (e) {
- expect(e).toBeInstanceOf(ReferenceError);
- expect(e.message).toEqual("'nestedBlocksStrictFunction' is not defined");
- }
- {
- expect(nestedBlocksStrictFunction()).toEqual("nestedBlocksStrictFunction");
- function nestedBlocksStrictFunction() {
- return "nestedBlocksStrictFunction";
- }
- }
- try {
- nestedBlocksStrictFunction;
- expect().fail();
- } catch (e) {
- expect(e).toBeInstanceOf(ReferenceError);
- expect(e.message).toEqual("'nestedBlocksStrictFunction' is not defined");
- }
- }
- try {
- nestedBlocksStrictFunction;
- expect().fail();
- } catch (e) {
- expect(e).toBeInstanceOf(ReferenceError);
- expect(e.message).toEqual("'nestedBlocksStrictFunction' is not defined");
- }
- expect(notBlockStrictFunctionTopLevel()).toBe("second");
- function notBlockStrictFunctionTopLevel() {
- return "first";
- }
- expect(notBlockStrictFunctionTopLevel()).toBe("second");
- function notBlockStrictFunctionTopLevel() {
- return "second";
- }
- {
- expect(notBlockStrictFunctionTopLevel()).toBe("third");
- function notBlockStrictFunctionTopLevel() {
- return "third";
- }
- expect(notBlockStrictFunctionTopLevel()).toBe("third");
- }
- expect(notBlockStrictFunctionTopLevel()).toBe("second");
- // Inside a block inside a strict function gives a syntax error
- let didNotRunEval = true;
- expect(`
- didNotRunEval = false;
- () => {
- "use strict";
- {
- function f() {
- return "first";
- }
- function f() {
- return "second";
- }
- }
- };
- `).not.toEval();
- expect(didNotRunEval).toBeTrue();
- // However, in eval it's fine but the function does not escape the eval
- {
- let ranEval = false;
- eval(`
- expect(hoistSecondOneStrictFunction()).toBe("hoistSecondOneStrictFunction");
- function hoistSecondOneStrictFunction() {
- return "hoistFirstOneStrictFunction";
- }
- function hoistSecondOneStrictFunction() {
- return "hoistSecondOneStrictFunction";
- }
- ranEval = true;
- `);
- expect(ranEval).toBeTrue();
- try {
- hoistSecondOneStrictFunction;
- expect().fail();
- } catch (e) {
- expect(e).toBeInstanceOf(ReferenceError);
- expect(e.message).toEqual("'hoistSecondOneStrictFunction' is not defined");
- }
- }
- });
|