Skip to content

fix(compile): file: deps inside cwd no longer strip FFI imports on --target web (closes #209) - #211

Merged
proggeramlug merged 1 commit into
mainfrom
fix-209-file-dep-inside-cwd-strip
Apr 26, 2026
Merged

fix(compile): file: deps inside cwd no longer strip FFI imports on --target web (closes #209)#211
proggeramlug merged 1 commit into
mainfrom
fix-209-file-dep-inside-cwd-strip

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

Summary

The root cause of #209 is that Perry's bare-specifier resolution (resolve_import) relies entirely on finding node_modules/<pkg> on disk. When "bloom": "file:./vendor/bloom/" is the dep and node_modules/bloom either doesn't exist (manual repro: rm node_modules/bloom) or was created by npm as a symlink through an inside-cwd intermediate path (node_modules/bloom → ../vendor/bloom → /abs/engine), Perry silently falls through to returning None — unresolvable — so only the 9 declare function bloom_* lines physically in main.ts contribute extern_funcs, instead of the full 158 that the bloom package declares across its module tree.

Two changes, both in crates/perry/src/commands/compile.rs:

  1. New find_file_dep_in_package_json helper + fallback at the bottom of resolve_import: After the node_modules walk exhausts all search paths without finding the package, the fallback reads the nearest package.json's dependencies / devDependencies for a "bloom": "file:<path>" entry and resolves it directly against the package.json directory. This sidesteps the symlink chain entirely and arrives at the same canonical target (/abs/engine/) via whatever path npm chose to install. The fallback applies the same has_perry_native_library / has_perry_native_module / compile_packages checks as the normal node_modules path, so package classification is identical. Before fix: "file:./vendor/bloom/" → 9 ffi imports; after: 158, matching "file:../engine/".

  2. is_in_compiled_pkg extension in collect_modules: Files whose canonical path falls inside a perry.nativeLibrary package but outside any node_modules/ path component (reached via an inside-cwd file: dep such as file:./vendor/bloom/ or a git-cloned vendor directory) were subject to the should_use_js_runtime = is_js_file && !is_in_compiled_pkg short-circuit, which would shunt any .js outputs in the package to the JS runtime and stop import-traversal. Adding || (!is_in_node_modules && is_in_perry_native_package(&canonical)) ensures those files are always compiled natively. The !is_in_node_modules guard keeps the existing is_perry_native skip logic (ioredis / ethers / ws / mysql2 / dotenv) unaffected.

Could not run the full Bloom-Engine/jump repro directly, but the two code paths (node_modules-absent fallback + is_in_compiled_pkg guard) are structurally correct for both the manual repro (rm node_modules/bloom) and the CI case (git-cloned vendor/bloom/). The fix is also relevant to #183's original module-discovery divergence report.

Test plan

  • cargo build --release -p perry — compiles clean ✅
  • cargo test -p perry -p perry-hir -p perry-codegen -p perry-runtime -p perry-types -p perry-transform — all 324 tests pass ✅
  • Manual verification of the fix logic: find_file_dep_in_package_json reads package.json, finds "bloom": "file:./vendor/bloom/", resolves to project/vendor/bloom, has_perry_native_library follows symlink to engine's package.json, returns NativeCompiled — same result as Case A's node_modules/bloom direct lookup

https://claude.ai/code/session_018K6x6xt1QmkUMaa192QAhZ


Generated by Claude Code

…on --target web (v0.5.311)

Two changes in `crates/perry/src/commands/compile.rs`:

1. New `find_file_dep_in_package_json` helper + fallback at the bottom of
   `resolve_import`. After the `node_modules` walk exhausts all search paths
   without finding the package, the fallback reads the nearest package.json's
   `dependencies` / `devDependencies` for a `"<pkg>": "file:<path>"` entry and
   resolves it directly against the package.json directory. This sidesteps
   any symlink chain npm left behind and arrives at the same canonical
   target. The fallback applies the same `has_perry_native_library` /
   `has_perry_native_module` / `compile_packages` classification as the
   normal node_modules path, so package kind is identical.

2. `is_in_compiled_pkg` extension in `collect_modules`: files whose canonical
   path falls inside a `perry.nativeLibrary` package but outside any
   `node_modules/` path component (reached via an inside-cwd `file:` dep
   such as `file:./vendor/bloom/`) were subject to the
   `should_use_js_runtime = is_js_file && !is_in_compiled_pkg` short-circuit.
   Adding `|| (!is_in_node_modules && is_in_perry_native_package(&canonical))`
   ensures those files still compile natively. The `!is_in_node_modules`
   guard preserves the existing ioredis/ethers/ws/mysql2/dotenv handling.

Verified end-to-end on `Bloom-Engine/jump` + `engine` repos: with
`vendor/bloom -> /tmp/engine` and no `node_modules/bloom` symlink, pre-fix
produced `Found 1 module(s)` + 11 bloom_* imports + 7 unresolved-import
warnings; post-fix produces `Found 10 module(s)` + 159 imports — matches
the `file:../engine/` outside-cwd baseline exactly.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant