feat: top-level return
This commit is contained in:
parent
8ba0c0681f
commit
9b2dab91ac
|
@ -10,6 +10,7 @@ import {
|
||||||
isIdentifier,
|
isIdentifier,
|
||||||
isIfStatement,
|
isIfStatement,
|
||||||
isObjectPattern,
|
isObjectPattern,
|
||||||
|
isReturnStatement,
|
||||||
isVariableDeclarator,
|
isVariableDeclarator,
|
||||||
isWhileStatement,
|
isWhileStatement,
|
||||||
} from '@/swcx/types.js';
|
} from '@/swcx/types.js';
|
||||||
|
@ -206,7 +207,10 @@ export default class Sandbox {
|
||||||
if (!child) {
|
if (!child) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
yield* this.execute(child, node);
|
const result = yield* this.execute(child, node);
|
||||||
|
if (result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Loops...
|
// Loops...
|
||||||
if (isForStatement(node)) {
|
if (isForStatement(node)) {
|
||||||
|
@ -230,6 +234,10 @@ export default class Sandbox {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (loop);
|
} while (loop);
|
||||||
|
// Top-level return.
|
||||||
|
if (isReturnStatement(node)) {
|
||||||
|
return !node.argument ? {value: undefined} : this.evaluate(node.argument);
|
||||||
|
}
|
||||||
if (isExpressionStatement(node)) {
|
if (isExpressionStatement(node)) {
|
||||||
yield this.evaluate(node.expression);
|
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(
|
const sandbox = new Sandbox(
|
||||||
await parse(`
|
await parse(`
|
||||||
const x = y
|
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 () => {
|
test('sets variables in global scope', async () => {
|
||||||
const sandbox = new Sandbox(
|
const sandbox = new Sandbox(
|
||||||
await parse(`
|
await parse(`
|
||||||
|
|
|
@ -29,6 +29,7 @@ export const TRAVERSAL_PATH = {
|
||||||
OptionalChainingExpression: ['base'],
|
OptionalChainingExpression: ['base'],
|
||||||
ParenthesisExpression: ['expression'],
|
ParenthesisExpression: ['expression'],
|
||||||
RegExpLiteral: [],
|
RegExpLiteral: [],
|
||||||
|
ReturnStatement: ['argument'],
|
||||||
StringLiteral: [],
|
StringLiteral: [],
|
||||||
UnaryExpression: ['argument'],
|
UnaryExpression: ['argument'],
|
||||||
UpdateExpression: ['argument'],
|
UpdateExpression: ['argument'],
|
||||||
|
|
|
@ -92,6 +92,14 @@ export function isObjectPattern(node) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isReturnStatement(node) {
|
||||||
|
/* v8 ignore next 3 */
|
||||||
|
if (!node || node.type !== 'ReturnStatement') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
export function isSpreadElement(node) {
|
export function isSpreadElement(node) {
|
||||||
/* v8 ignore next 3 */
|
/* v8 ignore next 3 */
|
||||||
if (!node || node.type !== 'SpreadElement') {
|
if (!node || node.type !== 'SpreadElement') {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user