diff --git a/HOW.md b/HOW.md new file mode 100644 index 00000000000..3aa666d2660 --- /dev/null +++ b/HOW.md @@ -0,0 +1 @@ +# recursive the Identifier like this `this.variable.init.includePath` diff --git a/src/Graph.ts b/src/Graph.ts index fc47bfa3c54..2a41ffcf1ef 100644 --- a/src/Graph.ts +++ b/src/Graph.ts @@ -166,30 +166,44 @@ export default class Graph { } if (this.options.treeshake) { let treeshakingPass = 1; - do { - timeStart(`treeshaking pass ${treeshakingPass}`, 3); - this.needsTreeshakingPass = false; - for (const module of this.modules) { - if (module.isExecuted) { - if (module.info.moduleSideEffects === 'no-treeshake') { - module.includeAllInBundle(); - } else { - module.include(); + const loopTreeShaking = () => { + do { + timeStart(`treeshaking pass ${treeshakingPass}`, 3); + this.needsTreeshakingPass = false; + for (const module of this.modules) { + if (module.isExecuted) { + if (module.info.moduleSideEffects === 'no-treeshake') { + module.includeAllInBundle(); + } else { + module.include(); + } } } - } - if (treeshakingPass === 1) { - // We only include exports after the first pass to avoid issues with - // the TDZ detection logic - for (const module of entryModules) { - if (module.preserveSignature !== false) { - module.includeAllExports(false); - this.needsTreeshakingPass = true; + if (treeshakingPass === 1) { + // We only include exports after the first pass to avoid issues with + // the TDZ detection logic + for (const module of entryModules) { + if (module.preserveSignature !== false) { + module.includeAllExports(false); + this.needsTreeshakingPass = true; + } } } + timeEnd(`treeshaking pass ${treeshakingPass++}`, 3); + } while (this.needsTreeshakingPass); + }; + loopTreeShaking(); + for (const module of this.modules) { + for (const dynamicDependency of module.dynamicDependenciesIncludeAllExports) { + dynamicDependency.includeAllExports(true); } - timeEnd(`treeshaking pass ${treeshakingPass++}`, 3); - } while (this.needsTreeshakingPass); + } + if (this.needsTreeshakingPass) { + loopTreeShaking(); + } + if (this.needsTreeshakingPass) { + throw new Error('What What What!!!'); + } } else { for (const module of this.modules) module.includeAllInBundle(); } diff --git a/src/Module.ts b/src/Module.ts index 639ee18ea2c..86dfbf640be 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -217,6 +217,7 @@ export default class Module { readonly dynamicDependencies = new Set(); readonly dynamicImporters: string[] = []; readonly dynamicImports: DynamicImport[] = []; + dynamicDependenciesIncludeAllExports = new Set(); excludeFromSourcemap: boolean; execIndex = Infinity; readonly implicitlyLoadedAfter = new Set(); @@ -1308,23 +1309,23 @@ export default class Module { } private includeDynamicImport(node: ImportExpression): void { - const resolution = ( - this.dynamicImports.find(dynamicImport => dynamicImport.node === node) as { - resolution: string | Module | ExternalModule | undefined; - } - ).resolution; + const resolution = this.dynamicImports.find( + dynamicImport => dynamicImport.node === node + )!.resolution; if (resolution instanceof Module) { - resolution.includedDynamicImporters.push(this); + !resolution.includedDynamicImporters.includes(this) && + resolution.includedDynamicImporters.push(this); const importedNames = this.options.treeshake ? node.getDeterministicImportedNames() : undefined; if (importedNames) { + this.dynamicDependenciesIncludeAllExports.delete(resolution); resolution.includeExportsByNames(importedNames); } else { - resolution.includeAllExports(true); + this.dynamicDependenciesIncludeAllExports.add(resolution); } } } diff --git a/src/ast/nodes/Identifier.ts b/src/ast/nodes/Identifier.ts index 17dfbf9a6dc..fc5a356e70d 100644 --- a/src/ast/nodes/Identifier.ts +++ b/src/ast/nodes/Identifier.ts @@ -195,9 +195,14 @@ export default class Identifier extends NodeBase implements PatternNode { } } - includePath(): void { + includePath(path?: ObjectPath): void { if (!this.deoptimized) this.applyDeoptimizations(); - if (!this.included) { + if (this.included) { + if (path?.length && !this.includedPaths.has(path[0])) { + this.includedPaths.add(path[0]); + this.variable?.includePath(path); + } + } else { this.included = true; if (this.variable !== null) { this.scope.context.includeVariableInModule(this.variable); diff --git a/src/ast/nodes/ImportExpression.ts b/src/ast/nodes/ImportExpression.ts index 2ddf9fd70d4..cc6cb47f070 100644 --- a/src/ast/nodes/ImportExpression.ts +++ b/src/ast/nodes/ImportExpression.ts @@ -12,7 +12,7 @@ import { import { findFirstOccurrenceOutsideComment, type RenderOptions } from '../../utils/renderHelpers'; import type { InclusionContext } from '../ExecutionContext'; import type ChildScope from '../scopes/ChildScope'; -import type { ObjectPath } from '../utils/PathTracker'; +import { type ObjectPath, UnknownKey } from '../utils/PathTracker'; import type NamespaceVariable from '../variables/NamespaceVariable'; import ArrowFunctionExpression from './ArrowFunctionExpression'; import AwaitExpression from './AwaitExpression'; @@ -43,6 +43,7 @@ export default class ImportExpression extends NodeBase { declare type: NodeType.tImportExpression; declare sourceAstNode: AstNode; + private hasUnknownAccessedKey = false; private accessedPropKey = new Set(); private attributes: string | null | true = null; private mechanism: DynamicImportMechanism | null = null; @@ -85,6 +86,7 @@ export default class ImportExpression extends NodeBase { if (parent2 instanceof VariableDeclarator) { const declaration = parent2.id; if (declaration instanceof Identifier) { + if (this.hasUnknownAccessedKey) return undefined; return this.accessedPropKey.size > 0 ? [...this.accessedPropKey] : undefined; } if (declaration instanceof ObjectPattern) { @@ -170,8 +172,16 @@ export default class ImportExpression extends NodeBase { this.included = true; this.scope.context.includeDynamicImport(this); this.scope.addAccessedDynamicImport(this); + this.source.includePath(path, context, includeChildrenRecursively); + } + if (this.hasUnknownAccessedKey) return; + if (path[0] === UnknownKey) { + this.hasUnknownAccessedKey = true; + this.scope.context.includeDynamicImport(this); + } else if (typeof path[0] === 'string') { + this.accessedPropKey.add(path[0]); + this.scope.context.includeDynamicImport(this); } - this.source.includePath(path, context, includeChildrenRecursively); } initialise(): void { diff --git a/src/ast/nodes/MemberExpression.ts b/src/ast/nodes/MemberExpression.ts index d349527cd64..56f3cac6547 100644 --- a/src/ast/nodes/MemberExpression.ts +++ b/src/ast/nodes/MemberExpression.ts @@ -27,12 +27,9 @@ import { } from '../utils/PathTracker'; import { UNDEFINED_EXPRESSION } from '../values'; import ExternalVariable from '../variables/ExternalVariable'; -import LocalVariable from '../variables/LocalVariable'; import type NamespaceVariable from '../variables/NamespaceVariable'; import type Variable from '../variables/Variable'; -import AwaitExpression from './AwaitExpression'; import Identifier from './Identifier'; -import type ImportExpression from './ImportExpression'; import Literal from './Literal'; import type * as NodeType from './NodeType'; import type PrivateIdentifier from './PrivateIdentifier'; @@ -49,10 +46,6 @@ import { import type { ChainElement, ExpressionNode, IncludeChildren } from './shared/Node'; import { NodeBase } from './shared/Node'; -function isImportExpression(node: ExpressionNode): node is ImportExpression { - return node.type === 'ImportExpression'; -} - // To avoid infinite recursions const MAX_PATH_DEPTH = 7; @@ -168,16 +161,6 @@ export default class MemberExpression } else { super.bind(); } - if (baseVariable instanceof LocalVariable) { - const init = baseVariable.init; - if ( - init instanceof AwaitExpression && - isImportExpression(init.argument) && - typeof this.propertyKey === 'string' - ) { - init.argument.addAccessedPropKey(this.propertyKey); - } - } } deoptimizeArgumentsOnInteractionAtPath( @@ -316,12 +299,12 @@ export default class MemberExpression } includePath( - path: ObjectPath, + _: ObjectPath, context: InclusionContext, includeChildrenRecursively: IncludeChildren ): void { if (!this.deoptimized) this.applyDeoptimizations(); - this.includeProperties(path, context, includeChildrenRecursively); + this.includeProperties([this.propertyKey || UnknownKey], context, includeChildrenRecursively); } includeAsAssignmentTarget( diff --git a/src/ast/nodes/ObjectPattern.ts b/src/ast/nodes/ObjectPattern.ts index df8b9ef37b0..5c640860c84 100644 --- a/src/ast/nodes/ObjectPattern.ts +++ b/src/ast/nodes/ObjectPattern.ts @@ -1,12 +1,14 @@ -import type { HasEffectsContext } from '../ExecutionContext'; +import type { HasEffectsContext, InclusionContext } from '../ExecutionContext'; import type { NodeInteractionAssigned } from '../NodeInteractions'; -import { EMPTY_PATH, type ObjectPath } from '../utils/PathTracker'; +import { EMPTY_PATH, type ObjectPath, UNKNOWN_PATH } from '../utils/PathTracker'; import type LocalVariable from '../variables/LocalVariable'; import type Variable from '../variables/Variable'; import * as NodeType from './NodeType'; -import type Property from './Property'; -import type RestElement from './RestElement'; -import type { ExpressionEntity } from './shared/Expression'; +import Property from './Property'; +import RestElement from './RestElement'; +import VariableDeclarator from './VariableDeclarator'; +import type { ExpressionEntity, InclusionOptions } from './shared/Expression'; +import type { IncludeChildren } from './shared/Node'; import { NodeBase } from './shared/Node'; import type { PatternNode } from './shared/Pattern'; import type { VariableKind } from './shared/VariableKinds'; @@ -47,6 +49,25 @@ export default class ObjectPattern extends NodeBase implements PatternNode { } } + includePath( + path: ObjectPath, + context: InclusionContext, + includeChildrenRecursively: IncludeChildren, + options?: InclusionOptions | undefined + ): void { + super.includePath(path, context, includeChildrenRecursively, options); + if (this.parent instanceof VariableDeclarator) { + for (const p of this.properties) { + if (p instanceof Property) { + this.parent.init?.includePath([p.key.name], context, includeChildrenRecursively, options); + } + if (p instanceof RestElement) { + this.parent.init?.includePath(UNKNOWN_PATH, context, includeChildrenRecursively, options); + } + } + } + } + hasEffectsOnInteractionAtPath( // At the moment, this is only triggered for assignment left-hand sides, // where the path is empty diff --git a/src/ast/nodes/Property.ts b/src/ast/nodes/Property.ts index 10b5a32c0fe..63db7b5c83b 100644 --- a/src/ast/nodes/Property.ts +++ b/src/ast/nodes/Property.ts @@ -4,16 +4,16 @@ import type { RenderOptions } from '../../utils/renderHelpers'; import type { HasEffectsContext } from '../ExecutionContext'; import { UnknownKey } from '../utils/PathTracker'; import type LocalVariable from '../variables/LocalVariable'; +import type Identifier from './Identifier'; import type * as NodeType from './NodeType'; import { Flag, isFlagSet, setFlag } from './shared/BitFlags'; import { type ExpressionEntity, UNKNOWN_EXPRESSION } from './shared/Expression'; import MethodBase from './shared/MethodBase'; -import type { ExpressionNode } from './shared/Node'; import type { PatternNode } from './shared/Pattern'; import type { VariableKind } from './shared/VariableKinds'; export default class Property extends MethodBase implements PatternNode { - declare key: ExpressionNode; + declare key: Identifier; declare kind: 'init' | 'get' | 'set'; declare type: NodeType.tProperty; private declarationInit: ExpressionEntity | null = null; diff --git a/src/ast/nodes/shared/Expression.ts b/src/ast/nodes/shared/Expression.ts index 0ed8d789579..59d11d309fe 100644 --- a/src/ast/nodes/shared/Expression.ts +++ b/src/ast/nodes/shared/Expression.ts @@ -2,7 +2,12 @@ import type { DeoptimizableEntity } from '../../DeoptimizableEntity'; import type { WritableEntity } from '../../Entity'; import type { HasEffectsContext, InclusionContext } from '../../ExecutionContext'; import type { NodeInteraction, NodeInteractionCalled } from '../../NodeInteractions'; -import type { ObjectPath, PathTracker, SymbolToStringTag } from '../../utils/PathTracker'; +import type { + ObjectPath, + ObjectPathKey, + PathTracker, + SymbolToStringTag +} from '../../utils/PathTracker'; import { EMPTY_PATH, UNKNOWN_PATH } from '../../utils/PathTracker'; import type { LiteralValue } from '../Literal'; import type SpreadElement from '../SpreadElement'; @@ -29,6 +34,8 @@ export interface InclusionOptions { export class ExpressionEntity implements WritableEntity { protected flags: number = 0; + includedPaths = new Set(); + get included(): boolean { return isFlagSet(this.flags, Flag.included); } diff --git a/src/ast/variables/LocalVariable.ts b/src/ast/variables/LocalVariable.ts index 76e9eb752e2..6de4ceaded5 100644 --- a/src/ast/variables/LocalVariable.ts +++ b/src/ast/variables/LocalVariable.ts @@ -29,8 +29,6 @@ import Variable from './Variable'; export default class LocalVariable extends Variable { calledFromTryStatement = false; - init: ExpressionEntity; - readonly declarations: (Identifier | ExportDefaultDeclaration)[]; readonly module: Module; readonly kind: VariableKind; @@ -44,14 +42,13 @@ export default class LocalVariable extends Variable { constructor( name: string, declarator: Identifier | ExportDefaultDeclaration | null, - init: ExpressionEntity, + private init: ExpressionEntity, context: AstContext, kind: VariableKind ) { super(name); this.declarations = declarator ? [declarator] : []; this.deoptimizationTracker = context.deoptimizationTracker; - this.init = init; this.module = context.module; this.kind = kind; } @@ -185,8 +182,13 @@ export default class LocalVariable extends Variable { } } - includePath(): void { - if (!this.included) { + includePath(path?: ObjectPath): void { + if (this.included) { + if (path?.length && !this.includedPaths.has(path[0])) { + this.includedPaths.add(path[0]); + this.init.includePath(path, createInclusionContext(), false); + } + } else { super.includePath(); for (const declaration of this.declarations) { // If node is a default export, it can save a tree-shaking run to include the full declaration now diff --git a/src/ast/variables/Variable.ts b/src/ast/variables/Variable.ts index da6491ce33c..c12752194ff 100644 --- a/src/ast/variables/Variable.ts +++ b/src/ast/variables/Variable.ts @@ -79,7 +79,7 @@ export default class Variable extends ExpressionEntity { * previously. * Once a variable is included, it should take care all its declarations are included. */ - includePath(): void { + includePath(_path?: ObjectPath): void { this.included = true; this.renderedLikeHoisted?.includePath(); } diff --git a/test/chunking-form/samples/dynamic-import-identifier/_config.js b/test/chunking-form/samples/dynamic-import-identifier-1/_config.js similarity index 100% rename from test/chunking-form/samples/dynamic-import-identifier/_config.js rename to test/chunking-form/samples/dynamic-import-identifier-1/_config.js diff --git a/test/chunking-form/samples/dynamic-import-identifier-1/_expected/amd/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/amd/generated-module.js new file mode 100644 index 00000000000..530ed7983bc --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/amd/generated-module.js @@ -0,0 +1,11 @@ +define(['exports'], (function (exports) { 'use strict'; + + const foo = () => {}; + const bar = () => {}; + const baz = () => {}; + + exports.bar = bar; + exports.baz = baz; + exports.foo = foo; + +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-1/_expected/amd/main.js b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/amd/main.js new file mode 100644 index 00000000000..8006fc7557b --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/amd/main.js @@ -0,0 +1,10 @@ +define(['require'], (function (require) { 'use strict'; + + (async () => { + const module = await new Promise(function (resolve, reject) { require(['./generated-module'], resolve, reject); }); + module.foo(); + module[global.unknown](); + module.baz(); + })(); + +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-1/_expected/cjs/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/cjs/generated-module.js new file mode 100644 index 00000000000..22928b57a48 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/cjs/generated-module.js @@ -0,0 +1,9 @@ +'use strict'; + +const foo = () => {}; +const bar = () => {}; +const baz = () => {}; + +exports.bar = bar; +exports.baz = baz; +exports.foo = foo; diff --git a/test/chunking-form/samples/dynamic-import-identifier-1/_expected/cjs/main.js b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/cjs/main.js new file mode 100644 index 00000000000..3e988bd1320 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/cjs/main.js @@ -0,0 +1,8 @@ +'use strict'; + +(async () => { + const module = await Promise.resolve().then(function () { return require('./generated-module.js'); }); + module.foo(); + module[global.unknown](); + module.baz(); +})(); diff --git a/test/chunking-form/samples/dynamic-import-identifier-1/_expected/es/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/es/generated-module.js new file mode 100644 index 00000000000..2918fd37fb1 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/es/generated-module.js @@ -0,0 +1,5 @@ +const foo = () => {}; +const bar = () => {}; +const baz = () => {}; + +export { bar, baz, foo }; diff --git a/test/chunking-form/samples/dynamic-import-identifier-1/_expected/es/main.js b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/es/main.js new file mode 100644 index 00000000000..b54af417d62 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/es/main.js @@ -0,0 +1,6 @@ +(async () => { + const module = await import('./generated-module.js'); + module.foo(); + module[global.unknown](); + module.baz(); +})(); diff --git a/test/chunking-form/samples/dynamic-import-identifier-1/_expected/system/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/system/generated-module.js new file mode 100644 index 00000000000..5808ca6422f --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/system/generated-module.js @@ -0,0 +1,12 @@ +System.register([], (function (exports) { + 'use strict'; + return { + execute: (function () { + + const foo = exports("foo", () => {}); + const bar = exports("bar", () => {}); + const baz = exports("baz", () => {}); + + }) + }; +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-1/_expected/system/main.js b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/system/main.js new file mode 100644 index 00000000000..3c565a36b7b --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-1/_expected/system/main.js @@ -0,0 +1,15 @@ +System.register([], (function (exports, module) { + 'use strict'; + return { + execute: (function () { + + (async () => { + const module$1 = await module.import('./generated-module.js'); + module$1.foo(); + module$1[global.unknown](); + module$1.baz(); + })(); + + }) + }; +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-1/main.js b/test/chunking-form/samples/dynamic-import-identifier-1/main.js new file mode 100644 index 00000000000..0385611b4c2 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-1/main.js @@ -0,0 +1,6 @@ +(async () => { + const module = await import('./module'); + module.foo(); + module[global.unknown](); + module.baz(); +})(); diff --git a/test/chunking-form/samples/dynamic-import-identifier-1/module.js b/test/chunking-form/samples/dynamic-import-identifier-1/module.js new file mode 100644 index 00000000000..482358f67f7 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-1/module.js @@ -0,0 +1,3 @@ +export const foo = () => {}; +export const bar = () => {}; +export const baz = () => {}; diff --git a/test/chunking-form/samples/dynamic-import-identifier-2/_config.js b/test/chunking-form/samples/dynamic-import-identifier-2/_config.js new file mode 100644 index 00000000000..7ef5235a00c --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-2/_config.js @@ -0,0 +1,3 @@ +module.exports = defineTest({ + description: 'tree-shakes dynamic imports with identifier' +}); diff --git a/test/chunking-form/samples/dynamic-import-identifier/_expected/amd/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-2/_expected/amd/generated-module.js similarity index 100% rename from test/chunking-form/samples/dynamic-import-identifier/_expected/amd/generated-module.js rename to test/chunking-form/samples/dynamic-import-identifier-2/_expected/amd/generated-module.js diff --git a/test/chunking-form/samples/dynamic-import-identifier-2/_expected/amd/main.js b/test/chunking-form/samples/dynamic-import-identifier-2/_expected/amd/main.js new file mode 100644 index 00000000000..bced2dc8b19 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-2/_expected/amd/main.js @@ -0,0 +1,9 @@ +define(['require'], (function (require) { 'use strict'; + + (async () => { + const module = await new Promise(function (resolve, reject) { require(['./generated-module'], resolve, reject); }); + const module1 = module; + module1.foo(); + })(); + +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier/_expected/cjs/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-2/_expected/cjs/generated-module.js similarity index 100% rename from test/chunking-form/samples/dynamic-import-identifier/_expected/cjs/generated-module.js rename to test/chunking-form/samples/dynamic-import-identifier-2/_expected/cjs/generated-module.js diff --git a/test/chunking-form/samples/dynamic-import-identifier-2/_expected/cjs/main.js b/test/chunking-form/samples/dynamic-import-identifier-2/_expected/cjs/main.js new file mode 100644 index 00000000000..116c65e39e5 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-2/_expected/cjs/main.js @@ -0,0 +1,7 @@ +'use strict'; + +(async () => { + const module = await Promise.resolve().then(function () { return require('./generated-module.js'); }); + const module1 = module; + module1.foo(); +})(); diff --git a/test/chunking-form/samples/dynamic-import-identifier/_expected/es/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-2/_expected/es/generated-module.js similarity index 100% rename from test/chunking-form/samples/dynamic-import-identifier/_expected/es/generated-module.js rename to test/chunking-form/samples/dynamic-import-identifier-2/_expected/es/generated-module.js diff --git a/test/chunking-form/samples/dynamic-import-identifier-2/_expected/es/main.js b/test/chunking-form/samples/dynamic-import-identifier-2/_expected/es/main.js new file mode 100644 index 00000000000..e2d79f40708 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-2/_expected/es/main.js @@ -0,0 +1,5 @@ +(async () => { + const module = await import('./generated-module.js'); + const module1 = module; + module1.foo(); +})(); diff --git a/test/chunking-form/samples/dynamic-import-identifier/_expected/system/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-2/_expected/system/generated-module.js similarity index 100% rename from test/chunking-form/samples/dynamic-import-identifier/_expected/system/generated-module.js rename to test/chunking-form/samples/dynamic-import-identifier-2/_expected/system/generated-module.js diff --git a/test/chunking-form/samples/dynamic-import-identifier-2/_expected/system/main.js b/test/chunking-form/samples/dynamic-import-identifier-2/_expected/system/main.js new file mode 100644 index 00000000000..645ce0d2b24 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-2/_expected/system/main.js @@ -0,0 +1,14 @@ +System.register([], (function (exports, module) { + 'use strict'; + return { + execute: (function () { + + (async () => { + const module$1 = await module.import('./generated-module.js'); + const module1 = module$1; + module1.foo(); + })(); + + }) + }; +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-2/main.js b/test/chunking-form/samples/dynamic-import-identifier-2/main.js new file mode 100644 index 00000000000..1a5cf9578e1 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-2/main.js @@ -0,0 +1,5 @@ +(async () => { + const module = await import('./module'); + const module1 = module; + module1.foo(); +})(); diff --git a/test/chunking-form/samples/dynamic-import-identifier/module.js b/test/chunking-form/samples/dynamic-import-identifier-2/module.js similarity index 100% rename from test/chunking-form/samples/dynamic-import-identifier/module.js rename to test/chunking-form/samples/dynamic-import-identifier-2/module.js diff --git a/test/chunking-form/samples/dynamic-import-identifier-3-1/_config.js b/test/chunking-form/samples/dynamic-import-identifier-3-1/_config.js new file mode 100644 index 00000000000..f1f3e6ac277 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3-1/_config.js @@ -0,0 +1,3 @@ +module.exports = defineTest({ + description: 'wrong:tree-shakes dynamic imports with identifier' +}); diff --git a/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/amd/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/amd/generated-module.js new file mode 100644 index 00000000000..530ed7983bc --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/amd/generated-module.js @@ -0,0 +1,11 @@ +define(['exports'], (function (exports) { 'use strict'; + + const foo = () => {}; + const bar = () => {}; + const baz = () => {}; + + exports.bar = bar; + exports.baz = baz; + exports.foo = foo; + +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/amd/main.js b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/amd/main.js new file mode 100644 index 00000000000..c68fce3ff34 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/amd/main.js @@ -0,0 +1,10 @@ +define(['require'], (function (require) { 'use strict'; + + (async () => { + const module = await new Promise(function (resolve, reject) { require(['./generated-module'], resolve, reject); }); + const { foo, ...rest } = module; + foo(); + rest.bar(); + })(); + +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/cjs/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/cjs/generated-module.js new file mode 100644 index 00000000000..22928b57a48 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/cjs/generated-module.js @@ -0,0 +1,9 @@ +'use strict'; + +const foo = () => {}; +const bar = () => {}; +const baz = () => {}; + +exports.bar = bar; +exports.baz = baz; +exports.foo = foo; diff --git a/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/cjs/main.js b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/cjs/main.js new file mode 100644 index 00000000000..87fe2cc7880 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/cjs/main.js @@ -0,0 +1,8 @@ +'use strict'; + +(async () => { + const module = await Promise.resolve().then(function () { return require('./generated-module.js'); }); + const { foo, ...rest } = module; + foo(); + rest.bar(); +})(); diff --git a/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/es/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/es/generated-module.js new file mode 100644 index 00000000000..2918fd37fb1 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/es/generated-module.js @@ -0,0 +1,5 @@ +const foo = () => {}; +const bar = () => {}; +const baz = () => {}; + +export { bar, baz, foo }; diff --git a/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/es/main.js b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/es/main.js new file mode 100644 index 00000000000..9c785510e3a --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/es/main.js @@ -0,0 +1,6 @@ +(async () => { + const module = await import('./generated-module.js'); + const { foo, ...rest } = module; + foo(); + rest.bar(); +})(); diff --git a/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/system/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/system/generated-module.js new file mode 100644 index 00000000000..5808ca6422f --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/system/generated-module.js @@ -0,0 +1,12 @@ +System.register([], (function (exports) { + 'use strict'; + return { + execute: (function () { + + const foo = exports("foo", () => {}); + const bar = exports("bar", () => {}); + const baz = exports("baz", () => {}); + + }) + }; +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/system/main.js b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/system/main.js new file mode 100644 index 00000000000..899fa00fcab --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3-1/_expected/system/main.js @@ -0,0 +1,15 @@ +System.register([], (function (exports, module) { + 'use strict'; + return { + execute: (function () { + + (async () => { + const module$1 = await module.import('./generated-module.js'); + const { foo, ...rest } = module$1; + foo(); + rest.bar(); + })(); + + }) + }; +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-3-1/main.js b/test/chunking-form/samples/dynamic-import-identifier-3-1/main.js new file mode 100644 index 00000000000..4a570533854 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3-1/main.js @@ -0,0 +1,6 @@ +(async () => { + const module = await import('./module'); + const { foo, ...rest } = module; + foo(); + rest.bar(); +})(); diff --git a/test/chunking-form/samples/dynamic-import-identifier-3-1/module.js b/test/chunking-form/samples/dynamic-import-identifier-3-1/module.js new file mode 100644 index 00000000000..482358f67f7 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3-1/module.js @@ -0,0 +1,3 @@ +export const foo = () => {}; +export const bar = () => {}; +export const baz = () => {}; diff --git a/test/chunking-form/samples/dynamic-import-identifier-3/_config.js b/test/chunking-form/samples/dynamic-import-identifier-3/_config.js new file mode 100644 index 00000000000..f1f3e6ac277 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3/_config.js @@ -0,0 +1,3 @@ +module.exports = defineTest({ + description: 'wrong:tree-shakes dynamic imports with identifier' +}); diff --git a/test/chunking-form/samples/dynamic-import-identifier-3/_expected/amd/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/amd/generated-module.js new file mode 100644 index 00000000000..3123adef9b9 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/amd/generated-module.js @@ -0,0 +1,7 @@ +define(['exports'], (function (exports) { 'use strict'; + + const foo = () => {}; + + exports.foo = foo; + +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-3/_expected/amd/main.js b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/amd/main.js new file mode 100644 index 00000000000..393277bbc14 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/amd/main.js @@ -0,0 +1,9 @@ +define(['require'], (function (require) { 'use strict'; + + (async () => { + const module = await new Promise(function (resolve, reject) { require(['./generated-module'], resolve, reject); }); + const { foo } = module; + foo(); + })(); + +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-3/_expected/cjs/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/cjs/generated-module.js new file mode 100644 index 00000000000..02ce8a98f32 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/cjs/generated-module.js @@ -0,0 +1,5 @@ +'use strict'; + +const foo = () => {}; + +exports.foo = foo; diff --git a/test/chunking-form/samples/dynamic-import-identifier-3/_expected/cjs/main.js b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/cjs/main.js new file mode 100644 index 00000000000..4a1a8601b69 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/cjs/main.js @@ -0,0 +1,7 @@ +'use strict'; + +(async () => { + const module = await Promise.resolve().then(function () { return require('./generated-module.js'); }); + const { foo } = module; + foo(); +})(); diff --git a/test/chunking-form/samples/dynamic-import-identifier-3/_expected/es/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/es/generated-module.js new file mode 100644 index 00000000000..4ac31b619b3 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/es/generated-module.js @@ -0,0 +1,3 @@ +const foo = () => {}; + +export { foo }; diff --git a/test/chunking-form/samples/dynamic-import-identifier-3/_expected/es/main.js b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/es/main.js new file mode 100644 index 00000000000..f3e7e198a5d --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/es/main.js @@ -0,0 +1,5 @@ +(async () => { + const module = await import('./generated-module.js'); + const { foo } = module; + foo(); +})(); diff --git a/test/chunking-form/samples/dynamic-import-identifier-3/_expected/system/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/system/generated-module.js new file mode 100644 index 00000000000..72f26099c8c --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/system/generated-module.js @@ -0,0 +1,10 @@ +System.register([], (function (exports) { + 'use strict'; + return { + execute: (function () { + + const foo = exports("foo", () => {}); + + }) + }; +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-3/_expected/system/main.js b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/system/main.js new file mode 100644 index 00000000000..6ed7ec54c2e --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3/_expected/system/main.js @@ -0,0 +1,14 @@ +System.register([], (function (exports, module) { + 'use strict'; + return { + execute: (function () { + + (async () => { + const module$1 = await module.import('./generated-module.js'); + const { foo } = module$1; + foo(); + })(); + + }) + }; +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier/main.js b/test/chunking-form/samples/dynamic-import-identifier-3/main.js similarity index 65% rename from test/chunking-form/samples/dynamic-import-identifier/main.js rename to test/chunking-form/samples/dynamic-import-identifier-3/main.js index 5f4f8982c41..597d1a8665a 100644 --- a/test/chunking-form/samples/dynamic-import-identifier/main.js +++ b/test/chunking-form/samples/dynamic-import-identifier-3/main.js @@ -1,4 +1,5 @@ (async () => { const module = await import('./module'); - module.foo(); + const { foo } = module; + foo(); })(); diff --git a/test/chunking-form/samples/dynamic-import-identifier-3/module.js b/test/chunking-form/samples/dynamic-import-identifier-3/module.js new file mode 100644 index 00000000000..8beef0c8742 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-3/module.js @@ -0,0 +1,2 @@ +export const foo = () => {}; +export const bar = () => {}; diff --git a/test/chunking-form/samples/dynamic-import-identifier-4/_config.js b/test/chunking-form/samples/dynamic-import-identifier-4/_config.js new file mode 100644 index 00000000000..25a82f2baa6 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-4/_config.js @@ -0,0 +1,4 @@ +module.exports = defineTest({ + description: 'tree-shakes dynamic imports with identifier', + skip: true +}); diff --git a/test/chunking-form/samples/dynamic-import-identifier-4/_expected/amd/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-4/_expected/amd/generated-module.js new file mode 100644 index 00000000000..3123adef9b9 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-4/_expected/amd/generated-module.js @@ -0,0 +1,7 @@ +define(['exports'], (function (exports) { 'use strict'; + + const foo = () => {}; + + exports.foo = foo; + +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier/_expected/amd/main.js b/test/chunking-form/samples/dynamic-import-identifier-4/_expected/amd/main.js similarity index 100% rename from test/chunking-form/samples/dynamic-import-identifier/_expected/amd/main.js rename to test/chunking-form/samples/dynamic-import-identifier-4/_expected/amd/main.js diff --git a/test/chunking-form/samples/dynamic-import-identifier-4/_expected/cjs/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-4/_expected/cjs/generated-module.js new file mode 100644 index 00000000000..02ce8a98f32 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-4/_expected/cjs/generated-module.js @@ -0,0 +1,5 @@ +'use strict'; + +const foo = () => {}; + +exports.foo = foo; diff --git a/test/chunking-form/samples/dynamic-import-identifier/_expected/cjs/main.js b/test/chunking-form/samples/dynamic-import-identifier-4/_expected/cjs/main.js similarity index 100% rename from test/chunking-form/samples/dynamic-import-identifier/_expected/cjs/main.js rename to test/chunking-form/samples/dynamic-import-identifier-4/_expected/cjs/main.js diff --git a/test/chunking-form/samples/dynamic-import-identifier-4/_expected/es/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-4/_expected/es/generated-module.js new file mode 100644 index 00000000000..4ac31b619b3 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-4/_expected/es/generated-module.js @@ -0,0 +1,3 @@ +const foo = () => {}; + +export { foo }; diff --git a/test/chunking-form/samples/dynamic-import-identifier/_expected/es/main.js b/test/chunking-form/samples/dynamic-import-identifier-4/_expected/es/main.js similarity index 100% rename from test/chunking-form/samples/dynamic-import-identifier/_expected/es/main.js rename to test/chunking-form/samples/dynamic-import-identifier-4/_expected/es/main.js diff --git a/test/chunking-form/samples/dynamic-import-identifier-4/_expected/system/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-4/_expected/system/generated-module.js new file mode 100644 index 00000000000..72f26099c8c --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-4/_expected/system/generated-module.js @@ -0,0 +1,10 @@ +System.register([], (function (exports) { + 'use strict'; + return { + execute: (function () { + + const foo = exports("foo", () => {}); + + }) + }; +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier/_expected/system/main.js b/test/chunking-form/samples/dynamic-import-identifier-4/_expected/system/main.js similarity index 100% rename from test/chunking-form/samples/dynamic-import-identifier/_expected/system/main.js rename to test/chunking-form/samples/dynamic-import-identifier-4/_expected/system/main.js diff --git a/test/chunking-form/samples/dynamic-import-identifier-4/main.js b/test/chunking-form/samples/dynamic-import-identifier-4/main.js new file mode 100644 index 00000000000..24add6eb43d --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-4/main.js @@ -0,0 +1,7 @@ +(async () => { + const module = await import('./module'); + readBar(module); + function readBar(module1) { + module1.foo(); + } +})(); diff --git a/test/chunking-form/samples/dynamic-import-identifier-4/module.js b/test/chunking-form/samples/dynamic-import-identifier-4/module.js new file mode 100644 index 00000000000..8beef0c8742 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-4/module.js @@ -0,0 +1,2 @@ +export const foo = () => {}; +export const bar = () => {}; diff --git a/test/chunking-form/samples/dynamic-import-identifier-5/_config.js b/test/chunking-form/samples/dynamic-import-identifier-5/_config.js new file mode 100644 index 00000000000..7ef5235a00c --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-5/_config.js @@ -0,0 +1,3 @@ +module.exports = defineTest({ + description: 'tree-shakes dynamic imports with identifier' +}); diff --git a/test/chunking-form/samples/dynamic-import-identifier-5/_expected/amd/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/amd/generated-module.js new file mode 100644 index 00000000000..530ed7983bc --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/amd/generated-module.js @@ -0,0 +1,11 @@ +define(['exports'], (function (exports) { 'use strict'; + + const foo = () => {}; + const bar = () => {}; + const baz = () => {}; + + exports.bar = bar; + exports.baz = baz; + exports.foo = foo; + +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-5/_expected/amd/main.js b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/amd/main.js new file mode 100644 index 00000000000..0cc0d339c86 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/amd/main.js @@ -0,0 +1,10 @@ +define(['require'], (function (require) { 'use strict'; + + (async () => { + const module = await new Promise(function (resolve, reject) { require(['./generated-module'], resolve, reject); }); + (module).bar(); + (global.unknown && module).foo(); + (global.unknown ? module : 'foo').baz(); + })(); + +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-5/_expected/cjs/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/cjs/generated-module.js new file mode 100644 index 00000000000..22928b57a48 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/cjs/generated-module.js @@ -0,0 +1,9 @@ +'use strict'; + +const foo = () => {}; +const bar = () => {}; +const baz = () => {}; + +exports.bar = bar; +exports.baz = baz; +exports.foo = foo; diff --git a/test/chunking-form/samples/dynamic-import-identifier-5/_expected/cjs/main.js b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/cjs/main.js new file mode 100644 index 00000000000..f7b8f89dcc0 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/cjs/main.js @@ -0,0 +1,8 @@ +'use strict'; + +(async () => { + const module = await Promise.resolve().then(function () { return require('./generated-module.js'); }); + (module).bar(); + (global.unknown && module).foo(); + (global.unknown ? module : 'foo').baz(); +})(); diff --git a/test/chunking-form/samples/dynamic-import-identifier-5/_expected/es/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/es/generated-module.js new file mode 100644 index 00000000000..2918fd37fb1 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/es/generated-module.js @@ -0,0 +1,5 @@ +const foo = () => {}; +const bar = () => {}; +const baz = () => {}; + +export { bar, baz, foo }; diff --git a/test/chunking-form/samples/dynamic-import-identifier-5/_expected/es/main.js b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/es/main.js new file mode 100644 index 00000000000..08c649fb859 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/es/main.js @@ -0,0 +1,6 @@ +(async () => { + const module = await import('./generated-module.js'); + (module).bar(); + (global.unknown && module).foo(); + (global.unknown ? module : 'foo').baz(); +})(); diff --git a/test/chunking-form/samples/dynamic-import-identifier-5/_expected/system/generated-module.js b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/system/generated-module.js new file mode 100644 index 00000000000..5808ca6422f --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/system/generated-module.js @@ -0,0 +1,12 @@ +System.register([], (function (exports) { + 'use strict'; + return { + execute: (function () { + + const foo = exports("foo", () => {}); + const bar = exports("bar", () => {}); + const baz = exports("baz", () => {}); + + }) + }; +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-5/_expected/system/main.js b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/system/main.js new file mode 100644 index 00000000000..4f232981953 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-5/_expected/system/main.js @@ -0,0 +1,15 @@ +System.register([], (function (exports, module) { + 'use strict'; + return { + execute: (function () { + + (async () => { + const module$1 = await module.import('./generated-module.js'); + (module$1).bar(); + (global.unknown && module$1).foo(); + (global.unknown ? module$1 : 'foo').baz(); + })(); + + }) + }; +})); diff --git a/test/chunking-form/samples/dynamic-import-identifier-5/main.js b/test/chunking-form/samples/dynamic-import-identifier-5/main.js new file mode 100644 index 00000000000..88093f75405 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-5/main.js @@ -0,0 +1,6 @@ +(async () => { + const module = await import('./module'); + ('foo', module).bar(); + (global.unknown && module).foo(); + (global.unknown ? module : 'foo').baz(); +})(); diff --git a/test/chunking-form/samples/dynamic-import-identifier-5/module.js b/test/chunking-form/samples/dynamic-import-identifier-5/module.js new file mode 100644 index 00000000000..711d5691650 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-identifier-5/module.js @@ -0,0 +1,4 @@ +export const foo = () => {}; +export const bar = () => {}; +export const baz = () => {}; +export const qux = () => {};