refactor(stdlib): remove uuid native binding - #10701
proggeramlug wants to merge 2 commits into
Conversation
|
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (1)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (13)
💤 Files with no reviewable changes (8)
🚧 Files skipped from review as they are similar to previous changes (2)
Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review. 📝 WalkthroughWalkthroughThe pull request removes the bundled native ChangesUUID Binding Removal
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~10 minutes Change: Refactor Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 2⚔️ Resolve merge conflicts 💡
🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks 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 |
5ade053 to
067f2ae
Compare
Removes the native uuid binding so `import { v4, parse, stringify, NIL }
from "uuid"` (no perry.compilePackages entry) resolves to the real npm
package compiled from source, per the owner's decision to stop shipping
hand-written Rust reimplementations of npm packages.
The native binding is missing `parse`/`stringify` entirely (a
`parse`/`stringify` roundtrip throws: `bytes` comes back `undefined`),
and `NIL` reads as `undefined` (js_uuid_nil exists in the deleted source
but was never wired into either NativeModSig dispatch table or the API
manifest, so property access on the uuid module namespace fell through
to undefined). v1/v3/v4/v5/validate/version were correct in both.
Per #10678 (duplicate extern "C" exports across perry-ext-*/perry-stdlib
pairs), this binding existed twice: crates/perry-ext-uuid/ (the
governance-tracked binding crate) and crates/perry-stdlib/src/uuid.rs (a
second, independent implementation behind the now-removed bundled-uuid
feature). Both are deleted, along with the 7-entry NativeModSig dispatch
block in native_table/utils_crypto.rs, the well_known_bindings.toml
entry, the "uuid" NATIVE_MODULES entry and its 7 manifest rows, and the
6 Android stub exports.
crypto/random.rs entanglement: crypto.randomUUID()/randomUUID({v7:true})
and nodemailer's message-id generation both call the `uuid` Cargo crate
(uuid::Uuid::new_v4()/now_v7()) directly and unconditionally — neither
site has a cfg(feature) gate. The `uuid` crate dependency in
perry-stdlib/Cargo.toml was therefore never actually optional in
practice even though it was declared `optional = true` behind the
bundled-uuid npm-binding feature; removing that feature without also
dropping `optional = true` would have broken the build the moment
bundled-uuid stopped being enabled. Made `uuid` a required (non-optional)
dependency and retargeted the `ids` feature umbrella to
`["bundled-nanoid"]`. crypto.randomUUID()/randomUUID({v7:true}) and
node:crypto's randomBytes are unaffected — verified below.
Retargeted the one dts-shape regression test that used uuid.v4() as its
zero-arg-module-function fixture (perry-api-manifest's
dts_uuid_v4_has_no_args) to perry/gc.minor(), which is unrelated to any
binding-removal churn.
Built on perrymaster (--profile perry-dev). A real `npm install uuid`
project (no perry.compilePackages entry) exercising v1/v4/v5/v3,
validate/version, a parse/stringify roundtrip, and NIL, diffed against
`node --experimental-strip-types` (Node 26.5.1): byte-for-byte identical,
including the deterministic v5/v3 (name+namespace) values. Confirmed
against a pristine origin/main (8df83f8) baseline build that the same
program crashes there: `NIL: undefined`, `parse instanceof Uint8Array:
false`, then `TypeError: Cannot read properties of undefined (reading
'length')` on the roundtrip — reproducing the reported bug exactly.
crypto.randomUUID() and node:crypto's randomBytes/randomUUID were
re-checked against the fix and still work (both call the `uuid` crate
directly, unaffected by the binding removal).
- cargo build --profile perry-dev -p perry -p perry-runtime-static -p
perry-stdlib-static: clean; confirmed .a mtimes moved.
- cargo check --workspace --all-targets (host-compatible exclusion set
via workspace_architecture.py --print-excluded-scope) under
-D warnings: clean.
- cargo test -p perry-api-manifest: 39+4 passing (after retargeting the
uuid-fixture test).
- cargo test -p perry-codegen --test manifest_consistency: 5/5 passing.
- cargo test -p perry --bin perry -- well_known: 27/27 passing.
- cargo test -p perry-hir: full suite passing (test_lower_native_module_
registration uses "uuid" only as synthetic example data for a generic
register/lookup mechanism — unaffected by the registry removal).
- python3 scripts/binding_governance.py --check: OK (39 extension
crates).
- node scripts/binding_pins.mjs --check: OK (37 pinned, lock-step
holds).
- python3 scripts/workspace_architecture.py --check: OK.
- python3 scripts/native_result_ledger.py: OK, 371 rows/322 providers
unchanged (none of uuid's dispatch rows used a ledger-tracked NR_*
kind).
- python3 scripts/string_payload_access_inventory.py --write-baseline:
perry-stdlib inline-offset 40 -> 38 (uuid.rs's own 2 sites).
- Regenerated docs/api/perry.d.ts + docs/src/api/reference.md
(perry --print-api-manifest) and docs/src/native-libraries/
governance.md (binding_governance.py --table) from the fixed manifest.
- cargo fmt --all -- --check: clean.
- scripts/run_lint_gates.sh (SKIP_COMPILE_GATES=1): 76 of 77 passed; the
one failure (Public benchmark evidence freshness) is the pre-existing,
known-red-on-every-PR gate per this campaign's contract.
- Compile tier of run_lint_gates.sh (known-red on Linux per this
campaign's contract).
- Full gap suite (host stalls under auto-optimize per contract).
- test-files/test_parity_uuid.ts is already excluded from the parity
gate (test-parity/known_failures.json, "ci-env": Node's own oracle run
fails ERR_MODULE_NOT_FOUND because uuid was never added to the repo's
root package.json/package-lock.json — the same pre-existing gap
documented for nanoid, #8271). Its `@covers` comment now points at a
deleted file (crates/perry-stdlib/src/uuid.rs); leaving it untouched,
matching how the sibling nanoid PR (#10693) left its own equivalent
parity fixture alone.
- No version bump / CLAUDE.md edit — per this campaign's convention, the
maintainer bumps at merge time.
- crates/perry-ui-android/src/stdlib_stubs.rs was edited to remove the
matching 6 js_uuid_* stub exports (following the established pattern
from the sibling removals) but not build-verified — this host has no
Android NDK and the package is excluded from the host-compatible
check scope.
067f2ae to
7bc717c
Compare
|
Landed in merge train 225 (#10748), released as v0.5.1604 — main is now Closing rather than merging is how trains work here: both PRs were cherry-picked onto one tree, validated together, and landed under the train's own commit, so GitHub cannot mark this one merged even though your change is on main. Verified after the merge: For #10701 specifically: both of its conflicts were absolute-count files, which auto-merge cleanly while being wrong. Resolved by re-derivation against the assembled tree rather than hand-merge — Validation: all nine cheap gates, |
customAlphabet(alphabet, size) is documented to return a generator function; native customAlphabet instead returns the generated id string directly (js_nanoid_custom's own doc comment: "For simplicity, we combine this into one call"), so the only documented usage -- const gen = customAlphabet(...); gen(); -- crashes with TypeError: value is not a function. Per #10678 (duplicate extern "C" exports across perry-ext-*/perry-stdlib pairs), this binding existed twice: crates/perry-ext-nanoid/ (governance- tracked) and crates/perry-stdlib/src/nanoid.rs (a second, independent implementation behind the default-on bundled-nanoid feature, exporting the same js_nanoid/js_nanoid_sized/js_nanoid_custom symbols). customAlphabet is declared to codegen (data_stores.rs's js_nanoid_custom) but has no call-site wiring anywhere in perry-codegen -- no NativeModSig row, no lower_call special case. Only plain nanoid(size) had a dispatch row (native_table/utils_crypto.rs, routing to js_nanoid_sized), consistent with customAlphabet not being a first-class compiled call at all. Removed both crates, the 1-entry NativeModSig dispatch row, the 2 js_nanoid* FFI declarations, the well_known_bindings.toml entry, the "nanoid" NATIVE_MODULES entry + manifest row, the bundled-nanoid stdlib feature, and 2 Android stub exports. Dropped "nanoid" from the shared shipped_unproven_bindings_are_partial test array (dotenv remains; it is #10691's to remove). The "ids" umbrella is now EMPTY. It was retargeted to ["bundled-nanoid"] when #10701 removed uuid (train 225); removing bundled-nanoid leaves it with no members, so it is kept as `ids = []` -- an intentionally harmless no-op that preserves `--features ids` for existing callers rather than breaking them. The stale comments that described the two-member split (perry-stdlib/Cargo.toml, perry-stdlib/src/lib.rs, stdlib_features.rs) are rewritten to say so. perry-stdlib's `uuid` crate dependency is untouched: #10701 already made it non-optional because crypto/random.rs calls it unconditionally. test-files/test_parity_nanoid.ts (the exact customAlphabet(...)(); reproduction) is already excluded from the parity gate -- known_failures.json classifies it "ci-env": Node's own oracle fails with ERR_MODULE_NOT_FOUND in CI because nanoid was never added to the repo's root package.json, so npm ci never installs it. Not touched -- provisioning a real npm dependency in the root package.json is out of scope for a binding-removal PR, and the test remains excluded before and after this change for the same underlying reason. Regenerated docs/api/perry.d.ts (2067 entries/132 modules -> 2066/131) and docs/src/api/reference.md (3009/134 -> 3008/133) by running the built binary's --print-api-manifest, not by editing the headers. Regenerated docs/src/native-libraries/governance.md's row. Re-derived workspace-architecture.json from scripts/workspace_architecture.py against the resolved tree: workspace_members 78 -> 77, externalize 29 -> 28, keep 44 (unchanged). Cargo.lock regenerated with `cargo metadata`, not hand-merged. Rebased onto v0.5.1605 (train 226). The pre-rebase branch was written when uuid, jsonwebtoken and validator still existed, so most conflicts were of the form "main deleted X, this branch deleted Y, in one hunk"; every one was resolved to main's current content minus nanoid's own entries, which is neither side. Two of them (entries/part_1.rs, native_table/ utils_crypto.rs) fold on a shared trailing `),`/`},`, which silently left a dangling `method_sig(` opener until `cargo fmt --all -- --check` rejected it.
customAlphabet(alphabet, size) is documented to return a generator function; native customAlphabet instead returns the generated id string directly (js_nanoid_custom's own doc comment: "For simplicity, we combine this into one call"), so the only documented usage -- const gen = customAlphabet(...); gen(); -- crashes with TypeError: value is not a function. Per #10678 (duplicate extern "C" exports across perry-ext-*/perry-stdlib pairs), this binding existed twice: crates/perry-ext-nanoid/ (governance- tracked) and crates/perry-stdlib/src/nanoid.rs (a second, independent implementation behind the default-on bundled-nanoid feature, exporting the same js_nanoid/js_nanoid_sized/js_nanoid_custom symbols). customAlphabet is declared to codegen (data_stores.rs's js_nanoid_custom) but has no call-site wiring anywhere in perry-codegen -- no NativeModSig row, no lower_call special case. Only plain nanoid(size) had a dispatch row (native_table/utils_crypto.rs, routing to js_nanoid_sized), consistent with customAlphabet not being a first-class compiled call at all. Removed both crates, the 1-entry NativeModSig dispatch row, the 2 js_nanoid* FFI declarations, the well_known_bindings.toml entry, the "nanoid" NATIVE_MODULES entry + manifest row, the bundled-nanoid stdlib feature, and 2 Android stub exports. DELETED the shipped_unproven_bindings_are_partial test rather than emptying it. Its subject population was exactly the hand-written wrappers shipped without proven upstream parity: uuid (#10701), dotenv (#10691, landed in train 227) and nanoid (here). With the last one gone the array would read `for name in []` -- a test that compiles, runs, asserts nothing and reports green forever, which is failure mode #4 in CLAUDE.md's "four ways a gate can be unable to fail". Coverage is not lost: shipped_subset_bindings_are_partial is a separate test and still asserts the same property for undici, node-forge, lru-cache and qs. Verified the deletion orphans nothing -- the test module is `use super::*`, lookup_well_known has 9 other callers, BindingCompat::Partial has 5 other uses, and nothing in the tree keys on the test's name. The "ids" umbrella is now EMPTY. It was retargeted to ["bundled-nanoid"] when #10701 removed uuid (train 225); removing bundled-nanoid leaves it with no members, so it is kept as `ids = []` -- an intentionally harmless no-op that preserves `--features ids` for existing callers rather than breaking them. The stale comments that described the two-member split (perry-stdlib/Cargo.toml, perry-stdlib/src/lib.rs, stdlib_features.rs) are rewritten to say so. perry-stdlib's `uuid` crate dependency is untouched: #10701 already made it non-optional because crypto/random.rs calls it unconditionally. test-files/test_parity_nanoid.ts (the exact customAlphabet(...)(); reproduction) is already excluded from the parity gate -- known_failures.json classifies it "ci-env": Node's own oracle fails with ERR_MODULE_NOT_FOUND in CI because nanoid was never added to the repo's root package.json, so npm ci never installs it. Not touched -- provisioning a real npm dependency in the root package.json is out of scope for a binding-removal PR, and the test remains excluded before and after this change for the same underlying reason. Every absolute count re-derived from its own script against the resolved tree, never carried across the rebase and never hand-merged: workspace-architecture.json 77 -> 76 members, externalize 28 -> 27, keep 44 (scripts/workspace_architecture.py; git auto-merged this file with NO conflict and left the stale 77/28, which the script caught); docs/api/perry.d.ts 2065 entries/131 modules -> 2064/130 and docs/src/api/reference.md 3007/133 -> 3006/132, both regenerated by running the built binary's --print-api-manifest rather than editing the headers; Cargo.lock regenerated with `cargo metadata`. native_result_ledger (376 rows/326 providers), unrooted_local_shape (578) and string_payload_access (perry-stdlib inline-offset 37) confirmed unchanged by running them, not by assuming. Rebased onto v0.5.1606 (train 227). Conflicts were all of the form "main deleted dotenv, this branch deleted nanoid, in one hunk"; every one was resolved to main's current content minus nanoid's own entries, which is neither side.
customAlphabet(alphabet, size) is documented to return a generator function; native customAlphabet instead returns the generated id string directly (js_nanoid_custom's own doc comment: "For simplicity, we combine this into one call"), so the only documented usage -- const gen = customAlphabet(...); gen(); -- crashes with TypeError: value is not a function. Per #10678 (duplicate extern "C" exports across perry-ext-*/perry-stdlib pairs), this binding existed twice: crates/perry-ext-nanoid/ (governance- tracked) and crates/perry-stdlib/src/nanoid.rs (a second, independent implementation behind the default-on bundled-nanoid feature, exporting the same js_nanoid/js_nanoid_sized/js_nanoid_custom symbols). customAlphabet is declared to codegen (data_stores.rs's js_nanoid_custom) but has no call-site wiring anywhere in perry-codegen -- no NativeModSig row, no lower_call special case. Only plain nanoid(size) had a dispatch row (native_table/utils_crypto.rs, routing to js_nanoid_sized), consistent with customAlphabet not being a first-class compiled call at all. Removed both crates, the 1-entry NativeModSig dispatch row, the 2 js_nanoid* FFI declarations, the well_known_bindings.toml entry, the "nanoid" NATIVE_MODULES entry + manifest row, the bundled-nanoid stdlib feature, and 2 Android stub exports. DELETED the shipped_unproven_bindings_are_partial test rather than emptying it. Its subject population was exactly the hand-written wrappers shipped without proven upstream parity: uuid (#10701), dotenv (#10691, landed in train 227) and nanoid (here). With the last one gone the array would read `for name in []` -- a test that compiles, runs, asserts nothing and reports green forever, which is failure mode #4 in CLAUDE.md's "four ways a gate can be unable to fail". Coverage is not lost: shipped_subset_bindings_are_partial is a separate test and still asserts the same property for undici, node-forge, lru-cache and qs. Verified the deletion orphans nothing -- the test module is `use super::*`, lookup_well_known has 9 other callers, BindingCompat::Partial has 5 other uses, and nothing in the tree keys on the test's name. The "ids" umbrella is now EMPTY. It was retargeted to ["bundled-nanoid"] when #10701 removed uuid (train 225); removing bundled-nanoid leaves it with no members, so it is kept as `ids = []` -- an intentionally harmless no-op that preserves `--features ids` for existing callers rather than breaking them. The stale comments that described the two-member split (perry-stdlib/Cargo.toml, perry-stdlib/src/lib.rs, stdlib_features.rs) are rewritten to say so. perry-stdlib's `uuid` crate dependency is untouched: #10701 already made it non-optional because crypto/random.rs calls it unconditionally. test-files/test_parity_nanoid.ts (the exact customAlphabet(...)(); reproduction) is already excluded from the parity gate -- known_failures.json classifies it "ci-env": Node's own oracle fails with ERR_MODULE_NOT_FOUND in CI because nanoid was never added to the repo's root package.json, so npm ci never installs it. Not touched -- provisioning a real npm dependency in the root package.json is out of scope for a binding-removal PR, and the test remains excluded before and after this change for the same underlying reason. Every absolute count re-derived from its own script against the resolved tree, never carried across the rebase and never hand-merged: workspace-architecture.json 77 -> 76 members, externalize 28 -> 27, keep 44 (scripts/workspace_architecture.py; git auto-merged this file with NO conflict and left the stale 77/28, which the script caught); docs/api/perry.d.ts 2065 entries/131 modules -> 2064/130 and docs/src/api/reference.md 3007/133 -> 3006/132, both regenerated by running the built binary's --print-api-manifest rather than editing the headers; Cargo.lock regenerated with `cargo metadata`. native_result_ledger (376 rows/326 providers), unrooted_local_shape (578) and string_payload_access (perry-stdlib inline-offset 37) confirmed unchanged by running them, not by assuming. Rebased onto v0.5.1606 (train 227). Conflicts were all of the form "main deleted dotenv, this branch deleted nanoid, in one hunk"; every one was resolved to main's current content minus nanoid's own entries, which is neither side.
Summary
Removes the native
uuidbinding soimport { v4, parse, stringify, NIL } from "uuid"(noperry.compilePackagesentry) resolves to the real npmpackage, compiled from source, per the owner's decision to stop shipping
hand-written Rust reimplementations of npm packages.
This is the last of five verified binding removals in this campaign
(#10687 jsonwebtoken, #10690 validator, #10691 dotenv, #10693 nanoid).
The bug
The native binding is missing
parse/stringifyentirely — aparse/stringifyroundtrip throws (bytescomes backundefined, sobytes.lengthcrashes withTypeError).NILreads asundefined:js_uuid_nilexists in the deleted source but was never wired into eitherthe
NativeModSigdispatch table or the API manifest, so property accesson the
uuidmodule namespace fell through toundefined.v1/v3/v4/v5/validate/version were correct in both engines.
What was found and removed
Per #10678 (duplicate
extern "C"exports acrossperry-ext-*/perry-stdlibpairs), this binding existed twice:
crates/perry-ext-uuid/— the governance-tracked binding crate, wiredinto
well_known_bindings.toml's[bindings.uuid].crates/perry-stdlib/src/uuid.rs(127 lines) — a second, independentimplementation behind the
bundled-uuidfeature, exporting the samejs_uuid_*symbols.Removed both crates, the 7-entry
NativeModSigdispatch block(
native_table/utils_crypto.rs), thewell_known_bindings.tomlentry, the"uuid"NATIVE_MODULESentry and its 7 manifest rows, thebundled-uuidstdlib feature (
idsumbrella now expands to just["bundled-nanoid"]),and the 6 Android stub exports. Dropped
"uuid"from the sharedshipped_unproven_bindings_are_partialtest array incrates/perry/src/commands/compile/well_known.rs(keptdotenv/nanoid—their own PRs in this campaign are still open, not yet merged).
The crypto/random.rs entanglement
crypto.randomUUID()/crypto.randomUUID({ v7: true })(
crates/perry-stdlib/src/crypto/random.rs) and nodemailer's message-idgeneration (
crates/perry-stdlib/src/nodemailer.rs) both call theuuidCargo crate directly and unconditionally
(
uuid::Uuid::new_v4()/now_v7()) — neither call site has acfg(feature = ...)gate anywhere above it. Theuuidcrate dependency inperry-stdlib/Cargo.tomlwas declaredoptional = true, gated behind thebundled-uuidnpm-binding feature, but was never actually optional inpractice — those two call sites needed it unconditionally regardless of
whether
bundled-uuidwas enabled. Removing thebundled-uuidfeaturewithout also dropping
optional = truewould have broken the build themoment that feature stopped being enabled by default.
Fix: made
uuida required (non-optional) dependency inperry-stdlib/Cargo.toml, with a comment explaining why, and retargetedthe
idsfeature umbrella to dropbundled-uuid.crypto.randomUUID()/randomUUID({ v7: true })andnode:crypto'srandomBytesare unaffected— verified below (also relevant given #10643's recent Web Crypto
method-closure-caching fix touched adjacent code).
Also retargeted the one dts-shape regression test that used
uuid.v4()asits zero-arg-module-function fixture
(
perry-api-manifest::emit::tests::dts_uuid_v4_has_no_args) toperry/gc.minor(), which is unrelated to any binding-removal churn.Acceptance test: real
uuid, nocompilePackagesentry, roundtrip + NIL{ "dependencies": { "uuid": "^11.0.0" } }Built on perrymaster (
--profile perry-dev). Ran the binary and diffedagainst
node --experimental-strip-types(Node 26.5.1): byte-for-byteidentical — including the deterministic v5/v3 (name+namespace) values.
Proved the bug on a pristine baseline first: built
origin/main(
8df83f8c1) in a separate worktree and ran the identical program there.It printed
NIL: undefined,parse instanceof Uint8Array: false, thencrashed:
TypeError: Cannot read properties of undefined (reading 'length')— reproducing the reported bug exactly, before the fix wasapplied.
crypto.randomUUID()re-checked against the fixed build: still returns avalid v4 UUID (
validate()true,version()4).Verification
cargo build --profile perry-dev -p perry -p perry-runtime-static -p perry-stdlib-static: clean; confirmed.amtimes moved.cargo check --workspace --all-targets(host-compatible exclusion setvia
workspace_architecture.py --print-excluded-scope host-compatible)under
-D warnings: clean.cargo test -p perry-api-manifest: 39+4 passing (after retargeting theuuid-fixture test above).
cargo test -p perry-codegen --test manifest_consistency: 5/5 passing.cargo test -p perry --bin perry -- well_known: 27/27 passing.cargo test -p perry-hir: full suite passing(
test_lower_native_module_registrationuses"uuid"only as syntheticexample data for a generic register/lookup mechanism — unaffected by the
registry removal).
python3 scripts/binding_governance.py --check: OK (39 extensioncrates).
node scripts/binding_pins.mjs --check: OK (37 pinned, lock-step holds).python3 scripts/workspace_architecture.py --check: OK.python3 scripts/native_result_ledger.py: OK, 371 rows / 322 providersunchanged (none of uuid's dispatch rows used a ledger-tracked
NR_*kind).
python3 scripts/string_payload_access_inventory.py --write-baseline:perry-stdlibinline-offset40 → 38 (uuid.rs's own 2 sites).docs/api/perry.d.ts+docs/src/api/reference.md(
perry --print-api-manifest) anddocs/src/native-libraries/governance.md(binding_governance.py --table) from the fixed manifest.cargo fmt --all -- --check: clean.scripts/run_lint_gates.sh(SKIP_COMPILE_GATES=1): 76 of 77passed; the one failure (Public benchmark evidence freshness) is the
pre-existing, known-red-on-every-PR gate per this campaign's contract.
Not run / out of scope
run_lint_gates.sh(known-red on Linux per thiscampaign's contract).
targeted registry/consistency tests plus the direct acceptance test
(including a pristine-baseline A/B) instead.
test-files/test_parity_uuid.tsis already excluded from the paritygate (
test-parity/known_failures.json,"ci-env": Node's own oraclerun fails
ERR_MODULE_NOT_FOUNDbecauseuuidwas never added to therepo's root
package.json/package-lock.json— the same pre-existinggap documented for nanoid, parity: 2026-08-17 dark-debt audit — 93 parity + 27 compile failures unlisted after six dark weeks (90.7% aggregate) #8271). Its
@coverscomment now points at adeleted file (
crates/perry-stdlib/src/uuid.rs); left untouched,matching how the sibling nanoid PR (refactor(stdlib): remove nanoid native binding #10693) left its own equivalent
parity fixture alone.
CLAUDE.mdedit — per this campaign's convention, themaintainer bumps at merge time.
crates/perry-ui-android/src/stdlib_stubs.rswas edited to remove thematching 6
js_uuid_*stub exports (following the established patternfrom the sibling removals) but not build-verified — this host has no
Android NDK and the package is excluded from the host-compatible check
scope.
Rebase onto main @
7c5d04d0e(v0.5.1601), 2026-09-19Force-pushed a rebase (
5ade053d8a→067f2ae86e) past #10690 (validator)and an unrelated jsonwebtoken removal that also landed on
mainin themeantime (
fbac2de2f). #10691 (dotenv) has not merged yet — still open— so its entries are untouched here.
Conflicts (7 files) resolved by intent — main's current state minus
uuid's entries, never either side's copy wholesale:
crates/perry-codegen/src/lower_call/native_table/utils_crypto.rs,crates/perry-ui-android/src/stdlib_stubs.rs,docs/api/perry.d.ts,docs/src/api/reference.md,docs/src/native-libraries/governance.md,scripts/string_payload_access_baseline.txt,workspace-architecture.json.Two of these (
utils_crypto.rs,stdlib_stubs.rs) hit the brace-foldingtrap CLAUDE.md documents (both sides' trailing
}lines were textuallyidentical, so git folded them into "common" context) — resolved by
inspection, confirmed by a clean compile.
Cargo.lock: took main's side, then regenerated viacargo metadata --offline(not hand-merged). Verified: zero conflictmarkers, zero
perry-ext-uuidentries,uuiditself resolves once(1.26.0, required dep),
cargo metadataaccepts the tree.Counts recomputed from the resolved tree, independently confirmed:
workspace_architecture.py --check --print-summarybinding_governance.py --checkbinding_pins.mjs --check(Node 26.5.1)perry-stdlibinline-offsetstring_payload_access_inventory.py --write-baselineDocs regenerated for real (not hand-edited): built
target/perry-dev/perryin-tree and ran
--print-api-manifest=markdown/=dtsdirectly (avoids thescripts/regen_api_docs.shout-of-tree-truncation trap — CLAUDE.md's ★★gate — while still matching its output, since the manifest is compile-time
data unaffected by optimization level).
docs/api/perry.d.ts: 2085→2078entries, 134→133 modules.
docs/src/api/reference.md: 3027→3020 entries,136→135 modules.
git diff --staton both: 2 lines each (header only,tail intact) — the regeneration signature, not the truncation one.
native_result_ledger.pynow fails (expected 371 classified rows, found 376) — but this is pre-existing on pristineorigin/main(
7c5d04d0e) too, confirmed byte-for-byte identical via a throwawaygit worktree: the script'sEXPECTED_ROWSconstant wasn't bumped whenthe validator/jsonwebtoken removals landed. It's not in
run_lint_gates.sh's suite and its own workflow(
native-result-ledger.yml) is path-filtered to only run whenscripts/native_result_ledger.py/.tsvthemselves change — neither ofwhich this PR touches — so it doesn't gate this PR's CI. Reporting
separately rather than fixing it here (out of scope per this PR's
contract: don't block a removal on pre-existing drift it didn't cause).
Re-verified after rebase (rebuilt
perry-devin-tree,.a/binarymtimes moved):
npm install uuid(v11, realnpm package, no
perry.compilePackagesentry), compiled, diffed againstnode --experimental-strip-types(Node 26.5.1) — byte-for-byteidentical, including deterministic v3/v5,
NIL, and the parse/stringifyroundtrip.
crypto.randomUUID()re-checked standalone: valid v4 UUID.cargo check --workspace --all-targets(host-compatible exclusion set)under
-D warnings: clean, 0 warnings.cargo fmt --all -- --check: clean.scripts/run_lint_gates.sh(SKIP_COMPILE_GATES=1): 76 of 77 passed —same pre-existing Public benchmark evidence freshness failure as
before.
scripts/check_file_size.sh: OK.crates/perry-runtime/src/object/native_module/module_keys.rsuntouchedby this PR's resolution (still 1992/2000 lines; this removal didn't add
to it).
git diff --statchecked before every commit — no destructive doctruncation.
cargo metadataaccepts the tree; rootCargo.toml'smemberslist and path-dependency table both lackperry-ext-uuid.changelog.d/10701-uuid-native-binding-removal.md)survived the rebase and the
Cargo.lockconflict resolution intact.source of these crates is byte-identical after the rebase, only shared
registry files changed): the per-crate
cargo testruns, and the compiletier of
run_lint_gates.sh(still known-red on Linux).Pushed SHA:
067f2ae86ee5cfd2aa6c8dc702971047b18ae4ed.Summary by CodeRabbit
Bug Fixes
uuidpackage now compiles from its standard npm source, improving Node.js compatibility, includingparse,stringify, andNILbehavior.crypto.randomUUID(), UUID v7 generation, and email message IDs.Breaking Changes
uuidmodule and helper APIs (v1,v3,v4,v5,v7,validate, andversion) are no longer provided.Documentation
uuidmodule from API declarations and reference documentation.