core evaluate now works without transpiler

This commit is contained in:
Felix Roos 2022-11-08 20:23:30 +01:00
parent 16659c82d2
commit 2c7cc5d325
4 changed files with 31 additions and 14 deletions

View File

@ -24,8 +24,16 @@ export const evalScope = async (...args) => {
Object.assign(globalThis, ...modules, Pattern.prototype.bootstrap());
};
function safeEval(str) {
return Function('"use strict";return (' + str + ')')();
function safeEval(str, options = {}) {
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) => {
@ -35,7 +43,9 @@ export const evaluate = async (code, transpiler) => {
if (transpiler) {
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)) {
console.log('evaluated', evaluated);
const message = `got "${typeof evaluated}" instead of pattern`;

View File

@ -30,7 +30,8 @@ const isNote = (name) => /^[a-gC-G][bs]?[0-9]$/.test(name);
const addLocations = true;
export const addMiniLocations = 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) => {
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)
if (wrappedAsync) {
if (shouldAddReturn) {
addReturn(shifted);
}
const generated = undisguiseImports(codegen(shifted));
@ -153,7 +154,7 @@ ${code}
})()`;
}
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
.slice(0, -1)
.concat([new ReturnStatement({ expression: body.statements.slice(-1)[0] })]);

View File

@ -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 shapeshifter from '../shapeshifter.mjs';
import shapeshifter, { wrappedAsync } from '../shapeshifter.mjs';
describe('shapeshifter', () => {
it('Should shift simple double quote string', () => {
expect(shapeshifter('"c3"')).toEqual('(async()=>{return mini("c3").withMiniLocation([1,0,15],[1,4,19])})()');
});
it('Should handle dynamic imports', () => {
expect(shapeshifter('const { default: foo } = await import(\'https://bar.com/foo.js\');"c3"')).toEqual(
'(async()=>{const{default:foo}=await import("https://bar.com/foo.js");return mini("c3").withMiniLocation([1,64,79],[1,68,83])})()',
);
if (wrappedAsync) {
expect(shapeshifter('"c3"')).toEqual('(async()=>{return mini("c3").withMiniLocation([1,0,15],[1,4,19])})()');
} else {
expect(shapeshifter('"c3"')).toEqual('return mini("c3").withMiniLocation([1,0,0],[1,4,4])');
}
});
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])',
);
});
}
});

View File

@ -4,7 +4,7 @@ import { walk } from 'estree-walker';
import { isNote } from '@strudel.cycles/core';
export function transpiler(input, options = {}) {
const { wrapAsync = true, addReturn = true } = options;
const { wrapAsync = false, addReturn = true } = options;
let ast = parse(input, {
ecmaVersion: 2022,