Skip to content

Fix target-qualified native loader preflight - #24

Merged
biw merged 1 commit into
mainfrom
fix/swift-node-preflight
Aug 10, 2026
Merged

Fix target-qualified native loader preflight#24
biw merged 1 commit into
mainfrom
fix/swift-node-preflight

Conversation

@biw

@biw biw commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Summary

Target-qualified native loaders can check their original .node filename before requiring it. During a build, the plugin rewrites that require to an emitted hashed asset, so the original preflight check no longer describes the runtime file and can throw first.

This patch removes that throw-only preflight guard only after the plugin has resolved and rewritten the matching native-path require. It also increments the package version to 2.4.2.

What This PR Does

  • Detects if (!existsSync(nativePath)) throw ... guards for native path variables.
  • Deletes the matching guard when the corresponding require(nativePath) is rewritten to an emitted native asset.
  • Adds direct-transform and Vite bundle regressions using generic target-qualified loader fixtures.

What This Improves

Target-qualified native loaders can use hashed emitted addon filenames without retaining an existence check for the original source filename.

What This Does Not Do

  • It does not remove non-throwing existence checks.
  • It does not remove a guard unless the plugin resolved and rewrote the matching native require.
  • It does not change the existing resolver-function handling for other loader shapes.

Important Context

The native source file must already be present for the plugin to resolve and emit it. The guard removal is tied to that successful resolution rather than to a filename pattern alone.

Code To Review Closely

src/index.ts:1552

Review that the preflight guard is removed only on the same path-variable branch that has already resolved a real native file and replaced its require call.

const nodeFilePath = nativeFilePathVars.get(node.arguments[0].name);
if (nodeFilePath) {
  processNodeFile(nodeFilePath, node);
  removeNativePathPreflightGuard(node.arguments[0].name);
}

Gotchas, Risks, And Edge Cases

  • A throw-only existsSync guard is removed only when its path variable has a matching successful native-module rewrite.
  • Loaders that perform another fallback action instead of throwing retain their existence checks.
  • Tests use placeholder native files to validate transform and bundle output; they do not load a compiled addon at runtime.

Tests And Regression Coverage

Validation Run

  • pnpm test: passed — 205 tests.
  • pnpm lint: passed — formatting, lint, and type checks.
  • pnpm build: passed.
  • pnpm precommit: unavailable — this repository defines no precommit script.

Coverage Assessment

Sufficient for this transform regression: one test inspects the transformed loader, and another verifies Vite emits and references the native asset without the stale guard.

Regressions These Tests Should Catch

  • Rewriting a target-qualified require(nativePath) while leaving a stale preflight throw in the output.
  • Emitting the native asset without referencing it from the bundled loader.

Gaps And Recommended Follow-Up Tests

  • Runtime loading is intentionally outside this suite because the fixtures use placeholder native binaries.

Follow-Up Work

Not applicable.

@biw
biw merged commit 4825ae8 into main Aug 10, 2026
2 checks passed
@biw
biw deleted the fix/swift-node-preflight branch August 10, 2026 23:48
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