Skip to content

Commit

Permalink
codegen: rewrite literal eval hack to allow indirect
Browse files Browse the repository at this point in the history
test262: 55.75% (+0.20) | πŸ§ͺ 50259 | 🀠 28020 (+100) | ❌ 7293 (+90) | πŸ’€ 13726 (-191) | πŸ—οΈ 32 | πŸ’₯ 177 | ⏰ 11 | πŸ“ 1000 (+1)
  • Loading branch information
CanadaHonk committed Jan 6, 2025
1 parent 9a70d63 commit 3601eb0
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 13 deletions.
35 changes: 25 additions & 10 deletions compiler/codegen.js
Original file line number Diff line number Diff line change
Expand Up @@ -2037,15 +2037,18 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
name = func.name;
}

if (!decl._new && name === 'eval') {
if (!decl._new && (name === 'eval' || (decl.callee.type === 'SequenceExpression' && decl.callee.expressions.at(-1)?.name === 'eval'))) {
const known = knownValue(scope, decl.arguments[0]);
if (known !== unknownValue) {
// known value literal eval hack
// eval('with known/literal string')
const code = String(known);

let parsed;
try {
parsed = objectHack(parse(code));
parsed = {
type: 'BlockStatement',
body: parse(code).body.map(objectHack)
};
} catch (e) {
if (e.name === 'SyntaxError') {
// throw syntax errors of evals at runtime instead
Expand All @@ -2055,11 +2058,24 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
throw e;
}

if (decl.callee.type === 'SequenceExpression' || decl.optional) {
// indirect, use separate func+scope
const [ func ] = generateFunc({}, {
type: 'ArrowFunctionExpression',
body: parsed,
expression: true
}, true);

func.generate();

return [
[ Opcodes.call, func.index ],
...setLastType(scope)
];
}

scope.inEval = true;
const out = generate(scope, {
type: 'BlockStatement',
body: parsed.body
});
const out = generate(scope, parsed);
scope.inEval = false;

out.push(...setLastType(scope, getNodeType(scope, getLastNode(parsed.body))));
Expand All @@ -2070,7 +2086,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
if (name === 'Function') {
const known = knownValue(scope, decl.arguments[0]);
if (known !== unknownValue) {
// known value literal Function hack
// new Function('with known/literal string')
const code = String(known);

let parsed;
Expand Down Expand Up @@ -6484,8 +6500,7 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
start: decl.start,
locals: {},
localInd: 0,
// value, type
returns: [ valtypeBinary, Valtype.i32 ],
returns: [ valtypeBinary, Valtype.i32 ], // value, type
name,
index: currentFuncIndex++,
arrow,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "porffor",
"description": "a basic experimental wip aot optimizing js -> wasm engine/compiler/runtime in js",
"version": "0.55.12",
"version": "0.55.13",
"author": "CanadaHonk",
"license": "MIT",
"scripts": {},
Expand Down
2 changes: 1 addition & 1 deletion runner/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env node
import fs from 'node:fs';
globalThis.version = '0.55.12';
globalThis.version = '0.55.13';

// deno compat
if (typeof process === 'undefined' && typeof Deno !== 'undefined') {
Expand Down
2 changes: 1 addition & 1 deletion test262/history.json

Large diffs are not rendered by default.

0 comments on commit 3601eb0

Please sign in to comment.