From fd83efb5a0371988a480187da8ae08150cf1823a Mon Sep 17 00:00:00 2001 From: Lukas Taegert Date: Mon, 8 Oct 2018 08:54:28 +0200 Subject: [PATCH 1/2] Provide better error when creating a namespace object containing a reexported external namespace --- src/Chunk.ts | 14 ++++++-------- src/ast/variables/NamespaceVariable.ts | 14 +++++++++++++- .../internal-reexports-from-external/_config.js | 13 +++++++++++++ .../internal-reexports-from-external/main.js | 3 +++ .../internal-reexports-from-external/reexport.js | 1 + 5 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 test/function/samples/internal-reexports-from-external/_config.js create mode 100644 test/function/samples/internal-reexports-from-external/main.js create mode 100644 test/function/samples/internal-reexports-from-external/reexport.js diff --git a/src/Chunk.ts b/src/Chunk.ts index becc654a9cc..d2400faa44f 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -247,7 +247,10 @@ export default class Chunk { const tracedExports: { variable: Variable; module: Module | ExternalModule }[] = []; for (const [index, exportName] of entryExportEntries) { const traced = this.traceExport(exportName, this.entryModule); - if (traced.variable && !traced.variable.included && !traced.variable.isExternal) { + if ( + !traced || + (traced.variable && !traced.variable.included && !traced.variable.isExternal) + ) { continue; } tracedExports[index] = traced; @@ -332,8 +335,8 @@ export default class Chunk { ): { variable: Variable; module: Module | ExternalModule; - } { - if (name === '*' || module instanceof ExternalModule) { + } | void { + if (name[0] === '*' || module instanceof ExternalModule) { return { variable: module.traceExport(name), module }; } @@ -365,11 +368,6 @@ export default class Chunk { return; } - // external star exports - if (name[0] === '*') { - return { variable: undefined, module: this.graph.moduleById.get(name.substr(1)) }; - } - // resolve known star exports for (let i = 0; i < module.exportAllModules.length; i++) { const exportAllModule = module.exportAllModules[i]; diff --git a/src/ast/variables/NamespaceVariable.ts b/src/ast/variables/NamespaceVariable.ts index 073bea6e59f..fd59ac472ed 100644 --- a/src/ast/variables/NamespaceVariable.ts +++ b/src/ast/variables/NamespaceVariable.ts @@ -11,17 +11,19 @@ export default class NamespaceVariable extends Variable { // Not initialised during construction originals: { [name: string]: Variable } = Object.create(null); needsNamespaceBlock: boolean = false; - + // only to be used for chunk-to-chunk import tracing, use context for data manipulation module: Module; private referencedEarly: boolean = false; private references: Identifier[] = []; + private containsExternalNamespace: boolean = false; constructor(context: AstContext, module: Module) { super(context.getModuleName()); this.context = context; this.module = module; for (const name of this.context.getExports().concat(this.context.getReexports())) { + if (name[0] === '*' && name.length > 1) this.containsExternalNamespace = true; this.originals[name] = this.context.traceExport(name); } } @@ -33,6 +35,16 @@ export default class NamespaceVariable extends Variable { include() { if (!this.included) { + if (this.containsExternalNamespace) { + this.context.error( + { + code: 'NAMESPACE_CANNOT_CONTAIN_EXTERNAL', + message: `Cannot create an explicit namespace object for module "${this.context.getModuleName()}" because it contains a reexported external namespace`, + id: this.module.id + }, + undefined + ); + } this.context.includeNamespace(); this.included = true; this.needsNamespaceBlock = true; diff --git a/test/function/samples/internal-reexports-from-external/_config.js b/test/function/samples/internal-reexports-from-external/_config.js new file mode 100644 index 00000000000..6e8fed55108 --- /dev/null +++ b/test/function/samples/internal-reexports-from-external/_config.js @@ -0,0 +1,13 @@ +module.exports = { + description: + 'fails with a helpful error if creating a namespace object containing a reexported external namespace', + options: { + external: ['external'] + }, + error: { + code: 'NAMESPACE_CANNOT_CONTAIN_EXTERNAL', + message: + 'Cannot create an explicit namespace object for module "reexport" because it contains a reexported external namespace', + id: __dirname + '/reexport.js' + } +}; diff --git a/test/function/samples/internal-reexports-from-external/main.js b/test/function/samples/internal-reexports-from-external/main.js new file mode 100644 index 00000000000..0006fef87b4 --- /dev/null +++ b/test/function/samples/internal-reexports-from-external/main.js @@ -0,0 +1,3 @@ +import * as namespace from './reexport.js'; + +console.log(namespace); diff --git a/test/function/samples/internal-reexports-from-external/reexport.js b/test/function/samples/internal-reexports-from-external/reexport.js new file mode 100644 index 00000000000..4953eb6e351 --- /dev/null +++ b/test/function/samples/internal-reexports-from-external/reexport.js @@ -0,0 +1 @@ +export * from 'external'; From a38518dc4621797d6d8527d3f6e55638c293d5d9 Mon Sep 17 00:00:00 2001 From: Lukas Taegert Date: Tue, 9 Oct 2018 06:28:48 +0200 Subject: [PATCH 2/2] Fix windows path error --- .../samples/internal-reexports-from-external/_config.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/function/samples/internal-reexports-from-external/_config.js b/test/function/samples/internal-reexports-from-external/_config.js index 6e8fed55108..79d4f56d24d 100644 --- a/test/function/samples/internal-reexports-from-external/_config.js +++ b/test/function/samples/internal-reexports-from-external/_config.js @@ -1,3 +1,5 @@ +const path = require('path'); + module.exports = { description: 'fails with a helpful error if creating a namespace object containing a reexported external namespace', @@ -8,6 +10,6 @@ module.exports = { code: 'NAMESPACE_CANNOT_CONTAIN_EXTERNAL', message: 'Cannot create an explicit namespace object for module "reexport" because it contains a reexported external namespace', - id: __dirname + '/reexport.js' + id: path.join(__dirname, '/reexport.js') } };