mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 17:10:23 +00:00
352 lines
9.5 KiB
JavaScript
352 lines
9.5 KiB
JavaScript
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");
|
|
}
|
|
}
|
|
});
|