Repository navigation
Compile function export objects; name conditional export objects - #1434
Merged
Merged
Conversation
A CommonJS module whose export object is one of its own top-level functions (semver 5/6's `exports = module.exports = SemVer`) reaches its members through that function after the statement: member reads and writes through module.exports (and, after the rebinding, every `exports` reference) become members of the function, the expando form both resolvers model, and the rebinding itself drops. Constructor functions exported whole with members attached afterwards no longer lose those members at runtime. Replacing module.exports or rebinding exports inside a branch (an environment-dependent export object, readable-stream 2.x) now names the construct instead of the generic assignment fence, and a required builtin module object is truthy in the LLVM backend. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A chunk whose whole body is `module.exports = require("<builtin>")`
(readable-stream's internal/streams/stream.js) is the builtin module:
its calls become that require, and no chunk module is emitted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Its number collided with another open change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Renumbers this branch's npm cases 2567-2568 to 2583-2584: #1422 now uses 2567. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # tests/harness/npm-cases.ts
The pass respells `exports.x` and `module.exports.x` through the
exported function's name. A parameter, local, nested function or catch
binding of that name between a respelled read and the top level would
capture it, so the pass now applies only when the file binds the name
once, at its top-level declaration.
`{ exports }` after the rebinding respelled to `{ SemVer }`, which
renames the property; the shorthand now becomes `{ exports: SemVer }`.
This branch was successfully deployed
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.
Stacked on #1427 (which is stacked on #1422 and #1411). Review those first; this branch is based on
opt/npm-lazy-loaders.Summary
Function export objects. Some CommonJS modules make one of their own top-level functions the export object and attach members to it. semver 5 and 6 do this:
After that statement,
module.exportsis the function. After the rebinding form, so isexports. A new npm-static pass therefore respells member reads and writes through them as members of the function, which is the expando form both resolvers model, and drops theexports =rebinding.The pass applies only where the rewrite is exact:
module.exportsandexports;moduleandexportsare the CommonJS globals.This also fixes a silent divergence. A constructor function exported whole lost the function-valued members attached afterwards through
module.exports: Node ran them, and the binary threw "is not a function".Conditional export objects. Replacing
module.exports, or rebindingexports, inside a branch makes the exports depend on which path ran. readable-stream 2.x does this with itsREADABLE_STREAM=disableswitch. scriptc now names that construct precisely instead of the generic assignment fence.Required builtin modules are truthy. The LLVM backend now treats a required builtin module object as truthy in boolean contexts, as any object is. readable-stream's
… && StreamandStream || exportsguards failed to compile before.Bundled builtin forwarders. A bundled chunk that only re-exports a builtin,
module.exports = require("stream"), is now that builtin: its calls become therequire, and no chunk module is emitted.Evidence
2583-cjs-function-exports: the semver idiom and a constructor function with members attached afterwards, run with both values of the environment variable the module reads.2584-cjs-conditional-exports: a readable-stream-style environment-dependent export object, which is refused by name.required-module-truthiness.cjs. Main fails it withSC3001 truthy:moduleNs.npm-staticsuite, the compiler unit tests andorder-paritypass.pnpm lint,pnpm format:checkandtest:ts7 --baselines-onlypass. The self-hosted compiler builds its IR cleanly, andself-hosting-native-driver.test.tspasses.🤖 Generated with Claude Code