refactor(stdlib): remove mysql2 native binding - #10680
proggeramlug wants to merge 3 commits into
Conversation
Deletes perry-ext-mysql2 (the well-known-table crate that provided js_mysql2_* symbols for plain `import mysql from "mysql2"`) and perry-stdlib/src/mysql2/ (a second, duplicate hand-written mysql2 implementation gated behind the bundled-mysql2 feature). Removes the supporting registry wiring: well_known_bindings.toml, NATIVE_MODULES / manifest entries in perry-api-manifest, the native_table/databases.rs MySQL2 codegen rows, ext_registry.rs FFI routing, the bundled-mysql2 HIR heuristic for bundler-inlined mysql2 (superseded by #10675's dyn_eval class-expression support), stdlib_features.rs / optimized_libs driver+freshness wiring, workspace-architecture.json, and the unrooted-local-shape baseline entries for the deleted files. Based on wip/10661-dyn-eval-class-expr (#10675) — mysql2 does not compile from real source without that fix.
…docs) - cargo fmt after the removal (entries.rs / resolve.rs realignment) - drop the two explicit -p perry-ext-mysql2 args from .github/workflows/test.yml (compile-smoke + UI-backend jobs) and from run_doc_tests.sh/.ps1 - drop the 14 js_mysql2_* rows from scripts/native_result_ledger.tsv and update its EXPECTED_ROWS/EXPECTED_PROVIDERS counts (343/308) - refresh workspace-architecture.json's baseline counts (82 members, externalize=32) so scripts/workspace_architecture.py --check passes - rewrite scripts/string_payload_access_baseline.txt via --write-baseline (perry-ext-mysql2 row dropped, perry-stdlib 40 -> 38) - regenerate docs/src/api/reference.md, docs/api/perry.d.ts, and docs/src/native-libraries/governance.md's generated table; add a "Completed source migrations" entry for mysql2 run_lint_gates.sh (SKIP_COMPILE_GATES=1): 76/77 passed, only the pre-existing "Public benchmark evidence freshness" red.
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Heads-up before this is queued: this PR's recorded workspace baseline is stale and will fail It records Full table and reasoning in #10739. The short version, for whoever rebases this:
Also relevant to the acceptance run whenever it happens: #10735 is live on main — |
Summary
Removes the mysql2 native binding so
import mysql from "mysql2"resolves tothe real npm package, per the owner's decision to stop shipping hand-written
Rust reimplementations of npm packages (they drift from the real thing — see
the
jsonwebtoken.verifyexample in the campaign background).Must not merge before #10675 (
wip/10661-dyn-eval-class-expr, this PR'sbase). mysql2's real source does not compile without that PR's
dyn_evalclass-expression support —
generate-functionbuilds mysql2's row parserswith a runtime
new Function(...)that returns a class expression.What was removed and why
Two candidate locations turned out to be genuinely separate, both hand-written
reimplementations of mysql2 using
sqlxdirectly:crates/perry-ext-mysql2— the governance-tracked binding(
docs/src/native-libraries/governance.md: "Source package", target"Compile the upstream package source"). Wired into
well_known_bindings.toml's[bindings.mysql2]/[bindings."mysql2/promise"],and the crate a plain
import mysql from "mysql2"(nocompilePackages)actually linked against.
crates/perry-stdlib/src/mysql2/(~1870 lines) — a second,independent mysql2 implementation gated behind perry-stdlib's
bundled-mysql2feature (default-on viafull). It defined the exact samejs_mysql2_*symbol names as perry-ext-mysql2, in a separate handleregistry (perry-ffi's handle table and perry-stdlib's
common::handletable are explicitly documented as disjoint integer spaces — see
crates/perry-ffi/src/handle.rs). Itsdispatch_mysql2_method/dispatch_mysql2_propertydynamic-dispatch fallback (for Drizzle'sinterface-typed client fields) could only ever resolve handles created by
its own
js_mysql2_create_connection/createPool— which lose the linkto whichever archive the linker picks between two archives exporting the
same symbol names. In the default (
full) feature build both crates shipjs_mysql2_*, so this was already a live footgun, not merely inert.Both were removed. Neither is separable from "the mysql2 native binding"
— they are the same category of hand-written duplicate the campaign targets,
just delivered through two different mechanisms (well-known ext-crate flip vs.
a default-on stdlib feature).
Also removed the
bundled-mysql2HIR heuristic inperry-hir/src/lower/expr_call/native_module.rs(mysql2_config_signature/detect_bundled_mysql2_create) that recognized a bundler-inlined(webpack/turbopack)
createPool/createConnectioncall by its config-objectshape and routed it to
perry-ext-mysql2's FFI symbols. That workaroundexisted only because the AOT binary couldn't run mysql2's
generate-functionrow parsers; #10675 fixes that generally via
dyn_eval, so the heuristic (andits
bundled_mysql2_testsmodule, trimmed rather than deleted — it alsocovered an unrelated
is_process_active_array_helpertest, kept under arenamed
native_module_helper_testsmod) is no longer needed.Left alone, deliberately: a handful of shared perry-hir files
(
local_natives.rs,native_new.rs,native_fetch.rs,misc.rs,module_decl.rs,static_and_instance.rs) still pattern-match on the stringliterals
"mysql2"/"mysql2/promise"for class-shape inference (e.g.tagging
createPool()'s result as aPool). These are now structurallyunreachable — the only two producers of a
NativeMethodCall/NativeModuleRefwith that module string were
NATIVE_MODULESmembership (removed) and thebundled-heuristic above (removed) — but hand-editing every multi-package match
arm in files shared with the concurrent axios/pg removal branches risked a
larger, conflict-prone diff for no behavioral change. Also left alone:
prose comments across perry-runtime/perry-codegen that cite real mysql2
source shapes (
MockBuffer,generate-function, drizzle transactions) asmotivating examples for unrelated compiler features — those describe why the
compiler behaves a certain way, not the binding being removed.
Registries and gates touched
crates/perry/well_known_bindings.toml— drop[bindings.mysql2]/[bindings."mysql2/promise"]crates/perry-api-manifest/src/entries.rs(+entries/part_1.rs,entries/part_3.rs) — dropNATIVE_MODULESentries and all mysql2manifest rows
crates/perry-codegen/src/lower_call/native_table/databases.rs— drop theMySQL2NativeModSigsectioncrates/perry-codegen/src/ext_registry.rs— drop the mysql2FFI_REGISTRYrows
crates/perry/src/commands/stdlib_features.rs,optimized_libs/driver.rs,optimized_libs/freshness.rs— drop themysql2→bundled-mysql2wiringcrates/perry/src/commands/compile/resolve.rs—PERRY_NATIVE_EXTENSION_PACKAGES(this is what let mysql2's real.jssource reach the module walker instead of being silently skipped as
"handled by native stdlib")
workspace-architecture.json— drop theperry-ext-mysql2decision entryand refresh the baseline counts (
workspace_members,externalize)scripts/unrooted_local_shape_baseline.json,scripts/string_payload_access_baseline.txt,scripts/native_result_ledger.tsv(+EXPECTED_ROWS/EXPECTED_PROVIDERSin
native_result_ledger.py) — drop entries for the deleted files/symbols.github/workflows/test.yml,scripts/run_doc_tests.sh/.ps1— drop the twoexplicit
-p perry-ext-mysql2cargo build args (compile-smoke + UI-backendjobs, doc-tests harness); these would otherwise fail with "no such package"
crates/perry-ui-android/src/stdlib_stubs.rs— drop the 14js_mysql2_*Android stub exports
docs/src/api/reference.md,docs/api/perry.d.ts— regenerated(
--print-api-manifest)docs/src/native-libraries/governance.md— regenerated table (drops theperry-ext-mysql2row) + a new "Completed source migrations" bullet,matching the existing
slugifyentry's patterncrates/perry/src/commands/compile/collect_modules/binding_faithfulness.rs— dropped
lookup_preserves_registered_subpaths_before_falling_back, theone test whose only real-world fixture (
mysql2/promise'salias-of = "mysql2") no longer exists inwell_known_bindings.toml(itwas the only root+subpath alias in the whole table); the sibling test
using
"mysql2"as an arbitrary on-disk-directory fixture name is untouchedsince it doesn't depend on the registry.
Acceptance test: real query round-trip, no
compilePackagesentryBuilt on the perrymaster host (
--profile perry-dev,-p perry -p perry-runtime-static -p perry-stdlib-static, thenPERRY_WORKSPACE_ROOTsetso auto-optimize could pull in the wrapper crates the real mysql2 source
needs —
perry-wasm-host,perry-ext-net,perry-ext-events,perry-ext-zlib). Test program:with
package.json:{ "dependencies": { "mysql2": "^3" } }No
perry.compilePackagesentry at all — not formysql2, not for itstransitive deps. Compile log:
Compile package wildcard: expanded to 60 installed package(s)(Perry's default automatic package-routing path,already used by the
slugifymigration) compiled real mysql2 + itsdependency tree (
generate-function,iconv-lite,long,lru.min,named-placeholders,sql-escaper,aws-ssl-profiles, ...) from source.One informational notice:
generate-function/index.js:362's runtimenew Function(...)— mysql2's row-parser factory — was "handled at runtime:runtime interpreter (#6559)", i.e.
dyn_eval, exactly the mechanism #10675added.
Ran the resulting binary against the real local MySQL 8.0.46 server:
CREATE TABLE/INSERT/SELECT/DROP TABLEall round-tripped with thereal row parser, real wire protocol, real auth handshake.
Verification
cargo check/cargo build --profile perry-dev -p perry -p perry-runtime-static -p perry-stdlib-static: clean (confirmed.amtimesmoved after the edits)
cargo test -p perry-api-manifest -p perry-hir: all passingcargo test -p perry-codegen --test manifest_consistency: all 5 passing(
every_native_module_has_at_least_one_manifest_entry,every_dispatch_entry_has_manifest_counterpart, etc.) — confirms theregistry edits are internally consistent
python3 scripts/binding_governance.py --check: OK (39 extension cratesclassified)
node scripts/binding_pins.mjs --check: OK (37 pinned, lock-step holds)scripts/run_lint_gates.sh(SKIP_COMPILE_GATES=1): 76 of 77 passed.The one failure, "Public benchmark evidence freshness", is pre-existing on
every PR in this repo (per the campaign's own fix-agent contract) — not
touched here.
Not run / out of scope
run_lint_gates.sh(known-red on Linux per the campaigncontract; not run)
ran the targeted registry/consistency tests instead
CLAUDE.mdedit — per this campaign's convention, themaintainer bumps at merge time