feat: top-level return

This commit is contained in:
cha0s 2024-06-18 22:29:40 -05:00
parent 8ba0c0681f
commit 9b2dab91ac
4 changed files with 49 additions and 2 deletions

View File

@ -10,6 +10,7 @@ import {
isIdentifier,
isIfStatement,
isObjectPattern,
isReturnStatement,
isVariableDeclarator,
isWhileStatement,
} from '@/swcx/types.js';
@ -206,7 +207,10 @@ export default class Sandbox {
if (!child) {
continue;
}
yield* this.execute(child, node);
const result = yield* this.execute(child, node);
if (result) {
return result;
}
}
// Loops...
if (isForStatement(node)) {
@ -230,6 +234,10 @@ export default class Sandbox {
}
}
} while (loop);
// Top-level return.
if (isReturnStatement(node)) {
return !node.argument ? {value: undefined} : this.evaluate(node.argument);
}
if (isExpressionStatement(node)) {
yield this.evaluate(node.expression);
}

View File

@ -151,7 +151,7 @@ test('evaluates loops', async () => {
});
});
test('retuns undefined for nonexistent variables in scope', async () => {
test('evaluates undefined for nonexistent variables in scope', async () => {
const sandbox = new Sandbox(
await parse(`
const x = y
@ -164,6 +164,36 @@ test('retuns undefined for nonexistent variables in scope', async () => {
});
});
test('returns values at the top level', async () => {
let sandbox;
sandbox = new Sandbox(
await parse(`
x = 16
y = 4
return [x * 3, y * 3]
x = 32
y = 8
`, {allowReturnOutsideFunction: true}),
);
const {value: {value}} = sandbox.run();
expect(value)
.to.deep.equal([48, 12]);
expect(sandbox.context)
.to.deep.equal({x: 16, y: 4});
sandbox = new Sandbox(
await parse(`
x = 16
y = 4
return
x = 32
y = 8
`, {allowReturnOutsideFunction: true}),
);
sandbox.run();
expect(sandbox.context)
.to.deep.equal({x: 16, y: 4});
});
test('sets variables in global scope', async () => {
const sandbox = new Sandbox(
await parse(`

View File

@ -29,6 +29,7 @@ export const TRAVERSAL_PATH = {
OptionalChainingExpression: ['base'],
ParenthesisExpression: ['expression'],
RegExpLiteral: [],
ReturnStatement: ['argument'],
StringLiteral: [],
UnaryExpression: ['argument'],
UpdateExpression: ['argument'],

View File

@ -92,6 +92,14 @@ export function isObjectPattern(node) {
return true;
}
export function isReturnStatement(node) {
/* v8 ignore next 3 */
if (!node || node.type !== 'ReturnStatement') {
return false;
}
return true;
}
export function isSpreadElement(node) {
/* v8 ignore next 3 */
if (!node || node.type !== 'SpreadElement') {