core evaluate now works without transpiler
This commit is contained in:
parent
16659c82d2
commit
2c7cc5d325
4 changed files with 31 additions and 14 deletions
|
|
@ -24,8 +24,16 @@ export const evalScope = async (...args) => {
|
||||||
Object.assign(globalThis, ...modules, Pattern.prototype.bootstrap());
|
Object.assign(globalThis, ...modules, Pattern.prototype.bootstrap());
|
||||||
};
|
};
|
||||||
|
|
||||||
function safeEval(str) {
|
function safeEval(str, options = {}) {
|
||||||
return Function('"use strict";return (' + str + ')')();
|
const { wrapExpression = true, wrapAsync = true } = options;
|
||||||
|
if (wrapExpression) {
|
||||||
|
str = `{${str}}`;
|
||||||
|
}
|
||||||
|
if (wrapAsync) {
|
||||||
|
str = `(async ()=>${str})()`;
|
||||||
|
}
|
||||||
|
const body = `"use strict";return (${str})`;
|
||||||
|
return Function(body)();
|
||||||
}
|
}
|
||||||
|
|
||||||
export const evaluate = async (code, transpiler) => {
|
export const evaluate = async (code, transpiler) => {
|
||||||
|
|
@ -35,7 +43,9 @@ export const evaluate = async (code, transpiler) => {
|
||||||
if (transpiler) {
|
if (transpiler) {
|
||||||
code = transpiler(code); // transform syntactically correct js code to semantically usable code
|
code = transpiler(code); // transform syntactically correct js code to semantically usable code
|
||||||
}
|
}
|
||||||
let evaluated = await safeEval(code);
|
// if no transpiler is given, we expect a single instruction (!wrapExpression)
|
||||||
|
const options = { wrapExpression: !!transpiler };
|
||||||
|
let evaluated = await safeEval(code, options);
|
||||||
if (!isPattern(evaluated)) {
|
if (!isPattern(evaluated)) {
|
||||||
console.log('evaluated', evaluated);
|
console.log('evaluated', evaluated);
|
||||||
const message = `got "${typeof evaluated}" instead of pattern`;
|
const message = `got "${typeof evaluated}" instead of pattern`;
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,8 @@ const isNote = (name) => /^[a-gC-G][bs]?[0-9]$/.test(name);
|
||||||
const addLocations = true;
|
const addLocations = true;
|
||||||
export const addMiniLocations = true;
|
export const addMiniLocations = true;
|
||||||
export const minifyStrings = true;
|
export const minifyStrings = true;
|
||||||
export const wrappedAsync = true;
|
export const wrappedAsync = false; // this is now handled by core evaluate by default
|
||||||
|
export const shouldAddReturn = true;
|
||||||
|
|
||||||
export default (_code) => {
|
export default (_code) => {
|
||||||
const { code, addReturn } = wrapAsync(_code);
|
const { code, addReturn } = wrapAsync(_code);
|
||||||
|
|
@ -125,7 +126,7 @@ export default (_code) => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// add return to last statement (because it's wrapped in an async function artificially)
|
// add return to last statement (because it's wrapped in an async function artificially)
|
||||||
if (wrappedAsync) {
|
if (shouldAddReturn) {
|
||||||
addReturn(shifted);
|
addReturn(shifted);
|
||||||
}
|
}
|
||||||
const generated = undisguiseImports(codegen(shifted));
|
const generated = undisguiseImports(codegen(shifted));
|
||||||
|
|
@ -153,7 +154,7 @@ ${code}
|
||||||
})()`;
|
})()`;
|
||||||
}
|
}
|
||||||
const addReturn = (ast) => {
|
const addReturn = (ast) => {
|
||||||
const body = ast.statements[0].expression.callee.body; // actual code ast inside async function body
|
const body = wrappedAsync ? ast.statements[0].expression.callee.body : ast;
|
||||||
body.statements = body.statements
|
body.statements = body.statements
|
||||||
.slice(0, -1)
|
.slice(0, -1)
|
||||||
.concat([new ReturnStatement({ expression: body.statements.slice(-1)[0] })]);
|
.concat([new ReturnStatement({ expression: body.statements.slice(-1)[0] })]);
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,21 @@ This program is free software: you can redistribute it and/or modify it under th
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import shapeshifter from '../shapeshifter.mjs';
|
import shapeshifter, { wrappedAsync } from '../shapeshifter.mjs';
|
||||||
|
|
||||||
describe('shapeshifter', () => {
|
describe('shapeshifter', () => {
|
||||||
it('Should shift simple double quote string', () => {
|
it('Should shift simple double quote string', () => {
|
||||||
expect(shapeshifter('"c3"')).toEqual('(async()=>{return mini("c3").withMiniLocation([1,0,15],[1,4,19])})()');
|
if (wrappedAsync) {
|
||||||
});
|
expect(shapeshifter('"c3"')).toEqual('(async()=>{return mini("c3").withMiniLocation([1,0,15],[1,4,19])})()');
|
||||||
it('Should handle dynamic imports', () => {
|
} else {
|
||||||
expect(shapeshifter('const { default: foo } = await import(\'https://bar.com/foo.js\');"c3"')).toEqual(
|
expect(shapeshifter('"c3"')).toEqual('return mini("c3").withMiniLocation([1,0,0],[1,4,4])');
|
||||||
'(async()=>{const{default:foo}=await import("https://bar.com/foo.js");return mini("c3").withMiniLocation([1,64,79],[1,68,83])})()',
|
}
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
if (wrappedAsync) {
|
||||||
|
it('Should handle dynamic imports', () => {
|
||||||
|
expect(shapeshifter('const { default: foo } = await import(\'https://bar.com/foo.js\');"c3"')).toEqual(
|
||||||
|
'const{default:foo}=await import("https://bar.com/foo.js");return mini("c3").withMiniLocation([1,64,79],[1,68,83])',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { walk } from 'estree-walker';
|
||||||
import { isNote } from '@strudel.cycles/core';
|
import { isNote } from '@strudel.cycles/core';
|
||||||
|
|
||||||
export function transpiler(input, options = {}) {
|
export function transpiler(input, options = {}) {
|
||||||
const { wrapAsync = true, addReturn = true } = options;
|
const { wrapAsync = false, addReturn = true } = options;
|
||||||
|
|
||||||
let ast = parse(input, {
|
let ast = parse(input, {
|
||||||
ecmaVersion: 2022,
|
ecmaVersion: 2022,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue