From bab3d3d666e8af9c17f0280833f34dc3054ed8ad Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Mon, 1 Feb 2021 07:11:50 +0100 Subject: [PATCH] Make sure default exports snapshot synthetic named exports (#3946) --- src/Module.ts | 2 +- src/ast/variables/ExportDefaultVariable.ts | 4 +++- src/ast/variables/SyntheticNamedExportVariable.ts | 11 ----------- .../chained-default-reexport/lib-reexport.js | 2 +- .../chained-default-reexport/lib-reexport2.js | 2 +- .../circular-synthetic-exports/_config.js | 5 +++-- .../circular-synthetic-exports/dep.js | 3 +-- .../circular-synthetic-exports2/_config.js | 11 +++++++++++ .../circular-synthetic-exports2/dep1.js | 2 ++ .../circular-synthetic-exports2/dep2.js | 2 ++ .../circular-synthetic-exports2/main.js | 2 ++ .../synthetic-named-export-as-default/_config.js | 10 ++++++++++ .../synthetic-named-export-as-default/dep.js | 2 ++ .../synthetic-named-export-as-default/main.js | 6 ++++++ .../synthetic-named-export-as-default/synthetic.js | 2 ++ 15 files changed, 47 insertions(+), 19 deletions(-) create mode 100644 test/function/samples/synthetic-named-exports/circular-synthetic-exports2/_config.js create mode 100644 test/function/samples/synthetic-named-exports/circular-synthetic-exports2/dep1.js create mode 100644 test/function/samples/synthetic-named-exports/circular-synthetic-exports2/dep2.js create mode 100644 test/function/samples/synthetic-named-exports/circular-synthetic-exports2/main.js create mode 100644 test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/_config.js create mode 100644 test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/dep.js create mode 100644 test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/main.js create mode 100644 test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/synthetic.js diff --git a/src/Module.ts b/src/Module.ts index 80eeb58d547..137345edbe1 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -199,7 +199,7 @@ function getAndExtendSideEffectModules(variable: Variable, module: Module): Set< if (!currentVariable || referencedVariables.has(currentVariable)) { break; } - referencedVariables.add(variable); + referencedVariables.add(currentVariable); sideEffectModules.add(importingModule); const originalSideEffects = importingModule.sideEffectDependenciesByVariable.get( currentVariable diff --git a/src/ast/variables/ExportDefaultVariable.ts b/src/ast/variables/ExportDefaultVariable.ts index 3a9fbcbfdfe..c6abe791886 100644 --- a/src/ast/variables/ExportDefaultVariable.ts +++ b/src/ast/variables/ExportDefaultVariable.ts @@ -55,7 +55,9 @@ export default class ExportDefaultVariable extends LocalVariable { (this.hasId || !( this.originalId.variable.isReassigned || - this.originalId.variable instanceof UndefinedVariable + this.originalId.variable instanceof UndefinedVariable || + // this avoids a circular dependency + 'syntheticNamespace' in this.originalId.variable )) ? this.originalId.variable : null; diff --git a/src/ast/variables/SyntheticNamedExportVariable.ts b/src/ast/variables/SyntheticNamedExportVariable.ts index 898f9219cb0..61ab764ee8b 100644 --- a/src/ast/variables/SyntheticNamedExportVariable.ts +++ b/src/ast/variables/SyntheticNamedExportVariable.ts @@ -1,5 +1,4 @@ import Module, { AstContext } from '../../Module'; -import { error, errSyntheticNamedExportsNeedNamespaceExport } from '../../utils/error'; import { RESERVED_NAMES } from '../../utils/reservedNames'; import ExportDefaultVariable from './ExportDefaultVariable'; import Variable from './Variable'; @@ -21,12 +20,10 @@ export default class SyntheticNamedExportVariable extends Variable { getBaseVariable(): Variable { if (this.baseVariable) return this.baseVariable; let baseVariable = this.syntheticNamespace; - const checkedVariables = new Set(); while ( baseVariable instanceof ExportDefaultVariable || baseVariable instanceof SyntheticNamedExportVariable ) { - checkedVariables.add(baseVariable); if (baseVariable instanceof ExportDefaultVariable) { const original = baseVariable.getOriginalVariable(); if (original === baseVariable) break; @@ -35,14 +32,6 @@ export default class SyntheticNamedExportVariable extends Variable { if (baseVariable instanceof SyntheticNamedExportVariable) { baseVariable = baseVariable.syntheticNamespace; } - if (checkedVariables.has(baseVariable)) { - return error( - errSyntheticNamedExportsNeedNamespaceExport( - this.module.id, - this.module.info.syntheticNamedExports - ) - ); - } } return (this.baseVariable = baseVariable); } diff --git a/test/chunking-form/samples/synthetic-named-exports/chained-default-reexport/lib-reexport.js b/test/chunking-form/samples/synthetic-named-exports/chained-default-reexport/lib-reexport.js index a73053bc0b2..c54ab1d9aee 100644 --- a/test/chunking-form/samples/synthetic-named-exports/chained-default-reexport/lib-reexport.js +++ b/test/chunking-form/samples/synthetic-named-exports/chained-default-reexport/lib-reexport.js @@ -1,3 +1,3 @@ import { named } from './lib-reexport2.js'; console.log('side-effect', named); -export default named; +export { named as default }; diff --git a/test/chunking-form/samples/synthetic-named-exports/chained-default-reexport/lib-reexport2.js b/test/chunking-form/samples/synthetic-named-exports/chained-default-reexport/lib-reexport2.js index de7bd3c9677..b7da20c84d0 100644 --- a/test/chunking-form/samples/synthetic-named-exports/chained-default-reexport/lib-reexport2.js +++ b/test/chunking-form/samples/synthetic-named-exports/chained-default-reexport/lib-reexport2.js @@ -1,3 +1,3 @@ import { named } from './lib.js'; console.log('side-effect', named); -export default named; +export { named as default }; diff --git a/test/function/samples/synthetic-named-exports/circular-synthetic-exports/_config.js b/test/function/samples/synthetic-named-exports/circular-synthetic-exports/_config.js index 8fe3e8a1b61..35a95977898 100644 --- a/test/function/samples/synthetic-named-exports/circular-synthetic-exports/_config.js +++ b/test/function/samples/synthetic-named-exports/circular-synthetic-exports/_config.js @@ -12,9 +12,10 @@ module.exports = { } ] }, - generateError: { + error: { code: 'SYNTHETIC_NAMED_EXPORTS_NEED_NAMESPACE_EXPORT', id: path.join(__dirname, 'main.js'), - message: `Module "main.js" that is marked with 'syntheticNamedExports: "__synthetic"' needs an export named "__synthetic" that does not reexport an unresolved named export of the same module.` + message: `Module "main.js" that is marked with 'syntheticNamedExports: "__synthetic"' needs an export named "__synthetic" that does not reexport an unresolved named export of the same module.`, + watchFiles: [path.join(__dirname, 'main.js'), path.join(__dirname, 'dep.js')] } }; diff --git a/test/function/samples/synthetic-named-exports/circular-synthetic-exports/dep.js b/test/function/samples/synthetic-named-exports/circular-synthetic-exports/dep.js index 44d71542717..b4f28ecf2b6 100644 --- a/test/function/samples/synthetic-named-exports/circular-synthetic-exports/dep.js +++ b/test/function/samples/synthetic-named-exports/circular-synthetic-exports/dep.js @@ -1,2 +1 @@ -import { foo } from './main.js'; -export default foo; +export { foo as default } from './main.js'; diff --git a/test/function/samples/synthetic-named-exports/circular-synthetic-exports2/_config.js b/test/function/samples/synthetic-named-exports/circular-synthetic-exports2/_config.js new file mode 100644 index 00000000000..5ed72a4ae8a --- /dev/null +++ b/test/function/samples/synthetic-named-exports/circular-synthetic-exports2/_config.js @@ -0,0 +1,11 @@ +module.exports = { + description: 'handles circular synthetic exports', + warnings: [ + { + code: 'CIRCULAR_DEPENDENCY', + cycle: ['dep1.js', 'dep2.js', 'dep1.js'], + importer: 'dep1.js', + message: 'Circular dependency: dep1.js -> dep2.js -> dep1.js' + } + ] +}; diff --git a/test/function/samples/synthetic-named-exports/circular-synthetic-exports2/dep1.js b/test/function/samples/synthetic-named-exports/circular-synthetic-exports2/dep1.js new file mode 100644 index 00000000000..a57b22f817e --- /dev/null +++ b/test/function/samples/synthetic-named-exports/circular-synthetic-exports2/dep1.js @@ -0,0 +1,2 @@ +import dep2 from './dep2'; +export default dep2; \ No newline at end of file diff --git a/test/function/samples/synthetic-named-exports/circular-synthetic-exports2/dep2.js b/test/function/samples/synthetic-named-exports/circular-synthetic-exports2/dep2.js new file mode 100644 index 00000000000..2db4702fed5 --- /dev/null +++ b/test/function/samples/synthetic-named-exports/circular-synthetic-exports2/dep2.js @@ -0,0 +1,2 @@ +import dep1 from './dep1'; +export default dep1; diff --git a/test/function/samples/synthetic-named-exports/circular-synthetic-exports2/main.js b/test/function/samples/synthetic-named-exports/circular-synthetic-exports2/main.js new file mode 100644 index 00000000000..4d48bdf7cdd --- /dev/null +++ b/test/function/samples/synthetic-named-exports/circular-synthetic-exports2/main.js @@ -0,0 +1,2 @@ +import dep1 from './dep1'; +assert.strictEqual(dep1, undefined); diff --git a/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/_config.js b/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/_config.js new file mode 100644 index 00000000000..d23377b2df2 --- /dev/null +++ b/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/_config.js @@ -0,0 +1,10 @@ +module.exports = { + description: 'makes sure default exports of synthetic named exports are snapshots', + options: { + plugins: { + transform() { + return { syntheticNamedExports: '__synthetic' }; + } + } + } +}; diff --git a/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/dep.js b/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/dep.js new file mode 100644 index 00000000000..097a935aa90 --- /dev/null +++ b/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/dep.js @@ -0,0 +1,2 @@ +import { foo } from './synthetic'; +export default foo; diff --git a/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/main.js b/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/main.js new file mode 100644 index 00000000000..1c0363e5882 --- /dev/null +++ b/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/main.js @@ -0,0 +1,6 @@ +import foo from './dep'; +import { update } from './synthetic'; + +assert.strictEqual(foo, 'original'); +update(); +assert.strictEqual(foo, 'original'); diff --git a/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/synthetic.js b/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/synthetic.js new file mode 100644 index 00000000000..c30a3957862 --- /dev/null +++ b/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/synthetic.js @@ -0,0 +1,2 @@ +export const __synthetic = { foo: 'original' }; +export const update = () => (__synthetic.foo = 'reassigned');