silphius/app/astride/evaluators/object.js

77 lines
2.2 KiB
JavaScript
Raw Normal View History

2024-06-16 08:01:01 -05:00
export default function(node, {evaluate, scope}) {
const {properties} = node;
let isAsync = false;
const entries = [];
for (let i = 0; i < properties.length; i++) {
2024-06-30 14:20:37 -05:00
if ('Property' === properties[i].type) {
2024-06-22 10:47:17 -05:00
const {computed, key, value} = properties[i];
2024-06-16 08:01:01 -05:00
let k;
2024-06-22 10:47:17 -05:00
if (computed) {
2024-06-16 08:01:01 -05:00
k = evaluate(key, {scope});
}
2024-06-30 14:20:37 -05:00
else if ('Identifier' === key.type) {
2024-06-22 10:47:17 -05:00
k = {value: key.name};
2024-06-16 08:01:01 -05:00
}
2024-06-30 14:20:37 -05:00
else if ('Literal' === key.type) {
2024-06-16 08:01:01 -05:00
k = {value: key.value};
}
/* v8 ignore next 3 */
else {
throw new Error(`property key type ${key.type} not implemented`);
}
const v = evaluate(value, {scope});
isAsync ||= k.async || v.async;
if (k.async || v.async) {
entries.push(Promise.all([k.value, v.value]));
}
else {
entries.push([k.value, v.value]);
}
}
2024-06-30 14:20:37 -05:00
if ('SpreadElement' === properties[i].type) {
2024-06-22 10:47:17 -05:00
const {argument} = properties[i];
2024-06-16 08:01:01 -05:00
const spreading = evaluate(argument, {scope});
isAsync ||= spreading.async;
if (spreading.async) {
entries.push(Promise.resolve(spreading.value).then((spreading) => {
const entries = [];
const keys = Object.keys(spreading);
for (let i = 0; i < keys.length; ++i) {
const key = keys[i];
entries.push([key, spreading[key]]);
}
return entries;
}));
}
else {
const keys = Object.keys(spreading.value);
for (let i = 0; i < keys.length; ++i) {
const key = keys[i];
entries.push([key, spreading.value[key]]);
}
}
}
}
return {
async: !!isAsync,
value: isAsync
? Promise.all(entries)
.then((entries) => {
const flat = [];
for (let i = 0; i < entries.length; ++i) {
const entry = entries[i];
if (Array.isArray(entry[0])) {
for (let j = 0; j < entry.length; j++) {
flat.push(entry[j]);
}
}
else {
flat.push(entry);
}
}
return Object.fromEntries(flat);
})
: Object.fromEntries(entries),
};
}