Skip to content

Check syntax eagerly in vm.Script constructor - #28667

Closed
robobun wants to merge 3 commits into
mainfrom
farm/4b685849/vm-script-syntax-check
Closed

Check syntax eagerly in vm.Script constructor#28667
robobun wants to merge 3 commits into
mainfrom
farm/4b685849/vm-script-syntax-check

Conversation

@robobun

@robobun robobun commented Mar 30, 2026

Copy link
Copy Markdown
Collaborator

Fixes #28666

Problem

vm.Script was not throwing SyntaxError at construction time for invalid JavaScript syntax. The source was stored but only parsed at execution time (runInThisContext, etc.), deferring the error.

Node.js eagerly compiles in the Script constructor, catching syntax errors immediately:

const { Script } = require('vm');
try {
  new Script('Math.max(a, b', { filename: 'main' });
} catch (error) {
  console.log(error.message); // missing ) after argument list
}

Bun silently created the Script object and only threw when runInThisContext() was called.

Fix

Call JSC::checkSyntax() in constructScript() after creating the SourceCode but before creating the NodeVMScript object. This follows the same pattern already used in NodeVM.cpp for compileFunction.

Verification

  • USE_SYSTEM_BUN=1 bun test test/regression/issue/28666.test.ts → 3 fail (bug present)
  • bun bd test test/regression/issue/28666.test.ts → 5 pass
  • bun bd test test/js/node/vm/vm.test.ts → 198 pass, 0 fail

@robobun

robobun commented Mar 30, 2026

Copy link
Copy Markdown
Collaborator Author
Updated 8:06 AM PT - May 5th, 2026

@robobun, your commit 68b2343 has 3 failures in Build #51676 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 28667

That installs a local version of the PR into your bun-28667 executable, so you can run:

bun-28667 --bun

@coderabbitai

coderabbitai Bot commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds an explicit JavaScript syntax validation step to vm.Script construction so invalid source throws a SyntaxError during Script construction. Tests updated to expect constructor-time syntax errors and a new regression suite verifies multiple invalid-source cases and that valid source does not throw.

Changes

Cohort / File(s) Summary
Bindings: vm.Script construction
src/bun.js/bindings/NodeVMScript.cpp
Insert explicit syntax validation via JSC::checkSyntax(vm, source, error) after creating SourceCode; on syntax failure convert ParserError to a JS error, throw it with JSC::throwException(...), and return early to abort script construction.
Tests: node:vm unit test
test/js/node/vm/vm.test.ts
Update assertion so createCachedData() now yields the same SyntaxError raised at construction time for invalid export syntax; existing runInThisContext() expectation remains unchanged.
Tests: regression suite
test/regression/issue/28666.test.ts
Add regression tests validating that new Script(source, { filename }) synchronously throws SyntaxError for several malformed inputs, ensures errors occur at construction time (not deferred), and verifies valid source constructs without throwing.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Check syntax eagerly in vm.Script constructor' directly describes the main change: adding eager syntax validation to the Script constructor.
Description check ✅ Passed The description includes both required sections: 'Problem' explains the issue clearly and 'Fix' describes the solution. However, the 'How did you verify your code works?' template section is renamed 'Verification' with detailed test results provided.
Linked Issues check ✅ Passed The PR fully addresses issue #28666 by implementing eager syntax checking in vm.Script constructor, causing SyntaxError to be thrown at construction time rather than deferred to execution, matching Node.js behavior.
Out of Scope Changes check ✅ Passed All changes are directly related to the issue: syntax validation in NodeVMScript.cpp, test update in vm.test.ts, and new regression test for issue #28666. No unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — the fix is correct and follows established patterns; the inline nit on test 4 doesn't affect correctness.

Extended reasoning...

Overview

The PR adds a call to JSC::checkSyntax() in constructScript() (NodeVMScript.cpp) immediately after creating the SourceCode, before constructing the NodeVMScript object. This mirrors the identical pattern already used for compileFunction in NodeVM.cpp. Two test files are updated: the existing vm.test.ts has one expectation corrected to reflect the new construction-time error, and a new regression test file with 5 tests is added.

Security risks

None. The change adds eager syntax validation that was already happening at run-time; it only moves when the error is surfaced, not whether it is.

Level of scrutiny

Low — this is a small, self-contained correctness fix on a well-tested code path. The pattern is already proven by NodeVM.cpp. All 198 existing vm.test.ts tests continue to pass per the PR description.

Other factors

The one bug flagged is a [Nit]: test 4 of 5 in the regression file wraps both the constructor and runInThisContext() in a single try-catch, so it cannot distinguish construction-time from run-time errors. However, tests 1–3 already cover the construction-time requirement correctly using expect(() => new Script(...)).toThrow(SyntaxError), so regression coverage is intact. The nit is worth fixing but is not a blocker.

Comment thread test/regression/issue/28666.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/regression/issue/28666.test.ts`:
- Around line 22-32: The test currently treats any caught error as success by
calling script.runInThisContext() and marking the test passed on any exception;
instead, assert that a construction-time (compilation) error is thrown by
creating the VM Script itself. Replace the runtime invocation with an explicit
construction/assertion: call new vm.Script(source) (or assert.throws(() => new
vm.Script(source), SyntaxError)) so the test fails if syntax errors are deferred
to runtime, and remove the logic that treats any caught runtime error as a
passing condition.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d69bb7cc-d6ea-422d-935c-fa477a6c507e

📥 Commits

Reviewing files that changed from the base of the PR and between 17616ae and 4088e5dcc4a0ea51e6c880878cd6e8891f8af8e6.

📒 Files selected for processing (3)
  • src/bun.js/bindings/NodeVMScript.cpp
  • test/js/node/vm/vm.test.ts
  • test/regression/issue/28666.test.ts

Comment thread test/regression/issue/28666.test.ts
Comment thread test/js/node/vm/vm.test.ts

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — the fix is correct and follows the established pattern.

Extended reasoning...

Overview

This PR adds 10 lines to src/bun.js/bindings/NodeVMScript.cpp that call JSC::checkSyntax() inside constructScript(), converting a ParserError into a thrown JS exception and aborting construction. This mirrors the identical pattern already present in NodeVM.cpp for compileFunction. Two test files are updated: a test in vm.test.ts that previously expected a createCachedData failed error now expects the correct SyntaxError from construction, and a new regression file test/regression/issue/28666.test.ts adds five targeted tests.

Security risks

None. This change makes error reporting more eager; it does not affect sandbox isolation, permissions, or any security-sensitive code paths.

Level of scrutiny

Low. The change is a small, self-contained addition to a constructor, touches no shared state, and follows a well-established pattern in the same codebase. The regression test suite adequately covers the new behavior.

Other factors

A prior concern I raised (test 4 in 28666.test.ts not distinguishing construction-time from run-time errors) was addressed in commit 7c4b105 via the reachedRun flag approach. A secondary nit I flagged about dead code in vm.test.ts (lines after `new Script("export default {};")" in the lambda) is still present but does not affect test correctness or regression protection — the test passes and the SyntaxError is caught either way.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — both prior concerns addressed, implementation follows established pattern.

Extended reasoning...

Overview

Adds eager syntax validation in 's by calling after the is created but before constructing the object. Three files changed: the C++ binding, an updated unit test in , and a new regression test file for issue #28666.

Security risks

None. This is a correctness fix that makes error behavior match Node.js — errors are surfaced earlier (at construction) rather than later (at execution). No auth, crypto, or permissions code is touched.

Level of scrutiny

Low. The change is small (~10 lines of C++), follows the identical pattern already used in for , and is covered by both the existing vm test suite (198 tests passing per PR description) and new regression tests.

Other factors

Two reviewer concerns were raised and resolved: (1) the flawed test that couldn't distinguish construction-time vs runtime errors — fixed with the flag; (2) dead code in from unreachable / calls — removed in a00a96e. The final state of both test files is clean and correct.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — both test issues from prior reviews are resolved, and the C++ fix follows the established pattern from NodeVM.cpp.

Extended reasoning...

Overview

The PR adds eager syntax checking in NodeVMScript.cpp's constructScript() by calling JSC::checkSyntax(vm, source, error) after SourceCode creation, converting a ParserError into a thrown JS SyntaxError. Two test files are updated: vm.test.ts removes previously-dead runInThisContext/createCachedData calls, and a new regression file 28666.test.ts is added.

Security risks

None. This change only makes errors earlier (construction-time vs. run-time) and does not affect sandboxing, auth, or permissions.

Level of scrutiny

Low. The fix is a small, focused change to a single function in a non-security-critical code path. It mirrors an existing pattern already used in NodeVM.cpp for compileFunction. The previous two review rounds caught and resolved test correctness issues; those fixes are verified in the current diff.

Other factors

Both issues I identified in prior rounds were addressed: the reachedRun sentinel correctly enforces construction-time semantics, and the dead method calls were removed. No bugs were found by the bug hunting system. Tests pass per the PR description (198 pass, 0 fail).

@robobun
robobun force-pushed the farm/4b685849/vm-script-syntax-check branch from 3d49109 to c7aed54 Compare March 30, 2026 14:00

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — prior concerns addressed, implementation is correct.

Extended reasoning...

Overview

The PR adds a single syntax-check call () in after the is created but before the object is allocated. This matches the pattern already used in for . Three files are modified: the C++ binding, an existing vm test, and a new regression test suite.

Security risks

None. The change throws a earlier (at construction time instead of execution time), which is strictly a bug-fix alignment with Node.js behavior. No new attack surface is introduced.

Level of scrutiny

Low. The change is small, self-contained, and follows an established in-repo pattern. The regression test covers multiple invalid-syntax cases and a valid-syntax non-throw case.

Other factors

Two test-quality issues I flagged in earlier reviews were both fixed prior to this review: the construction-time distinction is now enforced via a reachedRun flag, and dead method calls after a throwing constructor were removed. No bugs were found by the automated bug-hunting system. CI is passing.

@robobun
robobun force-pushed the farm/4b685849/vm-script-syntax-check branch from c7aed54 to d2fb91f Compare March 30, 2026 14:37

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — the core fix correctly mirrors the pattern.

Extended reasoning...

Overview

PR adds call in (NodeVMScript.cpp) between SourceCode creation and NodeVMScript object creation, matching the existing pattern in NodeVM.cpp for compileFunction. Changes touch NodeVMScript.cpp, the existing vm.test.ts test, and a new regression suite (28666.test.ts).

Security risks

None. The change adds a syntax-validation step that rejects invalid source earlier; it does not alter sandbox isolation, permissions, or data exposure.

Level of scrutiny

Low. This is a small, well-scoped C++ change (~10 lines) following an already-established pattern. The regression test file properly validates construction-time throwing (the reachedRun flag correctly enforces the regression boundary). The only outstanding item is a nit (missing ASSERT(error.isValid())) already posted as an inline comment.

Other factors

Prior feedback I left was addressed: the test-validity issue on 28666.test.ts was fixed with the reachedRun flag. The dead-code note on vm.test.ts was acknowledged but the calls remain; however, the tests still pass and the regression is correctly caught by the other tests. Both residual items are defensive-programming nits that do not affect correctness.

Comment thread src/jsc/bindings/NodeVMScript.cpp
@robobun
robobun force-pushed the farm/4b685849/vm-script-syntax-check branch from d2fb91f to 5ca28b2 Compare March 30, 2026 15:00

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Extended reasoning...

Overview

This PR adds eager syntax validation to vm.Script's constructor by calling JSC::checkSyntax() after creating the SourceCode object but before constructing the NodeVMScript instance. It fixes issue #28666 where Bun deferred syntax errors to execution time instead of throwing at construction, diverging from Node.js behavior.

Modified files: NodeVMScript.cpp (core fix), test/js/node/vm/vm.test.ts (updated assertion), test/regression/issue/28666.test.ts (new regression tests).

Security risks

None. This is a JavaScript VM behavior compatibility fix with no authentication, crypto, or permission-sensitive code involved.

Level of scrutiny

Low-to-medium. The change is a self-contained, well-scoped addition following an established pattern already used in NodeVM.cpp for compileFunction. The ASSERT(error.isValid()) guard (matching the analogous call site) was added after my prior review.

Other factors

All three issues I raised in prior reviews have been addressed: the misleading threwAtConstruction pattern in the regression test (fixed with reachedRun flag), the missing ASSERT(error.isValid()), and the test assertion message update. The remaining dead code (runInThisContext() / createCachedData() calls on lines 694/699 of vm.test.ts) is a test-clarity nit — the tests remain functionally correct since the constructor throws and .toThrow() catches it as expected. Regression coverage is adequate.

@robobun
robobun force-pushed the farm/4b685849/vm-script-syntax-check branch from 5ca28b2 to d6aa759 Compare March 30, 2026 15:34

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — all previously flagged issues have been addressed.

Extended reasoning...

Overview

This PR adds eager syntax validation to the vm.Script constructor by calling JSC::checkSyntax() on the SourceCode before creating the NodeVMScript object. Three files are touched: the C++ constructor (NodeVMScript.cpp), an existing vm test (vm.test.ts), and a new regression suite (28666.test.ts).

Security risks

No security-sensitive code paths are affected. The change narrows the error surface (syntax errors surface earlier) and does not touch auth, crypto, or permissions.

Level of scrutiny

This is a focused correctness fix for a Node.js compatibility gap. The pattern precisely mirrors what NodeVM.cpp already does for compileFunction. The risk is low — the only observable behavior change is that new Script(invalidSyntax) now throws instead of succeeding silently.

Other factors

All three issues from my prior reviews were resolved: the reachedRun flag correctly enforces the construction-time assertion, the dead runtime-method calls were removed, and ASSERT(error.isValid()) was added to match the established codebase pattern. The remaining open bug report is a performance nit (double-parse) that is an acknowledged tradeoff of this approach and is suitable as a follow-up.

Comment on lines +134 to +142
{
JSC::ParserError error;
if (!JSC::checkSyntax(vm, source, error)) {
ASSERT(error.isValid());
auto exception = error.toErrorObject(globalObject, source);
RETURN_IF_EXCEPTION(scope, {});
JSC::throwException(globalObject, scope, exception);
return {};
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Every followed by execution now incurs two full JSC parses instead of one: in the constructor fully parses the source and discards the AST, then re-parses from scratch at run time. Pre-fix Bun did one parse (at run time); Node.js/V8 does one compile at construction time and reuses cached bytecode — this PR is strictly worse than both for the common case of valid scripts that are executed.

Extended reasoning...

What the bug is and how it manifests

The new call added to (NodeVMScript.cpp lines 134–142) performs a full source parse internally — it calls the JSC parser, builds a complete AST, validates it, and then discards everything. When the script is later executed via , , or , creates a new and re-parses the same source from scratch to produce bytecode. This means every object that is created and then run now incurs two full parses instead of one.

The specific code path that triggers it

  1. calls → JSC parser runs a full pass, builds an AST, returns true/false, discards the AST.
  2. Later, calls → JSC creates a new , re-parses the same source string via the same parser path, and compiles to bytecode.
    There is no mechanism to pass any intermediate representation between these two calls.

Why existing code doesn't prevent it / addressing the refutation

The refutation suggests "JSC may have internal caching that mitigates the double-parse cost." JSC does have a that caches bytecode keyed by source. However, does NOT produce bytecode — it produces only a parsed AST that is immediately discarded. The sourceProviderCache is populated only by successful compilation (via or similar). Therefore, the cache cannot be populated by , and the second parse in is a full cold parse. The double-parse is confirmed real.

The refutation is correct that this is intentional and mirrors the pattern in NodeVM.cpp. This is a known tradeoff accepted by the PR author to achieve eager correctness checking. It is not a hidden defect.

What the impact would be

For valid scripts (the common case — invalid scripts throw at construction and are never run), every construction + execution now costs ~2× the parsing work compared to pre-fix Bun. For large scripts or hot paths that create many instances (template engines, test runners, repeated patterns), this is a measurable regression. Node.js/V8 avoids this entirely by eagerly compiling in the constructor (producing cacheable bytecode), so V8 does one compile and zero re-parses on execution. Pre-fix Bun did one parse (deferred to run time). This PR makes Bun do two parses for every valid script that gets executed.

How to fix it and step-by-step proof

The correct fix is to replace + discard with an eager compile that stores the resulting or its bytecode for reuse by subsequent calls — matching Node.js/V8 behavior. This is a larger change outside this PR's scope and is noted as a follow-up in the synthesis description. A concrete step-by-step showing the regression: (1) is called; (2) parses , builds AST, returns , AST is freed; (3) the object is created storing only the string; (4) is called; (5) creates a fresh , parses again from the source string, compiles to bytecode, runs it. Two parses for one script execution — where pre-fix Bun did one and Node.js does zero (after construction-time compile).

@robobun
robobun force-pushed the farm/4b685849/vm-script-syntax-check branch from d6aa759 to b0a60b7 Compare March 30, 2026 16:10
@robobun
robobun force-pushed the farm/4b685849/vm-script-syntax-check branch from b0a60b7 to febc56a Compare May 4, 2026 21:19
Comment on lines +1 to +2
import { expect, test } from "bun:test";
import { Script } from "node:vm";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Per root CLAUDE.md (line 66) and test/CLAUDE.md (line 153), test/regression/issue/${issueNumber}.test.ts is reserved for true regressions — behavior that worked in a previous release and then broke. Issue #28666 is a Node.js-compat gap (vm.Script never eagerly checked syntax in any prior Bun release), so these five tests belong in test/js/node/vm/vm.test.ts, which this PR already modifies.

Extended reasoning...

What the issue is

Both governing CLAUDE.md files for this directory tree state the same rule:

  • CLAUDE.md line 66: "test/regression/issue/${issueNumber}.test.ts is reserved for bugs that have a GitHub issue number and are true regressions (worked in a previous release, then broke). An issue number alone is not enough — if the behavior was never correct, it's not a regression and the test belongs in the existing file for that module."
  • test/CLAUDE.md line 153: "An issue number alone does not qualify — if it was never correct, put the test in the module's existing test file instead."

Issue #28666 is not a regression. The PR description itself states "The source was stored but only parsed at execution time" and "Bun silently created the Script object" — i.e., the eager syntax check never existed in any prior Bun release. The pre-PR assertion in vm.test.ts (createCachedData() throwing "createCachedData failed" rather than the constructor throwing) confirms the constructor never threw before. This is a never-implemented Node.js-compat behavior, not something that worked and then broke.

Why the convention matters here

The repo's documented intent is that compat-gap coverage lives alongside the module's other tests so future readers find all vm.Script behavior in one place, and so test/regression/issue/ remains a clean signal of "this once worked, don't let it break again." Filing compat gaps under regression/ dilutes that signal.

Addressing the objection

One reviewer noted that test/regression/issue/ already contains many compat-gap tests, suggesting loose enforcement, and that file placement is purely stylistic. That is true historically, but the rule is now explicitly documented in two CLAUDE.md files — including the very sentence "An issue number alone does not qualify" — which exists precisely to stop new instances of this pattern. Since this PR already touches test/js/node/vm/vm.test.ts, moving the five tests there is essentially zero-cost. This is not a functional defect, hence nit severity, but it is a documented convention being newly violated rather than a pre-existing one.

Step-by-step

  1. test/regression/issue/28666.test.ts is created with 5 tests covering construction-time SyntaxError behavior.
  2. Per CLAUDE.md:66 and test/CLAUDE.md:153, this path is reserved for behavior that worked in a prior release and then broke.
  3. new Script(invalidSource) has never thrown at construction time in any released Bun — confirmed by the pre-PR vm.test.ts expectation and the PR's own problem statement.
  4. Therefore Bun does not throw when using invalid Syntax within vm.Script #28666 is a compat gap, not a regression, and the tests belong in test/js/node/vm/vm.test.ts.

How to fix

Move the five test cases from test/regression/issue/28666.test.ts into test/js/node/vm/vm.test.ts (e.g., a describe("Script constructor syntax checking", ...) block near the existing "can't use export syntax in vm.Script" test) and delete the new regression file.

@robobun

robobun commented May 5, 2026

Copy link
Copy Markdown
Collaborator Author

CI infrastructure has been unreliable on this PR — most recent build (#51555) has most jobs "Expired" due to Buildkite queue timeouts (not code failures). Previous builds had different Windows test runners flake with exit status 2, while other runners passed.

Local verification:

  • bun bd succeeds on Linux
  • bun bd test test/regression/issue/28666.test.ts test/js/node/vm/vm.test.ts → 203 pass, 0 fail (10+ runs)
  • Only 12 lines of C++ added (JSC::checkSyntax() call in vm.Script constructor), mirroring existing pattern in NodeVM.cpp for compileFunction.

The fix itself is correct and tested; awaiting stable CI run.

robobun added 2 commits May 5, 2026 06:10
vm.Script was deferring syntax checking to execution time. Node.js checks
syntax at construction time and throws SyntaxError immediately. Add a
checkSyntax call in the Script constructor to match.

Fixes #28666
Constructor now throws SyntaxError before createCachedData is reached.
@robobun
robobun force-pushed the farm/4b685849/vm-script-syntax-check branch from 1a5e330 to 1a654fd Compare May 5, 2026 06:13
@robobun

robobun commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator Author

#28666 was fixed on main by #31827: vm.Script now runs JSC::checkSyntax in the constructor (see the issue's closing comment), which is the same change this PR makes.

This PR's test/regression/issue/28666.test.ts passes on current main (165dc9f) without this change (5 pass, 0 fail), and main's test/js/node/vm/vm.test.ts already carries the same assertion ("throws SyntaxError at construction like Node"). The one-line vm.test.ts change here conflicts with main, which rewrote that test for eager parsing.

Closing as already landed.

@robobun robobun closed this Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bun does not throw when using invalid Syntax within vm.Script

1 participant