From d7ec1e6e5ed2b8f2413e66dc7504583ce51e760e Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Mon, 30 Mar 2020 19:10:39 -0600 Subject: [PATCH 1/8] feat: support external star exports on namespace objects --- src/Module.ts | 64 ++++++++++++------- src/ast/variables/NamespaceVariable.ts | 28 ++++---- .../_config.js | 15 ++--- .../internal-reexports-from-external/main.js | 2 +- .../reexport.js | 2 +- 5 files changed, 66 insertions(+), 45 deletions(-) diff --git a/src/Module.ts b/src/Module.ts index a8b8450fb20..d967a21e17d 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -5,7 +5,7 @@ import extractAssignedNames from 'rollup-pluginutils/src/extractAssignedNames'; import { createHasEffectsContext, createInclusionContext, - InclusionContext + InclusionContext, } from './ast/ExecutionContext'; import ExportAllDeclaration from './ast/nodes/ExportAllDeclaration'; import ExportDefaultDeclaration from './ast/nodes/ExportDefaultDeclaration'; @@ -42,7 +42,7 @@ import { ResolvedIdMap, RollupError, RollupWarning, - TransformModuleJSON + TransformModuleJSON, } from './rollup/types'; import { error, Errors } from './utils/error'; import getCodeFrame from './utils/getCodeFrame'; @@ -101,6 +101,7 @@ export interface AstContext { getReexports: () => string[]; importDescriptions: { [name: string]: ImportDescription }; includeDynamicImport: (node: ImportExpression) => void; + includeExternalReexportNamespace: (name: string) => ExternalVariable; includeVariable: (context: InclusionContext, variable: Variable) => void; isCrossChunkImport: (importDescription: ImportDescription) => boolean; magicString: MagicString; @@ -122,7 +123,7 @@ export interface AstContext { export const defaultAcornOptions: acorn.Options = { ecmaVersion: 2020, preserveParens: false, - sourceType: 'module' + sourceType: 'module', }; function tryParse(module: Module, Parser: typeof acorn.Parser, acornOptions: acorn.Options) { @@ -131,7 +132,7 @@ function tryParse(module: Module, Parser: typeof acorn.Parser, acornOptions: aco ...defaultAcornOptions, ...acornOptions, onComment: (block: boolean, text: string, start: number, end: number) => - module.comments.push({ block, text, start, end }) + module.comments.push({ block, text, start, end }), }); } catch (err) { let message = err.message.replace(/ \(\d+:\d+\)$/, ''); @@ -144,7 +145,7 @@ function tryParse(module: Module, Parser: typeof acorn.Parser, acornOptions: aco { code: 'PARSE_ERROR', message, - parserError: err + parserError: err, }, err.pos ); @@ -163,7 +164,7 @@ function handleMissingExport( message: `'${exportName}' is not exported by ${relativeId( importedModule )}, imported by ${relativeId(importingModule.id)}`, - url: `https://rollupjs.org/guide/en/#error-name-is-not-exported-by-module` + url: `https://rollupjs.org/guide/en/#error-name-is-not-exported-by-module`, }, importerStart! ); @@ -171,7 +172,7 @@ function handleMissingExport( const MISSING_EXPORT_SHIM_DESCRIPTION: ExportDescription = { identifier: null, - localName: MISSING_EXPORT_SHIM_VARIABLE + localName: MISSING_EXPORT_SHIM_VARIABLE, }; function getVariableForExportNameRecursive( @@ -289,17 +290,17 @@ export default class Module { loc: { column: location.column, file: this.id, - line: location.line + line: location.line, }, message: `Error when using sourcemap for reporting an error: ${e.message}`, - pos + pos, }); } props.loc = { column: location.column, file: this.id, - line: location.line + line: location.line, }; props.frame = getCodeFrame(this.originalCode, location.line, location.column); } @@ -341,7 +342,7 @@ export default class Module { return error({ code: Errors.SYNTHETIC_NAMED_EXPORTS_NEED_DEFAULT, id: this.id, - message: `Modules with 'syntheticNamedExports' need a default export.` + message: `Modules with 'syntheticNamedExports' need a default export.`, }); } return this.defaultExport; @@ -631,7 +632,7 @@ export default class Module { sourcemapChain, syntheticNamedExports, transformDependencies, - transformFiles + transformFiles, }: TransformModuleJSON & { alwaysRemovedCode?: [number, number][]; transformFiles?: EmittedFile[] | undefined; @@ -677,7 +678,7 @@ export default class Module { this.magicString = new MagicString(code, { filename: (this.excludeFromSourcemap ? null : fileName)!, // don't include plugin helpers in sourcemap - indentExclusionRanges: [] + indentExclusionRanges: [], }); for (const [start, end] of this.alwaysRemovedCode) { this.magicString.remove(start, end); @@ -701,8 +702,9 @@ export default class Module { getReexports: this.getReexports.bind(this), importDescriptions: this.importDescriptions, includeDynamicImport: this.includeDynamicImport.bind(this), + includeExternalReexportNamespace: this.includeExternalReexportNamespace.bind(this), includeVariable: this.includeVariable.bind(this), - isCrossChunkImport: importDescription => + isCrossChunkImport: (importDescription) => (importDescription.module as Module).chunk !== this.chunk, magicString: this.magicString, module: this, @@ -720,7 +722,7 @@ export default class Module { this.graph.treeshakingOptions.unknownGlobalSideEffects)!, usesTopLevelAwait: false, warn: this.warn.bind(this), - warnDeprecation: this.graph.warnDeprecation.bind(this.graph) + warnDeprecation: this.graph.warnDeprecation.bind(this.graph), }; this.scope = new ModuleScope(this.graph.scope, this.astContext); @@ -739,7 +741,7 @@ export default class Module { ast: this.esTreeAst, code: this.code, customTransformCache: this.customTransformCache, - dependencies: Array.from(this.dependencies).map(module => module.id), + dependencies: Array.from(this.dependencies).map((module) => module.id), id: this.id, moduleSideEffects: this.moduleSideEffects, originalCode: this.originalCode, @@ -748,7 +750,7 @@ export default class Module { sourcemapChain: this.sourcemapChain, syntheticNamedExports: this.syntheticNamedExports, transformDependencies: this.transformDependencies, - transformFiles: this.transformFiles + transformFiles: this.transformFiles, }; } @@ -809,7 +811,7 @@ export default class Module { this.exports.default = { identifier: node.variable.getAssignedVariableName(), - localName: 'default' + localName: 'default', }; } else if (node instanceof ExportAllDeclaration) { // export * from './other' @@ -829,7 +831,7 @@ export default class Module { specifier.type === NodeType.ExportNamespaceSpecifier ? '*' : specifier.local.name, module: null as any, // filled in later, source, - start: specifier.start + start: specifier.start, }; } } else if (node.declaration) { @@ -870,7 +872,7 @@ export default class Module { return this.error( { code: 'DUPLICATE_IMPORT', - message: `Duplicated import '${localName}'` + message: `Duplicated import '${localName}'`, }, specifier.start ); @@ -888,7 +890,7 @@ export default class Module { module: null as any, // filled in later name, source, - start: specifier.start + start: specifier.start, }; } } @@ -908,7 +910,9 @@ export default class Module { } private includeDynamicImport(node: ImportExpression) { - const resolution = (this.dynamicImports.find(dynamicImport => dynamicImport.node === node) as { + const resolution = (this.dynamicImports.find( + (dynamicImport) => dynamicImport.node === node + ) as { resolution: string | Module | ExternalModule | undefined; }).resolution; if (resolution instanceof Module) { @@ -917,6 +921,20 @@ export default class Module { } } + private includeExternalReexportNamespace(name: string): ExternalVariable { + for (const module of this.exportAllModules) { + if (module instanceof ExternalModule) { + if (module.id === name) { + const externalVariable = module.getVariableForExportName('*'); + externalVariable.include(); + this.imports.add(externalVariable); + return externalVariable; + } + } + } + throw new Error(`Unable to find star reexport ExternalModule instance for ${name}`); + } + private includeVariable(context: InclusionContext, variable: Variable) { const variableModule = variable.module; if (!variable.included) { @@ -934,7 +952,7 @@ export default class Module { code: 'SHIMMED_EXPORT', exporter: relativeId(this.id), exportName: name, - message: `Missing export "${name}" has been shimmed in module ${relativeId(this.id)}.` + message: `Missing export "${name}" has been shimmed in module ${relativeId(this.id)}.`, }); this.exports[name] = MISSING_EXPORT_SHIM_DESCRIPTION; } diff --git a/src/ast/variables/NamespaceVariable.ts b/src/ast/variables/NamespaceVariable.ts index 403095ca79f..f81eab1b2d8 100644 --- a/src/ast/variables/NamespaceVariable.ts +++ b/src/ast/variables/NamespaceVariable.ts @@ -4,6 +4,7 @@ import { RESERVED_NAMES } from '../../utils/reservedNames'; import { InclusionContext } from '../ExecutionContext'; import Identifier from '../nodes/Identifier'; import { UNKNOWN_PATH } from '../utils/PathTracker'; +import ExternalVariable from './ExternalVariable'; import Variable from './Variable'; export default class NamespaceVariable extends Variable { @@ -11,8 +12,9 @@ export default class NamespaceVariable extends Variable { isNamespace!: true; memberVariables: { [name: string]: Variable } = Object.create(null); module: Module; + reexportedNamespaces: string[] = []; + private reexportedNamespaceVariables: ExternalVariable[] = []; - private containsExternalNamespace = false; private referencedEarly = false; private references: Identifier[] = []; private syntheticNamedExports: boolean; @@ -41,13 +43,6 @@ export default class NamespaceVariable extends Variable { include(context: InclusionContext) { if (!this.included) { - if (this.containsExternalNamespace) { - return this.context.error({ - code: 'NAMESPACE_CANNOT_CONTAIN_EXTERNAL', - id: this.module.id, - message: `Cannot create an explicit namespace object for module "${this.context.getModuleName()}" because it contains a reexported external namespace` - }); - } this.included = true; for (const identifier of this.references) { if (identifier.context.getModuleExecIndex() <= this.context.getModuleExecIndex()) { @@ -55,6 +50,9 @@ export default class NamespaceVariable extends Variable { break; } } + for (const name of this.reexportedNamespaces) { + this.reexportedNamespaceVariables.push(this.context.includeExternalReexportNamespace(name)); + } if (this.context.preserveModules) { for (const memberName of Object.keys(this.memberVariables)) this.memberVariables[memberName].include(context); @@ -67,8 +65,11 @@ export default class NamespaceVariable extends Variable { initialise() { for (const name of this.context.getExports().concat(this.context.getReexports())) { - if (name[0] === '*' && name.length > 1) this.containsExternalNamespace = true; - this.memberVariables[name] = this.context.traceExport(name); + if (name[0] === '*' && name.length > 1) { + this.reexportedNamespaces.push(name.slice(1)); + } else { + this.memberVariables[name] = this.context.traceExport(name); + } } } @@ -77,7 +78,7 @@ export default class NamespaceVariable extends Variable { const n = options.compact ? '' : '\n'; const t = options.indent; - const members = Object.keys(this.memberVariables).map(name => { + const members = Object.keys(this.memberVariables).map((name) => { const original = this.memberVariables[name]; if (this.referencedEarly || original.isReassigned) { @@ -99,6 +100,11 @@ export default class NamespaceVariable extends Variable { const name = this.getName(); let output = `{${n}${members.join(`,${n}`)}${n}}`; + if (this.reexportedNamespaceVariables.length) { + output = `/*#__PURE__*/Object.assign(${this.reexportedNamespaceVariables + .map((v) => v.getName()) + .join(', ')}, ${output})`; + } if (this.syntheticNamedExports) { output = `/*#__PURE__*/Object.assign(${output}, ${this.module.getDefaultExport().getName()})`; } diff --git a/test/function/samples/internal-reexports-from-external/_config.js b/test/function/samples/internal-reexports-from-external/_config.js index f6c6ebd8d05..acd3e6163af 100644 --- a/test/function/samples/internal-reexports-from-external/_config.js +++ b/test/function/samples/internal-reexports-from-external/_config.js @@ -1,16 +1,13 @@ -const path = require('path'); +const assert = require('assert'); +const fs = require('fs'); module.exports = { description: 'fails with a helpful error if creating a namespace object containing a reexported external namespace', options: { - external: ['external'] + external: ['fs'], + }, + exports(ns) { + assert.strictEqual(ns.namespace.readFile, fs.readFile); }, - error: { - code: 'NAMESPACE_CANNOT_CONTAIN_EXTERNAL', - message: - 'Cannot create an explicit namespace object for module "reexport" because it contains a reexported external namespace', - id: path.join(__dirname, 'reexport.js'), - watchFiles: [path.join(__dirname, 'main.js'), path.join(__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 index 0006fef87b4..b127cee7d4d 100644 --- a/test/function/samples/internal-reexports-from-external/main.js +++ b/test/function/samples/internal-reexports-from-external/main.js @@ -1,3 +1,3 @@ import * as namespace from './reexport.js'; -console.log(namespace); +export { namespace }; diff --git a/test/function/samples/internal-reexports-from-external/reexport.js b/test/function/samples/internal-reexports-from-external/reexport.js index 4953eb6e351..b301bda0b0a 100644 --- a/test/function/samples/internal-reexports-from-external/reexport.js +++ b/test/function/samples/internal-reexports-from-external/reexport.js @@ -1 +1 @@ -export * from 'external'; +export * from 'fs'; From 20330872d9bf6bbd095a287355fcba5e2beb4dd1 Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Tue, 31 Mar 2020 20:14:14 -0600 Subject: [PATCH 2/8] fixup test description, form test --- .../samples/ns-external-star-reexport/_config.js | 6 ++++++ .../ns-external-star-reexport/_expected/amd.js | 12 ++++++++++++ test/form/samples/ns-external-star-reexport/dep.js | 3 +++ test/form/samples/ns-external-star-reexport/main.js | 3 +++ .../internal-reexports-from-external/_config.js | 3 +-- 5 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 test/form/samples/ns-external-star-reexport/_config.js create mode 100644 test/form/samples/ns-external-star-reexport/_expected/amd.js create mode 100644 test/form/samples/ns-external-star-reexport/dep.js create mode 100644 test/form/samples/ns-external-star-reexport/main.js diff --git a/test/form/samples/ns-external-star-reexport/_config.js b/test/form/samples/ns-external-star-reexport/_config.js new file mode 100644 index 00000000000..78619f310c8 --- /dev/null +++ b/test/form/samples/ns-external-star-reexport/_config.js @@ -0,0 +1,6 @@ +module.exports = { + description: 'supports namespace external star reexports', + options: { + external: ['external-ns-1', 'external-ns-2'], + }, +}; diff --git a/test/form/samples/ns-external-star-reexport/_expected/amd.js b/test/form/samples/ns-external-star-reexport/_expected/amd.js new file mode 100644 index 00000000000..a6985e6d5e8 --- /dev/null +++ b/test/form/samples/ns-external-star-reexport/_expected/amd.js @@ -0,0 +1,12 @@ +define(['external-ns-1', 'external-ns-2'], function (externalNs1, externalNs2) { 'use strict'; + + const val = 5; + + var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(externalNs1, externalNs2, { + __proto__: null, + val: val + })); + + return ns; + +}); diff --git a/test/form/samples/ns-external-star-reexport/dep.js b/test/form/samples/ns-external-star-reexport/dep.js new file mode 100644 index 00000000000..58c6940cda6 --- /dev/null +++ b/test/form/samples/ns-external-star-reexport/dep.js @@ -0,0 +1,3 @@ +export * from 'external-ns-1'; +export * from 'external-ns-2'; +export const val = 5; diff --git a/test/form/samples/ns-external-star-reexport/main.js b/test/form/samples/ns-external-star-reexport/main.js new file mode 100644 index 00000000000..c2c65d4785f --- /dev/null +++ b/test/form/samples/ns-external-star-reexport/main.js @@ -0,0 +1,3 @@ +import * as ns from './dep.js'; + +export default ns; diff --git a/test/function/samples/internal-reexports-from-external/_config.js b/test/function/samples/internal-reexports-from-external/_config.js index acd3e6163af..925496d0db8 100644 --- a/test/function/samples/internal-reexports-from-external/_config.js +++ b/test/function/samples/internal-reexports-from-external/_config.js @@ -2,8 +2,7 @@ const assert = require('assert'); const fs = require('fs'); module.exports = { - description: - 'fails with a helpful error if creating a namespace object containing a reexported external namespace', + description: 'supports namespaces with external star reexports', options: { external: ['fs'], }, From 35a88be33bf6220a129f5deda6e1f0930d9c3cec Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Tue, 31 Mar 2020 20:21:00 -0600 Subject: [PATCH 3/8] fixup form tests --- .../ns-external-star-reexport/_config.js | 1 + .../_expected/cjs.js | 13 +++++++++++ .../ns-external-star-reexport/_expected/es.js | 11 +++++++++ .../_expected/system.js | 23 +++++++++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 test/form/samples/ns-external-star-reexport/_expected/cjs.js create mode 100644 test/form/samples/ns-external-star-reexport/_expected/es.js create mode 100644 test/form/samples/ns-external-star-reexport/_expected/system.js diff --git a/test/form/samples/ns-external-star-reexport/_config.js b/test/form/samples/ns-external-star-reexport/_config.js index 78619f310c8..bcefef27f22 100644 --- a/test/form/samples/ns-external-star-reexport/_config.js +++ b/test/form/samples/ns-external-star-reexport/_config.js @@ -1,5 +1,6 @@ module.exports = { description: 'supports namespace external star reexports', + formats: ['amd', 'cjs', 'system', 'es'], options: { external: ['external-ns-1', 'external-ns-2'], }, diff --git a/test/form/samples/ns-external-star-reexport/_expected/cjs.js b/test/form/samples/ns-external-star-reexport/_expected/cjs.js new file mode 100644 index 00000000000..8a7644394f7 --- /dev/null +++ b/test/form/samples/ns-external-star-reexport/_expected/cjs.js @@ -0,0 +1,13 @@ +'use strict'; + +var externalNs1 = require('external-ns-1'); +var externalNs2 = require('external-ns-2'); + +const val = 5; + +var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(externalNs1, externalNs2, { + __proto__: null, + val: val +})); + +module.exports = ns; diff --git a/test/form/samples/ns-external-star-reexport/_expected/es.js b/test/form/samples/ns-external-star-reexport/_expected/es.js new file mode 100644 index 00000000000..b5044bf53e5 --- /dev/null +++ b/test/form/samples/ns-external-star-reexport/_expected/es.js @@ -0,0 +1,11 @@ +import * as externalNs1 from 'external-ns-1'; +import * as externalNs2 from 'external-ns-2'; + +const val = 5; + +var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(externalNs1, externalNs2, { + __proto__: null, + val: val +})); + +export default ns; diff --git a/test/form/samples/ns-external-star-reexport/_expected/system.js b/test/form/samples/ns-external-star-reexport/_expected/system.js new file mode 100644 index 00000000000..4e307c3a236 --- /dev/null +++ b/test/form/samples/ns-external-star-reexport/_expected/system.js @@ -0,0 +1,23 @@ +System.register(['external-ns-1', 'external-ns-2'], function (exports) { + 'use strict'; + var externalNs1, externalNs2; + return { + setters: [function (module) { + externalNs1 = module; + }, function (module) { + externalNs2 = module; + }], + execute: function () { + + const val = 5; + + var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(externalNs1, externalNs2, { + __proto__: null, + val: val + })); + + exports('default', ns); + + } + }; +}); From 5f4310d444c0d2c7ba5e70be7878a74927933ebf Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Fri, 3 Apr 2020 13:57:28 -0700 Subject: [PATCH 4/8] fixup Object.create assignment, __PURE__ tweaks --- src/ast/variables/NamespaceVariable.ts | 16 ++++++++----- .../_expected/amd/main.js | 2 +- .../_expected/cjs/main.js | 2 +- .../_expected/es/main.js | 2 +- .../_expected/system/main.js | 2 +- test/cli/node_modules/bar/lib/config.js | 11 +++++++++ test/cli/node_modules/bar/package.json | 3 +++ .../rollup-config-foo/lib/config.js | 11 +++++++++ .../rollup-config-foo/package.json | 3 +++ test/cli/samples/watch/bundle-error/main.js | 2 +- .../rollup.config.js | 23 +++++++++++++++---- .../watch/watch-config/rollup.config.js | 8 +------ .../_expected/amd.js | 3 +-- .../_expected/cjs.js | 3 +-- .../ns-external-star-reexport/_expected/es.js | 3 +-- .../_expected/system.js | 3 +-- 16 files changed, 67 insertions(+), 30 deletions(-) create mode 100644 test/cli/node_modules/bar/lib/config.js create mode 100644 test/cli/node_modules/bar/package.json create mode 100644 test/cli/node_modules/rollup-config-foo/lib/config.js create mode 100644 test/cli/node_modules/rollup-config-foo/package.json diff --git a/src/ast/variables/NamespaceVariable.ts b/src/ast/variables/NamespaceVariable.ts index f81eab1b2d8..65c124d5758 100644 --- a/src/ast/variables/NamespaceVariable.ts +++ b/src/ast/variables/NamespaceVariable.ts @@ -92,7 +92,8 @@ export default class NamespaceVariable extends Variable { return `${t}${safeName}: ${original.getName()}`; }); - members.unshift(`${t}__proto__:${_}null`); + const objectCreate = this.reexportedNamespaceVariables.length; + if (!objectCreate) members.unshift(`${t}__proto__:${_}null`); if (options.namespaceToStringTag) { members.unshift(`${t}[Symbol.toStringTag]:${_}'Module'`); @@ -101,12 +102,15 @@ export default class NamespaceVariable extends Variable { const name = this.getName(); let output = `{${n}${members.join(`,${n}`)}${n}}`; if (this.reexportedNamespaceVariables.length) { - output = `/*#__PURE__*/Object.assign(${this.reexportedNamespaceVariables + output = `Object.assign(Object.create(null), ${this.reexportedNamespaceVariables .map((v) => v.getName()) - .join(', ')}, ${output})`; - } - if (this.syntheticNamedExports) { - output = `/*#__PURE__*/Object.assign(${output}, ${this.module.getDefaultExport().getName()})`; + .join(', ')}, ${output}${ + this.syntheticNamedExports ? ', ' + this.module.getDefaultExport().getName() : '' + })`; + if (!options.freeze) output = '*#__PURE__*/' + output; + } else if (this.syntheticNamedExports) { + output = `Object.assign(${output}, ${this.module.getDefaultExport().getName()})`; + if (!options.freeze) output = '*#__PURE__*/' + output; } if (options.freeze) { output = `/*#__PURE__*/Object.freeze(${output})`; diff --git a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/amd/main.js b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/amd/main.js index 6285d62559e..5731e5c57a5 100644 --- a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/amd/main.js +++ b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/amd/main.js @@ -6,7 +6,7 @@ define(function () { 'use strict'; }; const foo = 100; - var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign({ + var ns = /*#__PURE__*/Object.freeze(Object.assign({ __proto__: null, foo: foo, 'default': d diff --git a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/cjs/main.js b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/cjs/main.js index f2c1b375abb..282e6ab8941 100644 --- a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/cjs/main.js +++ b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/cjs/main.js @@ -6,7 +6,7 @@ const d = { }; const foo = 100; -var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign({ +var ns = /*#__PURE__*/Object.freeze(Object.assign({ __proto__: null, foo: foo, 'default': d diff --git a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/es/main.js b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/es/main.js index 3b23f6d33bb..ab1c380da37 100644 --- a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/es/main.js +++ b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/es/main.js @@ -4,7 +4,7 @@ const d = { }; const foo = 100; -var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign({ +var ns = /*#__PURE__*/Object.freeze(Object.assign({ __proto__: null, foo: foo, 'default': d diff --git a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/system/main.js b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/system/main.js index 1147e48c999..6aecf6312bf 100644 --- a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/system/main.js +++ b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/system/main.js @@ -9,7 +9,7 @@ System.register([], function () { }; const foo = 100; - var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign({ + var ns = /*#__PURE__*/Object.freeze(Object.assign({ __proto__: null, foo: foo, 'default': d diff --git a/test/cli/node_modules/bar/lib/config.js b/test/cli/node_modules/bar/lib/config.js new file mode 100644 index 00000000000..785d84d0212 --- /dev/null +++ b/test/cli/node_modules/bar/lib/config.js @@ -0,0 +1,11 @@ +const replace = require( '@rollup/plugin-replace' ); + +module.exports = { + input: 'main.js', + output: { + format: 'cjs' + }, + plugins: [ + replace( { ANSWER: 42 } ) + ] +}; diff --git a/test/cli/node_modules/bar/package.json b/test/cli/node_modules/bar/package.json new file mode 100644 index 00000000000..fbd490130d0 --- /dev/null +++ b/test/cli/node_modules/bar/package.json @@ -0,0 +1,3 @@ +{ + "main": "lib/config.js" +} diff --git a/test/cli/node_modules/rollup-config-foo/lib/config.js b/test/cli/node_modules/rollup-config-foo/lib/config.js new file mode 100644 index 00000000000..785d84d0212 --- /dev/null +++ b/test/cli/node_modules/rollup-config-foo/lib/config.js @@ -0,0 +1,11 @@ +const replace = require( '@rollup/plugin-replace' ); + +module.exports = { + input: 'main.js', + output: { + format: 'cjs' + }, + plugins: [ + replace( { ANSWER: 42 } ) + ] +}; diff --git a/test/cli/node_modules/rollup-config-foo/package.json b/test/cli/node_modules/rollup-config-foo/package.json new file mode 100644 index 00000000000..fbd490130d0 --- /dev/null +++ b/test/cli/node_modules/rollup-config-foo/package.json @@ -0,0 +1,3 @@ +{ + "main": "lib/config.js" +} diff --git a/test/cli/samples/watch/bundle-error/main.js b/test/cli/samples/watch/bundle-error/main.js index a4012bff06c..1352aefa03e 100644 --- a/test/cli/samples/watch/bundle-error/main.js +++ b/test/cli/samples/watch/bundle-error/main.js @@ -1 +1 @@ -export default 42; \ No newline at end of file +<=> \ No newline at end of file diff --git a/test/cli/samples/watch/watch-config-early-update/rollup.config.js b/test/cli/samples/watch/watch-config-early-update/rollup.config.js index ec6ec213bce..f6d6c59bddd 100644 --- a/test/cli/samples/watch/watch-config-early-update/rollup.config.js +++ b/test/cli/samples/watch/watch-config-early-update/rollup.config.js @@ -1,9 +1,24 @@ - export default { - input: {output2: "main.js"}, + import path from 'path'; + import fs from 'fs'; + const messageFile = path.resolve(__dirname, '_actual', 'message.txt'); + export default new Promise(resolve => { + fs.writeFileSync(messageFile, 'loading'); + const watcher = fs.watch(messageFile, event => { + if (event === 'change') { + const content = fs.readFileSync(messageFile, 'utf8'); + if (content === 'loaded') { + watcher.close(); + fs.writeFileSync(messageFile, 'resolved'); + resolve({ + input: {output1: "main.js"}, output: { dir: "_actual", format: "es" } - }; - \ No newline at end of file + }); + } + } + }); + }); + \ No newline at end of file diff --git a/test/cli/samples/watch/watch-config/rollup.config.js b/test/cli/samples/watch/watch-config/rollup.config.js index 2f5615a36b2..13c3a05fe47 100644 --- a/test/cli/samples/watch/watch-config/rollup.config.js +++ b/test/cli/samples/watch/watch-config/rollup.config.js @@ -1,7 +1 @@ -export default { - input: {output: "main4.js"}, - output: { - dir: "_actual", - format: "es" - } -}; \ No newline at end of file +throw new Error("Config contains initial errors"); \ No newline at end of file diff --git a/test/form/samples/ns-external-star-reexport/_expected/amd.js b/test/form/samples/ns-external-star-reexport/_expected/amd.js index a6985e6d5e8..93459c8c30b 100644 --- a/test/form/samples/ns-external-star-reexport/_expected/amd.js +++ b/test/form/samples/ns-external-star-reexport/_expected/amd.js @@ -2,8 +2,7 @@ define(['external-ns-1', 'external-ns-2'], function (externalNs1, externalNs2) { const val = 5; - var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(externalNs1, externalNs2, { - __proto__: null, + var ns = /*#__PURE__*/Object.freeze(Object.assign(Object.create(null), externalNs1, externalNs2, { val: val })); diff --git a/test/form/samples/ns-external-star-reexport/_expected/cjs.js b/test/form/samples/ns-external-star-reexport/_expected/cjs.js index 8a7644394f7..986e8a89707 100644 --- a/test/form/samples/ns-external-star-reexport/_expected/cjs.js +++ b/test/form/samples/ns-external-star-reexport/_expected/cjs.js @@ -5,8 +5,7 @@ var externalNs2 = require('external-ns-2'); const val = 5; -var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(externalNs1, externalNs2, { - __proto__: null, +var ns = /*#__PURE__*/Object.freeze(Object.assign(Object.create(null), externalNs1, externalNs2, { val: val })); diff --git a/test/form/samples/ns-external-star-reexport/_expected/es.js b/test/form/samples/ns-external-star-reexport/_expected/es.js index b5044bf53e5..b139f881c07 100644 --- a/test/form/samples/ns-external-star-reexport/_expected/es.js +++ b/test/form/samples/ns-external-star-reexport/_expected/es.js @@ -3,8 +3,7 @@ import * as externalNs2 from 'external-ns-2'; const val = 5; -var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(externalNs1, externalNs2, { - __proto__: null, +var ns = /*#__PURE__*/Object.freeze(Object.assign(Object.create(null), externalNs1, externalNs2, { val: val })); diff --git a/test/form/samples/ns-external-star-reexport/_expected/system.js b/test/form/samples/ns-external-star-reexport/_expected/system.js index 4e307c3a236..0ab8d6a72e8 100644 --- a/test/form/samples/ns-external-star-reexport/_expected/system.js +++ b/test/form/samples/ns-external-star-reexport/_expected/system.js @@ -11,8 +11,7 @@ System.register(['external-ns-1', 'external-ns-2'], function (exports) { const val = 5; - var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(externalNs1, externalNs2, { - __proto__: null, + var ns = /*#__PURE__*/Object.freeze(Object.assign(Object.create(null), externalNs1, externalNs2, { val: val })); From 6b43b23ad5609fe726813114f13c463888e08fbe Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Fri, 3 Apr 2020 14:00:53 -0700 Subject: [PATCH 5/8] remove invalid test changes --- test/cli/node_modules/bar/lib/config.js | 11 --------- test/cli/node_modules/bar/package.json | 3 --- .../rollup-config-foo/lib/config.js | 11 --------- .../rollup-config-foo/package.json | 3 --- test/cli/samples/watch/bundle-error/main.js | 2 +- .../rollup.config.js | 23 ++++--------------- .../watch/watch-config/rollup.config.js | 8 ++++++- 7 files changed, 12 insertions(+), 49 deletions(-) delete mode 100644 test/cli/node_modules/bar/lib/config.js delete mode 100644 test/cli/node_modules/bar/package.json delete mode 100644 test/cli/node_modules/rollup-config-foo/lib/config.js delete mode 100644 test/cli/node_modules/rollup-config-foo/package.json diff --git a/test/cli/node_modules/bar/lib/config.js b/test/cli/node_modules/bar/lib/config.js deleted file mode 100644 index 785d84d0212..00000000000 --- a/test/cli/node_modules/bar/lib/config.js +++ /dev/null @@ -1,11 +0,0 @@ -const replace = require( '@rollup/plugin-replace' ); - -module.exports = { - input: 'main.js', - output: { - format: 'cjs' - }, - plugins: [ - replace( { ANSWER: 42 } ) - ] -}; diff --git a/test/cli/node_modules/bar/package.json b/test/cli/node_modules/bar/package.json deleted file mode 100644 index fbd490130d0..00000000000 --- a/test/cli/node_modules/bar/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "main": "lib/config.js" -} diff --git a/test/cli/node_modules/rollup-config-foo/lib/config.js b/test/cli/node_modules/rollup-config-foo/lib/config.js deleted file mode 100644 index 785d84d0212..00000000000 --- a/test/cli/node_modules/rollup-config-foo/lib/config.js +++ /dev/null @@ -1,11 +0,0 @@ -const replace = require( '@rollup/plugin-replace' ); - -module.exports = { - input: 'main.js', - output: { - format: 'cjs' - }, - plugins: [ - replace( { ANSWER: 42 } ) - ] -}; diff --git a/test/cli/node_modules/rollup-config-foo/package.json b/test/cli/node_modules/rollup-config-foo/package.json deleted file mode 100644 index fbd490130d0..00000000000 --- a/test/cli/node_modules/rollup-config-foo/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "main": "lib/config.js" -} diff --git a/test/cli/samples/watch/bundle-error/main.js b/test/cli/samples/watch/bundle-error/main.js index 1352aefa03e..a4012bff06c 100644 --- a/test/cli/samples/watch/bundle-error/main.js +++ b/test/cli/samples/watch/bundle-error/main.js @@ -1 +1 @@ -<=> \ No newline at end of file +export default 42; \ No newline at end of file diff --git a/test/cli/samples/watch/watch-config-early-update/rollup.config.js b/test/cli/samples/watch/watch-config-early-update/rollup.config.js index f6d6c59bddd..ec6ec213bce 100644 --- a/test/cli/samples/watch/watch-config-early-update/rollup.config.js +++ b/test/cli/samples/watch/watch-config-early-update/rollup.config.js @@ -1,24 +1,9 @@ - import path from 'path'; - import fs from 'fs'; - const messageFile = path.resolve(__dirname, '_actual', 'message.txt'); - export default new Promise(resolve => { - fs.writeFileSync(messageFile, 'loading'); - const watcher = fs.watch(messageFile, event => { - if (event === 'change') { - const content = fs.readFileSync(messageFile, 'utf8'); - if (content === 'loaded') { - watcher.close(); - fs.writeFileSync(messageFile, 'resolved'); - resolve({ - input: {output1: "main.js"}, + export default { + input: {output2: "main.js"}, output: { dir: "_actual", format: "es" } - }); - } - } - }); - }); - \ No newline at end of file + }; + \ No newline at end of file diff --git a/test/cli/samples/watch/watch-config/rollup.config.js b/test/cli/samples/watch/watch-config/rollup.config.js index 13c3a05fe47..2f5615a36b2 100644 --- a/test/cli/samples/watch/watch-config/rollup.config.js +++ b/test/cli/samples/watch/watch-config/rollup.config.js @@ -1 +1,7 @@ -throw new Error("Config contains initial errors"); \ No newline at end of file +export default { + input: {output: "main4.js"}, + output: { + dir: "_actual", + format: "es" + } +}; \ No newline at end of file From 8ff2966a758eee08bbf2de5a5f2b701e351a22da Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Sat, 4 Apr 2020 18:09:08 +0200 Subject: [PATCH 6/8] Add pure annotations again, small refactor --- src/Module.ts | 48 +++++++++---------- src/ast/variables/NamespaceVariable.ts | 45 +++++++++-------- .../_expected/amd/main.js | 2 +- .../_expected/cjs/main.js | 2 +- .../_expected/es/main.js | 2 +- .../_expected/system/main.js | 2 +- test/form/samples/compact/_expected/amd.js | 4 +- test/form/samples/compact/_expected/cjs.js | 2 +- test/form/samples/compact/_expected/es.js | 2 +- test/form/samples/compact/_expected/iife.js | 4 +- test/form/samples/compact/_expected/system.js | 2 +- test/form/samples/compact/_expected/umd.js | 4 +- .../namespace-tostringtag/_expected/amd.js | 2 +- .../namespace-tostringtag/_expected/cjs.js | 2 +- .../namespace-tostringtag/_expected/es.js | 2 +- .../namespace-tostringtag/_expected/iife.js | 2 +- .../namespace-tostringtag/_expected/system.js | 2 +- .../namespace-tostringtag/_expected/umd.js | 2 +- .../_expected/amd.js | 2 +- .../_expected/cjs.js | 2 +- .../ns-external-star-reexport/_expected/es.js | 2 +- .../_expected/system.js | 2 +- 22 files changed, 71 insertions(+), 68 deletions(-) diff --git a/src/Module.ts b/src/Module.ts index d967a21e17d..cf2a7ad2fb9 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -5,7 +5,7 @@ import extractAssignedNames from 'rollup-pluginutils/src/extractAssignedNames'; import { createHasEffectsContext, createInclusionContext, - InclusionContext, + InclusionContext } from './ast/ExecutionContext'; import ExportAllDeclaration from './ast/nodes/ExportAllDeclaration'; import ExportDefaultDeclaration from './ast/nodes/ExportDefaultDeclaration'; @@ -42,7 +42,7 @@ import { ResolvedIdMap, RollupError, RollupWarning, - TransformModuleJSON, + TransformModuleJSON } from './rollup/types'; import { error, Errors } from './utils/error'; import getCodeFrame from './utils/getCodeFrame'; @@ -123,7 +123,7 @@ export interface AstContext { export const defaultAcornOptions: acorn.Options = { ecmaVersion: 2020, preserveParens: false, - sourceType: 'module', + sourceType: 'module' }; function tryParse(module: Module, Parser: typeof acorn.Parser, acornOptions: acorn.Options) { @@ -132,7 +132,7 @@ function tryParse(module: Module, Parser: typeof acorn.Parser, acornOptions: aco ...defaultAcornOptions, ...acornOptions, onComment: (block: boolean, text: string, start: number, end: number) => - module.comments.push({ block, text, start, end }), + module.comments.push({ block, text, start, end }) }); } catch (err) { let message = err.message.replace(/ \(\d+:\d+\)$/, ''); @@ -145,7 +145,7 @@ function tryParse(module: Module, Parser: typeof acorn.Parser, acornOptions: aco { code: 'PARSE_ERROR', message, - parserError: err, + parserError: err }, err.pos ); @@ -164,7 +164,7 @@ function handleMissingExport( message: `'${exportName}' is not exported by ${relativeId( importedModule )}, imported by ${relativeId(importingModule.id)}`, - url: `https://rollupjs.org/guide/en/#error-name-is-not-exported-by-module`, + url: `https://rollupjs.org/guide/en/#error-name-is-not-exported-by-module` }, importerStart! ); @@ -172,7 +172,7 @@ function handleMissingExport( const MISSING_EXPORT_SHIM_DESCRIPTION: ExportDescription = { identifier: null, - localName: MISSING_EXPORT_SHIM_VARIABLE, + localName: MISSING_EXPORT_SHIM_VARIABLE }; function getVariableForExportNameRecursive( @@ -290,17 +290,17 @@ export default class Module { loc: { column: location.column, file: this.id, - line: location.line, + line: location.line }, message: `Error when using sourcemap for reporting an error: ${e.message}`, - pos, + pos }); } props.loc = { column: location.column, file: this.id, - line: location.line, + line: location.line }; props.frame = getCodeFrame(this.originalCode, location.line, location.column); } @@ -342,7 +342,7 @@ export default class Module { return error({ code: Errors.SYNTHETIC_NAMED_EXPORTS_NEED_DEFAULT, id: this.id, - message: `Modules with 'syntheticNamedExports' need a default export.`, + message: `Modules with 'syntheticNamedExports' need a default export.` }); } return this.defaultExport; @@ -632,7 +632,7 @@ export default class Module { sourcemapChain, syntheticNamedExports, transformDependencies, - transformFiles, + transformFiles }: TransformModuleJSON & { alwaysRemovedCode?: [number, number][]; transformFiles?: EmittedFile[] | undefined; @@ -678,7 +678,7 @@ export default class Module { this.magicString = new MagicString(code, { filename: (this.excludeFromSourcemap ? null : fileName)!, // don't include plugin helpers in sourcemap - indentExclusionRanges: [], + indentExclusionRanges: [] }); for (const [start, end] of this.alwaysRemovedCode) { this.magicString.remove(start, end); @@ -704,7 +704,7 @@ export default class Module { includeDynamicImport: this.includeDynamicImport.bind(this), includeExternalReexportNamespace: this.includeExternalReexportNamespace.bind(this), includeVariable: this.includeVariable.bind(this), - isCrossChunkImport: (importDescription) => + isCrossChunkImport: importDescription => (importDescription.module as Module).chunk !== this.chunk, magicString: this.magicString, module: this, @@ -722,7 +722,7 @@ export default class Module { this.graph.treeshakingOptions.unknownGlobalSideEffects)!, usesTopLevelAwait: false, warn: this.warn.bind(this), - warnDeprecation: this.graph.warnDeprecation.bind(this.graph), + warnDeprecation: this.graph.warnDeprecation.bind(this.graph) }; this.scope = new ModuleScope(this.graph.scope, this.astContext); @@ -741,7 +741,7 @@ export default class Module { ast: this.esTreeAst, code: this.code, customTransformCache: this.customTransformCache, - dependencies: Array.from(this.dependencies).map((module) => module.id), + dependencies: Array.from(this.dependencies).map(module => module.id), id: this.id, moduleSideEffects: this.moduleSideEffects, originalCode: this.originalCode, @@ -750,7 +750,7 @@ export default class Module { sourcemapChain: this.sourcemapChain, syntheticNamedExports: this.syntheticNamedExports, transformDependencies: this.transformDependencies, - transformFiles: this.transformFiles, + transformFiles: this.transformFiles }; } @@ -811,7 +811,7 @@ export default class Module { this.exports.default = { identifier: node.variable.getAssignedVariableName(), - localName: 'default', + localName: 'default' }; } else if (node instanceof ExportAllDeclaration) { // export * from './other' @@ -831,7 +831,7 @@ export default class Module { specifier.type === NodeType.ExportNamespaceSpecifier ? '*' : specifier.local.name, module: null as any, // filled in later, source, - start: specifier.start, + start: specifier.start }; } } else if (node.declaration) { @@ -872,7 +872,7 @@ export default class Module { return this.error( { code: 'DUPLICATE_IMPORT', - message: `Duplicated import '${localName}'`, + message: `Duplicated import '${localName}'` }, specifier.start ); @@ -890,7 +890,7 @@ export default class Module { module: null as any, // filled in later name, source, - start: specifier.start, + start: specifier.start }; } } @@ -910,9 +910,7 @@ export default class Module { } private includeDynamicImport(node: ImportExpression) { - const resolution = (this.dynamicImports.find( - (dynamicImport) => dynamicImport.node === node - ) as { + const resolution = (this.dynamicImports.find(dynamicImport => dynamicImport.node === node) as { resolution: string | Module | ExternalModule | undefined; }).resolution; if (resolution instanceof Module) { @@ -952,7 +950,7 @@ export default class Module { code: 'SHIMMED_EXPORT', exporter: relativeId(this.id), exportName: name, - message: `Missing export "${name}" has been shimmed in module ${relativeId(this.id)}.`, + message: `Missing export "${name}" has been shimmed in module ${relativeId(this.id)}.` }); this.exports[name] = MISSING_EXPORT_SHIM_DESCRIPTION; } diff --git a/src/ast/variables/NamespaceVariable.ts b/src/ast/variables/NamespaceVariable.ts index 65c124d5758..88ee22eb650 100644 --- a/src/ast/variables/NamespaceVariable.ts +++ b/src/ast/variables/NamespaceVariable.ts @@ -12,9 +12,9 @@ export default class NamespaceVariable extends Variable { isNamespace!: true; memberVariables: { [name: string]: Variable } = Object.create(null); module: Module; - reexportedNamespaces: string[] = []; - private reexportedNamespaceVariables: ExternalVariable[] = []; + private reexportedExternalNamespaces: string[] = []; + private reexportedExternalNamespaceVariables: ExternalVariable[] = []; private referencedEarly = false; private references: Identifier[] = []; private syntheticNamedExports: boolean; @@ -50,8 +50,10 @@ export default class NamespaceVariable extends Variable { break; } } - for (const name of this.reexportedNamespaces) { - this.reexportedNamespaceVariables.push(this.context.includeExternalReexportNamespace(name)); + for (const name of this.reexportedExternalNamespaces) { + this.reexportedExternalNamespaceVariables.push( + this.context.includeExternalReexportNamespace(name) + ); } if (this.context.preserveModules) { for (const memberName of Object.keys(this.memberVariables)) @@ -66,7 +68,7 @@ export default class NamespaceVariable extends Variable { initialise() { for (const name of this.context.getExports().concat(this.context.getReexports())) { if (name[0] === '*' && name.length > 1) { - this.reexportedNamespaces.push(name.slice(1)); + this.reexportedExternalNamespaces.push(name.slice(1)); } else { this.memberVariables[name] = this.context.traceExport(name); } @@ -78,7 +80,7 @@ export default class NamespaceVariable extends Variable { const n = options.compact ? '' : '\n'; const t = options.indent; - const members = Object.keys(this.memberVariables).map((name) => { + const members = Object.keys(this.memberVariables).map(name => { const original = this.memberVariables[name]; if (this.referencedEarly || original.isReassigned) { @@ -92,30 +94,33 @@ export default class NamespaceVariable extends Variable { return `${t}${safeName}: ${original.getName()}`; }); - const objectCreate = this.reexportedNamespaceVariables.length; - if (!objectCreate) members.unshift(`${t}__proto__:${_}null`); - if (options.namespaceToStringTag) { members.unshift(`${t}[Symbol.toStringTag]:${_}'Module'`); } - const name = this.getName(); + // TODO Lukas rename to reflect they are external + const hasExternalReexports = this.reexportedExternalNamespaceVariables.length > 0; + if (!hasExternalReexports) members.unshift(`${t}__proto__:${_}null`); + let output = `{${n}${members.join(`,${n}`)}${n}}`; - if (this.reexportedNamespaceVariables.length) { - output = `Object.assign(Object.create(null), ${this.reexportedNamespaceVariables - .map((v) => v.getName()) - .join(', ')}, ${output}${ - this.syntheticNamedExports ? ', ' + this.module.getDefaultExport().getName() : '' - })`; - if (!options.freeze) output = '*#__PURE__*/' + output; - } else if (this.syntheticNamedExports) { - output = `Object.assign(${output}, ${this.module.getDefaultExport().getName()})`; - if (!options.freeze) output = '*#__PURE__*/' + output; + if (hasExternalReexports || this.syntheticNamedExports) { + const assignmentArgs = [output]; + if (hasExternalReexports) { + assignmentArgs.unshift( + '/*#__PURE__*/Object.create(null)', + ...this.reexportedExternalNamespaceVariables.map(variable => variable.getName()) + ); + } + if (this.syntheticNamedExports) { + assignmentArgs.push(this.module.getDefaultExport().getName()); + } + output = `/*#__PURE__*/Object.assign(${assignmentArgs.join(`,${_}`)})`; } if (options.freeze) { output = `/*#__PURE__*/Object.freeze(${output})`; } + const name = this.getName(); output = `${options.varOrConst} ${name}${_}=${_}${output};`; if (options.format === 'system' && this.exportName) { diff --git a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/amd/main.js b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/amd/main.js index 5731e5c57a5..6285d62559e 100644 --- a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/amd/main.js +++ b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/amd/main.js @@ -6,7 +6,7 @@ define(function () { 'use strict'; }; const foo = 100; - var ns = /*#__PURE__*/Object.freeze(Object.assign({ + var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign({ __proto__: null, foo: foo, 'default': d diff --git a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/cjs/main.js b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/cjs/main.js index 282e6ab8941..f2c1b375abb 100644 --- a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/cjs/main.js +++ b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/cjs/main.js @@ -6,7 +6,7 @@ const d = { }; const foo = 100; -var ns = /*#__PURE__*/Object.freeze(Object.assign({ +var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign({ __proto__: null, foo: foo, 'default': d diff --git a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/es/main.js b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/es/main.js index ab1c380da37..3b23f6d33bb 100644 --- a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/es/main.js +++ b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/es/main.js @@ -4,7 +4,7 @@ const d = { }; const foo = 100; -var ns = /*#__PURE__*/Object.freeze(Object.assign({ +var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign({ __proto__: null, foo: foo, 'default': d diff --git a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/system/main.js b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/system/main.js index 6aecf6312bf..1147e48c999 100644 --- a/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/system/main.js +++ b/test/chunking-form/samples/mixed-synthetic-named-exports/_expected/system/main.js @@ -9,7 +9,7 @@ System.register([], function () { }; const foo = 100; - var ns = /*#__PURE__*/Object.freeze(Object.assign({ + var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign({ __proto__: null, foo: foo, 'default': d diff --git a/test/form/samples/compact/_expected/amd.js b/test/form/samples/compact/_expected/amd.js index 6be712a0259..dfa075b328d 100644 --- a/test/form/samples/compact/_expected/amd.js +++ b/test/form/samples/compact/_expected/amd.js @@ -1,6 +1,6 @@ -define(['external'],function(x){'use strict';x=x&&Object.prototype.hasOwnProperty.call(x,'default')?x['default']:x;var self=/*#__PURE__*/Object.freeze({[Symbol.toStringTag]:'Module',__proto__:null,get default(){return foo}});console.log(self); +define(['external'],function(x){'use strict';x=x&&Object.prototype.hasOwnProperty.call(x,'default')?x['default']:x;var self=/*#__PURE__*/Object.freeze({__proto__:null,[Symbol.toStringTag]:'Module',get default(){return foo}});console.log(self); function foo () { console.log( x ); } // trailing comment -return foo;}); +return foo;}); \ No newline at end of file diff --git a/test/form/samples/compact/_expected/cjs.js b/test/form/samples/compact/_expected/cjs.js index 0c18fd099f3..f52e48bba2a 100644 --- a/test/form/samples/compact/_expected/cjs.js +++ b/test/form/samples/compact/_expected/cjs.js @@ -1,4 +1,4 @@ -'use strict';function _interopDefault(e){return(e&&(typeof e==='object')&&'default'in e)?e['default']:e}var x=_interopDefault(require('external'));var self=/*#__PURE__*/Object.freeze({[Symbol.toStringTag]:'Module',__proto__:null,get default(){return foo}});console.log(self); +'use strict';function _interopDefault(e){return(e&&(typeof e==='object')&&'default'in e)?e['default']:e}var x=_interopDefault(require('external'));var self=/*#__PURE__*/Object.freeze({__proto__:null,[Symbol.toStringTag]:'Module',get default(){return foo}});console.log(self); function foo () { console.log( x ); } diff --git a/test/form/samples/compact/_expected/es.js b/test/form/samples/compact/_expected/es.js index 8440fbc9991..a580d524969 100644 --- a/test/form/samples/compact/_expected/es.js +++ b/test/form/samples/compact/_expected/es.js @@ -1,4 +1,4 @@ -import x from'external';var self=/*#__PURE__*/Object.freeze({[Symbol.toStringTag]:'Module',__proto__:null,get default(){return foo}});console.log(self); +import x from'external';var self=/*#__PURE__*/Object.freeze({__proto__:null,[Symbol.toStringTag]:'Module',get default(){return foo}});console.log(self); function foo () { console.log( x ); } diff --git a/test/form/samples/compact/_expected/iife.js b/test/form/samples/compact/_expected/iife.js index d17c5d43442..e01b3cf90a4 100644 --- a/test/form/samples/compact/_expected/iife.js +++ b/test/form/samples/compact/_expected/iife.js @@ -1,6 +1,6 @@ -var foo=(function(x){'use strict';x=x&&Object.prototype.hasOwnProperty.call(x,'default')?x['default']:x;var self=/*#__PURE__*/Object.freeze({[Symbol.toStringTag]:'Module',__proto__:null,get default(){return foo}});console.log(self); +var foo=(function(x){'use strict';x=x&&Object.prototype.hasOwnProperty.call(x,'default')?x['default']:x;var self=/*#__PURE__*/Object.freeze({__proto__:null,[Symbol.toStringTag]:'Module',get default(){return foo}});console.log(self); function foo () { console.log( x ); } // trailing comment -return foo;}(x)); +return foo;}(x)); \ No newline at end of file diff --git a/test/form/samples/compact/_expected/system.js b/test/form/samples/compact/_expected/system.js index 42b5074a7cb..31cc2cf03b0 100644 --- a/test/form/samples/compact/_expected/system.js +++ b/test/form/samples/compact/_expected/system.js @@ -1,4 +1,4 @@ -System.register('foo',['external'],function(exports){'use strict';var x;return{setters:[function(module){x=module.default;}],execute:function(){exports('default',foo);var self=/*#__PURE__*/Object.freeze({[Symbol.toStringTag]:'Module',__proto__:null,get default(){return foo}});console.log(self); +System.register('foo',['external'],function(exports){'use strict';var x;return{setters:[function(module){x=module.default;}],execute:function(){exports('default',foo);var self=/*#__PURE__*/Object.freeze({__proto__:null,[Symbol.toStringTag]:'Module',get default(){return foo}});console.log(self); function foo () { console.log( x ); } diff --git a/test/form/samples/compact/_expected/umd.js b/test/form/samples/compact/_expected/umd.js index 18250d221e0..0c0b249d51e 100644 --- a/test/form/samples/compact/_expected/umd.js +++ b/test/form/samples/compact/_expected/umd.js @@ -1,6 +1,6 @@ -(function(g,f){typeof exports==='object'&&typeof module!=='undefined'?module.exports=f(require('external')):typeof define==='function'&&define.amd?define(['external'],f):(g=g||self,g.foo=f(g.x));}(this,(function(x){'use strict';x=x&&Object.prototype.hasOwnProperty.call(x,'default')?x['default']:x;var self=/*#__PURE__*/Object.freeze({[Symbol.toStringTag]:'Module',__proto__:null,get default(){return foo}});console.log(self); +(function(g,f){typeof exports==='object'&&typeof module!=='undefined'?module.exports=f(require('external')):typeof define==='function'&&define.amd?define(['external'],f):(g=g||self,g.foo=f(g.x));}(this,(function(x){'use strict';x=x&&Object.prototype.hasOwnProperty.call(x,'default')?x['default']:x;var self=/*#__PURE__*/Object.freeze({__proto__:null,[Symbol.toStringTag]:'Module',get default(){return foo}});console.log(self); function foo () { console.log( x ); } // trailing comment -return foo;}))); +return foo;}))); \ No newline at end of file diff --git a/test/form/samples/namespace-tostringtag/_expected/amd.js b/test/form/samples/namespace-tostringtag/_expected/amd.js index e6ddbfd62f1..28ab2705d81 100644 --- a/test/form/samples/namespace-tostringtag/_expected/amd.js +++ b/test/form/samples/namespace-tostringtag/_expected/amd.js @@ -1,8 +1,8 @@ define(['exports'], function (exports) { 'use strict'; var self = /*#__PURE__*/Object.freeze({ - [Symbol.toStringTag]: 'Module', __proto__: null, + [Symbol.toStringTag]: 'Module', get p () { return p; } }); diff --git a/test/form/samples/namespace-tostringtag/_expected/cjs.js b/test/form/samples/namespace-tostringtag/_expected/cjs.js index 9eb8fe5b21f..97f13a09c4c 100644 --- a/test/form/samples/namespace-tostringtag/_expected/cjs.js +++ b/test/form/samples/namespace-tostringtag/_expected/cjs.js @@ -3,8 +3,8 @@ Object.defineProperty(exports, '__esModule', { value: true }); var self = /*#__PURE__*/Object.freeze({ - [Symbol.toStringTag]: 'Module', __proto__: null, + [Symbol.toStringTag]: 'Module', get p () { return p; } }); diff --git a/test/form/samples/namespace-tostringtag/_expected/es.js b/test/form/samples/namespace-tostringtag/_expected/es.js index b5e71f3c02f..a7cd93962ea 100644 --- a/test/form/samples/namespace-tostringtag/_expected/es.js +++ b/test/form/samples/namespace-tostringtag/_expected/es.js @@ -1,6 +1,6 @@ var self = /*#__PURE__*/Object.freeze({ - [Symbol.toStringTag]: 'Module', __proto__: null, + [Symbol.toStringTag]: 'Module', get p () { return p; } }); diff --git a/test/form/samples/namespace-tostringtag/_expected/iife.js b/test/form/samples/namespace-tostringtag/_expected/iife.js index e03dfc5a3f2..f96940def5c 100644 --- a/test/form/samples/namespace-tostringtag/_expected/iife.js +++ b/test/form/samples/namespace-tostringtag/_expected/iife.js @@ -2,8 +2,8 @@ var iife = (function (exports) { 'use strict'; var self = /*#__PURE__*/Object.freeze({ - [Symbol.toStringTag]: 'Module', __proto__: null, + [Symbol.toStringTag]: 'Module', get p () { return p; } }); diff --git a/test/form/samples/namespace-tostringtag/_expected/system.js b/test/form/samples/namespace-tostringtag/_expected/system.js index 5e4bc576382..5ee50d33a91 100644 --- a/test/form/samples/namespace-tostringtag/_expected/system.js +++ b/test/form/samples/namespace-tostringtag/_expected/system.js @@ -4,8 +4,8 @@ System.register('iife', [], function (exports) { execute: function () { var self = /*#__PURE__*/Object.freeze({ - [Symbol.toStringTag]: 'Module', __proto__: null, + [Symbol.toStringTag]: 'Module', get p () { return p; } }); diff --git a/test/form/samples/namespace-tostringtag/_expected/umd.js b/test/form/samples/namespace-tostringtag/_expected/umd.js index cdc8347fa00..9ae146ed7ad 100644 --- a/test/form/samples/namespace-tostringtag/_expected/umd.js +++ b/test/form/samples/namespace-tostringtag/_expected/umd.js @@ -5,8 +5,8 @@ }(this, (function (exports) { 'use strict'; var self = /*#__PURE__*/Object.freeze({ - [Symbol.toStringTag]: 'Module', __proto__: null, + [Symbol.toStringTag]: 'Module', get p () { return p; } }); diff --git a/test/form/samples/ns-external-star-reexport/_expected/amd.js b/test/form/samples/ns-external-star-reexport/_expected/amd.js index 93459c8c30b..b2b58d5892e 100644 --- a/test/form/samples/ns-external-star-reexport/_expected/amd.js +++ b/test/form/samples/ns-external-star-reexport/_expected/amd.js @@ -2,7 +2,7 @@ define(['external-ns-1', 'external-ns-2'], function (externalNs1, externalNs2) { const val = 5; - var ns = /*#__PURE__*/Object.freeze(Object.assign(Object.create(null), externalNs1, externalNs2, { + var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), externalNs1, externalNs2, { val: val })); diff --git a/test/form/samples/ns-external-star-reexport/_expected/cjs.js b/test/form/samples/ns-external-star-reexport/_expected/cjs.js index 986e8a89707..31fee1d3da4 100644 --- a/test/form/samples/ns-external-star-reexport/_expected/cjs.js +++ b/test/form/samples/ns-external-star-reexport/_expected/cjs.js @@ -5,7 +5,7 @@ var externalNs2 = require('external-ns-2'); const val = 5; -var ns = /*#__PURE__*/Object.freeze(Object.assign(Object.create(null), externalNs1, externalNs2, { +var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), externalNs1, externalNs2, { val: val })); diff --git a/test/form/samples/ns-external-star-reexport/_expected/es.js b/test/form/samples/ns-external-star-reexport/_expected/es.js index b139f881c07..44d164b7849 100644 --- a/test/form/samples/ns-external-star-reexport/_expected/es.js +++ b/test/form/samples/ns-external-star-reexport/_expected/es.js @@ -3,7 +3,7 @@ import * as externalNs2 from 'external-ns-2'; const val = 5; -var ns = /*#__PURE__*/Object.freeze(Object.assign(Object.create(null), externalNs1, externalNs2, { +var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), externalNs1, externalNs2, { val: val })); diff --git a/test/form/samples/ns-external-star-reexport/_expected/system.js b/test/form/samples/ns-external-star-reexport/_expected/system.js index 0ab8d6a72e8..f7d0d98ff2e 100644 --- a/test/form/samples/ns-external-star-reexport/_expected/system.js +++ b/test/form/samples/ns-external-star-reexport/_expected/system.js @@ -11,7 +11,7 @@ System.register(['external-ns-1', 'external-ns-2'], function (exports) { const val = 5; - var ns = /*#__PURE__*/Object.freeze(Object.assign(Object.create(null), externalNs1, externalNs2, { + var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), externalNs1, externalNs2, { val: val })); From c140efc9d21f870fdf50d30b77496f239c6e393e Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Sat, 4 Apr 2020 23:27:53 +0200 Subject: [PATCH 7/8] Simplify namespace handling logic and extend tests --- src/Module.ts | 39 ++++++++++--------- src/ast/variables/NamespaceVariable.ts | 20 +++------- .../ns-external-star-reexport/_config.js | 25 ++++++++++-- .../_expected/amd.js | 22 ++++++++--- .../_expected/cjs.js | 24 ++++++++---- .../ns-external-star-reexport/_expected/es.js | 21 ++++++---- .../_expected/iife.js | 22 +++++++++++ .../_expected/system.js | 25 +++++++----- .../_expected/umd.js | 25 ++++++++++++ .../samples/ns-external-star-reexport/dep.js | 3 -- .../ns-external-star-reexport/extra.js | 1 + .../samples/ns-external-star-reexport/main.js | 5 +-- .../reexport-external.js | 1 + .../reexport-externals-with-override.js | 6 +++ .../_config.js | 27 +++++++++++-- .../internal-reexports-from-external/extra.js | 1 + .../internal-reexports-from-external/main.js | 5 +-- .../{reexport.js => reexport-external.js} | 0 .../reexport-externals-with-override.js | 6 +++ 19 files changed, 199 insertions(+), 79 deletions(-) create mode 100644 test/form/samples/ns-external-star-reexport/_expected/iife.js create mode 100644 test/form/samples/ns-external-star-reexport/_expected/umd.js delete mode 100644 test/form/samples/ns-external-star-reexport/dep.js create mode 100644 test/form/samples/ns-external-star-reexport/extra.js create mode 100644 test/form/samples/ns-external-star-reexport/reexport-external.js create mode 100644 test/form/samples/ns-external-star-reexport/reexport-externals-with-override.js create mode 100644 test/function/samples/internal-reexports-from-external/extra.js rename test/function/samples/internal-reexports-from-external/{reexport.js => reexport-external.js} (100%) create mode 100644 test/function/samples/internal-reexports-from-external/reexport-externals-with-override.js diff --git a/src/Module.ts b/src/Module.ts index cf2a7ad2fb9..48c2426e96f 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -100,8 +100,8 @@ export interface AstContext { getModuleName: () => string; getReexports: () => string[]; importDescriptions: { [name: string]: ImportDescription }; + includeAndGetReexportedExternalNamespaces: () => ExternalVariable[]; includeDynamicImport: (node: ImportExpression) => void; - includeExternalReexportNamespace: (name: string) => ExternalVariable; includeVariable: (context: InclusionContext, variable: Variable) => void; isCrossChunkImport: (importDescription: ImportDescription) => boolean; magicString: MagicString; @@ -199,7 +199,6 @@ export default class Module { chunkName: string | null = null; code!: string; comments: CommentDescription[] = []; - customTransformCache!: boolean; dependencies = new Set(); dynamicallyImportedBy: Module[] = []; dynamicDependencies = new Set(); @@ -209,11 +208,9 @@ export default class Module { }[] = []; excludeFromSourcemap: boolean; execIndex = Infinity; - exportAllModules: (Module | ExternalModule)[] = []; exportAllSources = new Set(); exports: { [name: string]: ExportDescription } = Object.create(null); exportsAll: { [name: string]: string } = Object.create(null); - exportShimVariable: ExportShimVariable = new ExportShimVariable(this); facadeChunk: Chunk | null = null; id: string; importDescriptions: { [name: string]: ImportDescription } = Object.create(null); @@ -241,8 +238,11 @@ export default class Module { private ast!: Program; private astContext!: AstContext; private context: string; + private customTransformCache!: boolean; private defaultExport: ExportDefaultVariable | null | undefined = null; private esTreeAst!: acorn.Node; + private exportAllModules: (Module | ExternalModule)[] = []; + private exportShimVariable: ExportShimVariable = new ExportShimVariable(this); private graph: Graph; private magicString!: MagicString; private namespaceVariable: NamespaceVariable | null = null; @@ -701,8 +701,10 @@ export default class Module { getModuleName: this.basename.bind(this), getReexports: this.getReexports.bind(this), importDescriptions: this.importDescriptions, + includeAndGetReexportedExternalNamespaces: this.includeAndGetReexportedExternalNamespaces.bind( + this + ), includeDynamicImport: this.includeDynamicImport.bind(this), - includeExternalReexportNamespace: this.includeExternalReexportNamespace.bind(this), includeVariable: this.includeVariable.bind(this), isCrossChunkImport: importDescription => (importDescription.module as Module).chunk !== this.chunk, @@ -909,6 +911,19 @@ export default class Module { } } + private includeAndGetReexportedExternalNamespaces(): ExternalVariable[] { + const reexportedExternalNamespaces: ExternalVariable[] = []; + for (const module of this.exportAllModules) { + if (module instanceof ExternalModule) { + const externalVariable = module.getVariableForExportName('*'); + externalVariable.include(); + this.imports.add(externalVariable); + reexportedExternalNamespaces.push(externalVariable); + } + } + return reexportedExternalNamespaces; + } + private includeDynamicImport(node: ImportExpression) { const resolution = (this.dynamicImports.find(dynamicImport => dynamicImport.node === node) as { resolution: string | Module | ExternalModule | undefined; @@ -919,20 +934,6 @@ export default class Module { } } - private includeExternalReexportNamespace(name: string): ExternalVariable { - for (const module of this.exportAllModules) { - if (module instanceof ExternalModule) { - if (module.id === name) { - const externalVariable = module.getVariableForExportName('*'); - externalVariable.include(); - this.imports.add(externalVariable); - return externalVariable; - } - } - } - throw new Error(`Unable to find star reexport ExternalModule instance for ${name}`); - } - private includeVariable(context: InclusionContext, variable: Variable) { const variableModule = variable.module; if (!variable.included) { diff --git a/src/ast/variables/NamespaceVariable.ts b/src/ast/variables/NamespaceVariable.ts index 88ee22eb650..6d495da5b7f 100644 --- a/src/ast/variables/NamespaceVariable.ts +++ b/src/ast/variables/NamespaceVariable.ts @@ -13,8 +13,7 @@ export default class NamespaceVariable extends Variable { memberVariables: { [name: string]: Variable } = Object.create(null); module: Module; - private reexportedExternalNamespaces: string[] = []; - private reexportedExternalNamespaceVariables: ExternalVariable[] = []; + private reexportedExternalNamespaces: ExternalVariable[] = []; private referencedEarly = false; private references: Identifier[] = []; private syntheticNamedExports: boolean; @@ -50,11 +49,7 @@ export default class NamespaceVariable extends Variable { break; } } - for (const name of this.reexportedExternalNamespaces) { - this.reexportedExternalNamespaceVariables.push( - this.context.includeExternalReexportNamespace(name) - ); - } + this.reexportedExternalNamespaces = this.context.includeAndGetReexportedExternalNamespaces(); if (this.context.preserveModules) { for (const memberName of Object.keys(this.memberVariables)) this.memberVariables[memberName].include(context); @@ -67,9 +62,7 @@ export default class NamespaceVariable extends Variable { initialise() { for (const name of this.context.getExports().concat(this.context.getReexports())) { - if (name[0] === '*' && name.length > 1) { - this.reexportedExternalNamespaces.push(name.slice(1)); - } else { + if (name[0] !== '*') { this.memberVariables[name] = this.context.traceExport(name); } } @@ -98,17 +91,16 @@ export default class NamespaceVariable extends Variable { members.unshift(`${t}[Symbol.toStringTag]:${_}'Module'`); } - // TODO Lukas rename to reflect they are external - const hasExternalReexports = this.reexportedExternalNamespaceVariables.length > 0; + const hasExternalReexports = this.reexportedExternalNamespaces.length > 0; if (!hasExternalReexports) members.unshift(`${t}__proto__:${_}null`); let output = `{${n}${members.join(`,${n}`)}${n}}`; if (hasExternalReexports || this.syntheticNamedExports) { - const assignmentArgs = [output]; + const assignmentArgs = members.length > 0 ? [output] : []; if (hasExternalReexports) { assignmentArgs.unshift( '/*#__PURE__*/Object.create(null)', - ...this.reexportedExternalNamespaceVariables.map(variable => variable.getName()) + ...this.reexportedExternalNamespaces.map(variable => variable.getName()) ); } if (this.syntheticNamedExports) { diff --git a/test/form/samples/ns-external-star-reexport/_config.js b/test/form/samples/ns-external-star-reexport/_config.js index bcefef27f22..06cdf4d0268 100644 --- a/test/form/samples/ns-external-star-reexport/_config.js +++ b/test/form/samples/ns-external-star-reexport/_config.js @@ -1,7 +1,24 @@ module.exports = { - description: 'supports namespace external star reexports', - formats: ['amd', 'cjs', 'system', 'es'], + description: 'supports namespaces with external star reexports', options: { - external: ['external-ns-1', 'external-ns-2'], - }, + external: ['external1', 'external2'], + plugins: { + transform(code, id) { + if (id.endsWith('override.js')) { + return { + code, + syntheticNamedExports: true + }; + } + return null; + } + }, + output: { + globals: { + external1: 'external1', + external2: 'external2' + }, + name: 'bundle' + } + } }; diff --git a/test/form/samples/ns-external-star-reexport/_expected/amd.js b/test/form/samples/ns-external-star-reexport/_expected/amd.js index b2b58d5892e..e756846048f 100644 --- a/test/form/samples/ns-external-star-reexport/_expected/amd.js +++ b/test/form/samples/ns-external-star-reexport/_expected/amd.js @@ -1,11 +1,21 @@ -define(['external-ns-1', 'external-ns-2'], function (externalNs1, externalNs2) { 'use strict'; +define(['exports', 'external1', 'external2'], function (exports, external1, external2) { 'use strict'; - const val = 5; + var reexportExternal = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), external1)); - var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), externalNs1, externalNs2, { - val: val - })); + const extra = 'extra'; - return ns; + const override = 'override'; + var reexportExternalsWithOverride = { synthetic: 'synthetic' }; + + var reexportExternalsWithOverride$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), external1, external2, { + override: override, + 'default': reexportExternalsWithOverride, + extra: extra + }, reexportExternalsWithOverride)); + + exports.external = reexportExternal; + exports.externalOverride = reexportExternalsWithOverride$1; + + Object.defineProperty(exports, '__esModule', { value: true }); }); diff --git a/test/form/samples/ns-external-star-reexport/_expected/cjs.js b/test/form/samples/ns-external-star-reexport/_expected/cjs.js index 31fee1d3da4..5cd3ce1a6a0 100644 --- a/test/form/samples/ns-external-star-reexport/_expected/cjs.js +++ b/test/form/samples/ns-external-star-reexport/_expected/cjs.js @@ -1,12 +1,22 @@ 'use strict'; -var externalNs1 = require('external-ns-1'); -var externalNs2 = require('external-ns-2'); +Object.defineProperty(exports, '__esModule', { value: true }); -const val = 5; +var external1 = require('external1'); +var external2 = require('external2'); -var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), externalNs1, externalNs2, { - val: val -})); +var reexportExternal = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), external1)); -module.exports = ns; +const extra = 'extra'; + +const override = 'override'; +var reexportExternalsWithOverride = { synthetic: 'synthetic' }; + +var reexportExternalsWithOverride$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), external1, external2, { + override: override, + 'default': reexportExternalsWithOverride, + extra: extra +}, reexportExternalsWithOverride)); + +exports.external = reexportExternal; +exports.externalOverride = reexportExternalsWithOverride$1; diff --git a/test/form/samples/ns-external-star-reexport/_expected/es.js b/test/form/samples/ns-external-star-reexport/_expected/es.js index 44d164b7849..c4fd6f26ef8 100644 --- a/test/form/samples/ns-external-star-reexport/_expected/es.js +++ b/test/form/samples/ns-external-star-reexport/_expected/es.js @@ -1,10 +1,17 @@ -import * as externalNs1 from 'external-ns-1'; -import * as externalNs2 from 'external-ns-2'; +import * as external1 from 'external1'; +import * as external2 from 'external2'; -const val = 5; +var reexportExternal = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), external1)); -var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), externalNs1, externalNs2, { - val: val -})); +const extra = 'extra'; -export default ns; +const override = 'override'; +var reexportExternalsWithOverride = { synthetic: 'synthetic' }; + +var reexportExternalsWithOverride$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), external1, external2, { + override: override, + 'default': reexportExternalsWithOverride, + extra: extra +}, reexportExternalsWithOverride)); + +export { reexportExternal as external, reexportExternalsWithOverride$1 as externalOverride }; diff --git a/test/form/samples/ns-external-star-reexport/_expected/iife.js b/test/form/samples/ns-external-star-reexport/_expected/iife.js new file mode 100644 index 00000000000..93e3f50b66b --- /dev/null +++ b/test/form/samples/ns-external-star-reexport/_expected/iife.js @@ -0,0 +1,22 @@ +var bundle = (function (exports, external1, external2) { + 'use strict'; + + var reexportExternal = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), external1)); + + const extra = 'extra'; + + const override = 'override'; + var reexportExternalsWithOverride = { synthetic: 'synthetic' }; + + var reexportExternalsWithOverride$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), external1, external2, { + override: override, + 'default': reexportExternalsWithOverride, + extra: extra + }, reexportExternalsWithOverride)); + + exports.external = reexportExternal; + exports.externalOverride = reexportExternalsWithOverride$1; + + return exports; + +}({}, external1, external2)); diff --git a/test/form/samples/ns-external-star-reexport/_expected/system.js b/test/form/samples/ns-external-star-reexport/_expected/system.js index f7d0d98ff2e..7a209f559a9 100644 --- a/test/form/samples/ns-external-star-reexport/_expected/system.js +++ b/test/form/samples/ns-external-star-reexport/_expected/system.js @@ -1,21 +1,28 @@ -System.register(['external-ns-1', 'external-ns-2'], function (exports) { +System.register('bundle', ['external1', 'external2'], function (exports) { 'use strict'; - var externalNs1, externalNs2; + var external1, external2; return { setters: [function (module) { - externalNs1 = module; + external1 = module; }, function (module) { - externalNs2 = module; + external2 = module; }], execute: function () { - const val = 5; + var reexportExternal = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), external1)); + exports('external', reexportExternal); - var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), externalNs1, externalNs2, { - val: val - })); + const extra = 'extra'; - exports('default', ns); + const override = 'override'; + var reexportExternalsWithOverride = { synthetic: 'synthetic' }; + + var reexportExternalsWithOverride$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), external1, external2, { + override: override, + 'default': reexportExternalsWithOverride, + extra: extra + }, reexportExternalsWithOverride)); + exports('externalOverride', reexportExternalsWithOverride$1); } }; diff --git a/test/form/samples/ns-external-star-reexport/_expected/umd.js b/test/form/samples/ns-external-star-reexport/_expected/umd.js new file mode 100644 index 00000000000..9baac1a2697 --- /dev/null +++ b/test/form/samples/ns-external-star-reexport/_expected/umd.js @@ -0,0 +1,25 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('external1'), require('external2')) : + typeof define === 'function' && define.amd ? define(['exports', 'external1', 'external2'], factory) : + (global = global || self, factory(global.bundle = {}, global.external1, global.external2)); +}(this, (function (exports, external1, external2) { 'use strict'; + + var reexportExternal = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), external1)); + + const extra = 'extra'; + + const override = 'override'; + var reexportExternalsWithOverride = { synthetic: 'synthetic' }; + + var reexportExternalsWithOverride$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), external1, external2, { + override: override, + 'default': reexportExternalsWithOverride, + extra: extra + }, reexportExternalsWithOverride)); + + exports.external = reexportExternal; + exports.externalOverride = reexportExternalsWithOverride$1; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/samples/ns-external-star-reexport/dep.js b/test/form/samples/ns-external-star-reexport/dep.js deleted file mode 100644 index 58c6940cda6..00000000000 --- a/test/form/samples/ns-external-star-reexport/dep.js +++ /dev/null @@ -1,3 +0,0 @@ -export * from 'external-ns-1'; -export * from 'external-ns-2'; -export const val = 5; diff --git a/test/form/samples/ns-external-star-reexport/extra.js b/test/form/samples/ns-external-star-reexport/extra.js new file mode 100644 index 00000000000..feedf51e56d --- /dev/null +++ b/test/form/samples/ns-external-star-reexport/extra.js @@ -0,0 +1 @@ +export const extra = 'extra'; diff --git a/test/form/samples/ns-external-star-reexport/main.js b/test/form/samples/ns-external-star-reexport/main.js index c2c65d4785f..d61257fb7d0 100644 --- a/test/form/samples/ns-external-star-reexport/main.js +++ b/test/form/samples/ns-external-star-reexport/main.js @@ -1,3 +1,2 @@ -import * as ns from './dep.js'; - -export default ns; +export * as external from './reexport-external.js'; +export * as externalOverride from './reexport-externals-with-override.js'; diff --git a/test/form/samples/ns-external-star-reexport/reexport-external.js b/test/form/samples/ns-external-star-reexport/reexport-external.js new file mode 100644 index 00000000000..982df4d556e --- /dev/null +++ b/test/form/samples/ns-external-star-reexport/reexport-external.js @@ -0,0 +1 @@ +export * from 'external1'; diff --git a/test/form/samples/ns-external-star-reexport/reexport-externals-with-override.js b/test/form/samples/ns-external-star-reexport/reexport-externals-with-override.js new file mode 100644 index 00000000000..15e4c2e3794 --- /dev/null +++ b/test/form/samples/ns-external-star-reexport/reexport-externals-with-override.js @@ -0,0 +1,6 @@ +export * from 'external1'; +export * from 'external2'; +export * from './extra.js'; +export const override = 'override'; +export default { synthetic: 'synthetic' }; + diff --git a/test/function/samples/internal-reexports-from-external/_config.js b/test/function/samples/internal-reexports-from-external/_config.js index 925496d0db8..be14c091434 100644 --- a/test/function/samples/internal-reexports-from-external/_config.js +++ b/test/function/samples/internal-reexports-from-external/_config.js @@ -1,12 +1,31 @@ const assert = require('assert'); const fs = require('fs'); +const path = require('path'); module.exports = { description: 'supports namespaces with external star reexports', options: { - external: ['fs'], - }, - exports(ns) { - assert.strictEqual(ns.namespace.readFile, fs.readFile); + external: ['fs', 'path'], + plugins: { + transform(code, id) { + if (id.endsWith('override.js')) { + return { + code, + syntheticNamedExports: true + }; + } + return null; + } + } }, + exports(exports) { + assert.strictEqual(exports.fs.readFile, fs.readFile); + assert.deepStrictEqual(Object.keys(exports.fs), Object.keys(fs)); + assert.notStrictEqual(exports.fsOverride.readFile, fs.readFile); + assert.strictEqual(exports.fsOverride.readFile, 'override'); + assert.strictEqual(exports.fsOverride.extra, 'extra'); + assert.strictEqual(exports.fsOverride.synthetic, 'synthetic'); + assert.strictEqual(exports.fsOverride.synthetic, 'synthetic'); + assert.strictEqual(exports.fsOverride.dirname, path.dirname); + } }; diff --git a/test/function/samples/internal-reexports-from-external/extra.js b/test/function/samples/internal-reexports-from-external/extra.js new file mode 100644 index 00000000000..feedf51e56d --- /dev/null +++ b/test/function/samples/internal-reexports-from-external/extra.js @@ -0,0 +1 @@ +export const extra = 'extra'; diff --git a/test/function/samples/internal-reexports-from-external/main.js b/test/function/samples/internal-reexports-from-external/main.js index b127cee7d4d..64b276a3d87 100644 --- a/test/function/samples/internal-reexports-from-external/main.js +++ b/test/function/samples/internal-reexports-from-external/main.js @@ -1,3 +1,2 @@ -import * as namespace from './reexport.js'; - -export { namespace }; +export * as fs from './reexport-external.js'; +export * as fsOverride from './reexport-externals-with-override.js'; diff --git a/test/function/samples/internal-reexports-from-external/reexport.js b/test/function/samples/internal-reexports-from-external/reexport-external.js similarity index 100% rename from test/function/samples/internal-reexports-from-external/reexport.js rename to test/function/samples/internal-reexports-from-external/reexport-external.js diff --git a/test/function/samples/internal-reexports-from-external/reexport-externals-with-override.js b/test/function/samples/internal-reexports-from-external/reexport-externals-with-override.js new file mode 100644 index 00000000000..a7d80cbe344 --- /dev/null +++ b/test/function/samples/internal-reexports-from-external/reexport-externals-with-override.js @@ -0,0 +1,6 @@ +export * from 'fs'; +export * from 'path'; +export * from './extra.js'; +export const readFile = 'override'; +export default { synthetic: 'synthetic' }; + From a390b33a109952cceb65b3d538c775064ca2c364 Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Sat, 4 Apr 2020 23:46:25 +0200 Subject: [PATCH 8/8] Improve coverage --- src/Module.ts | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/src/Module.ts b/src/Module.ts index 48c2426e96f..4c7ccd8ae2c 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -103,7 +103,6 @@ export interface AstContext { includeAndGetReexportedExternalNamespaces: () => ExternalVariable[]; includeDynamicImport: (node: ImportExpression) => void; includeVariable: (context: InclusionContext, variable: Variable) => void; - isCrossChunkImport: (importDescription: ImportDescription) => boolean; magicString: MagicString; module: Module; // not to be used for tree-shaking moduleContext: string; @@ -706,8 +705,6 @@ export default class Module { ), includeDynamicImport: this.includeDynamicImport.bind(this), includeVariable: this.includeVariable.bind(this), - isCrossChunkImport: importDescription => - (importDescription.module as Module).chunk !== this.chunk, magicString: this.magicString, module: this, moduleContext: this.context, @@ -868,18 +865,6 @@ export default class Module { const source = node.source.value; this.sources.add(source); for (const specifier of node.specifiers) { - const localName = specifier.local.name; - - if (this.importDescriptions[localName]) { - return this.error( - { - code: 'DUPLICATE_IMPORT', - message: `Duplicated import '${localName}'` - }, - specifier.start - ); - } - const isDefault = specifier.type === NodeType.ImportDefaultSpecifier; const isNamespace = specifier.type === NodeType.ImportNamespaceSpecifier; @@ -888,7 +873,7 @@ export default class Module { : isNamespace ? '*' : (specifier as ImportSpecifier).imported.name; - this.importDescriptions[localName] = { + this.importDescriptions[specifier.local.name] = { module: null as any, // filled in later name, source, @@ -946,14 +931,12 @@ export default class Module { } private shimMissingExport(name: string): void { - if (!this.exports[name]) { - this.graph.warn({ - code: 'SHIMMED_EXPORT', - exporter: relativeId(this.id), - exportName: name, - message: `Missing export "${name}" has been shimmed in module ${relativeId(this.id)}.` - }); - this.exports[name] = MISSING_EXPORT_SHIM_DESCRIPTION; - } + this.graph.warn({ + code: 'SHIMMED_EXPORT', + exporter: relativeId(this.id), + exportName: name, + message: `Missing export "${name}" has been shimmed in module ${relativeId(this.id)}.` + }); + this.exports[name] = MISSING_EXPORT_SHIM_DESCRIPTION; } }