Skip to content

Function(...), Function.apply(...) and Function.call(...) with a runtime body compile to a stub that always throws, while the notice says "→ runtime interpreter" #10422

Closed

Description

@proggeramlug

Found by the package audit (compiling real npm packages from source instead of Perry's native bindings) on
Perry e6dcb62 (v0.5.1587), Linux x64. With a runtime-built body, new Function(p, body) runs through the #6559 interpreter. The call-without-new spellings Function(p, body), Function.apply(null, [...]) and Function.call(null, ...) are compiled to a function that always throws "new Function() cannot run in an ahead-of-time compiled binary", even though the runtime has the interpreter and the end-of-build notice says these sites go to it.

Reproduction

main.ts:

const body = ["return a", "+", "b"].join(" "); // any runtime-built body
const t = (label: string, mk: () => any) => {
  try { console.log(label, mk()(2, 3)); } catch (e) { console.log(label, "THREW", String(e)); }
};
t("new Function(a, b, body)      ", () => new Function("a", "b", body));
t("Function(a, b, body)          ", () => Function("a", "b", body));
t("Function.apply(null, [a,b,body])", () => Function.apply(null, ["a", "b", body]));
t("Function.call(null, a, b, body)", () => Function.call(null, "a", "b", body));
perry compile main.ts -o out && ./out
PERRY_NO_AUTO_OPTIMIZE=1 perry compile main.ts -o out2 && ./out2   # identical result

Expected (Node 26.5.1)

new Function(a, b, body)       5
Function(a, b, body)           5
Function.apply(null, [a,b,body]) 5
Function.call(null, a, b, body) 5

Actual (Perry)

Compile-time notice (both modes):

notice: 4 ahead-of-time-unsupported sites handled at runtime:
  - Function(...)          main.ts:6   → runtime interpreter (#6559)
  - Function(...)          main.ts:7   → runtime interpreter (#6559)
  - Function(...)          main.ts:8   → runtime interpreter (#6559)
  - new Function(...)      main.ts:5   → runtime interpreter (#6559)

Run (both modes; <dir> stands for the absolute project path):

new Function(a, b, body)       5
Function(a, b, body)           THREW Error: new Function() cannot run in an ahead-of-time compiled binary (<dir>/main.ts:6)
Function.apply(null, [a,b,body]) THREW Error: new Function() cannot run in an ahead-of-time compiled binary (<dir>/main.ts:7)
Function.call(null, a, b, body) THREW Error: new Function() cannot run in an ahead-of-time compiled binary (<dir>/main.ts:8)

The new Function line in the same binary shows that the interpreter is linked.

Impact

Notes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    package-auditFound by the 2026 package audit: compiling real npm packages from source instead of native bindings

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions