feat: top-level return
This commit is contained in:
parent
8ba0c0681f
commit
9b2dab91ac
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(`
|
||||
|
|
|
@ -29,6 +29,7 @@ export const TRAVERSAL_PATH = {
|
|||
OptionalChainingExpression: ['base'],
|
||||
ParenthesisExpression: ['expression'],
|
||||
RegExpLiteral: [],
|
||||
ReturnStatement: ['argument'],
|
||||
StringLiteral: [],
|
||||
UnaryExpression: ['argument'],
|
||||
UpdateExpression: ['argument'],
|
||||
|
|
|
@ -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') {
|
||||
|
|
Loading…
Reference in New Issue
Block a user