Skip to content

Commit 258b2ec

Browse files
yycmartin-henz
authored andcommitted
fix standalone block statement scoping (#75)
1 parent 3464f4d commit 258b2ec

File tree

3 files changed

+34
-13
lines changed

3 files changed

+34
-13
lines changed

src/__tests__/__snapshots__/block_scoping.ts.snap

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ Object {
3838
}
3939
`;
4040

41+
exports[`standalone block statements 1`] = `
42+
Object {
43+
"status": "finished",
44+
"value": true,
45+
}
46+
`;
47+
4148
exports[`while loops use block scoping instead of function scoping 1`] = `
4249
Object {
4350
"status": "finished",

src/__tests__/block_scoping.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,27 @@ import { mockContext } from "../mocks/context";
22
import { parseError, runInContext } from "../index";
33
import { Finished } from "../types";
44

5+
// This is bad practice. Don't do this!
6+
test("standalone block statements", () => {
7+
const code = `
8+
function test(){
9+
const x = true;
10+
{
11+
const x = false;
12+
}
13+
return x;
14+
}
15+
test();
16+
`;
17+
const context = mockContext();
18+
const promise = runInContext(code, context, { scheduler: "preemptive" });
19+
return promise.then(obj => {
20+
expect(obj).toMatchSnapshot();
21+
expect(obj.status).toBe("finished");
22+
expect((obj as Finished).value).toBe(true);
23+
});
24+
});
25+
526
// This is bad practice. Don't do this!
627
test("const uses block scoping instead of function scoping", () => {
728
const code = `

src/interpreter.ts

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -425,18 +425,11 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
425425
handleError(context, error)
426426
return undefined
427427
}
428-
429-
// Create a new frame (block scoping)
430-
const frame = createBlockFrame(context, "ifBlockFrame")
431-
pushFrame(context, frame)
432-
433428
if (test) {
434429
const result = yield* evaluate(node.consequent, context)
435-
popFrame(context)
436430
return result
437431
} else if (node.alternate) {
438432
const result = yield* evaluate(node.alternate, context)
439-
popFrame(context)
440433
return result
441434
} else {
442435
return undefined
@@ -468,13 +461,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
468461
!(value instanceof BreakValue) &&
469462
!(value instanceof TailCallReturnValue)
470463
) {
471-
// Create a new frame (block scoping)
472-
const frame = createBlockFrame(context, "whileBlockFrame")
473-
pushFrame(context, frame)
474-
475464
value = yield* evaluate(node.body, context)
476-
477-
popFrame(context)
478465
}
479466
if (value instanceof BreakValue) {
480467
return undefined
@@ -496,6 +483,11 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
496483
},
497484
BlockStatement: function*(node: es.BlockStatement, context: Context) {
498485
let result: Value
486+
487+
// Create a new frame (block scoping)
488+
const frame = createBlockFrame(context, "blockFrame")
489+
pushFrame(context, frame)
490+
499491
for (const statement of node.body) {
500492
result = yield* evaluate(statement, context)
501493
if (
@@ -506,6 +498,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
506498
break
507499
}
508500
}
501+
popFrame(context)
509502
return result
510503
},
511504
Program: function*(node: es.BlockStatement, context: Context) {

0 commit comments

Comments
 (0)