mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 09:00:22 +00:00
LibJS: Add thorough tests for try/finally using continue and break
I wrote these tests a while ago while trying to improve the bytecode, but didn't end up making them pass and gave up. They work in AST interpreter mode, so we can have them in now to have them around for anyone who wants to try and make them pass in bytecode.
This commit is contained in:
parent
fd6bb41519
commit
08750f69e4
Notes:
sideshowbarker
2024-07-17 04:40:24 +09:00
Author: https://github.com/Lubrsi Commit: https://github.com/SerenityOS/serenity/commit/08750f69e4 Pull-request: https://github.com/SerenityOS/serenity/pull/15983 Reviewed-by: https://github.com/linusg ✅
2 changed files with 1020 additions and 0 deletions
341
Userland/Libraries/LibJS/Tests/try-finally-break.js
Normal file
341
Userland/Libraries/LibJS/Tests/try-finally-break.js
Normal file
|
@ -0,0 +1,341 @@
|
|||
test("Nested try/catch/finally with break", () => {
|
||||
const executionOrder = [];
|
||||
|
||||
try {
|
||||
for (const i = 1337; ; expect().fail("Jumped to for loop update block")) {
|
||||
try {
|
||||
try {
|
||||
try {
|
||||
break;
|
||||
} finally {
|
||||
expect(i).toBe(1337);
|
||||
executionOrder.push(1);
|
||||
}
|
||||
} finally {
|
||||
expect(i).toBe(1337);
|
||||
executionOrder.push(2);
|
||||
}
|
||||
} finally {
|
||||
expect(i).toBe(1337);
|
||||
executionOrder.push(3);
|
||||
}
|
||||
|
||||
expect().fail("Running code after second to most outer try");
|
||||
}
|
||||
} finally {
|
||||
expect(() => {
|
||||
i;
|
||||
}).toThrowWithMessage(ReferenceError, "'i' is not defined");
|
||||
|
||||
executionOrder.push(4);
|
||||
}
|
||||
|
||||
expect(() => {
|
||||
i;
|
||||
}).toThrowWithMessage(ReferenceError, "'i' is not defined");
|
||||
|
||||
expect(executionOrder).toEqual([1, 2, 3, 4]);
|
||||
});
|
||||
|
||||
test("Nested try/finally with labelled break", () => {
|
||||
const executionOrder = [];
|
||||
|
||||
outer: try {
|
||||
const libjs = 0;
|
||||
expect(libjs).toBe(0);
|
||||
|
||||
try {
|
||||
const serenity = 1;
|
||||
expect(libjs).toBe(0);
|
||||
expect(serenity).toBe(1);
|
||||
|
||||
for (const i = 2; ; expect().fail("Jumped to for loop update block")) {
|
||||
const foo = 3;
|
||||
|
||||
expect(libjs).toBe(0);
|
||||
expect(serenity).toBe(1);
|
||||
expect(i).toBe(2);
|
||||
expect(foo).toBe(3);
|
||||
|
||||
try {
|
||||
const bar = 4;
|
||||
|
||||
expect(libjs).toBe(0);
|
||||
expect(serenity).toBe(1);
|
||||
expect(i).toBe(2);
|
||||
expect(foo).toBe(3);
|
||||
expect(bar).toBe(4);
|
||||
|
||||
try {
|
||||
const baz = 5;
|
||||
|
||||
expect(libjs).toBe(0);
|
||||
expect(serenity).toBe(1);
|
||||
expect(i).toBe(2);
|
||||
expect(foo).toBe(3);
|
||||
expect(bar).toBe(4);
|
||||
expect(baz).toBe(5);
|
||||
|
||||
try {
|
||||
const whf = 6;
|
||||
|
||||
expect(libjs).toBe(0);
|
||||
expect(serenity).toBe(1);
|
||||
expect(i).toBe(2);
|
||||
expect(foo).toBe(3);
|
||||
expect(bar).toBe(4);
|
||||
expect(baz).toBe(5);
|
||||
expect(whf).toBe(6);
|
||||
|
||||
break outer;
|
||||
} finally {
|
||||
const innerFinally1 = 7;
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(libjs).toBe(0);
|
||||
expect(serenity).toBe(1);
|
||||
expect(i).toBe(2);
|
||||
expect(foo).toBe(3);
|
||||
expect(bar).toBe(4);
|
||||
expect(baz).toBe(5);
|
||||
expect(innerFinally1).toBe(7);
|
||||
|
||||
executionOrder.push(1);
|
||||
}
|
||||
|
||||
expect().fail("Running code after most inner try");
|
||||
} finally {
|
||||
const innerFinally2 = 8;
|
||||
|
||||
expect(() => {
|
||||
baz;
|
||||
}).toThrowWithMessage(ReferenceError, "'baz' is not defined");
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(libjs).toBe(0);
|
||||
expect(serenity).toBe(1);
|
||||
expect(i).toBe(2);
|
||||
expect(foo).toBe(3);
|
||||
expect(bar).toBe(4);
|
||||
expect(innerFinally2).toBe(8);
|
||||
|
||||
executionOrder.push(2);
|
||||
}
|
||||
|
||||
expect().fail("Running code after second to most inner try");
|
||||
} finally {
|
||||
const innerFinally3 = 9;
|
||||
|
||||
expect(() => {
|
||||
bar;
|
||||
}).toThrowWithMessage(ReferenceError, "'bar' is not defined");
|
||||
|
||||
expect(() => {
|
||||
baz;
|
||||
}).toThrowWithMessage(ReferenceError, "'baz' is not defined");
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally2;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally2' is not defined");
|
||||
|
||||
expect(libjs).toBe(0);
|
||||
expect(serenity).toBe(1);
|
||||
expect(i).toBe(2);
|
||||
expect(foo).toBe(3);
|
||||
expect(innerFinally3).toBe(9);
|
||||
|
||||
executionOrder.push(3);
|
||||
}
|
||||
|
||||
expect().fail("Running code after third to most inner try");
|
||||
}
|
||||
|
||||
expect().fail("Running code after for loop");
|
||||
} finally {
|
||||
const innerFinally4 = 10;
|
||||
|
||||
expect(() => {
|
||||
serenity;
|
||||
}).toThrowWithMessage(ReferenceError, "'serenity' is not defined");
|
||||
|
||||
expect(() => {
|
||||
i;
|
||||
}).toThrowWithMessage(ReferenceError, "'i' is not defined");
|
||||
|
||||
expect(() => {
|
||||
foo;
|
||||
}).toThrowWithMessage(ReferenceError, "'foo' is not defined");
|
||||
|
||||
expect(() => {
|
||||
bar;
|
||||
}).toThrowWithMessage(ReferenceError, "'bar' is not defined");
|
||||
|
||||
expect(() => {
|
||||
baz;
|
||||
}).toThrowWithMessage(ReferenceError, "'baz' is not defined");
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally2;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally2' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally3;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally3' is not defined");
|
||||
|
||||
expect(libjs).toBe(0);
|
||||
expect(innerFinally4).toBe(10);
|
||||
|
||||
executionOrder.push(4);
|
||||
}
|
||||
|
||||
expect().fail("Running code after second to outer try");
|
||||
} finally {
|
||||
const innerFinally5 = 11;
|
||||
|
||||
expect(() => {
|
||||
libjs;
|
||||
}).toThrowWithMessage(ReferenceError, "'libjs' is not defined");
|
||||
|
||||
expect(() => {
|
||||
serenity;
|
||||
}).toThrowWithMessage(ReferenceError, "'serenity' is not defined");
|
||||
|
||||
expect(() => {
|
||||
i;
|
||||
}).toThrowWithMessage(ReferenceError, "'i' is not defined");
|
||||
|
||||
expect(() => {
|
||||
foo;
|
||||
}).toThrowWithMessage(ReferenceError, "'foo' is not defined");
|
||||
|
||||
expect(() => {
|
||||
bar;
|
||||
}).toThrowWithMessage(ReferenceError, "'bar' is not defined");
|
||||
|
||||
expect(() => {
|
||||
baz;
|
||||
}).toThrowWithMessage(ReferenceError, "'baz' is not defined");
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally2;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally2' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally3;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally3' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally4;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally4' is not defined");
|
||||
|
||||
expect(innerFinally5).toBe(11);
|
||||
|
||||
executionOrder.push(5);
|
||||
}
|
||||
|
||||
expect(() => {
|
||||
libjs;
|
||||
}).toThrowWithMessage(ReferenceError, "'libjs' is not defined");
|
||||
|
||||
expect(() => {
|
||||
serenity;
|
||||
}).toThrowWithMessage(ReferenceError, "'serenity' is not defined");
|
||||
|
||||
expect(() => {
|
||||
i;
|
||||
}).toThrowWithMessage(ReferenceError, "'i' is not defined");
|
||||
|
||||
expect(() => {
|
||||
foo;
|
||||
}).toThrowWithMessage(ReferenceError, "'foo' is not defined");
|
||||
|
||||
expect(() => {
|
||||
bar;
|
||||
}).toThrowWithMessage(ReferenceError, "'bar' is not defined");
|
||||
|
||||
expect(() => {
|
||||
baz;
|
||||
}).toThrowWithMessage(ReferenceError, "'baz' is not defined");
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally2;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally2' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally3;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally3' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally4;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally4' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally5;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally5' is not defined");
|
||||
|
||||
expect(executionOrder).toEqual([1, 2, 3, 4, 5]);
|
||||
});
|
||||
|
||||
test("labelled break in finally overrides labelled break in try", () => {
|
||||
const executionOrder = [];
|
||||
|
||||
outer: for (const i = 1; ; expect().fail("Jumped to outer for loop update block")) {
|
||||
inner: for (const j = 2; ; expect().fail("Jumped to inner for loop update block")) {
|
||||
try {
|
||||
executionOrder.push(1);
|
||||
break inner;
|
||||
} finally {
|
||||
executionOrder.push(2);
|
||||
break outer;
|
||||
}
|
||||
|
||||
expect().fail("Running code after try block");
|
||||
}
|
||||
|
||||
expect().fail("Running code after inner for loop");
|
||||
}
|
||||
|
||||
expect(executionOrder).toEqual([1, 2]);
|
||||
});
|
679
Userland/Libraries/LibJS/Tests/try-finally-continue.js
Normal file
679
Userland/Libraries/LibJS/Tests/try-finally-continue.js
Normal file
|
@ -0,0 +1,679 @@
|
|||
test("Nested try/catch/finally with continue", () => {
|
||||
const executionOrder = [];
|
||||
|
||||
function callFromUpdateBlock(i) {
|
||||
expect(i).toBe(2);
|
||||
executionOrder.push(4);
|
||||
}
|
||||
|
||||
function callFromTestBlock(i) {
|
||||
expect(i).toBe(2);
|
||||
executionOrder.push(5);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const foo = 0;
|
||||
|
||||
expect(foo).toBe(0);
|
||||
|
||||
for (let i = 1; i >= 2 ? callFromTestBlock(i) : true; ++i, callFromUpdateBlock(i)) {
|
||||
const bar = 2;
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(i).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
|
||||
try {
|
||||
const baz = 3;
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(i).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
expect(baz).toBe(3);
|
||||
|
||||
try {
|
||||
const serenity = 4;
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(i).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
expect(baz).toBe(3);
|
||||
expect(serenity).toBe(4);
|
||||
|
||||
try {
|
||||
const whf = 5;
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(i).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
expect(baz).toBe(3);
|
||||
expect(serenity).toBe(4);
|
||||
expect(whf).toBe(5);
|
||||
|
||||
continue;
|
||||
} finally {
|
||||
const innerFinally1 = 6;
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(i).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
expect(baz).toBe(3);
|
||||
expect(serenity).toBe(4);
|
||||
expect(innerFinally1).toBe(6);
|
||||
|
||||
executionOrder.push(1);
|
||||
}
|
||||
|
||||
expect().fail("Running code after most inner try in for loop");
|
||||
} finally {
|
||||
const innerFinally2 = 7;
|
||||
|
||||
expect(() => {
|
||||
serenity;
|
||||
}).toThrowWithMessage(ReferenceError, "'serenity' is not defined");
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(i).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
expect(baz).toBe(3);
|
||||
expect(innerFinally2).toBe(7);
|
||||
|
||||
executionOrder.push(2);
|
||||
}
|
||||
|
||||
expect().fail("Running code from after the middle try in for loop");
|
||||
} finally {
|
||||
const innerFinally3 = 8;
|
||||
|
||||
expect(() => {
|
||||
baz;
|
||||
}).toThrowWithMessage(ReferenceError, "'baz' is not defined");
|
||||
|
||||
expect(() => {
|
||||
serenity;
|
||||
}).toThrowWithMessage(ReferenceError, "'serenity' is not defined");
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally2;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally2' is not defined");
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(i).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
expect(innerFinally3).toBe(8);
|
||||
|
||||
executionOrder.push(3);
|
||||
}
|
||||
|
||||
expect().fail("Running code from after the outer try in for loop");
|
||||
}
|
||||
|
||||
executionOrder.push(6);
|
||||
|
||||
expect(() => {
|
||||
i;
|
||||
}).toThrowWithMessage(ReferenceError, "'i' is not defined");
|
||||
|
||||
expect(() => {
|
||||
bar;
|
||||
}).toThrowWithMessage(ReferenceError, "'bar' is not defined");
|
||||
|
||||
expect(() => {
|
||||
baz;
|
||||
}).toThrowWithMessage(ReferenceError, "'baz' is not defined");
|
||||
|
||||
expect(() => {
|
||||
serenity;
|
||||
}).toThrowWithMessage(ReferenceError, "'serenity' is not defined");
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally2;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally2' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally3;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally3' is not defined");
|
||||
|
||||
expect(foo).toBe(0);
|
||||
} finally {
|
||||
const innerFinally4 = 9;
|
||||
|
||||
expect(() => {
|
||||
foo;
|
||||
}).toThrowWithMessage(ReferenceError, "'foo' is not defined");
|
||||
|
||||
expect(() => {
|
||||
i;
|
||||
}).toThrowWithMessage(ReferenceError, "'i' is not defined");
|
||||
|
||||
expect(() => {
|
||||
bar;
|
||||
}).toThrowWithMessage(ReferenceError, "'bar' is not defined");
|
||||
|
||||
expect(() => {
|
||||
baz;
|
||||
}).toThrowWithMessage(ReferenceError, "'baz' is not defined");
|
||||
|
||||
expect(() => {
|
||||
serenity;
|
||||
}).toThrowWithMessage(ReferenceError, "'serenity' is not defined");
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally2;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally2' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally3;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally3' is not defined");
|
||||
|
||||
expect(innerFinally4).toBe(9);
|
||||
|
||||
executionOrder.push(7);
|
||||
}
|
||||
|
||||
expect(() => {
|
||||
foo;
|
||||
}).toThrowWithMessage(ReferenceError, "'foo' is not defined");
|
||||
|
||||
expect(() => {
|
||||
i;
|
||||
}).toThrowWithMessage(ReferenceError, "'i' is not defined");
|
||||
|
||||
expect(() => {
|
||||
bar;
|
||||
}).toThrowWithMessage(ReferenceError, "'bar' is not defined");
|
||||
|
||||
expect(() => {
|
||||
baz;
|
||||
}).toThrowWithMessage(ReferenceError, "'baz' is not defined");
|
||||
|
||||
expect(() => {
|
||||
serenity;
|
||||
}).toThrowWithMessage(ReferenceError, "'serenity' is not defined");
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally2;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally2' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally3;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally3' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally4;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally4' is not defined");
|
||||
|
||||
expect(executionOrder).toEqual([1, 2, 3, 4, 5, 6, 7]);
|
||||
});
|
||||
|
||||
test("Nested try/catch/finally with labelled continue", () => {
|
||||
const executionOrder = [];
|
||||
|
||||
function callFromUpdateBlock(j) {
|
||||
expect(j).toBe(2);
|
||||
executionOrder.push(5);
|
||||
}
|
||||
|
||||
function callFromTestBlock(j) {
|
||||
expect(j).toBe(2);
|
||||
executionOrder.push(6);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const foo = 0;
|
||||
|
||||
expect(foo).toBe(0);
|
||||
|
||||
outer: for (let j = 1; j >= 2 ? callFromTestBlock(j) : true; ++j, callFromUpdateBlock(j)) {
|
||||
const bar = 2;
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(j).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
|
||||
try {
|
||||
const baz = 3;
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(j).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
expect(baz).toBe(3);
|
||||
|
||||
for (const i = 4; ; expect().fail("Jumped to inner for loop update block")) {
|
||||
const serenity = 5;
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(j).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
expect(baz).toBe(3);
|
||||
expect(i).toBe(4);
|
||||
expect(serenity).toBe(5);
|
||||
|
||||
try {
|
||||
const whf = 6;
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(j).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
expect(baz).toBe(3);
|
||||
expect(i).toBe(4);
|
||||
expect(serenity).toBe(5);
|
||||
expect(whf).toBe(6);
|
||||
|
||||
try {
|
||||
const beforeContinueTry = 7;
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(j).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
expect(baz).toBe(3);
|
||||
expect(i).toBe(4);
|
||||
expect(serenity).toBe(5);
|
||||
expect(whf).toBe(6);
|
||||
expect(beforeContinueTry).toBe(7);
|
||||
|
||||
try {
|
||||
const continueTry = 8;
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(j).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
expect(baz).toBe(3);
|
||||
expect(i).toBe(4);
|
||||
expect(serenity).toBe(5);
|
||||
expect(whf).toBe(6);
|
||||
expect(beforeContinueTry).toBe(7);
|
||||
expect(continueTry).toBe(8);
|
||||
|
||||
continue outer;
|
||||
} finally {
|
||||
const innerFinally1 = 9;
|
||||
|
||||
expect(() => {
|
||||
continueTry;
|
||||
}).toThrowWithMessage(
|
||||
ReferenceError,
|
||||
"'continueTry' is not defined"
|
||||
);
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(j).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
expect(baz).toBe(3);
|
||||
expect(i).toBe(4);
|
||||
expect(serenity).toBe(5);
|
||||
expect(whf).toBe(6);
|
||||
expect(beforeContinueTry).toBe(7);
|
||||
expect(innerFinally1).toBe(9);
|
||||
|
||||
executionOrder.push(1);
|
||||
}
|
||||
|
||||
expect().fail("Running code after most inner try");
|
||||
} finally {
|
||||
const innerFinally2 = 10;
|
||||
|
||||
expect(() => {
|
||||
beforeContinueTry;
|
||||
}).toThrowWithMessage(
|
||||
ReferenceError,
|
||||
"'beforeContinueTry' is not defined"
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
continueTry;
|
||||
}).toThrowWithMessage(ReferenceError, "'continueTry' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(j).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
expect(baz).toBe(3);
|
||||
expect(i).toBe(4);
|
||||
expect(serenity).toBe(5);
|
||||
expect(whf).toBe(6);
|
||||
expect(innerFinally2).toBe(10);
|
||||
|
||||
executionOrder.push(2);
|
||||
}
|
||||
|
||||
expect().fail("Running code after second to most inner try");
|
||||
} finally {
|
||||
const innerFinally3 = 11;
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(() => {
|
||||
beforeContinueTry;
|
||||
}).toThrowWithMessage(ReferenceError, "'beforeContinueTry' is not defined");
|
||||
|
||||
expect(() => {
|
||||
continueTry;
|
||||
}).toThrowWithMessage(ReferenceError, "'continueTry' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally2;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally2' is not defined");
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(j).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
expect(baz).toBe(3);
|
||||
expect(i).toBe(4);
|
||||
expect(serenity).toBe(5);
|
||||
expect(innerFinally3).toBe(11);
|
||||
|
||||
executionOrder.push(3);
|
||||
}
|
||||
|
||||
expect().fail("Running code after third to most inner try");
|
||||
}
|
||||
|
||||
expect().fail("Running code after inner for loop");
|
||||
} finally {
|
||||
const innerFinally4 = 12;
|
||||
|
||||
expect(() => {
|
||||
baz;
|
||||
}).toThrowWithMessage(ReferenceError, "'baz' is not defined");
|
||||
|
||||
expect(() => {
|
||||
i;
|
||||
}).toThrowWithMessage(ReferenceError, "'i' is not defined");
|
||||
|
||||
expect(() => {
|
||||
serenity;
|
||||
}).toThrowWithMessage(ReferenceError, "'serenity' is not defined");
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(() => {
|
||||
beforeContinueTry;
|
||||
}).toThrowWithMessage(ReferenceError, "'beforeContinueTry' is not defined");
|
||||
|
||||
expect(() => {
|
||||
continueTry;
|
||||
}).toThrowWithMessage(ReferenceError, "'continueTry' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally2;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally2' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally3;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally3' is not defined");
|
||||
|
||||
expect(foo).toBe(0);
|
||||
expect(j).toBe(1);
|
||||
expect(bar).toBe(2);
|
||||
expect(innerFinally4).toBe(12);
|
||||
|
||||
executionOrder.push(4);
|
||||
}
|
||||
|
||||
expect().fail("Running code after try in outer for loop");
|
||||
}
|
||||
|
||||
expect(() => {
|
||||
j;
|
||||
}).toThrowWithMessage(ReferenceError, "'j' is not defined");
|
||||
|
||||
expect(() => {
|
||||
bar;
|
||||
}).toThrowWithMessage(ReferenceError, "'bar' is not defined");
|
||||
|
||||
expect(() => {
|
||||
baz;
|
||||
}).toThrowWithMessage(ReferenceError, "'baz' is not defined");
|
||||
|
||||
expect(() => {
|
||||
i;
|
||||
}).toThrowWithMessage(ReferenceError, "'i' is not defined");
|
||||
|
||||
expect(() => {
|
||||
serenity;
|
||||
}).toThrowWithMessage(ReferenceError, "'serenity' is not defined");
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(() => {
|
||||
beforeContinueTry;
|
||||
}).toThrowWithMessage(ReferenceError, "'beforeContinueTry' is not defined");
|
||||
|
||||
expect(() => {
|
||||
continueTry;
|
||||
}).toThrowWithMessage(ReferenceError, "'continueTry' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally2;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally2' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally3;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally3' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally4;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally4' is not defined");
|
||||
|
||||
expect(foo).toBe(0);
|
||||
|
||||
executionOrder.push(7);
|
||||
} finally {
|
||||
const innerFinally5 = 13;
|
||||
|
||||
expect(() => {
|
||||
foo;
|
||||
}).toThrowWithMessage(ReferenceError, "'foo' is not defined");
|
||||
|
||||
expect(() => {
|
||||
j;
|
||||
}).toThrowWithMessage(ReferenceError, "'j' is not defined");
|
||||
|
||||
expect(() => {
|
||||
bar;
|
||||
}).toThrowWithMessage(ReferenceError, "'bar' is not defined");
|
||||
|
||||
expect(() => {
|
||||
baz;
|
||||
}).toThrowWithMessage(ReferenceError, "'baz' is not defined");
|
||||
|
||||
expect(() => {
|
||||
i;
|
||||
}).toThrowWithMessage(ReferenceError, "'i' is not defined");
|
||||
|
||||
expect(() => {
|
||||
serenity;
|
||||
}).toThrowWithMessage(ReferenceError, "'serenity' is not defined");
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(() => {
|
||||
beforeContinueTry;
|
||||
}).toThrowWithMessage(ReferenceError, "'beforeContinueTry' is not defined");
|
||||
|
||||
expect(() => {
|
||||
continueTry;
|
||||
}).toThrowWithMessage(ReferenceError, "'continueTry' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally2;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally2' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally3;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally3' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally4;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally4' is not defined");
|
||||
|
||||
expect(innerFinally5).toBe(13);
|
||||
|
||||
executionOrder.push(8);
|
||||
}
|
||||
|
||||
expect(() => {
|
||||
foo;
|
||||
}).toThrowWithMessage(ReferenceError, "'foo' is not defined");
|
||||
|
||||
expect(() => {
|
||||
j;
|
||||
}).toThrowWithMessage(ReferenceError, "'j' is not defined");
|
||||
|
||||
expect(() => {
|
||||
bar;
|
||||
}).toThrowWithMessage(ReferenceError, "'bar' is not defined");
|
||||
|
||||
expect(() => {
|
||||
baz;
|
||||
}).toThrowWithMessage(ReferenceError, "'baz' is not defined");
|
||||
|
||||
expect(() => {
|
||||
i;
|
||||
}).toThrowWithMessage(ReferenceError, "'i' is not defined");
|
||||
|
||||
expect(() => {
|
||||
serenity;
|
||||
}).toThrowWithMessage(ReferenceError, "'serenity' is not defined");
|
||||
|
||||
expect(() => {
|
||||
whf;
|
||||
}).toThrowWithMessage(ReferenceError, "'whf' is not defined");
|
||||
|
||||
expect(() => {
|
||||
beforeContinueTry;
|
||||
}).toThrowWithMessage(ReferenceError, "'beforeContinueTry' is not defined");
|
||||
|
||||
expect(() => {
|
||||
continueTry;
|
||||
}).toThrowWithMessage(ReferenceError, "'continueTry' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally1;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally1' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally2;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally2' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally3;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally3' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally4;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally4' is not defined");
|
||||
|
||||
expect(() => {
|
||||
innerFinally5;
|
||||
}).toThrowWithMessage(ReferenceError, "'innerFinally5' is not defined");
|
||||
|
||||
expect(executionOrder).toEqual([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
});
|
||||
|
||||
test("labelled continue in finally overrides labelled continue in try", () => {
|
||||
const executionOrder = [];
|
||||
|
||||
function callFromUpdateBlock(i) {
|
||||
expect(i).toBe(2);
|
||||
executionOrder.push(3);
|
||||
}
|
||||
|
||||
function callFromTestBlock(i) {
|
||||
expect(i).toBe(2);
|
||||
executionOrder.push(4);
|
||||
return false;
|
||||
}
|
||||
|
||||
outer: for (let i = 1; i >= 2 ? callFromTestBlock(i) : true; ++i, callFromUpdateBlock(i)) {
|
||||
inner: for (const j = 2; ; expect().fail("Jumped to inner for loop update block")) {
|
||||
try {
|
||||
executionOrder.push(1);
|
||||
continue inner;
|
||||
} finally {
|
||||
executionOrder.push(2);
|
||||
continue outer;
|
||||
}
|
||||
|
||||
expect().fail("Running code after try block");
|
||||
}
|
||||
|
||||
expect().fail("Running code after inner for loop");
|
||||
}
|
||||
|
||||
expect(executionOrder).toEqual([1, 2, 3, 4]);
|
||||
});
|
Loading…
Reference in a new issue