feat: add portable bundler wrapper API - #270
Draft
BridgeAR wants to merge 11 commits into
Draft
Conversation
Bundler plugins need to own virtual module IDs and resolution. Returning import metadata separately keeps canonical module URLs out of generated import specifiers without duplicating IITM's export-binding logic. Refs: DataDog/dd-trace-js#9383
Consumers currently need separate RITM and bundler-specific paths for CommonJS, which duplicates matching, metadata, and replacement behavior. 1. Make synchronous hooks opt into CommonJS and route both formats through the shared Hook registry. 2. Make bundler wrappers format-aware, preserve opaque adapter targets, and carry JSON metadata into runtime hooks. 3. Verify the contracts with native sync hooks, real esbuild and webpack bundles, and nft tracing. Refs: #270 Refs: DataDog/dd-trace-js#9383
## Summary - Keep CommonJS and bundler metadata on opt-in IITM paths. - Remove bundler-specific dependencies, fixtures, and license churn. ## Why Existing ESM wrapper registration and callback paths must retain their hot-path behavior. The standalone register-hooks TypeScript test also bypassed the TypeScript loader on Node 18 and stopped the CI matrix. ## Test plan - npm test - npm run test:ts - npm run test:e2e - npm run lint
## Summary Expose the loader-known ESM or CommonJS format as the optional fifth Hook callback argument. ## Why Consumers that support both formats cannot safely infer namespace semantics from user exports. ## Test plan - npm test - npm run test:ts - npm run test:e2e - npm run lint
## Summary Emit valid identifier export names without string-literal syntax while preserving quoted names that require it. ## Why Webpack 5.54 accepts string-literal export names in the parser but crashes while analyzing the generated module. Most package exports are ordinary identifiers and do not need the newer syntax. ## Test plan - npm test - npm run test:ts - npm run test:e2e - npm run lint - webpack 5.54.0 ESM integration in dd-trace-js - webpack 5.109.2 ESM integration in dd-trace-js
Bundler integrations need synchronous format detection before generating a wrapper, but that behavior was only available inside the ESM loader. The facade keeps format detection synchronous without eagerly loading the wrapper parser.
## Summary Report package-relative names for CommonJS modules registered through extended hooks. ## Why CommonJS hooks historically receive package internals without opting into ESM internal interception. Bundler and synchronous loader wrappers need the same contract or file-specific instrumentation such as express/lib/express.js is skipped. ## Test plan - npm test - npm run test:ts - npm run lint
## Summary Keep require, module, exports, __filename, and __dirname bound to the bundler factory when createWrapperModule emits a CommonJS wrapper. ## Why Shadowing require in the generated factory prevents bundlers from resolving relative dependencies. The synchronous Node loader still uses explicit CommonJS parameters, while bundler wrappers preserve their outer bindings. ## Test plan - npm test - npm run test:ts - npm run lint
## Summary Inject the filesystem reader into shared module-format detection instead of requiring it from the CommonJS helper. ## Why Node.js 21 routes a CommonJS builtin require from an active ESM loader through resolveSync, but its loader worker does not implement that method. Importing fs in the ESM caller and requiring it in the CommonJS facade keeps each path on its native module system. ## Test plan - npm test - npm run lint - Node.js 21.7.3 npm test - Node.js 21.7.3 test/other/double-loading.mjs
## Summary Key extended hooks by their existing loader hook instead of tracking a parallel array and WeakMap. ## Why The registries must be removed together. One key makes that invariant explicit and avoids extra per-Hook bookkeeping without changing legacy ESM dispatch. ## Test plan - npm test - npm run test:ts - npm run lint
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bundler plugins currently have to duplicate IITM's wrapper generation or inject resolved URLs into generated ESM. This adds
createWrapperModule(), which returns relative import placeholders and a typed resolution/watch manifest while sharing export-binding generation with the Node loader. Each call parses caller-provided source independently so rebuilds see changed exports.Why
The runtime manifest entry stays non-external. Bundling it keeps generated wrappers and
Hookon the same registry.Refs: DataDog/dd-trace-js#9383