Skip to content

Create synthetic exports symbol for commonjs module - #42655

Merged
Nathan Shively-Sanders (sandersn) merged 3 commits into
masterfrom
create-synthetic-exports-symbol-for-commonjs-module
Feb 5, 2021
Merged

Nathan Shively-Sanders (sandersn) merged 3 commits into
masterfrom
create-synthetic-exports-symbol-for-commonjs-module

Conversation

@sandersn

Copy link
Copy Markdown
Member

Previously, the module identifier in commonjs modules got a synthetic type with a single property exports. The exports property reused the file's symbol, which, for a module file, gives the correct exported properties.

However, the name of this symbol was still the filename of the file, not exports. This PR creates a synthetic symbol for exports by copying in a similar way to esModuleInterop's default symbol in resolveESModuleSymbol (although the intent there is to strip off signatures from the symbol).

It's not possible to use cloneSymbol because that function merges the symbols, altering the original to point to the new symbol.

Fixes #41764

Previously, the `module` identifier in commonjs modules got a synthetic
type with a single property `exports`. The exports property reused the
file's symbol, which, for a module file, gives the correct exported
properties.

However, the name of this symbol was still the filename of the file, not
`exports`. This PR creates a synthetic symbol for `exports` by copying
in a similar way to esModuleInterop's `default` symbol in
`resolveESModuleSymbol` (although the intent there is to strip off
signatures from the symbol).
Comment thread src/compiler/checker.ts Outdated
const fileSymbol = getSymbolOfNode(getSourceFileOfNode(symbol.valueDeclaration));
const result = createSymbol(fileSymbol.flags, "exports" as __String);
result.declarations = fileSymbol.declarations ? fileSymbol.declarations.slice() : [];
result.parent = fileSymbol.parent;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parent should be reset to the module symbol in module.exports, no?

Comment thread src/compiler/checker.ts
Comment on lines +8776 to +8777
if (fileSymbol.members) result.members = new Map(fileSymbol.members);
if (fileSymbol.exports) result.exports = new Map(fileSymbol.exports);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How much of a memory hit for big checkJs projects (that use module.exports) is this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only baseline we have for this is "does chrome-devtools-frontend run out of memory?". I'll run the user tests.

A priori, it shouldn't be gigantic; a file with 1000 exports will add 1000 map entries. The first page of google only returns an SO answer from a V8 developer, which points out that each entry has key,value and next pointers. So...is that 6000 bytes per large file? It's not too expensive, but on the other hand this is a mostly cosmetic feature. The exception is the bug that the PR fixes.

@sandersn

Copy link
Copy Markdown
Member Author

TypeScript Bot (@typescript-bot) user test this

@typescript-bot

TypeScript Bot (typescript-bot) commented Feb 5, 2021 •

Copy link
Copy Markdown
Contributor

Heya Nathan Shively-Sanders (@sandersn), I've started to run the parallelized community code test suite on this PR at 5289808. You can monitor the build here.

@typescript-bot

Copy link
Copy Markdown
Contributor

The user suite test run you requested has finished and failed. I've opened a PR with the baseline diff from master.

@sandersn

Copy link
Copy Markdown
Member Author

User test baselines finished OK, so I think this is safe enough.
(It also found a couple instances of the pattern from the original bug.)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Author: Team For Milestone Bug PRs that fix a bug with a specific milestone

Projects

None yet

Development

Successfully merging this pull request may close these issues.

In JS, checking require.main === module causes the type of module to get messed up

4 participants