Skip to content
Permalink
Browse files
Merge branch 'chunk-export-mode-fix'
  • Loading branch information
lukastaegert committed May 15, 2018
2 parents f837dd0 + 32913d0 commit 4fbdd1d212a3bfab92b860e38b84f11635ab31b3
Showing 26 changed files with 194 additions and 65 deletions.
@@ -10,6 +10,7 @@
* Improve handling of external modules imported as both default and named imports ([#2136](https://github.com/rollup/rollup/pull/2136))
* Properly deconflict named imports from other chunks ([#2177](https://github.com/rollup/rollup/pull/2177))
* Fix an issue with namespaces containing reexports ([#2157](https://github.com/rollup/rollup/pull/2157))
* Fix an issue with with incorrectly mapped default exports when code-splitting CJS or AMD modules ([#2178](https://github.com/rollup/rollup/pull/2178))
* Fix an issue with wrong paths of relative external imports ([#2160](https://github.com/rollup/rollup/pull/2160))
* Fix an issue when using default exports and `interop: false` ([#2149](https://github.com/rollup/rollup/pull/2149))
* Fix in issue with invalid syntax in SystemJS output ([#2187](https://github.com/rollup/rollup/pull/2187))
@@ -2,7 +2,6 @@ import { timeEnd, timeStart } from './utils/timers';
import MagicString, { Bundle as MagicStringBundle, SourceMap } from 'magic-string';
import Module from './Module';
import finalisers from './finalisers/index';
import getExportMode from './utils/getExportMode';
import getIndentString from './utils/getIndentString';
import transformBundle from './utils/transformBundle';
import collapseSourcemaps from './utils/collapseSourcemaps';
@@ -31,6 +30,7 @@ export interface ModuleDeclarations {

export interface ModuleDeclarationDependency {
id: string;
namedExportsMode: boolean;
name: string;
globalName: string;
isChunk: boolean;
@@ -83,6 +83,7 @@ function getGlobalName(
export default class Chunk {
hasDynamicImport: boolean = false;
indentString: string = undefined;
exportMode: string = 'named';
usedModules: Module[] = undefined;
id: string = undefined;
name: string;
@@ -503,7 +504,9 @@ export default class Chunk {
safeName = getSafeName(variable.name);
toDeshadow.add(safeName);
} else {
safeName = `${(<Module>module).chunk.name}.${module.chunk.getVariableExportName(variable)}`;
const chunk = (<Module>module).chunk;
if (chunk.exportMode === 'default') safeName = chunk.name;
else safeName = `${chunk.name}.${module.chunk.getVariableExportName(variable)}`;
}
if (safeName) variable.setSafeName(safeName);
});
@@ -618,10 +621,9 @@ export default class Chunk {
}
}

// id is left undefined for other chunks for now
// this will be populated on render
dependencies.push({
id,
id, // chunk id updated on render
namedExportsMode: true, // default mode updated on render
globalName,
name: dep.name,
isChunk: !(<ExternalModule>dep).isExternal,
@@ -801,7 +803,7 @@ export default class Chunk {

this.renderedDeclarations = {
dependencies: this.getChunkDependencyDeclarations(options, inputBase),
exports: this.getChunkExportDeclarations()
exports: this.exportMode === 'none' ? [] : this.getChunkExportDeclarations()
};

timeEnd('render modules', 3);
@@ -966,9 +968,6 @@ export default class Chunk {
if (!this.renderedSource)
throw new Error('Internal error: Chunk render called before preRender');

// Determine export mode - 'default', 'named', 'none'
const exportMode = this.isEntryModuleFacade ? getExportMode(this, options) : 'named';

const finalise = finalisers[options.format];
if (!finalise) {
error({
@@ -984,22 +983,32 @@ export default class Chunk {
for (let i = 0; i < this.dependencies.length; i++) {
const dep = this.dependencies[i];
if (dep instanceof ExternalModule && !dep.renormalizeRenderPath) continue;

const renderedDependency = this.renderedDeclarations.dependencies[i];

let depId = dep instanceof ExternalModule ? renderedDependency.id : dep.id;
let relPath = this.id ? normalize(relative(dirname(this.id), depId)) : depId;
if (!relPath.startsWith('../')) relPath = './' + relPath;

if (dep instanceof Chunk) renderedDependency.namedExportsMode = dep.exportMode !== 'default';
renderedDependency.id = relPath;
}

if (this.graph.dynamicImport) this.finaliseDynamicImports();

const hasImportMeta = this.orderedModules.some(module => module.hasImportMeta);
const hasExports =
this.renderedDeclarations.exports.length !== 0 ||
this.renderedDeclarations.dependencies.some(
dep => dep.reexports && dep.reexports.length !== 0
);

const magicString = finalise(
this.renderedSource,
{
exportMode,
indentString: this.indentString,
namedExportsMode: this.exportMode !== 'default',
hasExports,
intro: addons.intro,
outro: addons.outro,
dynamicImport: this.hasDynamicImport,
@@ -10,7 +10,8 @@ export default function amd(
magicString: MagicStringBundle,
{
graph,
exportMode,
namedExportsMode,
hasExports,
indentString,
intro,
outro,
@@ -27,7 +28,7 @@ export default function amd(
const deps = dependencies.map(m => `'${m.id}'`);
const args = dependencies.map(m => m.name);

if (exportMode === 'named') {
if (namedExportsMode && hasExports) {
args.unshift(`exports`);
deps.unshift(`'exports'`);
}
@@ -57,9 +58,9 @@ export default function amd(

if (intro) magicString.prepend(intro);

const exportBlock = getExportBlock(exports, dependencies, exportMode, options.interop);
const exportBlock = getExportBlock(exports, dependencies, namedExportsMode, options.interop);
if (exportBlock) magicString.append('\n\n' + exportBlock);
if (exportMode === 'named' && options.legacy !== true && isEntryModuleFacade)
if (namedExportsMode && hasExports && options.legacy !== true && isEntryModuleFacade)
magicString.append(`\n\n${esModuleExport}`);
if (outro) magicString.append(outro);

@@ -6,12 +6,21 @@ import { FinaliserOptions } from './index';

export default function cjs(
magicString: MagicStringBundle,
{ graph, isEntryModuleFacade, exportMode, intro, outro, dependencies, exports }: FinaliserOptions,
{
graph,
isEntryModuleFacade,
namedExportsMode,
hasExports,
intro,
outro,
dependencies,
exports
}: FinaliserOptions,
options: OutputOptions
) {
intro =
(options.strict === false ? intro : `'use strict';\n\n${intro}`) +
(exportMode === 'named' && options.legacy !== true && isEntryModuleFacade
(namedExportsMode && hasExports && options.legacy !== true && isEntryModuleFacade
? `${esModuleExport}\n\n`
: '');

@@ -21,26 +30,37 @@ export default function cjs(
const interop = options.interop !== false;

const importBlock = dependencies
.map(({ id, isChunk, name, reexports, imports, exportsNames, exportsDefault }) => {
if (!reexports && !imports) {
return `require('${id}');`;
}
.map(
({
id,
namedExportsMode,
isChunk,
name,
reexports,
imports,
exportsNames,
exportsDefault
}) => {
if (!reexports && !imports) {
return `require('${id}');`;
}

if (!interop || isChunk || !exportsDefault) {
return `${varOrConst} ${name} = require('${id}');`;
}
if (!interop || isChunk || !exportsDefault || !namedExportsMode) {
return `${varOrConst} ${name} = require('${id}');`;
}

needsInterop = true;
needsInterop = true;

if (exportsNames) {
return (
`${varOrConst} ${name} = require('${id}');` +
`\n${varOrConst} ${name}__default = _interopDefault(${name});`
);
}
if (exportsNames) {
return (
`${varOrConst} ${name} = require('${id}');` +
`\n${varOrConst} ${name}__default = _interopDefault(${name});`
);
}

return `${varOrConst} ${name} = _interopDefault(require('${id}'));`;
})
return `${varOrConst} ${name} = _interopDefault(require('${id}'));`;
}
)
.join('\n');

if (needsInterop) {
@@ -54,7 +74,7 @@ export default function cjs(
const exportBlock = getExportBlock(
exports,
dependencies,
exportMode,
namedExportsMode,
options.interop,
'module.exports ='
);
@@ -14,7 +14,16 @@ const thisProp = (name: string) => `this${keypath(name)}`;

export default function iife(
magicString: MagicStringBundle,
{ graph, exportMode, indentString, intro, outro, dependencies, exports }: FinaliserOptions,
{
graph,
namedExportsMode,
hasExports,
indentString,
intro,
outro,
dependencies,
exports
}: FinaliserOptions,
options: OutputOptions
) {
const { extend, name } = options;
@@ -34,7 +43,7 @@ export default function iife(
const deps = external.map(dep => dep.globalName || 'null');
const args = external.map(m => m.name);

if (exportMode !== 'none' && !name) {
if (hasExports && !name) {
error({
code: 'INVALID_OPTION',
message: `You must supply output.name for IIFE bundles`
@@ -44,7 +53,7 @@ export default function iife(
if (extend) {
deps.unshift(`(${thisProp(name)} = ${thisProp(name)} || {})`);
args.unshift('exports');
} else if (exportMode === 'named') {
} else if (namedExportsMode && hasExports) {
deps.unshift('{}');
args.unshift('exports');
}
@@ -53,7 +62,7 @@ export default function iife(

let wrapperIntro = `(function (${args}) {\n${useStrict}`;

if (exportMode !== 'none' && !extend) {
if (hasExports && !extend) {
wrapperIntro =
(isNamespaced ? thisProp(name) : `${graph.varOrConst} ${name}`) + ` = ${wrapperIntro}`;
}
@@ -64,7 +73,7 @@ export default function iife(

let wrapperOutro = `\n\n}(${deps}));`;

if (!extend && exportMode === 'named') {
if (!extend && namedExportsMode && hasExports) {
wrapperOutro = `\n\n${indentString}return exports;${wrapperOutro}`;
}

@@ -74,7 +83,7 @@ export default function iife(

if (intro) magicString.prepend(intro);

const exportBlock = getExportBlock(exports, dependencies, exportMode, options.interop);
const exportBlock = getExportBlock(exports, dependencies, namedExportsMode, options.interop);
if (exportBlock) magicString.append('\n\n' + exportBlock);
if (outro) magicString.append(outro);

@@ -10,8 +10,9 @@ import { OutputOptions } from '../rollup/types';
import Graph from '../Graph';

export interface FinaliserOptions {
exportMode: string;
indentString: string;
namedExportsMode: boolean;
hasExports: boolean;
intro: string;
outro: string;
dynamicImport: boolean;
@@ -3,11 +3,11 @@ import { ChunkExports, ChunkDependencies } from '../../Chunk';
export default function getExportBlock(
exports: ChunkExports,
dependencies: ChunkDependencies,
exportMode: string,
namedExportsMode: boolean,
interop: boolean,
mechanism = 'return'
) {
if (exportMode === 'default') {
if (!namedExportsMode) {
let local;
exports.some(expt => {
if (expt.exported === 'default') {
@@ -22,7 +22,7 @@ export default function getExportBlock(
if (!dep.reexports) return false;
return dep.reexports.some(expt => {
if (expt.reexported === 'default') {
local = `${dep.name}.${expt.imported}`;
local = dep.namedExportsMode ? `${dep.name}.${expt.imported}` : dep.name;
return true;
}
return false;
@@ -36,7 +36,7 @@ export default function getExportBlock(

// star exports must always output first for precedence
dependencies.forEach(({ name, reexports }) => {
if (reexports && exportMode !== 'default') {
if (reexports && namedExportsMode) {
reexports.forEach(specifier => {
if (specifier.reexported === '*') {
exportBlock += `${
@@ -48,7 +48,7 @@ export default function getExportBlock(
});

dependencies.forEach(({ name, imports, reexports, isChunk }) => {
if (reexports && exportMode !== 'default') {
if (reexports && namedExportsMode) {
reexports.forEach(specifier => {
if (specifier.imported === 'default' && !isChunk) {
const exportsNamesOrNamespace =
@@ -7,7 +7,9 @@ export default function getInteropBlock(
varOrConst: string
) {
return dependencies
.map(({ name, exportsNames, exportsDefault }) => {
.map(({ name, exportsNames, exportsDefault, namedExportsMode }) => {
if (!namedExportsMode) return;

if (!exportsDefault || options.interop === false) return null;

if (exportsNames)

0 comments on commit 4fbdd1d

Please sign in to comment.