Skip to content

Commit

Permalink
Add moduleParsed hook
Browse files Browse the repository at this point in the history
  • Loading branch information
lukastaegert committed Oct 8, 2020
1 parent dfd9dcb commit 0161f8b
Show file tree
Hide file tree
Showing 17 changed files with 267 additions and 128 deletions.
6 changes: 3 additions & 3 deletions cli/help.md
Expand Up @@ -32,6 +32,7 @@ Basic options:
--exports <mode> Specify export mode (auto, default, named, none)
--extend Extend global variable defined by --name
--no-externalLiveBindings Do not generate code to support live bindings
--failAfterWarnings Exit with an error if the build produced warnings
--footer <text> Code to insert at end of bundle (outside wrapper)
--no-freeze Do not freeze namespace objects
--no-hoistTransitiveImports Do not hoist transitive imports into entry chunks
Expand All @@ -46,14 +47,13 @@ Basic options:
--preferConst Use `const` instead of `var` for exports
--no-preserveEntrySignatures Avoid facade chunks for entry points
--preserveModules Preserve module structure
--preserveModulesRoot Preserved modules under this path are rooted in output `dir`
--preserveModulesRoot Put preserved modules under this path at root level
--preserveSymlinks Do not follow symlinks when resolving files
--shimMissingExports Create shim variables for missing exports
--silent Don't print warnings
--failAfterWarnings Exit with an error code if there was a warning during the build
--sourcemapExcludeSources Do not include source code in source maps
--sourcemapFile <file> Specify bundle position for source maps
--stdin=ext Specify file extension used for stdin input - default is none
--stdin=ext Specify file extension used for stdin input
--no-stdin Do not read "-" from stdin
--no-strict Don't emit `"use strict";` in the generated modules
--strictDeprecations Throw errors for deprecated features
Expand Down
6 changes: 3 additions & 3 deletions docs/01-command-line-reference.md
Expand Up @@ -290,6 +290,7 @@ Many options have command line equivalents. In those cases, any arguments passed
--exports <mode> Specify export mode (auto, default, named, none)
--extend Extend global variable defined by --name
--no-externalLiveBindings Do not generate code to support live bindings
--failAfterWarnings Exit with an error if the build produced warnings
--footer <text> Code to insert at end of bundle (outside wrapper)
--no-freeze Do not freeze namespace objects
--no-hoistTransitiveImports Do not hoist transitive imports into entry chunks
Expand All @@ -304,14 +305,13 @@ Many options have command line equivalents. In those cases, any arguments passed
--preferConst Use `const` instead of `var` for exports
--no-preserveEntrySignatures Avoid facade chunks for entry points
--preserveModules Preserve module structure
--preserveModulesRoot Preserved modules under this path are rooted in output `dir`
--preserveModulesRoot Put preserved modules under this path at root level
--preserveSymlinks Do not follow symlinks when resolving files
--shimMissingExports Create shim variables for missing exports
--silent Don't print warnings
--failAfterWarnings Exit with an error code if there was a warning during the build
--sourcemapExcludeSources Do not include source code in source maps
--sourcemapFile <file> Specify bundle position for source maps
--stdin=ext Specify file extension used for stdin input - default is none
--stdin=ext Specify file extension used for stdin input
--no-stdin Do not read "-" from stdin
--no-strict Don't emit `"use strict";` in the generated modules
--strictDeprecations Throw errors for deprecated features
Expand Down
7 changes: 6 additions & 1 deletion docs/05-plugin-development.md
Expand Up @@ -624,6 +624,8 @@ Returns additional information about the module in question in the form
```
{
id: string, // the id of the module, for convenience
code: string | null, // the source code of the module, `null` if external or not yet available
ast: ESTree.Program, // the parsed abstract syntax tree if available
isEntry: boolean, // is this a user- or plugin-defined entry point
isExternal: boolean, // for external modules that are referenced but not included in the graph
importedIds: string[], // the module ids statically imported by this module
Expand All @@ -636,7 +638,10 @@ Returns additional information about the module in question in the form
}
```
This utility function returns `null` if the module id cannot be found.
During the build, this object represents currently available information about the module. Before the [`buildEnd`](guide/en/#buildend) hook, this information may be incomplete as e.g.
the `importedIds` are not yet resolved or additional `importers` are discovered.
Returns `null` if the module id cannot be found.
#### `this.meta: {rollupVersion: string, watchMode: boolean}`
Expand Down
2 changes: 1 addition & 1 deletion src/Bundle.ts
Expand Up @@ -267,7 +267,7 @@ function getIncludedModules(modulesById: Map<string, Module | ExternalModule>):
return [...modulesById.values()].filter(
module =>
module instanceof Module &&
(module.isIncluded() || module.isEntryPoint || module.includedDynamicImporters.length > 0)
(module.isIncluded() || module.info.isEntry || module.includedDynamicImporters.length > 0)
) as Module[];
}

Expand Down
12 changes: 6 additions & 6 deletions src/Chunk.ts
Expand Up @@ -162,7 +162,7 @@ export default class Chunk {
}
if (
!chunk.dependencies.has(chunkByModule.get(facadedModule)!) &&
facadedModule.moduleSideEffects &&
facadedModule.info.hasModuleSideEffects &&
facadedModule.hasEffects()
) {
chunk.dependencies.add(chunkByModule.get(facadedModule)!);
Expand Down Expand Up @@ -234,7 +234,7 @@ export default class Chunk {
if (this.isEmpty && module.isIncluded()) {
this.isEmpty = false;
}
if (module.isEntryPoint || outputOptions.preserveModules) {
if (module.info.isEntry || outputOptions.preserveModules) {
this.entryModules.push(module);
}
for (const importer of module.includedDynamicImporters) {
Expand Down Expand Up @@ -307,7 +307,7 @@ export default class Chunk {
} else {
assignExportsToNames(remainingExports, this.exportsByName, this.exportNamesByVariable);
}
if (this.outputOptions.preserveModules || (this.facadeModule && this.facadeModule.isEntryPoint))
if (this.outputOptions.preserveModules || (this.facadeModule && this.facadeModule.info.isEntry))
this.exportMode = getExportMode(
this,
this.outputOptions,
Expand Down Expand Up @@ -473,7 +473,7 @@ export default class Chunk {
exports: this.getExportNames(),
facadeModuleId: facadeModule && facadeModule.id,
isDynamicEntry: this.dynamicEntryModules.length > 0,
isEntry: facadeModule !== null && facadeModule.isEntryPoint,
isEntry: facadeModule !== null && facadeModule.info.isEntry,
isImplicitEntry: this.implicitEntryModules.length > 0,
modules: this.renderedModules,
get name() {
Expand Down Expand Up @@ -718,7 +718,7 @@ export default class Chunk {
intro: addons.intro!,
isEntryModuleFacade:
this.outputOptions.preserveModules ||
(this.facadeModule !== null && this.facadeModule.isEntryPoint),
(this.facadeModule !== null && this.facadeModule.info.isEntry),
namedExportsMode: this.exportMode !== 'default',
outro: addons.outro!,
usesTopLevelAwait,
Expand Down Expand Up @@ -1307,7 +1307,7 @@ export default class Chunk {
}
if (
this.includedNamespaces.has(module) ||
(module.isEntryPoint && module.preserveSignature !== false) ||
(module.info.isEntry && module.preserveSignature !== false) ||
module.includedDynamicImporters.some(importer => this.chunkByModule.get(importer) !== this)
) {
this.ensureReexportsAreAvailableForModule(module);
Expand Down
37 changes: 27 additions & 10 deletions src/ExternalModule.ts
@@ -1,22 +1,23 @@
import ExternalVariable from './ast/variables/ExternalVariable';
import {
CustomPluginOptions,
ModuleInfo,
NormalizedInputOptions,
NormalizedOutputOptions
} from './rollup/types';
import { EMPTY_ARRAY } from './utils/blank';
import { makeLegal } from './utils/identifierHelpers';
import { isAbsolute, normalize, relative } from './utils/path';

export default class ExternalModule {
chunk: void;
// TODO Lukas get from resolution
custom: CustomPluginOptions = {};
declarations: { [name: string]: ExternalVariable };
defaultVariableName = '';
dynamicImporters: string[] = [];
execIndex: number;
exportedVariables: Map<ExternalVariable, string>;
importers: string[] = [];
info: ModuleInfo;
mostCommonSuggestion = 0;
namespaceVariableName = '';
nameSuggestions: { [name: string]: number };
Expand All @@ -30,19 +31,35 @@ export default class ExternalModule {
constructor(
private readonly options: NormalizedInputOptions,
public readonly id: string,
public moduleSideEffects: boolean | 'no-treeshake',
public meta: CustomPluginOptions
hasModuleSideEffects: boolean | 'no-treeshake',
meta: CustomPluginOptions
) {
this.id = id;
this.execIndex = Infinity;
this.moduleSideEffects = moduleSideEffects;

const parts = id.split(/[\\/]/);
this.suggestedVariableName = makeLegal(parts.pop()!);

this.suggestedVariableName = makeLegal(id.split(/[\\/]/).pop()!);
this.nameSuggestions = Object.create(null);
this.declarations = Object.create(null);
this.exportedVariables = new Map();

const module = this;
this.info = {
ast: null,
code: null,
dynamicallyImportedIds: EMPTY_ARRAY,
get dynamicImporters() {
return module.dynamicImporters.sort();
},
hasModuleSideEffects,
id,
implicitlyLoadedAfterOneOf: EMPTY_ARRAY,
implicitlyLoadedBefore: EMPTY_ARRAY,
importedIds: EMPTY_ARRAY,
get importers() {
return module.importers.sort();
},
isEntry: false,
isExternal: true,
meta
};
}

getVariableForExportName(name: string): ExternalVariable {
Expand Down
50 changes: 3 additions & 47 deletions src/Graph.ts
Expand Up @@ -12,11 +12,9 @@ import {
RollupWatcher,
SerializablePluginCache
} from './rollup/types';
import { EMPTY_ARRAY } from './utils/blank';
import { BuildPhase } from './utils/buildPhase';
import { errImplicitDependantIsNotIncluded, error } from './utils/error';
import { analyseModuleExecution } from './utils/executionOrder';
import { getId } from './utils/getId';
import { PluginDriver } from './utils/PluginDriver';
import relativeId from './utils/relativeId';
import { timeEnd, timeStart } from './utils/timers';
Expand Down Expand Up @@ -136,49 +134,7 @@ export default class Graph {
getModuleInfo = (moduleId: string): ModuleInfo | null => {
const foundModule = this.modulesById.get(moduleId);
if (!foundModule) return null;
return {
ast: (foundModule as Module).ast?.esTreeNode || null,
code: foundModule instanceof Module ? foundModule.code : null,
get dynamicallyImportedIds() {
if (foundModule instanceof Module) {
const dynamicallyImportedIds: string[] = [];
for (const { resolution } of foundModule.dynamicImports) {
if (resolution instanceof Module || resolution instanceof ExternalModule) {
dynamicallyImportedIds.push(resolution.id);
}
}
return dynamicallyImportedIds;
}
return EMPTY_ARRAY;
},
get dynamicImporters() {
return foundModule!.dynamicImporters.sort();
},
hasModuleSideEffects: foundModule.moduleSideEffects,
id: foundModule.id,
get implicitlyLoadedAfterOneOf() {
return foundModule instanceof Module
? Array.from(foundModule.implicitlyLoadedAfter, getId)
: EMPTY_ARRAY;
},
get implicitlyLoadedBefore() {
return foundModule instanceof Module
? Array.from(foundModule.implicitlyLoadedBefore, getId)
: [];
},
get importedIds() {
if (foundModule instanceof Module) {
return Array.from(foundModule.sources, source => foundModule.resolvedIds[source].id);
}
return EMPTY_ARRAY;
},
get importers() {
return foundModule!.importers.sort();
},
isEntry: foundModule instanceof Module && foundModule.isEntryPoint,
isExternal: foundModule instanceof ExternalModule,
meta: foundModule.meta
};
return foundModule.info;
};

private async generateModuleGraph(): Promise<void> {
Expand Down Expand Up @@ -213,7 +169,7 @@ export default class Graph {
this.needsTreeshakingPass = false;
for (const module of this.modules) {
if (module.isExecuted) {
if (module.moduleSideEffects === 'no-treeshake') {
if (module.info.hasModuleSideEffects === 'no-treeshake') {
module.includeAllInBundle();
} else {
module.include();
Expand All @@ -228,7 +184,7 @@ export default class Graph {
for (const externalModule of this.externalModules) externalModule.warnUnusedImports();
for (const module of this.implicitEntryModules) {
for (const dependant of module.implicitlyLoadedAfter) {
if (!(dependant.isEntryPoint || dependant.isIncluded())) {
if (!(dependant.info.isEntry || dependant.isIncluded())) {
error(errImplicitDependantIsNotIncluded(dependant));
}
}
Expand Down

0 comments on commit 0161f8b

Please sign in to comment.