From 0e2ebd5e376bb1e8ca6dd9256742cb0df1da9d27 Mon Sep 17 00:00:00 2001 From: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com> Date: Wed, 13 Apr 2022 03:52:39 +0200 Subject: [PATCH] getSymbolResolution: fallback to asset's symbol with non-static dependencies (#7944) --- packages/core/core/src/BundleGraph.js | 31 ++++++++++++++----- .../formats/esm-filename-import/index.js | 3 ++ .../formats/esm-filename-import/package.json | 8 +++++ .../formats/esm-filename-import/yarn.lock | 0 .../integration-tests/test/output-formats.js | 11 +++++++ 5 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 packages/core/integration-tests/test/integration/formats/esm-filename-import/index.js create mode 100644 packages/core/integration-tests/test/integration/formats/esm-filename-import/package.json create mode 100644 packages/core/integration-tests/test/integration/formats/esm-filename-import/yarn.lock diff --git a/packages/core/core/src/BundleGraph.js b/packages/core/core/src/BundleGraph.js index 3f0de396c84..4ee291557fd 100644 --- a/packages/core/core/src/BundleGraph.js +++ b/packages/core/core/src/BundleGraph.js @@ -1398,13 +1398,14 @@ export default class BundleGraph { } let found = false; + let nonStaticDependency = false; let skipped = false; let deps = this.getDependencies(asset).reverse(); let potentialResults = []; for (let dep of deps) { let depSymbols = dep.symbols; if (!depSymbols) { - found = true; + nonStaticDependency = true; continue; } // If this is a re-export, find the original module. @@ -1523,15 +1524,31 @@ export default class BundleGraph { // ..., but if it does exist, it has to be behind this one reexport. return potentialResults[0]; } else { - // ... and there is no single reexport, but `bailout` tells us if it might still be exported. + let result = identifier; + if (skipped) { + // ... and it was excluded (by symbol propagation) or deferred. + result = false; + } else { + // ... and there is no single reexport, but it might still be exported: + if (found) { + // Fallback to namespace access, because of a bundle boundary. + result = null; + } else if (result === undefined) { + // If not exported explicitly by the asset (= would have to be in * or a reexport-all) ... + if (nonStaticDependency || asset.symbols?.has('*')) { + // ... and if there are non-statically analyzable dependencies or it's a CJS asset, + // fallback to namespace access. + result = null; + } + // (It shouldn't be possible for the symbol to be in a reexport-all and to end up here). + // Otherwise return undefined to report that the symbol wasn't found. + } + } + return { asset, exportSymbol: symbol, - symbol: skipped - ? false - : found - ? null - : identifier ?? (asset.symbols?.has('*') ? null : undefined), + symbol: result, loc: asset.symbols?.get(symbol)?.loc, }; } diff --git a/packages/core/integration-tests/test/integration/formats/esm-filename-import/index.js b/packages/core/integration-tests/test/integration/formats/esm-filename-import/index.js new file mode 100644 index 00000000000..b58a6e7c90b --- /dev/null +++ b/packages/core/integration-tests/test/integration/formats/esm-filename-import/index.js @@ -0,0 +1,3 @@ +import path from "path"; + +export const foo = __filename; diff --git a/packages/core/integration-tests/test/integration/formats/esm-filename-import/package.json b/packages/core/integration-tests/test/integration/formats/esm-filename-import/package.json new file mode 100644 index 00000000000..b02e8668a8e --- /dev/null +++ b/packages/core/integration-tests/test/integration/formats/esm-filename-import/package.json @@ -0,0 +1,8 @@ +{ + "name": "esm-filename-import", + "private": true, + "main": "dist/index.js", + "engines": { + "node": ">=10" + } +} diff --git a/packages/core/integration-tests/test/integration/formats/esm-filename-import/yarn.lock b/packages/core/integration-tests/test/integration/formats/esm-filename-import/yarn.lock new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/core/integration-tests/test/output-formats.js b/packages/core/integration-tests/test/output-formats.js index 834dc7a56f0..7b71ef26b90 100644 --- a/packages/core/integration-tests/test/output-formats.js +++ b/packages/core/integration-tests/test/output-formats.js @@ -1206,6 +1206,17 @@ describe('output formats', function () { assert.deepEqual({...ns}, {default: {default: 'default'}}); }); + it('should support rewriting filename and importing path', async function () { + let input = path.join( + __dirname, + '/integration/formats/esm-filename-import/index.js', + ); + let b = await bundle(input); + + let ns = await run(b); + assert.deepEqual(ns.foo, input); + }); + it('should rename shadowed imported specifiers to something unique', async function () { let b = await bundle( path.join(__dirname, '/integration/formats/esm-import-shadow/a.mjs'),