From ac12fafa168ed98662ab2dd3ee4e2633e30a7e93 Mon Sep 17 00:00:00 2001 From: cha0s Date: Wed, 26 Jun 2024 04:15:52 -0500 Subject: [PATCH] feat: array spread --- app/astride/evaluators/array.js | 40 ++++++++++++++++++++++++---- app/astride/evaluators/array.test.js | 13 ++++++--- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/app/astride/evaluators/array.js b/app/astride/evaluators/array.js index d7bac01..16cee39 100644 --- a/app/astride/evaluators/array.js +++ b/app/astride/evaluators/array.js @@ -1,13 +1,43 @@ +import {isSpreadElement} from '@/astride/types.js'; + export default function(node, {evaluate, scope}) { const elements = []; + const asyncSpread = Object.create(null); let isAsync = false; - for (const element of node.elements) { - const {async, value} = evaluate(element, {scope}); - isAsync = isAsync || async; - elements.push(value); + for (const index in node.elements) { + const element = node.elements[index]; + if (isSpreadElement(element)) { + 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 { 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; + }), }; } diff --git a/app/astride/evaluators/array.test.js b/app/astride/evaluators/array.test.js index 7428e9a..a3ed8b9 100644 --- a/app/astride/evaluators/array.test.js +++ b/app/astride/evaluators/array.test.js @@ -6,12 +6,19 @@ import expression from '@/astride/test/expression.js'; test('evaluates array of literals', async () => { expect(evaluate(await expression('[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"]')); expect(evaluated.async) .to.equal(true); expect(await evaluated.value) .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']); +});