feat: array spread

This commit is contained in:
cha0s 2024-06-26 04:15:52 -05:00
parent 694cd90645
commit ac12fafa16
2 changed files with 45 additions and 8 deletions

View File

@ -1,13 +1,43 @@
import {isSpreadElement} from '@/astride/types.js';
export default function(node, {evaluate, scope}) { export default function(node, {evaluate, scope}) {
const elements = []; const elements = [];
const asyncSpread = Object.create(null);
let isAsync = false; let isAsync = false;
for (const element of node.elements) { for (const index in node.elements) {
const {async, value} = evaluate(element, {scope}); const element = node.elements[index];
isAsync = isAsync || async; if (isSpreadElement(element)) {
elements.push(value); const {async, value} = evaluate(element.argument, {scope});
isAsync = isAsync || async;
if (async) {
elements.push(value);
asyncSpread[elements.length - 1] = true;
}
else {
elements.push(...value);
}
}
else {
const {async, value} = evaluate(element, {scope});
isAsync = isAsync || async;
elements.push(value);
}
} }
return { return {
async: !!isAsync, async: !!isAsync,
value: isAsync ? Promise.all(elements) : elements, value: !isAsync
? elements
: Promise.all(elements).then((elementsAndOrSpreads) => {
const elements = [];
for (let i = 0; i < elementsAndOrSpreads.length; ++i) {
if (asyncSpread[i]) {
elements.push(...elementsAndOrSpreads[i]);
}
else {
elements.push(elementsAndOrSpreads[i]);
}
}
return elements;
}),
}; };
} }

View File

@ -6,12 +6,19 @@ import expression from '@/astride/test/expression.js';
test('evaluates array of literals', async () => { test('evaluates array of literals', async () => {
expect(evaluate(await expression('[1.5, 2, "three"]'))) expect(evaluate(await expression('[1.5, 2, "three"]')))
.to.deep.include({value: [1.5, 2, 'three']}); .to.deep.include({value: [1.5, 2, 'three']});
});
test('evaluates array containing promises', async () => {
const evaluated = evaluate(await expression('[1.5, 2, await "three"]')); const evaluated = evaluate(await expression('[1.5, 2, await "three"]'));
expect(evaluated.async) expect(evaluated.async)
.to.equal(true); .to.equal(true);
expect(await evaluated.value) expect(await evaluated.value)
.to.deep.equal([1.5, 2, 'three']); .to.deep.equal([1.5, 2, 'three']);
}); });
test('evaluates array spread', async () => {
expect(evaluate(await expression('[...[4, 5, 6], 1.5, 2, "three"]')))
.to.deep.include({value: [4, 5, 6, 1.5, 2, 'three']});
const evaluated = evaluate(await expression('[...(await [4, 5, 6]), 1.5, 2, await "three"]'));
expect(evaluated.async)
.to.equal(true);
expect(await evaluated.value)
.to.deep.equal([4, 5, 6, 1.5, 2, 'three']);
});