SIGN IN SIGN UP

core: externalize the JS prelude to core/js/prelude.js + a derived-globals lint gate (#52)

A2 from the core stabilization audit (#49).

1,824 lines of JavaScript lived inside a Rust string literal in v8host.rs --
the JS half of the entire plugin-facing API. A JS-only change was reviewed as
a Rust diff, no editor tooling saw it, and nothing checked that it only calls
natives Rust actually registers. v8host.rs: 19,268 -> 17,453 lines.

The prelude runs in a BARE V8 context, so the only callable globals are the
~218 natives core installs. Referencing one that does not exist is a silent
runtime failure on whichever path happens to hit it. core/js/eslint.config.mjs
therefore DERIVES its globals from core's own source (regexing set_native out
of v8host.rs at config-load time) rather than hand-listing them, which would
drift and reduce the gate to decoration; it throws if the regex matches
nothing. That makes the gate bidirectional, verified by mutation: a JS typo
and a Rust-side rename with stale JS both fail no-undef.

Moved verbatim except for one deliberate difference: the old r#" literal
opened with a newline, shifting every V8-reported line by one. The file starts
at globalThis.HookResult, so file line N is now V8 line N. Otherwise identical
to git show origin/main:core/src/v8host.rs | sed -n '1193,3016p'.

ONE file, not one per module: the body shares a single IIFE scope and later
sections reference earlier declarations, so a split would make concatenation
order silently load-bearing. Worth doing once this gate exists to catch scope
breakage -- not in the same PR as the move.

include_str! keeps the binary self-contained: nothing is read at runtime, so a
missing file is a build error, never a boot-time degrade.

eslint was present only via workspace hoisting; declared at the root and
pinned EXACT (10.7.0) because ^10.7.0 resolved to 10.8.0 and dragged
@eslint/config-helpers 0.6.0 -> 0.7.0 along -- a refactor PR should not bump
what the SDK builds against.

cargo test -p s2script-core: 463 passed (the in-isolate tests smoke-eval the
prelude in every context). CI=1 make ci: green.
G
Gabriel Hirakawa committed
723491969bc7de1ed2689c9bcb03b0ab61cefe2e
Parent: c032e32
Committed by GitHub <noreply@github.com> on 8/1/2026, 5:55:40 AM