From 48a023f51cd0cb6ce04fd52e418c5a4ed790fdca Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Sun, 19 May 2019 08:13:38 +0200 Subject: [PATCH 1/4] Resolve export default original variables over several stages --- src/Chunk.ts | 8 +-- src/Module.ts | 13 ++-- src/ast/nodes/BreakStatement.ts | 2 +- src/ast/nodes/ClassDeclaration.ts | 6 +- src/ast/nodes/ExportDefaultDeclaration.ts | 2 +- src/ast/nodes/ExportNamedDeclaration.ts | 2 +- src/ast/nodes/FunctionDeclaration.ts | 4 +- src/ast/nodes/Identifier.ts | 14 ++-- src/ast/nodes/ReturnStatement.ts | 2 +- src/ast/nodes/UpdateExpression.ts | 4 +- src/ast/nodes/VariableDeclaration.ts | 13 ++-- src/ast/nodes/YieldExpression.ts | 2 +- src/ast/nodes/shared/ClassNode.ts | 8 ++- src/ast/nodes/shared/FunctionNode.ts | 6 +- src/ast/variables/ExportDefaultVariable.ts | 65 +++++++++++-------- src/utils/deconflictChunk.ts | 2 +- .../default-export-name-conflict/_config.js | 6 ++ .../_expected/amd/generated-chunk.js | 8 +++ .../_expected/amd/main1.js | 5 ++ .../_expected/amd/main2.js | 5 ++ .../_expected/cjs/generated-chunk.js | 6 ++ .../_expected/cjs/main1.js | 5 ++ .../_expected/cjs/main2.js | 5 ++ .../_expected/es/generated-chunk.js | 3 + .../_expected/es/main1.js | 3 + .../_expected/es/main2.js | 3 + .../_expected/system/generated-chunk.js | 13 ++++ .../_expected/system/main1.js | 14 ++++ .../_expected/system/main2.js | 14 ++++ .../default-export-name-conflict/main1.js | 4 ++ .../default-export-name-conflict/main2.js | 4 ++ .../default-export-name-conflict/module1.js | 2 + .../default-export-name-conflict/module2.js | 2 + .../default-export-name-conflict/module3.js | 2 + 34 files changed, 188 insertions(+), 69 deletions(-) create mode 100644 test/chunking-form/samples/default-export-name-conflict/_config.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/_expected/amd/generated-chunk.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/_expected/amd/main1.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/_expected/amd/main2.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/_expected/cjs/generated-chunk.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/_expected/cjs/main1.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/_expected/cjs/main2.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/_expected/es/generated-chunk.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/_expected/es/main1.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/_expected/es/main2.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/_expected/system/generated-chunk.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/_expected/system/main1.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/_expected/system/main2.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/main1.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/main2.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/module1.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/module2.js create mode 100644 test/chunking-form/samples/default-export-name-conflict/module3.js diff --git a/src/Chunk.ts b/src/Chunk.ts index 6fdc53bc7a5..f3d037c508a 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -706,7 +706,7 @@ export default class Chunk { this.facadeModule = facadedModule; facadedModule.facadeChunk = this; for (const exportName of facadedModule.getAllExports()) { - const tracedVariable = facadedModule.getVariableForExportName(exportName) as Variable; + const tracedVariable = facadedModule.getVariableForExportName(exportName); this.exports.add(tracedVariable); this.exportNames[exportName] = tracedVariable; } @@ -878,9 +878,7 @@ export default class Chunk { const imports: ImportSpecifier[] = []; for (const variable of this.imports) { const renderedVariable = - variable instanceof ExportDefaultVariable && variable.referencesOriginal() - ? (variable.getOriginalVariable() as Variable) - : variable; + variable instanceof ExportDefaultVariable ? variable.getOriginalVariable() : variable; if ( (variable.module instanceof Module ? variable.module.chunk === dep @@ -1089,7 +1087,7 @@ export default class Chunk { if (module.getOrCreateNamespace().included) { for (const reexportName of Object.keys(module.reexports)) { const reexport = module.reexports[reexportName]; - const variable = reexport.module.getVariableForExportName(reexport.localName) as Variable; + const variable = reexport.module.getVariableForExportName(reexport.localName); if ((variable.module as Module).chunk !== this) { this.imports.add(variable); if (variable.module instanceof Module) { diff --git a/src/Module.ts b/src/Module.ts index ce0c688d565..fb59a0eff4d 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -69,7 +69,7 @@ export interface ImportDescription { } export interface ExportDescription { - identifier?: string; + identifier: string | null; localName: string; } @@ -163,6 +163,7 @@ function handleMissingExport( } const MISSING_EXPORT_SHIM_DESCRIPTION: ExportDescription = { + identifier: null, localName: MISSING_EXPORT_SHIM_VARIABLE }; @@ -354,7 +355,7 @@ export default class Module { getTransitiveDependencies() { return this.dependencies.concat( this.getReexports().map( - exportName => (this.getVariableForExportName(exportName)).module as Module + exportName => this.getVariableForExportName(exportName).module as Module ) ); } @@ -686,7 +687,7 @@ export default class Module { } this.exports.default = { - identifier: node.variable.getOriginalVariableName() as string | undefined, + identifier: node.variable.getAssignedVariableName(), localName: 'default' }; } else if ((node as ExportNamedDeclaration).declaration) { @@ -702,13 +703,13 @@ export default class Module { if (declaration.type === NodeType.VariableDeclaration) { for (const decl of declaration.declarations) { for (const localName of extractAssignedNames(decl.id)) { - this.exports[localName] = { localName }; + this.exports[localName] = { identifier: null, localName }; } } } else { // export function foo () {} const localName = (declaration.id as Identifier).name; - this.exports[localName] = { localName }; + this.exports[localName] = { identifier: null, localName }; } } else { // export { foo, bar, baz } @@ -726,7 +727,7 @@ export default class Module { ); } - this.exports[exportedName] = { localName }; + this.exports[exportedName] = { identifier: null, localName }; } } } diff --git a/src/ast/nodes/BreakStatement.ts b/src/ast/nodes/BreakStatement.ts index cb4eb5f6538..51d365cceb2 100644 --- a/src/ast/nodes/BreakStatement.ts +++ b/src/ast/nodes/BreakStatement.ts @@ -11,7 +11,7 @@ export default class BreakStatement extends StatementBase { return ( super.hasEffects(options) || !options.ignoreBreakStatements() || - ((this.label && !options.ignoreLabel(this.label.name)) as boolean) + (this.label !== null && !options.ignoreLabel(this.label.name)) ); } } diff --git a/src/ast/nodes/ClassDeclaration.ts b/src/ast/nodes/ClassDeclaration.ts index 917fc05d1e1..342a25f4535 100644 --- a/src/ast/nodes/ClassDeclaration.ts +++ b/src/ast/nodes/ClassDeclaration.ts @@ -1,7 +1,7 @@ import MagicString from 'magic-string'; import { RenderOptions } from '../../utils/renderHelpers'; import ChildScope from '../scopes/ChildScope'; -import Identifier from './Identifier'; +import { IdentifierWithVariable } from './Identifier'; import * as NodeType from './NodeType'; import ClassNode from './shared/ClassNode'; import { GenericEsTreeNode, Node } from './shared/Node'; @@ -11,7 +11,7 @@ export function isClassDeclaration(node: Node): node is ClassDeclaration { } export default class ClassDeclaration extends ClassNode { - id: Identifier; + id: IdentifierWithVariable | null; type: NodeType.tClassDeclaration; initialise() { @@ -24,7 +24,7 @@ export default class ClassDeclaration extends ClassNode { parseNode(esTreeNode: GenericEsTreeNode) { if (esTreeNode.id !== null) { this.id = new this.context.nodeConstructors.Identifier(esTreeNode.id, this, this.scope - .parent as ChildScope) as Identifier; + .parent as ChildScope) as IdentifierWithVariable; } super.parseNode(esTreeNode); } diff --git a/src/ast/nodes/ExportDefaultDeclaration.ts b/src/ast/nodes/ExportDefaultDeclaration.ts index 4354a2f5d15..05d7f6f85c3 100644 --- a/src/ast/nodes/ExportDefaultDeclaration.ts +++ b/src/ast/nodes/ExportDefaultDeclaration.ts @@ -86,7 +86,7 @@ export default class ExportDefaultDeclaration extends NodeBase { this.declaration.id === null, options ); - } else if (this.variable.referencesOriginal()) { + } 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( diff --git a/src/ast/nodes/ExportNamedDeclaration.ts b/src/ast/nodes/ExportNamedDeclaration.ts index 626839ebcd8..26529c7d336 100644 --- a/src/ast/nodes/ExportNamedDeclaration.ts +++ b/src/ast/nodes/ExportNamedDeclaration.ts @@ -23,7 +23,7 @@ export default class ExportNamedDeclaration extends NodeBase { } hasEffects(options: ExecutionPathOptions) { - return (this.declaration && this.declaration.hasEffects(options)) as boolean; + return this.declaration !== null && this.declaration.hasEffects(options); } initialise() { diff --git a/src/ast/nodes/FunctionDeclaration.ts b/src/ast/nodes/FunctionDeclaration.ts index 37167e1324e..36f96409ef4 100644 --- a/src/ast/nodes/FunctionDeclaration.ts +++ b/src/ast/nodes/FunctionDeclaration.ts @@ -1,5 +1,5 @@ import ChildScope from '../scopes/ChildScope'; -import Identifier from './Identifier'; +import { IdentifierWithVariable } from './Identifier'; import * as NodeType from './NodeType'; import FunctionNode from './shared/FunctionNode'; import { GenericEsTreeNode, Node } from './shared/Node'; @@ -21,7 +21,7 @@ export default class FunctionDeclaration extends FunctionNode { parseNode(esTreeNode: GenericEsTreeNode) { if (esTreeNode.id !== null) { this.id = new this.context.nodeConstructors.Identifier(esTreeNode.id, this, this.scope - .parent as ChildScope) as Identifier; + .parent as ChildScope) as IdentifierWithVariable; } super.parseNode(esTreeNode); } diff --git a/src/ast/nodes/Identifier.ts b/src/ast/nodes/Identifier.ts index b8a138f1bea..cbea7bbd66e 100644 --- a/src/ast/nodes/Identifier.ts +++ b/src/ast/nodes/Identifier.ts @@ -12,22 +12,20 @@ import LocalVariable from '../variables/LocalVariable'; import Variable from '../variables/Variable'; import * as NodeType from './NodeType'; import { ExpressionEntity } from './shared/Expression'; -import { Node, NodeBase } from './shared/Node'; +import { NodeBase } from './shared/Node'; import { PatternNode } from './shared/Pattern'; -export function isIdentifier(node: Node): node is Identifier { - return node.type === NodeType.Identifier; -} +export type IdentifierWithVariable = Identifier & { variable: Variable }; export default class Identifier extends NodeBase implements PatternNode { name: string; type: NodeType.tIdentifier; - variable: Variable; + variable: Variable | null; private bound: boolean; addExportedVariables(variables: Variable[]): void { - if (this.variable.exportName) { + if (this.variable !== null && this.variable.exportName) { variables.push(this.variable); } } @@ -106,7 +104,7 @@ export default class Identifier extends NodeBase implements PatternNode { } hasEffectsWhenAccessedAtPath(path: ObjectPath, options: ExecutionPathOptions): boolean { - return this.variable && this.variable.hasEffectsWhenAccessedAtPath(path, options); + return this.variable !== null && this.variable.hasEffectsWhenAccessedAtPath(path, options); } hasEffectsWhenAssignedAtPath(path: ObjectPath, options: ExecutionPathOptions): boolean { @@ -135,7 +133,7 @@ export default class Identifier extends NodeBase implements PatternNode { this.bound = false; // To avoid later shape mutations if (!this.variable) { - this.variable = null as any; + this.variable = null; } } diff --git a/src/ast/nodes/ReturnStatement.ts b/src/ast/nodes/ReturnStatement.ts index bc7b4d9dab2..c456fc9983b 100644 --- a/src/ast/nodes/ReturnStatement.ts +++ b/src/ast/nodes/ReturnStatement.ts @@ -12,7 +12,7 @@ export default class ReturnStatement extends StatementBase { hasEffects(options: ExecutionPathOptions) { return ( !options.ignoreReturnAwaitYield() || - ((this.argument && this.argument.hasEffects(options)) as boolean) + (this.argument !== null && this.argument.hasEffects(options)) ); } diff --git a/src/ast/nodes/UpdateExpression.ts b/src/ast/nodes/UpdateExpression.ts index 22cbaec58a2..38cccb5e625 100644 --- a/src/ast/nodes/UpdateExpression.ts +++ b/src/ast/nodes/UpdateExpression.ts @@ -2,7 +2,7 @@ import MagicString from 'magic-string'; import { RenderOptions } from '../../utils/renderHelpers'; import { ExecutionPathOptions } from '../ExecutionPathOptions'; import { EMPTY_PATH, ObjectPath } from '../values'; -import { isIdentifier } from './Identifier'; +import Identifier from './Identifier'; import * as NodeType from './NodeType'; import { ExpressionNode, NodeBase } from './shared/Node'; @@ -15,7 +15,7 @@ export default class UpdateExpression extends NodeBase { bind() { super.bind(); this.argument.deoptimizePath(EMPTY_PATH); - if (isIdentifier(this.argument)) { + if (this.argument instanceof Identifier) { const variable = this.scope.findVariable(this.argument.name); variable.isReassigned = true; } diff --git a/src/ast/nodes/VariableDeclaration.ts b/src/ast/nodes/VariableDeclaration.ts index 0f83f423114..cb559c4efb0 100644 --- a/src/ast/nodes/VariableDeclaration.ts +++ b/src/ast/nodes/VariableDeclaration.ts @@ -9,13 +9,13 @@ import { getSystemExportStatement } from '../../utils/systemJsRendering'; import { ExecutionPathOptions } from '../ExecutionPathOptions'; import { EMPTY_PATH, ObjectPath } from '../values'; import Variable from '../variables/Variable'; -import { isIdentifier } from './Identifier'; +import Identifier, { IdentifierWithVariable } from './Identifier'; import * as NodeType from './NodeType'; import { NodeBase } from './shared/Node'; import VariableDeclarator from './VariableDeclarator'; function isReassignedExportsMember(variable: Variable): boolean { - return (variable.renderBaseName && variable.exportName && variable.isReassigned) as boolean; + return variable.renderBaseName !== null && variable.exportName !== null && variable.isReassigned; } function areAllDeclarationsIncludedAndNotExported(declarations: VariableDeclarator[]): boolean { @@ -155,14 +155,19 @@ export default class VariableDeclaration extends NodeBase { for (const { node, start, separator, contentEnd, end } of separatedNodes) { if ( !node.included || - (isIdentifier(node.id) && isReassignedExportsMember(node.id.variable) && node.init === null) + (node.id instanceof Identifier && + isReassignedExportsMember((node.id as IdentifierWithVariable).variable) && + node.init === null) ) { code.remove(start, end); continue; } leadingString = ''; nextSeparatorString = ''; - if (isIdentifier(node.id) && isReassignedExportsMember(node.id.variable)) { + if ( + node.id instanceof Identifier && + isReassignedExportsMember((node.id as IdentifierWithVariable).variable) + ) { if (hasRenderedContent) { separatorString += ';'; } diff --git a/src/ast/nodes/YieldExpression.ts b/src/ast/nodes/YieldExpression.ts index b26b33bb66f..2620dedd5a6 100644 --- a/src/ast/nodes/YieldExpression.ts +++ b/src/ast/nodes/YieldExpression.ts @@ -20,7 +20,7 @@ export default class YieldExpression extends NodeBase { hasEffects(options: ExecutionPathOptions) { return ( !options.ignoreReturnAwaitYield() || - ((this.argument && this.argument.hasEffects(options)) as boolean) + (this.argument !== null && this.argument.hasEffects(options)) ); } diff --git a/src/ast/nodes/shared/ClassNode.ts b/src/ast/nodes/shared/ClassNode.ts index eba037768a6..7761dcae3fb 100644 --- a/src/ast/nodes/shared/ClassNode.ts +++ b/src/ast/nodes/shared/ClassNode.ts @@ -29,9 +29,11 @@ export default class ClassNode extends NodeBase { callOptions: CallOptions, options: ExecutionPathOptions ) { - return (this.body.hasEffectsWhenCalledAtPath(path, callOptions, options) || - (this.superClass && - this.superClass.hasEffectsWhenCalledAtPath(path, callOptions, options))) as boolean; + return ( + this.body.hasEffectsWhenCalledAtPath(path, callOptions, options) || + (this.superClass !== null && + this.superClass.hasEffectsWhenCalledAtPath(path, callOptions, options)) + ); } initialise() { diff --git a/src/ast/nodes/shared/FunctionNode.ts b/src/ast/nodes/shared/FunctionNode.ts index 44a0ca3fa5a..e4304b10bf2 100644 --- a/src/ast/nodes/shared/FunctionNode.ts +++ b/src/ast/nodes/shared/FunctionNode.ts @@ -4,14 +4,14 @@ import FunctionScope from '../../scopes/FunctionScope'; import BlockScope from '../../scopes/FunctionScope'; import { ObjectPath, UNKNOWN_EXPRESSION, UNKNOWN_KEY, UNKNOWN_PATH } from '../../values'; import BlockStatement from '../BlockStatement'; -import Identifier from '../Identifier'; +import { IdentifierWithVariable } from '../Identifier'; import { GenericEsTreeNode, NodeBase } from './Node'; import { PatternNode } from './Pattern'; export default class FunctionNode extends NodeBase { async: boolean; body: BlockStatement; - id: Identifier | null; + id: IdentifierWithVariable | null; params: PatternNode[]; preventChildBlockScope: true; scope: BlockScope; @@ -41,7 +41,7 @@ export default class FunctionNode extends NodeBase { } hasEffects(options: ExecutionPathOptions) { - return (this.id && this.id.hasEffects(options)) as boolean; + return this.id !== null && this.id.hasEffects(options); } hasEffectsWhenAccessedAtPath(path: ObjectPath) { diff --git a/src/ast/variables/ExportDefaultVariable.ts b/src/ast/variables/ExportDefaultVariable.ts index 403bc4c8d8d..a51669603f2 100644 --- a/src/ast/variables/ExportDefaultVariable.ts +++ b/src/ast/variables/ExportDefaultVariable.ts @@ -2,8 +2,7 @@ import { AstContext } from '../../Module'; import ClassDeclaration from '../nodes/ClassDeclaration'; import ExportDefaultDeclaration from '../nodes/ExportDefaultDeclaration'; import FunctionDeclaration from '../nodes/FunctionDeclaration'; -import Identifier from '../nodes/Identifier'; -import * as NodeType from '../nodes/NodeType'; +import Identifier, { IdentifierWithVariable } from '../nodes/Identifier'; import LocalVariable from './LocalVariable'; import Variable from './Variable'; @@ -16,7 +15,8 @@ export default class ExportDefaultVariable extends LocalVariable { isDefault: true; // Not initialised during construction - private originalId: Identifier | null = null; + private originalId: IdentifierWithVariable | null = null; + private originalVariable: Variable | null = null; constructor( name: string, @@ -26,14 +26,13 @@ export default class ExportDefaultVariable extends LocalVariable { super(name, exportDefaultDeclaration, exportDefaultDeclaration.declaration, context); const declaration = exportDefaultDeclaration.declaration; if ( - (declaration.type === NodeType.FunctionDeclaration || - declaration.type === NodeType.ClassDeclaration) && - (declaration as FunctionDeclaration | ClassDeclaration).id + (declaration instanceof FunctionDeclaration || declaration instanceof ClassDeclaration) && + declaration.id ) { this.hasId = true; - this.originalId = (declaration as FunctionDeclaration | ClassDeclaration).id; - } else if (declaration.type === NodeType.Identifier) { - this.originalId = declaration as Identifier; + this.originalId = declaration.id; + } else if (declaration instanceof Identifier) { + this.originalId = declaration as IdentifierWithVariable; } } @@ -43,37 +42,49 @@ export default class ExportDefaultVariable extends LocalVariable { } } - getName() { - return this.referencesOriginal() - ? (this.originalId as Identifier).variable.getName() - : super.getName(); - } - - getOriginalVariable(): Variable | null { - return (this.originalId && this.originalId.variable) || null; + getAssignedVariableName(): string | null { + return (this.originalId && this.originalId.name) || null; } - getOriginalVariableName(): string | null { - return (this.originalId && this.originalId.name) || null; + getName() { + const original = this.getOriginalVariable(); + if (original === this) { + return super.getName(); + } else { + return original.getName(); + } } - referencesOriginal() { - return this.originalId && (this.hasId || !this.originalId.variable.isReassigned); + getOriginalVariable(): Variable { + if (this.originalVariable === null) { + if (!this.originalId || (!this.hasId && this.originalId.variable.isReassigned)) { + this.originalVariable = this; + } else { + const assignedOriginal = this.originalId.variable; + this.originalVariable = + assignedOriginal instanceof ExportDefaultVariable + ? assignedOriginal.getOriginalVariable() + : assignedOriginal; + } + } + return this.originalVariable; } setRenderNames(baseName: string | null, name: string | null) { - if (this.referencesOriginal()) { - (this.originalId as Identifier).variable.setRenderNames(baseName, name); - } else { + const original = this.getOriginalVariable(); + if (original === this) { super.setRenderNames(baseName, name); + } else { + original.setRenderNames(baseName, name); } } setSafeName(name: string | null) { - if (this.referencesOriginal()) { - (this.originalId as Identifier).variable.setSafeName(name); - } else { + const original = this.getOriginalVariable(); + if (original === this) { super.setSafeName(name); + } else { + original.setSafeName(name); } } } diff --git a/src/utils/deconflictChunk.ts b/src/utils/deconflictChunk.ts index b62fd72e610..1deb225fd85 100644 --- a/src/utils/deconflictChunk.ts +++ b/src/utils/deconflictChunk.ts @@ -131,7 +131,7 @@ function deconflictTopLevelVariables(usedNames: NameCollection, modules: Module[ // this will only happen for exports in some formats !( variable.renderBaseName || - (variable instanceof ExportDefaultVariable && variable.referencesOriginal()) + (variable instanceof ExportDefaultVariable && variable.getOriginalVariable() !== variable) ) ) { variable.setRenderNames(null, getSafeName(variable.name, usedNames)); diff --git a/test/chunking-form/samples/default-export-name-conflict/_config.js b/test/chunking-form/samples/default-export-name-conflict/_config.js new file mode 100644 index 00000000000..958b2db90bb --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/_config.js @@ -0,0 +1,6 @@ +module.exports = { + description: 'does not produce name conflicts when reexporting via default exports', + options: { + input: ['main1', 'main2'] + } +}; diff --git a/test/chunking-form/samples/default-export-name-conflict/_expected/amd/generated-chunk.js b/test/chunking-form/samples/default-export-name-conflict/_expected/amd/generated-chunk.js new file mode 100644 index 00000000000..b402aacb5f5 --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/_expected/amd/generated-chunk.js @@ -0,0 +1,8 @@ +define(['exports'], function (exports) { 'use strict'; + + const firebase = {}; + + exports.a = firebase; + exports.b = firebase; + +}); diff --git a/test/chunking-form/samples/default-export-name-conflict/_expected/amd/main1.js b/test/chunking-form/samples/default-export-name-conflict/_expected/amd/main1.js new file mode 100644 index 00000000000..0ed08f8c0a5 --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/_expected/amd/main1.js @@ -0,0 +1,5 @@ +define(['./generated-chunk'], function (__chunk_1) { 'use strict'; + + console.log(__chunk_1.b, __chunk_1.b); + +}); diff --git a/test/chunking-form/samples/default-export-name-conflict/_expected/amd/main2.js b/test/chunking-form/samples/default-export-name-conflict/_expected/amd/main2.js new file mode 100644 index 00000000000..0ed08f8c0a5 --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/_expected/amd/main2.js @@ -0,0 +1,5 @@ +define(['./generated-chunk'], function (__chunk_1) { 'use strict'; + + console.log(__chunk_1.b, __chunk_1.b); + +}); diff --git a/test/chunking-form/samples/default-export-name-conflict/_expected/cjs/generated-chunk.js b/test/chunking-form/samples/default-export-name-conflict/_expected/cjs/generated-chunk.js new file mode 100644 index 00000000000..77a70689c42 --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/_expected/cjs/generated-chunk.js @@ -0,0 +1,6 @@ +'use strict'; + +const firebase = {}; + +exports.a = firebase; +exports.b = firebase; diff --git a/test/chunking-form/samples/default-export-name-conflict/_expected/cjs/main1.js b/test/chunking-form/samples/default-export-name-conflict/_expected/cjs/main1.js new file mode 100644 index 00000000000..52ebedf3a5d --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/_expected/cjs/main1.js @@ -0,0 +1,5 @@ +'use strict'; + +var __chunk_1 = require('./generated-chunk.js'); + +console.log(__chunk_1.b, __chunk_1.b); diff --git a/test/chunking-form/samples/default-export-name-conflict/_expected/cjs/main2.js b/test/chunking-form/samples/default-export-name-conflict/_expected/cjs/main2.js new file mode 100644 index 00000000000..52ebedf3a5d --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/_expected/cjs/main2.js @@ -0,0 +1,5 @@ +'use strict'; + +var __chunk_1 = require('./generated-chunk.js'); + +console.log(__chunk_1.b, __chunk_1.b); diff --git a/test/chunking-form/samples/default-export-name-conflict/_expected/es/generated-chunk.js b/test/chunking-form/samples/default-export-name-conflict/_expected/es/generated-chunk.js new file mode 100644 index 00000000000..3a15db69b38 --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/_expected/es/generated-chunk.js @@ -0,0 +1,3 @@ +const firebase = {}; + +export { firebase as a, firebase as b }; diff --git a/test/chunking-form/samples/default-export-name-conflict/_expected/es/main1.js b/test/chunking-form/samples/default-export-name-conflict/_expected/es/main1.js new file mode 100644 index 00000000000..2e9179b6dc9 --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/_expected/es/main1.js @@ -0,0 +1,3 @@ +import { a as b } from './generated-chunk.js'; + +console.log(b, b); diff --git a/test/chunking-form/samples/default-export-name-conflict/_expected/es/main2.js b/test/chunking-form/samples/default-export-name-conflict/_expected/es/main2.js new file mode 100644 index 00000000000..2e9179b6dc9 --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/_expected/es/main2.js @@ -0,0 +1,3 @@ +import { a as b } from './generated-chunk.js'; + +console.log(b, b); diff --git a/test/chunking-form/samples/default-export-name-conflict/_expected/system/generated-chunk.js b/test/chunking-form/samples/default-export-name-conflict/_expected/system/generated-chunk.js new file mode 100644 index 00000000000..3a380e061a4 --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/_expected/system/generated-chunk.js @@ -0,0 +1,13 @@ +System.register([], function (exports, module) { + 'use strict'; + return { + execute: function () { + + const firebase = {}; + exports('a', firebase); + + exports('b', firebase); + + } + }; +}); diff --git a/test/chunking-form/samples/default-export-name-conflict/_expected/system/main1.js b/test/chunking-form/samples/default-export-name-conflict/_expected/system/main1.js new file mode 100644 index 00000000000..015e0fc309c --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/_expected/system/main1.js @@ -0,0 +1,14 @@ +System.register(['./generated-chunk.js'], function (exports, module) { + 'use strict'; + var b; + return { + setters: [function (module) { + b = module.a; + }], + execute: function () { + + console.log(b, b); + + } + }; +}); diff --git a/test/chunking-form/samples/default-export-name-conflict/_expected/system/main2.js b/test/chunking-form/samples/default-export-name-conflict/_expected/system/main2.js new file mode 100644 index 00000000000..015e0fc309c --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/_expected/system/main2.js @@ -0,0 +1,14 @@ +System.register(['./generated-chunk.js'], function (exports, module) { + 'use strict'; + var b; + return { + setters: [function (module) { + b = module.a; + }], + execute: function () { + + console.log(b, b); + + } + }; +}); diff --git a/test/chunking-form/samples/default-export-name-conflict/main1.js b/test/chunking-form/samples/default-export-name-conflict/main1.js new file mode 100644 index 00000000000..654f5860331 --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/main1.js @@ -0,0 +1,4 @@ +import a from './module1.js'; +import b from './module3.js'; + +console.log(a, b); diff --git a/test/chunking-form/samples/default-export-name-conflict/main2.js b/test/chunking-form/samples/default-export-name-conflict/main2.js new file mode 100644 index 00000000000..654f5860331 --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/main2.js @@ -0,0 +1,4 @@ +import a from './module1.js'; +import b from './module3.js'; + +console.log(a, b); diff --git a/test/chunking-form/samples/default-export-name-conflict/module1.js b/test/chunking-form/samples/default-export-name-conflict/module1.js new file mode 100644 index 00000000000..f8928c86b05 --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/module1.js @@ -0,0 +1,2 @@ +const firebase = {}; +export default firebase; diff --git a/test/chunking-form/samples/default-export-name-conflict/module2.js b/test/chunking-form/samples/default-export-name-conflict/module2.js new file mode 100644 index 00000000000..896bcab2773 --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/module2.js @@ -0,0 +1,2 @@ +import firebase from './module1'; +export default firebase; diff --git a/test/chunking-form/samples/default-export-name-conflict/module3.js b/test/chunking-form/samples/default-export-name-conflict/module3.js new file mode 100644 index 00000000000..2cea88a040f --- /dev/null +++ b/test/chunking-form/samples/default-export-name-conflict/module3.js @@ -0,0 +1,2 @@ +import firebase from './module2'; +export default firebase; From 6ca0c2620d63dc895f40ef5ad2890a7a98e66cab Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Sun, 19 May 2019 08:25:29 +0200 Subject: [PATCH 2/4] Streamline chunk export assembly --- src/Chunk.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Chunk.ts b/src/Chunk.ts index f3d037c508a..b3f641434d5 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -1,6 +1,7 @@ import sha256 from 'hash.js/lib/hash/sha/256'; import MagicString, { Bundle as MagicStringBundle, SourceMap } from 'magic-string'; -import * as NodeType from './ast/nodes/NodeType'; +import ExportDefaultDeclaration from './ast/nodes/ExportDefaultDeclaration'; +import FunctionDeclaration from './ast/nodes/FunctionDeclaration'; import { UNDEFINED_EXPRESSION } from './ast/values'; import ExportDefaultVariable, { isExportDefaultVariable @@ -953,13 +954,16 @@ export default class Chunk { if (variable.init === UNDEFINED_EXPRESSION) { uninitialized = true; } - variable.declarations.forEach(decl => { - if (decl.type === NodeType.ExportDefaultDeclaration) { - if (decl.declaration.type === NodeType.FunctionDeclaration) hoisted = true; - } else if (decl.parent.type === NodeType.FunctionDeclaration) { + for (const declaration of variable.declarations) { + if ( + declaration.parent instanceof FunctionDeclaration || + (declaration instanceof ExportDefaultDeclaration && + declaration.declaration instanceof FunctionDeclaration) + ) { hoisted = true; + break; } - }); + } } else if (variable instanceof GlobalVariable) { hoisted = true; } From 397b96ddc9115ecd8330a46ccaa7ffc0b3c4f8fa Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Sun, 19 May 2019 09:51:18 +0200 Subject: [PATCH 3/4] Replace manual type guards with instanceof --- src/Chunk.ts | 6 ++---- src/Module.ts | 14 ++++++-------- src/ast/nodes/BlockStatement.ts | 4 ---- src/ast/nodes/ClassDeclaration.ts | 6 +----- src/ast/nodes/ExportDefaultDeclaration.ts | 16 ++++++---------- src/ast/nodes/ForInStatement.ts | 6 +----- src/ast/nodes/ForOfStatement.ts | 6 +----- src/ast/nodes/ForStatement.ts | 6 +----- src/ast/nodes/FunctionDeclaration.ts | 6 +----- src/ast/nodes/Literal.ts | 6 +----- src/ast/nodes/MemberExpression.ts | 8 ++------ src/ast/nodes/TemplateLiteral.ts | 6 +----- src/ast/variables/ExportDefaultVariable.ts | 4 ---- 13 files changed, 23 insertions(+), 71 deletions(-) diff --git a/src/Chunk.ts b/src/Chunk.ts index b3f641434d5..3b55ad0c4b6 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -3,9 +3,7 @@ import MagicString, { Bundle as MagicStringBundle, SourceMap } from 'magic-strin import ExportDefaultDeclaration from './ast/nodes/ExportDefaultDeclaration'; import FunctionDeclaration from './ast/nodes/FunctionDeclaration'; import { UNDEFINED_EXPRESSION } from './ast/values'; -import ExportDefaultVariable, { - isExportDefaultVariable -} from './ast/variables/ExportDefaultVariable'; +import ExportDefaultVariable from './ast/variables/ExportDefaultVariable'; import ExportShimVariable from './ast/variables/ExportShimVariable'; import GlobalVariable from './ast/variables/GlobalVariable'; import LocalVariable from './ast/variables/LocalVariable'; @@ -1054,7 +1052,7 @@ export default class Chunk { options.format !== 'system' && exportVariable.isReassigned && !exportVariable.isId && - (!isExportDefaultVariable(exportVariable) || !exportVariable.hasId) + !(exportVariable instanceof ExportDefaultVariable && exportVariable.hasId) ) { exportVariable.setRenderNames('exports', exportName); } else { diff --git a/src/Module.ts b/src/Module.ts index fb59a0eff4d..4f906cbca8c 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -5,9 +5,7 @@ import MagicString from 'magic-string'; import extractAssignedNames from 'rollup-pluginutils/src/extractAssignedNames'; import ClassDeclaration from './ast/nodes/ClassDeclaration'; import ExportAllDeclaration from './ast/nodes/ExportAllDeclaration'; -import ExportDefaultDeclaration, { - isExportDefaultDeclaration -} from './ast/nodes/ExportDefaultDeclaration'; +import ExportDefaultDeclaration from './ast/nodes/ExportDefaultDeclaration'; import ExportNamedDeclaration from './ast/nodes/ExportNamedDeclaration'; import FunctionDeclaration from './ast/nodes/FunctionDeclaration'; import Identifier from './ast/nodes/Identifier'; @@ -15,12 +13,12 @@ import Import from './ast/nodes/Import'; import ImportDeclaration from './ast/nodes/ImportDeclaration'; import ImportSpecifier from './ast/nodes/ImportSpecifier'; import { nodeConstructors } from './ast/nodes/index'; -import { isLiteral } from './ast/nodes/Literal'; +import Literal from './ast/nodes/Literal'; import MetaProperty from './ast/nodes/MetaProperty'; import * as NodeType from './ast/nodes/NodeType'; import Program from './ast/nodes/Program'; import { Node, NodeBase } from './ast/nodes/shared/Node'; -import { isTemplateLiteral } from './ast/nodes/TemplateLiteral'; +import TemplateLiteral from './ast/nodes/TemplateLiteral'; import VariableDeclaration from './ast/nodes/VariableDeclaration'; import ModuleScope from './ast/scopes/ModuleScope'; import { EntityPathTracker } from './ast/utils/EntityPathTracker'; @@ -293,11 +291,11 @@ export default class Module { getDynamicImportExpressions(): (string | Node)[] { return this.dynamicImports.map(({ node }) => { const importArgument = node.parent.arguments[0]; - if (isTemplateLiteral(importArgument)) { + if (importArgument instanceof TemplateLiteral) { if (importArgument.expressions.length === 0 && importArgument.quasis.length === 1) { return importArgument.quasis[0].value.cooked; } - } else if (isLiteral(importArgument)) { + } else if (importArgument instanceof Literal) { if (typeof importArgument.value === 'string') { return importArgument.value; } @@ -672,7 +670,7 @@ export default class Module { }; } } - } else if (isExportDefaultDeclaration(node)) { + } else if (node instanceof ExportDefaultDeclaration) { // export default function foo () {} // export default foo; // export default 42; diff --git a/src/ast/nodes/BlockStatement.ts b/src/ast/nodes/BlockStatement.ts index 56355a78ec4..79fa8e8d97e 100644 --- a/src/ast/nodes/BlockStatement.ts +++ b/src/ast/nodes/BlockStatement.ts @@ -8,10 +8,6 @@ import { UNKNOWN_EXPRESSION } from '../values'; import * as NodeType from './NodeType'; import { Node, StatementBase, StatementNode } from './shared/Node'; -export function isBlockStatement(node: Node): node is BlockStatement { - return node.type === NodeType.BlockStatement; -} - export default class BlockStatement extends StatementBase { body: StatementNode[]; type: NodeType.tBlockStatement; diff --git a/src/ast/nodes/ClassDeclaration.ts b/src/ast/nodes/ClassDeclaration.ts index 342a25f4535..42207d580a7 100644 --- a/src/ast/nodes/ClassDeclaration.ts +++ b/src/ast/nodes/ClassDeclaration.ts @@ -4,11 +4,7 @@ import ChildScope from '../scopes/ChildScope'; import { IdentifierWithVariable } from './Identifier'; import * as NodeType from './NodeType'; import ClassNode from './shared/ClassNode'; -import { GenericEsTreeNode, Node } from './shared/Node'; - -export function isClassDeclaration(node: Node): node is ClassDeclaration { - return node.type === NodeType.ClassDeclaration; -} +import { GenericEsTreeNode } from './shared/Node'; export default class ClassDeclaration extends ClassNode { id: IdentifierWithVariable | null; diff --git a/src/ast/nodes/ExportDefaultDeclaration.ts b/src/ast/nodes/ExportDefaultDeclaration.ts index 05d7f6f85c3..d266878444d 100644 --- a/src/ast/nodes/ExportDefaultDeclaration.ts +++ b/src/ast/nodes/ExportDefaultDeclaration.ts @@ -8,11 +8,11 @@ import { import { treeshakeNode } from '../../utils/treeshakeNode'; import ModuleScope from '../scopes/ModuleScope'; import ExportDefaultVariable from '../variables/ExportDefaultVariable'; -import ClassDeclaration, { isClassDeclaration } from './ClassDeclaration'; -import FunctionDeclaration, { isFunctionDeclaration } from './FunctionDeclaration'; +import ClassDeclaration from './ClassDeclaration'; +import FunctionDeclaration from './FunctionDeclaration'; import Identifier from './Identifier'; import * as NodeType from './NodeType'; -import { ExpressionNode, Node, NodeBase } from './shared/Node'; +import { ExpressionNode, NodeBase } from './shared/Node'; const WHITESPACE = /\s/; @@ -34,10 +34,6 @@ function getIdInsertPosition(code: string, declarationKeyword: string, start = 0 return declarationEnd + generatorStarPos + 1; } -export function isExportDefaultDeclaration(node: Node): node is ExportDefaultDeclaration { - return node.type === NodeType.ExportDefaultDeclaration; -} - export default class ExportDefaultDeclaration extends NodeBase { declaration: FunctionDeclaration | ClassDeclaration | ExpressionNode; needsBoundaries: true; @@ -70,7 +66,7 @@ export default class ExportDefaultDeclaration extends NodeBase { render(code: MagicString, options: RenderOptions, { start, end }: NodeRenderOptions = BLANK) { const declarationStart = getDeclarationStart(code.original, this.start); - if (isFunctionDeclaration(this.declaration)) { + if (this.declaration instanceof FunctionDeclaration) { this.renderNamedDeclaration( code, declarationStart, @@ -78,7 +74,7 @@ export default class ExportDefaultDeclaration extends NodeBase { this.declaration.id === null, options ); - } else if (isClassDeclaration(this.declaration)) { + } else if (this.declaration instanceof ClassDeclaration) { this.renderNamedDeclaration( code, declarationStart, @@ -133,7 +129,7 @@ export default class ExportDefaultDeclaration extends NodeBase { } if ( options.format === 'system' && - isClassDeclaration(this.declaration) && + this.declaration instanceof ClassDeclaration && this.variable.exportName ) { code.appendLeft(this.end, ` exports('${this.variable.exportName}', ${name});`); diff --git a/src/ast/nodes/ForInStatement.ts b/src/ast/nodes/ForInStatement.ts index 343d19da734..3dcb9cd0ed7 100644 --- a/src/ast/nodes/ForInStatement.ts +++ b/src/ast/nodes/ForInStatement.ts @@ -5,14 +5,10 @@ import BlockScope from '../scopes/BlockScope'; import Scope from '../scopes/Scope'; import { EMPTY_PATH } from '../values'; import * as NodeType from './NodeType'; -import { ExpressionNode, Node, StatementBase, StatementNode } from './shared/Node'; +import { ExpressionNode, StatementBase, StatementNode } from './shared/Node'; import { PatternNode } from './shared/Pattern'; import VariableDeclaration from './VariableDeclaration'; -export function isForInStatement(node: Node): node is ForInStatement { - return node.type === NodeType.ForInStatement; -} - export default class ForInStatement extends StatementBase { body: StatementNode; left: VariableDeclaration | PatternNode; diff --git a/src/ast/nodes/ForOfStatement.ts b/src/ast/nodes/ForOfStatement.ts index 31dc2b78b21..15599acc6a2 100644 --- a/src/ast/nodes/ForOfStatement.ts +++ b/src/ast/nodes/ForOfStatement.ts @@ -5,14 +5,10 @@ import BlockScope from '../scopes/BlockScope'; import Scope from '../scopes/Scope'; import { EMPTY_PATH } from '../values'; import * as NodeType from './NodeType'; -import { ExpressionNode, Node, StatementBase, StatementNode } from './shared/Node'; +import { ExpressionNode, StatementBase, StatementNode } from './shared/Node'; import { PatternNode } from './shared/Pattern'; import VariableDeclaration from './VariableDeclaration'; -export function isForOfStatement(node: Node): node is ForOfStatement { - return node.type === NodeType.ForOfStatement; -} - export default class ForOfStatement extends StatementBase { await: boolean; body: StatementNode; diff --git a/src/ast/nodes/ForStatement.ts b/src/ast/nodes/ForStatement.ts index e5bf059c776..dc8c283982b 100644 --- a/src/ast/nodes/ForStatement.ts +++ b/src/ast/nodes/ForStatement.ts @@ -4,13 +4,9 @@ import { ExecutionPathOptions } from '../ExecutionPathOptions'; import BlockScope from '../scopes/BlockScope'; import Scope from '../scopes/Scope'; import * as NodeType from './NodeType'; -import { ExpressionNode, Node, StatementBase, StatementNode } from './shared/Node'; +import { ExpressionNode, StatementBase, StatementNode } from './shared/Node'; import VariableDeclaration from './VariableDeclaration'; -export function isForStatement(node: Node): node is ForStatement { - return node.type === NodeType.ForStatement; -} - export default class ForStatement extends StatementBase { body: StatementNode; init: VariableDeclaration | ExpressionNode | null; diff --git a/src/ast/nodes/FunctionDeclaration.ts b/src/ast/nodes/FunctionDeclaration.ts index 36f96409ef4..8eb6af0d413 100644 --- a/src/ast/nodes/FunctionDeclaration.ts +++ b/src/ast/nodes/FunctionDeclaration.ts @@ -2,11 +2,7 @@ import ChildScope from '../scopes/ChildScope'; import { IdentifierWithVariable } from './Identifier'; import * as NodeType from './NodeType'; import FunctionNode from './shared/FunctionNode'; -import { GenericEsTreeNode, Node } from './shared/Node'; - -export function isFunctionDeclaration(node: Node): node is FunctionDeclaration { - return node.type === NodeType.FunctionDeclaration; -} +import { GenericEsTreeNode } from './shared/Node'; export default class FunctionDeclaration extends FunctionNode { type: NodeType.tFunctionDeclaration; diff --git a/src/ast/nodes/Literal.ts b/src/ast/nodes/Literal.ts index a68fbb60f18..0130868a7a7 100644 --- a/src/ast/nodes/Literal.ts +++ b/src/ast/nodes/Literal.ts @@ -13,14 +13,10 @@ import { UNKNOWN_VALUE } from '../values'; import * as NodeType from './NodeType'; -import { Node, NodeBase } from './shared/Node'; +import { NodeBase } from './shared/Node'; export type LiteralValue = string | boolean | null | number | RegExp | undefined; -export function isLiteral(node: Node): node is Literal { - return node.type === NodeType.Literal; -} - export default class Literal extends NodeBase { type: NodeType.tLiteral; value: T; diff --git a/src/ast/nodes/MemberExpression.ts b/src/ast/nodes/MemberExpression.ts index 24e192031f9..31010a3834c 100644 --- a/src/ast/nodes/MemberExpression.ts +++ b/src/ast/nodes/MemberExpression.ts @@ -23,7 +23,7 @@ import Variable from '../variables/Variable'; import Identifier from './Identifier'; import Literal from './Literal'; import * as NodeType from './NodeType'; -import { ExpressionNode, Node, NodeBase } from './shared/Node'; +import { ExpressionNode, NodeBase } from './shared/Node'; import { PatternNode } from './shared/Pattern'; function getResolvablePropertyKey(memberExpression: MemberExpression): string | null { @@ -51,7 +51,7 @@ function getPathIfNotComputed(memberExpression: MemberExpression): PathWithPosit { key: nextPathKey, pos: memberExpression.property.start } ]; } - if (isMemberExpression(object)) { + if (object instanceof MemberExpression) { const parentPath = getPathIfNotComputed(object); return ( parentPath && [...parentPath, { key: nextPathKey, pos: memberExpression.property.start }] @@ -69,10 +69,6 @@ function getStringFromPath(path: PathWithPositions): string { return pathString; } -export function isMemberExpression(node: Node): node is MemberExpression { - return node.type === NodeType.MemberExpression; -} - export default class MemberExpression extends NodeBase implements DeoptimizableEntity, PatternNode { computed: boolean; object: ExpressionNode; diff --git a/src/ast/nodes/TemplateLiteral.ts b/src/ast/nodes/TemplateLiteral.ts index 0bc820ca371..d4b283a56b6 100644 --- a/src/ast/nodes/TemplateLiteral.ts +++ b/src/ast/nodes/TemplateLiteral.ts @@ -2,13 +2,9 @@ import MagicString from 'magic-string'; import { RenderOptions } from '../../utils/renderHelpers'; import { LiteralValueOrUnknown, ObjectPath, UNKNOWN_VALUE } from '../values'; import * as NodeType from './NodeType'; -import { ExpressionNode, Node, NodeBase } from './shared/Node'; +import { ExpressionNode, NodeBase } from './shared/Node'; import TemplateElement from './TemplateElement'; -export function isTemplateLiteral(node: Node): node is TemplateLiteral { - return node.type === NodeType.TemplateLiteral; -} - export default class TemplateLiteral extends NodeBase { expressions: ExpressionNode[]; quasis: TemplateElement[]; diff --git a/src/ast/variables/ExportDefaultVariable.ts b/src/ast/variables/ExportDefaultVariable.ts index a51669603f2..6ad3902cd4c 100644 --- a/src/ast/variables/ExportDefaultVariable.ts +++ b/src/ast/variables/ExportDefaultVariable.ts @@ -6,10 +6,6 @@ import Identifier, { IdentifierWithVariable } from '../nodes/Identifier'; import LocalVariable from './LocalVariable'; import Variable from './Variable'; -export function isExportDefaultVariable(variable: Variable): variable is ExportDefaultVariable { - return variable.isDefault as boolean; -} - export default class ExportDefaultVariable extends LocalVariable { hasId: boolean; isDefault: true; From 2a9d73d4548f1301a1e2a2f1e89959b960c45e9d Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Sun, 19 May 2019 10:57:57 +0200 Subject: [PATCH 4/4] Start using the "unknown" type for options --- src/Graph.ts | 2 +- src/rollup/types.d.ts | 6 ++- src/utils/mergeOptions.ts | 86 +++++++++++++++++++++++---------------- 3 files changed, 58 insertions(+), 36 deletions(-) diff --git a/src/Graph.ts b/src/Graph.ts index 3e95d2b223f..2bfcad933a4 100644 --- a/src/Graph.ts +++ b/src/Graph.ts @@ -164,7 +164,7 @@ export default class Graph { this.getModuleContext = () => this.context; } - this.onwarn = options.onwarn || makeOnwarn(); + this.onwarn = (options.onwarn as WarningHandler) || makeOnwarn(); this.acornOptions = options.acorn || {}; const acornPluginsToInject = []; diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index 40524ee604a..bb020febbcc 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -357,7 +357,7 @@ export interface InputOptions { input?: InputOption; manualChunks?: ManualChunksOption; moduleContext?: ((id: string) => string) | { [id: string]: string }; - onwarn?: WarningHandler; + onwarn?: WarningHandlerWithDefault; perf?: boolean; plugins?: Plugin[]; preserveModules?: boolean; @@ -421,6 +421,10 @@ export interface OutputOptions { strict?: boolean; } +export type WarningHandlerWithDefault = ( + warning: string | RollupWarning, + defaultHandler: WarningHandler +) => void; export type WarningHandler = (warning: string | RollupWarning) => void; export interface SerializedTimings { diff --git a/src/utils/mergeOptions.ts b/src/utils/mergeOptions.ts index 5b26c3f57c9..b726aa493c1 100644 --- a/src/utils/mergeOptions.ts +++ b/src/utils/mergeOptions.ts @@ -1,13 +1,24 @@ -import { InputOptions, OutputOptions, WarningHandler } from '../rollup/types'; +import { + InputOptions, + OutputOptions, + WarningHandler, + WarningHandlerWithDefault +} from '../rollup/types'; export interface GenericConfigObject { - [key: string]: any; + [key: string]: unknown; +} + +export interface CommandConfigObject { + external: string[]; + globals: { [id: string]: string } | undefined; + [key: string]: unknown; } const createGetOption = (config: GenericConfigObject, command: GenericConfigObject) => ( name: string, - defaultValue?: any -) => + defaultValue?: unknown +): any => command[name] !== undefined ? command[name] : config[name] !== undefined @@ -47,21 +58,26 @@ const defaultOnWarn: WarningHandler = warning => { const getOnWarn = ( config: GenericConfigObject, - command: GenericConfigObject, + command: CommandConfigObject, defaultOnWarnHandler: WarningHandler = defaultOnWarn ): WarningHandler => command.silent ? () => {} : config.onwarn - ? warning => config.onwarn(warning, defaultOnWarnHandler) + ? warning => (config.onwarn as WarningHandlerWithDefault)(warning, defaultOnWarnHandler) : defaultOnWarnHandler; -const getExternal = (config: GenericConfigObject, command: GenericConfigObject) => { +const getExternal = (config: GenericConfigObject, command: CommandConfigObject) => { const configExternal = config.external; return typeof configExternal === 'function' ? (id: string, ...rest: string[]) => configExternal(id, ...rest) || command.external.indexOf(id) !== -1 - : (configExternal || []).concat(command.external); + : (typeof config.external === 'string' + ? [configExternal] + : Array.isArray(configExternal) + ? configExternal + : [] + ).concat(command.external); }; export const commandAliases: { [key: string]: string } = { @@ -166,55 +182,57 @@ function addUnknownOptionErrors( ); } -function getCommandOptions(rawCommandOptions: GenericConfigObject): GenericConfigObject { - const command = { ...rawCommandOptions }; - command.external = rawCommandOptions.external ? rawCommandOptions.external.split(',') : []; - - if (rawCommandOptions.globals) { - command.globals = Object.create(null); - - rawCommandOptions.globals.split(',').forEach((str: string) => { - const names = str.split(':'); - command.globals[names[0]] = names[1]; - - // Add missing Module IDs to external. - if (command.external.indexOf(names[0]) === -1) { - command.external.push(names[0]); - } - }); - } - return command; +function getCommandOptions(rawCommandOptions: GenericConfigObject): CommandConfigObject { + const external = + rawCommandOptions.external && typeof rawCommandOptions.external === 'string' + ? rawCommandOptions.external.split(',') + : []; + return { + ...rawCommandOptions, + external, + globals: + typeof rawCommandOptions.globals === 'string' + ? rawCommandOptions.globals.split(',').reduce((globals, globalDefinition) => { + const [id, variableName] = globalDefinition.split(':'); + globals[id] = variableName; + if (external.indexOf(id) === -1) { + external.push(id); + } + return globals; + }, Object.create(null)) + : undefined + }; } function getInputOptions( config: GenericConfigObject, - command: GenericConfigObject = {}, + command: CommandConfigObject = { external: [], globals: undefined }, defaultOnWarnHandler: WarningHandler ): InputOptions { const getOption = createGetOption(config, command); const inputOptions: InputOptions = { acorn: config.acorn, - acornInjectPlugins: config.acornInjectPlugins, + acornInjectPlugins: config.acornInjectPlugins as any, cache: getOption('cache'), chunkGroupingSize: getOption('chunkGroupingSize', 5000), - context: config.context, + context: config.context as any, experimentalCacheExpiry: getOption('experimentalCacheExpiry', 10), experimentalOptimizeChunks: getOption('experimentalOptimizeChunks'), experimentalTopLevelAwait: getOption('experimentalTopLevelAwait'), - external: getExternal(config, command), + external: getExternal(config, command) as any, inlineDynamicImports: getOption('inlineDynamicImports', false), input: getOption('input', []), manualChunks: getOption('manualChunks'), - moduleContext: config.moduleContext, + moduleContext: config.moduleContext as any, onwarn: getOnWarn(config, command, defaultOnWarnHandler), perf: getOption('perf', false), - plugins: config.plugins, + plugins: config.plugins as any, preserveModules: getOption('preserveModules'), preserveSymlinks: getOption('preserveSymlinks'), shimMissingExports: getOption('shimMissingExports'), treeshake: getObjectOption(config, command, 'treeshake'), - watch: config.watch + watch: config.watch as any }; // support rollup({ cache: prevBuildObject }) @@ -242,7 +260,7 @@ function getOutputOptions( } return { - amd: { ...config.amd, ...command.amd }, + amd: { ...config.amd, ...command.amd } as any, assetFileNames: getOption('assetFileNames'), banner: getOption('banner'), chunkFileNames: getOption('chunkFileNames'),