Skip to content

Commit

Permalink
Fix and improve default export alias logic (#3521)
Browse files Browse the repository at this point in the history
* Create failing test

* Improve default export short-cut handling

* Improve names

* Improve coverage
  • Loading branch information
lukastaegert committed Apr 29, 2020
1 parent 8db16bd commit e4f4d6a
Show file tree
Hide file tree
Showing 114 changed files with 370 additions and 252 deletions.
16 changes: 8 additions & 8 deletions src/Chunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -769,15 +769,13 @@ export default class Chunk {
for (const dep of this.dependencies) {
const imports: ImportSpecifier[] = [];
for (const variable of this.imports) {
const renderedVariable =
variable instanceof ExportDefaultVariable ? variable.getOriginalVariable() : variable;
if (
(variable.module instanceof Module
? variable.module.chunk === dep
: variable.module === dep) &&
!renderedImports.has(renderedVariable)
!renderedImports.has(variable)
) {
renderedImports.add(renderedVariable);
renderedImports.add(variable);
imports.push({
imported:
variable.module instanceof ExternalModule
Expand Down Expand Up @@ -1007,10 +1005,12 @@ export default class Chunk {

private setUpChunkImportsAndExportsForModule(module: Module) {
for (let variable of module.imports) {
if (variable instanceof SyntheticNamedExportVariable) {
variable = variable.getBaseVariable();
} else if (variable instanceof ExportDefaultVariable) {
variable = variable.getOriginalVariable();
}
if ((variable.module as Module).chunk !== this) {
if (variable instanceof SyntheticNamedExportVariable) {
variable = variable.getOriginalVariable();
}
this.imports.add(variable);
if (
!(variable instanceof NamespaceVariable && this.graph.preserveModules) &&
Expand All @@ -1029,7 +1029,7 @@ export default class Chunk {
this.exports.add(exportedVariable);
const isSynthetic = exportedVariable instanceof SyntheticNamedExportVariable;
const importedVariable = isSynthetic
? (exportedVariable as SyntheticNamedExportVariable).getOriginalVariable()
? (exportedVariable as SyntheticNamedExportVariable).getBaseVariable()
: exportedVariable;
const exportingModule = importedVariable.module;
if (
Expand Down
35 changes: 20 additions & 15 deletions src/Module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ export default class Module {
private astContext!: AstContext;
private context: string;
private customTransformCache!: boolean;
private defaultExport: ExportDefaultVariable | null | undefined = null;
private defaultExport: Variable | null | undefined = null;
private esTreeAst!: acorn.Node;
private exportAllModules: (Module | ExternalModule)[] = [];
private exportNamesByVariable: Map<Variable, string[]> | null = null;
Expand Down Expand Up @@ -324,7 +324,7 @@ export default class Module {
getDefaultExport() {
if (this.defaultExport === null) {
this.defaultExport = undefined;
this.defaultExport = this.getVariableForExportName('default') as ExportDefaultVariable;
this.defaultExport = this.getVariableForExportName('default');
}
if (!this.defaultExport) {
return error({
Expand All @@ -339,21 +339,23 @@ export default class Module {
getDependenciesToBeIncluded(): Set<Module | ExternalModule> {
if (this.relevantDependencies) return this.relevantDependencies;
const relevantDependencies = new Set<Module | ExternalModule>();
for (const variable of this.imports) {
relevantDependencies.add(
variable instanceof SyntheticNamedExportVariable
? variable.getOriginalVariable().module!
: variable.module!
);
for (let variable of this.imports) {
if (variable instanceof SyntheticNamedExportVariable) {
variable = variable.getBaseVariable();
} else if (variable instanceof ExportDefaultVariable) {
variable = variable.getOriginalVariable();
}
relevantDependencies.add(variable.module!);
}
if (this.isEntryPoint || this.dynamicallyImportedBy.length > 0 || this.graph.preserveModules) {
for (const exportName of [...this.getReexports(), ...this.getExports()]) {
const variable = this.getVariableForExportName(exportName);
relevantDependencies.add(
variable instanceof SyntheticNamedExportVariable
? variable.getOriginalVariable().module!
: variable.module!
);
let variable = this.getVariableForExportName(exportName);
if (variable instanceof SyntheticNamedExportVariable) {
variable = variable.getBaseVariable();
} else if (variable instanceof ExportDefaultVariable) {
variable = variable.getOriginalVariable();
}
relevantDependencies.add(variable.module!);
}
}
if (this.graph.treeshakingOptions) {
Expand Down Expand Up @@ -402,7 +404,10 @@ export default class Module {
}
const exportNamesByVariable: Map<Variable, string[]> = new Map();
for (const exportName of this.getAllExportNames()) {
const tracedVariable = this.getVariableForExportName(exportName);
let tracedVariable = this.getVariableForExportName(exportName);
if (tracedVariable instanceof ExportDefaultVariable) {
tracedVariable = tracedVariable.getOriginalVariable();
}
if (
!tracedVariable ||
!(tracedVariable.included || tracedVariable instanceof ExternalVariable)
Expand Down
14 changes: 3 additions & 11 deletions src/ast/nodes/ExportDefaultDeclaration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ import { ExpressionNode, IncludeChildren, NodeBase } from './shared/Node';
const WHITESPACE = /\s/;

// The header ends at the first non-white-space after "default"
function getDeclarationStart(code: string, start = 0) {
function getDeclarationStart(code: string, start: number) {
start = findFirstOccurrenceOutsideComment(code, 'default', start) + 7;
while (WHITESPACE.test(code[start])) start++;
return start;
}

function getIdInsertPosition(code: string, declarationKeyword: string, start = 0) {
function getIdInsertPosition(code: string, declarationKeyword: string, start: number) {
const declarationEnd =
findFirstOccurrenceOutsideComment(code, declarationKeyword, start) + declarationKeyword.length;
code = code.slice(declarationEnd, findFirstOccurrenceOutsideComment(code, '{', declarationEnd));
Expand Down Expand Up @@ -84,15 +84,7 @@ export default class ExportDefaultDeclaration extends NodeBase {
);
} else if (this.variable.getOriginalVariable() !== this.variable) {
// Remove altogether to prevent re-declaring the same variable
if (options.format === 'system' && this.variable.exportName) {
code.overwrite(
start,
end,
`exports('${this.variable.exportName}', ${this.variable.getName()});`
);
} else {
treeshakeNode(this, code, start, end);
}
treeshakeNode(this, code, start, end);
return;
} else if (this.variable.included) {
this.renderVariableDeclaration(code, declarationStart, options);
Expand Down
18 changes: 0 additions & 18 deletions src/ast/variables/ExportDefaultVariable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,22 +73,4 @@ export default class ExportDefaultVariable extends LocalVariable {
}
return this.originalVariable;
}

setRenderNames(baseName: string | null, name: string | null) {
const original = this.getOriginalVariable();
if (original === this) {
super.setRenderNames(baseName, name);
} else {
original.setRenderNames(baseName, name);
}
}

setSafeName(name: string | null) {
const original = this.getOriginalVariable();
if (original === this) {
super.setSafeName(name);
} else {
original.setSafeName(name);
}
}
}
15 changes: 8 additions & 7 deletions src/ast/variables/SyntheticNamedExportVariable.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
import Module, { AstContext } from '../../Module';
import ExportDefaultVariable from './ExportDefaultVariable';
import Variable from './Variable';

export default class SyntheticNamedExportVariable extends Variable {
context: AstContext;
defaultVariable: ExportDefaultVariable;
defaultVariable: Variable;
module: Module;

constructor(context: AstContext, name: string, defaultVariable: ExportDefaultVariable) {
constructor(context: AstContext, name: string, defaultVariable: Variable) {
super(name);
this.context = context;
this.module = context.module;
this.defaultVariable = defaultVariable;
}

getBaseVariable(): Variable {
return this.defaultVariable instanceof SyntheticNamedExportVariable
? this.defaultVariable.getBaseVariable()
: this.defaultVariable;
}

getName(): string {
const name = this.name;
const renderBaseName = this.defaultVariable.getName();
return `${renderBaseName}${getPropertyAccess(name)}`;
}

getOriginalVariable(): Variable {
return this.defaultVariable.getOriginalVariable();
}

include() {
if (!this.included) {
this.included = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ System.register([], function (exports) {
return {
execute: function () {

var x = 42;
exports('x', x);console.log('dep1');
var x = exports('x', 42);
console.log('dep1');

}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ System.register([], function (exports) {
return {
execute: function () {

var x = 43;
exports('x', x);console.log('dep2');
var x = exports('x', 43);
console.log('dep2');

}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ define(['exports'], function (exports) { 'use strict';
var shared = commonjsGlobal.data;

exports.commonjsGlobal = commonjsGlobal;
exports.d = shared;
exports.shared = shared;

});
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ define(['./generated-shared'], function (shared) { 'use strict';
shared.commonjsGlobal.fn = d => d + 1;
var cjs = shared.commonjsGlobal.fn;

var main1 = shared.d.map(cjs);
var main1 = shared.shared.map(cjs);

return main1;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
define(['./generated-shared'], function (shared) { 'use strict';

var main2 = shared.d.map(d => d + 2);
var main2 = shared.shared.map(d => d + 2);

return main2;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ commonjsGlobal.data = [4, 5, 6];
var shared = commonjsGlobal.data;

exports.commonjsGlobal = commonjsGlobal;
exports.d = shared;
exports.shared = shared;
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ var shared = require('./generated-shared.js');
shared.commonjsGlobal.fn = d => d + 1;
var cjs = shared.commonjsGlobal.fn;

var main1 = shared.d.map(cjs);
var main1 = shared.shared.map(cjs);

module.exports = main1;
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

var shared = require('./generated-shared.js');

var main2 = shared.d.map(d => d + 2);
var main2 = shared.shared.map(d => d + 2);

module.exports = main2;
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !==
commonjsGlobal.data = [4, 5, 6];
var shared = commonjsGlobal.data;

export { commonjsGlobal as c, shared as d };
export { commonjsGlobal as c, shared as s };
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { c as commonjsGlobal, d } from './generated-shared.js';
import { c as commonjsGlobal, s as shared } from './generated-shared.js';

commonjsGlobal.fn = d => d + 1;
var cjs = commonjsGlobal.fn;

var main1 = d.map(cjs);
var main1 = shared.map(cjs);

export default main1;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { d } from './generated-shared.js';
import { s as shared } from './generated-shared.js';

var main2 = d.map(d => d + 2);
var main2 = shared.map(d => d + 2);

export default main2;
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ System.register([], function (exports) {
var commonjsGlobal = exports('c', typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {});

commonjsGlobal.data = [4, 5, 6];
var shared = commonjsGlobal.data;
exports('d', shared);
var shared = exports('s', commonjsGlobal.data);

}
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
System.register(['./generated-shared.js'], function (exports) {
'use strict';
var commonjsGlobal, d;
var commonjsGlobal, shared;
return {
setters: [function (module) {
commonjsGlobal = module.c;
d = module.d;
shared = module.s;
}],
execute: function () {

commonjsGlobal.fn = d => d + 1;
var cjs = commonjsGlobal.fn;

var main1 = exports('default', d.map(cjs));
var main1 = exports('default', shared.map(cjs));

}
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
System.register(['./generated-shared.js'], function (exports) {
'use strict';
var d;
var shared;
return {
setters: [function (module) {
d = module.d;
shared = module.s;
}],
execute: function () {

var main2 = exports('default', d.map(d => d + 2));
var main2 = exports('default', shared.map(d => d + 2));

}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ define(['exports'], function (exports) { 'use strict';

const foo = {};

exports.bar = foo;
exports.foo = foo;

});
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
define(['./generated-proxy2'], function (proxy2) { 'use strict';
define(['./generated-foo'], function (foo) { 'use strict';

console.log(proxy2.bar, proxy2.bar);
console.log(foo.foo, foo.foo);

});
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
define(['./generated-proxy2'], function (proxy2) { 'use strict';
define(['./generated-foo'], function (foo) { 'use strict';

console.log(proxy2.bar, proxy2.bar);
console.log(foo.foo, foo.foo);

});
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@

const foo = {};

exports.bar = foo;
exports.foo = foo;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict';

var proxy2 = require('./generated-proxy2.js');
var foo = require('./generated-foo.js');

console.log(proxy2.bar, proxy2.bar);
console.log(foo.foo, foo.foo);
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict';

var proxy2 = require('./generated-proxy2.js');
var foo = require('./generated-foo.js');

console.log(proxy2.bar, proxy2.bar);
console.log(foo.foo, foo.foo);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const foo = {};

export { foo as f };

This file was deleted.

0 comments on commit e4f4d6a

Please sign in to comment.