mirror of https://github.com/webpack/webpack.git
chore(types): add Compiler and Compilation type support
This commit is contained in:
parent
687c03869f
commit
761d73b4e7
|
@ -8,6 +8,99 @@ declare namespace NodeJS {
|
|||
}
|
||||
}
|
||||
|
||||
declare module "neo-async" {
|
||||
export interface Dictionary<T> {
|
||||
[key: string]: T;
|
||||
}
|
||||
export type IterableCollection<T> = T[] | IterableIterator<T> | Dictionary<T>;
|
||||
|
||||
export interface ErrorCallback<T> {
|
||||
(err?: T): void;
|
||||
}
|
||||
export interface AsyncBooleanResultCallback<E> {
|
||||
(err?: E, truthValue?: boolean): void;
|
||||
}
|
||||
export interface AsyncResultCallback<T, E> {
|
||||
(err?: E, result?: T): void;
|
||||
}
|
||||
export interface AsyncResultArrayCallback<T, E> {
|
||||
(err?: E, results?: Array<T | undefined>): void;
|
||||
}
|
||||
export interface AsyncResultObjectCallback<T, E> {
|
||||
(err: E | undefined, results: Dictionary<T | undefined>): void;
|
||||
}
|
||||
|
||||
export interface AsyncFunction<T, E> {
|
||||
(callback: (err?: E, result?: T) => void): void;
|
||||
}
|
||||
export interface AsyncFunctionEx<T, E> {
|
||||
(callback: (err?: E, ...results: T[]) => void): void;
|
||||
}
|
||||
export interface AsyncIterator<T, E> {
|
||||
(item: T, callback: ErrorCallback<E>): void;
|
||||
}
|
||||
export interface AsyncForEachOfIterator<T, E> {
|
||||
(item: T, key: number | string, callback: ErrorCallback<E>): void;
|
||||
}
|
||||
export interface AsyncResultIterator<T, R, E> {
|
||||
(item: T, callback: AsyncResultCallback<R, E>): void;
|
||||
}
|
||||
export interface AsyncMemoIterator<T, R, E> {
|
||||
(memo: R | undefined, item: T, callback: AsyncResultCallback<R, E>): void;
|
||||
}
|
||||
export interface AsyncBooleanIterator<T, E> {
|
||||
(item: T, callback: AsyncBooleanResultCallback<E>): void;
|
||||
}
|
||||
|
||||
export interface AsyncWorker<T, E> {
|
||||
(task: T, callback: ErrorCallback<E>): void;
|
||||
}
|
||||
export interface AsyncVoidFunction<E> {
|
||||
(callback: ErrorCallback<E>): void;
|
||||
}
|
||||
|
||||
export type AsyncAutoTasks<R extends Dictionary<any>, E> = {
|
||||
[K in keyof R]: AsyncAutoTask<R[K], R, E>
|
||||
};
|
||||
export type AsyncAutoTask<R1, R extends Dictionary<any>, E> =
|
||||
| AsyncAutoTaskFunctionWithoutDependencies<R1, E>
|
||||
| (keyof R | AsyncAutoTaskFunction<R1, R, E>)[];
|
||||
export interface AsyncAutoTaskFunctionWithoutDependencies<R1, E> {
|
||||
(cb: AsyncResultCallback<R1, E> | ErrorCallback<E>): void;
|
||||
}
|
||||
export interface AsyncAutoTaskFunction<R1, R extends Dictionary<any>, E> {
|
||||
(results: R, cb: AsyncResultCallback<R1, E> | ErrorCallback<E>): void;
|
||||
}
|
||||
|
||||
export function each<T, E>(
|
||||
arr: IterableCollection<T>,
|
||||
iterator: AsyncIterator<T, E>,
|
||||
callback?: ErrorCallback<E>
|
||||
): void;
|
||||
|
||||
export function map<T, R, E>(
|
||||
arr: T[] | IterableIterator<T>,
|
||||
iterator: AsyncResultIterator<T, R, E>,
|
||||
callback?: AsyncResultArrayCallback<R, E>
|
||||
): void;
|
||||
export function map<T, R, E>(
|
||||
arr: Dictionary<T>,
|
||||
iterator: AsyncResultIterator<T, R, E>,
|
||||
callback?: AsyncResultArrayCallback<R, E>
|
||||
): void;
|
||||
|
||||
export function parallel<T, E>(
|
||||
tasks: Array<AsyncFunction<T, E>>,
|
||||
callback?: AsyncResultArrayCallback<T, E>
|
||||
): void;
|
||||
export function parallel<T, E>(
|
||||
tasks: Dictionary<AsyncFunction<T, E>>,
|
||||
callback?: AsyncResultObjectCallback<T, E>
|
||||
): void;
|
||||
|
||||
export const forEach: typeof each;
|
||||
}
|
||||
|
||||
// There are no typings for chrome-trace-event
|
||||
declare module "chrome-trace-event" {
|
||||
interface Event {
|
||||
|
|
|
@ -5,7 +5,34 @@
|
|||
"use strict";
|
||||
const DependenciesBlock = require("./DependenciesBlock");
|
||||
|
||||
/**
|
||||
* @typedef {import("./ChunkGroup")} ChunkGroup
|
||||
* @typedef {import("./Module")} Module
|
||||
* @typedef {import("crypto").Hash} Hash
|
||||
* @typedef {TODO} GroupOptions
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} SourcePosition
|
||||
* @property {number} line
|
||||
* @property {number} column
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} SourceLocation
|
||||
* @property {number} index
|
||||
* @property {SourcePosition} start
|
||||
* @property {SourcePosition} end
|
||||
*/
|
||||
|
||||
module.exports = class AsyncDependenciesBlock extends DependenciesBlock {
|
||||
/**
|
||||
* @param {GroupOptions} groupOptions options for the group
|
||||
* @param {Module} module the Module object
|
||||
* @param {SourceLocation=} loc the line of code
|
||||
* @param {TODO=} request the request
|
||||
*/
|
||||
constructor(groupOptions, module, loc, request) {
|
||||
super();
|
||||
if (typeof groupOptions === "string") {
|
||||
|
@ -14,28 +41,50 @@ module.exports = class AsyncDependenciesBlock extends DependenciesBlock {
|
|||
groupOptions = { name: undefined };
|
||||
}
|
||||
this.groupOptions = groupOptions;
|
||||
/** @type {ChunkGroup=} */
|
||||
this.chunkGroup = undefined;
|
||||
this.module = module;
|
||||
this.loc = loc;
|
||||
this.request = request;
|
||||
/** @type {DependenciesBlock} */
|
||||
this.parent = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string} The name of the chunk
|
||||
*/
|
||||
get chunkName() {
|
||||
return this.groupOptions.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} value The new chunk name
|
||||
* @returns {void}
|
||||
*/
|
||||
set chunkName(value) {
|
||||
this.groupOptions.name = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {never} this throws and should never be called
|
||||
*/
|
||||
get chunks() {
|
||||
throw new Error("Moved to AsyncDependenciesBlock.chunkGroup");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {never} value setter value
|
||||
* @returns {never} this is going to throw therefore we should throw type
|
||||
* assertions by returning never
|
||||
*/
|
||||
set chunks(value) {
|
||||
throw new Error("Moved to AsyncDependenciesBlock.chunkGroup");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Hash} hash the hash used to track block changes, from "crypto" module
|
||||
* @returns {void}
|
||||
*/
|
||||
updateHash(hash) {
|
||||
hash.update(JSON.stringify(this.groupOptions));
|
||||
hash.update(
|
||||
|
@ -50,16 +99,25 @@ module.exports = class AsyncDependenciesBlock extends DependenciesBlock {
|
|||
super.updateHash(hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {void}
|
||||
*/
|
||||
disconnect() {
|
||||
this.chunkGroup = undefined;
|
||||
super.disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {void}
|
||||
*/
|
||||
unseal() {
|
||||
this.chunkGroup = undefined;
|
||||
super.unseal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {void}
|
||||
*/
|
||||
sortItems() {
|
||||
super.sortItems();
|
||||
}
|
||||
|
|
22
lib/Chunk.js
22
lib/Chunk.js
|
@ -17,6 +17,7 @@ const ERR_CHUNK_INITIAL =
|
|||
/** @typedef {import("./ChunkGroup")} ChunkGroup */
|
||||
/** @typedef {import("./ModuleReason.js")} ModuleReason */
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
/** @typedef {import("crypto").Hash} Hash */
|
||||
|
||||
/**
|
||||
* @typedef {Object} Identifiable an object who contains an identifier function property
|
||||
|
@ -471,6 +472,11 @@ class Chunk {
|
|||
return this.addMultiplierAndOverhead(this.modulesSize(), options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Chunk} otherChunk the other chunk
|
||||
* @param {TODO} options the options for this function
|
||||
* @returns {number | false} the size, or false if it can't be integrated
|
||||
*/
|
||||
integratedSize(otherChunk, options) {
|
||||
// Chunk if it's possible to integrate this chunk
|
||||
if (!this.canBeIntegrated(otherChunk)) {
|
||||
|
@ -500,6 +506,9 @@ class Chunk {
|
|||
this.sortModules();
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Set<Chunk>} a set of all the async chunks
|
||||
*/
|
||||
getAllAsyncChunks() {
|
||||
const queue = new Set();
|
||||
const chunks = new Set();
|
||||
|
@ -522,6 +531,10 @@ class Chunk {
|
|||
return chunks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Hash} realHash the hash for the chunk maps
|
||||
* @returns {{ hash: TODO, contentHash: TODO, name: TODO }} the chunk map information
|
||||
*/
|
||||
getChunkMaps(realHash) {
|
||||
const chunkHashMap = Object.create(null);
|
||||
const chunkContentHashMap = Object.create(null);
|
||||
|
@ -544,6 +557,9 @@ class Chunk {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Record<string, Array<Set<TODO>>>} a record object of names to lists of child ids(?)
|
||||
*/
|
||||
getChildIdsByOrders() {
|
||||
const lists = new Map();
|
||||
for (const group of this.groupsIterable) {
|
||||
|
@ -600,6 +616,12 @@ class Chunk {
|
|||
return chunkMaps;
|
||||
}
|
||||
|
||||
/** @typedef {(module: Module) => true} FilterFn */
|
||||
|
||||
/**
|
||||
* @param {FilterFn} filterFn function used to filter modules
|
||||
* @returns {TODO} module map information
|
||||
*/
|
||||
getChunkModuleMaps(filterFn) {
|
||||
const chunkModuleIdMap = Object.create(null);
|
||||
const chunkModuleHashMap = Object.create(null);
|
||||
|
|
|
@ -35,14 +35,93 @@ const createHash = require("./util/createHash");
|
|||
const Queue = require("./util/Queue");
|
||||
const SortableSet = require("./util/SortableSet");
|
||||
const GraphHelpers = require("./GraphHelpers");
|
||||
const SingleEntryDependency = require("./dependencies/SingleEntryDependency");
|
||||
|
||||
const byId = (a, b) => {
|
||||
/** @typedef {import("./Module")} Module */
|
||||
/** @typedef {import("./Compiler")} Compiler */
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
/** @typedef {import("./WebpackError")} WebpackError */
|
||||
/** @typedef {import("./DependenciesBlockVariable")} DependenciesBlockVariable */
|
||||
/** @typedef {import("./dependencies/SingleEntryDependency")} SingleEntryDependency */
|
||||
/** @typedef {import("./dependencies/MultiEntryDependency")} MultiEntryDependency */
|
||||
/** @typedef {import("./dependencies/DllEntryDependency")} DllEntryDependency */
|
||||
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
|
||||
/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
|
||||
|
||||
/** @typedef {SingleEntryDependency|MultiEntryDependency|DllEntryDependency} PossibleEntryDependencies */
|
||||
/** @typedef {{[assetName: string]: Source}} CompilationAssets */
|
||||
/** @typedef {(err: Error|null, result?: Module) => void } ModuleCallback */
|
||||
/** @typedef {(err?: Error|null, result?: Module) => void } ModuleChainCallback */
|
||||
/** @typedef {(module: Module) => void} OnModuleCallback */
|
||||
/** @typedef {(err?: Error|null) => void} CompilationSealCallback */
|
||||
/** @typedef {{apply: (dep: Dependency, source: Source, runtime: RuntimeTemplate) => void}} DependencyTemplate */
|
||||
/** @typedef {(d: Dependency) => any} DepBlockVarDependenciesCallback */
|
||||
/** @typedef {new (...args: any[]) => Dependency} DepConstructor */
|
||||
/** @typedef {{apply: () => void}} Plugin */
|
||||
|
||||
/**
|
||||
* @typedef {Object} ModuleFactoryCreateDataContextInfo
|
||||
* @property {string} issuer
|
||||
* @property {string} compiler
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ModuleFactoryCreateData
|
||||
* @property {ModuleFactoryCreateDataContextInfo} contextInfo
|
||||
* @property {any=} resolveOptions
|
||||
* @property {string} context
|
||||
* @property {Dependency[]} dependencies
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ModuleFactory
|
||||
* @property {(data: ModuleFactoryCreateData, callback: ModuleCallback) => any} create
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} SortedDependency
|
||||
* @property {ModuleFactory} factory
|
||||
* @property {Dependency[]} dependencies
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} SourcePosition
|
||||
* @property {number} line
|
||||
* @property {number} column
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} SourceLocation
|
||||
* @property {number} index
|
||||
* @property {SourcePosition} start
|
||||
* @property {SourcePosition} end
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} AvailableModulesChunkGroupMapping
|
||||
* @property {ChunkGroup} chunkGroup
|
||||
* @property {Set<Module>} availableModules
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {Chunk} a first chunk to sort by id
|
||||
* @param {Chunk} b second chunk to sort by id
|
||||
* @returns {-1|0|1} sort value
|
||||
*/
|
||||
function byId(a, b) {
|
||||
if (a.id && b.id) {
|
||||
if (a.id < b.id) return -1;
|
||||
if (a.id > b.id) return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
const byIdOrIdentifier = (a, b) => {
|
||||
/**
|
||||
* @param {Module} a first module to sort by
|
||||
* @param {Module} b second module to sort by
|
||||
* @returns {-1|0|1} sort value
|
||||
*/
|
||||
function byIdOrIdentifier(a, b) {
|
||||
if (a.id < b.id) return -1;
|
||||
if (a.id > b.id) return 1;
|
||||
const identA = a.identifier();
|
||||
|
@ -50,9 +129,14 @@ const byIdOrIdentifier = (a, b) => {
|
|||
if (identA < identB) return -1;
|
||||
if (identA > identB) return 1;
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
const byIndexOrIdentifier = (a, b) => {
|
||||
/**
|
||||
* @param {Module} a first module to sort by
|
||||
* @param {Module} b second module to sort by
|
||||
* @returns {-1|0|1} sort value
|
||||
*/
|
||||
function byIndexOrIdentifier(a, b) {
|
||||
if (a.index < b.index) return -1;
|
||||
if (a.index > b.index) return 1;
|
||||
const identA = a.identifier();
|
||||
|
@ -60,35 +144,59 @@ const byIndexOrIdentifier = (a, b) => {
|
|||
if (identA < identB) return -1;
|
||||
if (identA > identB) return 1;
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
const byNameOrHash = (a, b) => {
|
||||
/**
|
||||
* @param {Compilation} a first compilation to sort by
|
||||
* @param {Compilation} b second compilation to sort by
|
||||
* @returns {-1|0|1} sort value
|
||||
*/
|
||||
function byNameOrHash(a, b) {
|
||||
if (a.name < b.name) return -1;
|
||||
if (a.name > b.name) return 1;
|
||||
if (a.fullHash < b.fullHash) return -1;
|
||||
if (a.fullhash > b.fullHash) return 1;
|
||||
if (a.fullHash > b.fullHash) return 1;
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
const iterationBlockVariable = (variables, fn) => {
|
||||
/**
|
||||
* @param {DependenciesBlockVariable[]} variables DepBlock Variables to iterate over
|
||||
* @param {DepBlockVarDependenciesCallback} fn callback to apply on iterated elements
|
||||
* @returns {void}
|
||||
*/
|
||||
function iterationBlockVariable(variables, fn) {
|
||||
for (
|
||||
let indexVariable = 0;
|
||||
indexVariable < variables.length;
|
||||
indexVariable++
|
||||
) {
|
||||
// TODO: Remove when Dependency + DependenciesBlockVariable is typed
|
||||
/** @type {Dependency[]} */
|
||||
const varDep = variables[indexVariable].dependencies;
|
||||
for (let indexVDep = 0; indexVDep < varDep.length; indexVDep++) {
|
||||
fn(varDep[indexVDep]);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const iterationOfArrayCallback = (arr, fn) => {
|
||||
/**
|
||||
* @template {T}
|
||||
* @param {T[]} arr array of elements to iterate over
|
||||
* @param {function(T): void} fn callback applied to each element
|
||||
* @returns {void}
|
||||
*/
|
||||
function iterationOfArrayCallback(arr, fn) {
|
||||
for (let index = 0; index < arr.length; index++) {
|
||||
fn(arr[index]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {T}
|
||||
* @param {Set<T>} set set to add items to
|
||||
* @param {Set<T>} otherSet set to add items from
|
||||
* @returns {void}
|
||||
*/
|
||||
function addAllToSet(set, otherSet) {
|
||||
for (const item of otherSet) {
|
||||
set.add(item);
|
||||
|
@ -96,92 +204,156 @@ function addAllToSet(set, otherSet) {
|
|||
}
|
||||
|
||||
class Compilation extends Tapable {
|
||||
/**
|
||||
* Creates an instance of Compilation.
|
||||
* @param {Compiler} compiler the compiler which created the compilation
|
||||
*/
|
||||
constructor(compiler) {
|
||||
super();
|
||||
this.hooks = {
|
||||
/** @type {SyncHook<Module>} */
|
||||
buildModule: new SyncHook(["module"]),
|
||||
/** @type {SyncHook<Module>} */
|
||||
rebuildModule: new SyncHook(["module"]),
|
||||
/** @type {SyncHook<Module, Error>} */
|
||||
failedModule: new SyncHook(["module", "error"]),
|
||||
/** @type {SyncHook<Module>} */
|
||||
succeedModule: new SyncHook(["module"]),
|
||||
|
||||
/** @type {SyncHook<Module[]>} */
|
||||
finishModules: new SyncHook(["modules"]),
|
||||
/** @type {SyncHook<Module>} */
|
||||
finishRebuildingModule: new SyncHook(["module"]),
|
||||
|
||||
/** @type {SyncHook} */
|
||||
unseal: new SyncHook([]),
|
||||
/** @type {SyncHook} */
|
||||
seal: new SyncHook([]),
|
||||
|
||||
/** @type {SyncBailHook<Module[]>} */
|
||||
optimizeDependenciesBasic: new SyncBailHook(["modules"]),
|
||||
/** @type {SyncBailHook<Module[]>} */
|
||||
optimizeDependencies: new SyncBailHook(["modules"]),
|
||||
/** @type {SyncBailHook<Module[]>} */
|
||||
optimizeDependenciesAdvanced: new SyncBailHook(["modules"]),
|
||||
/** @type {SyncBailHook<Module[]>} */
|
||||
afterOptimizeDependencies: new SyncHook(["modules"]),
|
||||
|
||||
/** @type {SyncHook} */
|
||||
optimize: new SyncHook([]),
|
||||
|
||||
/** @type {SyncBailHook<Module[]>} */
|
||||
optimizeModulesBasic: new SyncBailHook(["modules"]),
|
||||
/** @type {SyncBailHook<Module[]>} */
|
||||
optimizeModules: new SyncBailHook(["modules"]),
|
||||
/** @type {SyncBailHook<Module[]>} */
|
||||
optimizeModulesAdvanced: new SyncBailHook(["modules"]),
|
||||
/** @type {SyncHook<Module[]>} */
|
||||
afterOptimizeModules: new SyncHook(["modules"]),
|
||||
|
||||
/** @type {SyncBailHook<Chunk[], ChunkGroup[]>} */
|
||||
optimizeChunksBasic: new SyncBailHook(["chunks", "chunkGroups"]),
|
||||
/** @type {SyncBailHook<Chunk[], ChunkGroup[]>} */
|
||||
optimizeChunks: new SyncBailHook(["chunks", "chunkGroups"]),
|
||||
/** @type {SyncBailHook<Chunk[], ChunkGroup[]>} */
|
||||
optimizeChunksAdvanced: new SyncBailHook(["chunks", "chunkGroups"]),
|
||||
/** @type {SyncHook<Chunk[], ChunkGroup[]>} */
|
||||
afterOptimizeChunks: new SyncHook(["chunks", "chunkGroups"]),
|
||||
|
||||
/** @type {AsyncSeriesHook<Chunk[], Module[]>} */
|
||||
optimizeTree: new AsyncSeriesHook(["chunks", "modules"]),
|
||||
/** @type {SyncHook<Chunk[], Module[]>} */
|
||||
afterOptimizeTree: new SyncHook(["chunks", "modules"]),
|
||||
|
||||
/** @type {SyncBailHook<Chunk[], Module[]>} */
|
||||
optimizeChunkModulesBasic: new SyncBailHook(["chunks", "modules"]),
|
||||
/** @type {SyncBailHook<Chunk[], Module[]>} */
|
||||
optimizeChunkModules: new SyncBailHook(["chunks", "modules"]),
|
||||
/** @type {SyncBailHook<Chunk[], Module[]>} */
|
||||
optimizeChunkModulesAdvanced: new SyncBailHook(["chunks", "modules"]),
|
||||
/** @type {SyncHook<Chunk[], Module[]>} */
|
||||
afterOptimizeChunkModules: new SyncHook(["chunks", "modules"]),
|
||||
/** @type {SyncBailHook} */
|
||||
shouldRecord: new SyncBailHook([]),
|
||||
|
||||
/** @type {SyncHook<Module[], any>} */
|
||||
reviveModules: new SyncHook(["modules", "records"]),
|
||||
/** @type {SyncHook<Module[]>} */
|
||||
optimizeModuleOrder: new SyncHook(["modules"]),
|
||||
/** @type {SyncHook<Module[]>} */
|
||||
advancedOptimizeModuleOrder: new SyncHook(["modules"]),
|
||||
/** @type {SyncHook<Module[]>} */
|
||||
beforeModuleIds: new SyncHook(["modules"]),
|
||||
/** @type {SyncHook<Module[]>} */
|
||||
moduleIds: new SyncHook(["modules"]),
|
||||
/** @type {SyncHook<Module[]>} */
|
||||
optimizeModuleIds: new SyncHook(["modules"]),
|
||||
/** @type {SyncHook<Module[]>} */
|
||||
afterOptimizeModuleIds: new SyncHook(["modules"]),
|
||||
|
||||
/** @type {SyncHook<Chunk[], any>} */
|
||||
reviveChunks: new SyncHook(["chunks", "records"]),
|
||||
/** @type {SyncHook<Chunk[]>} */
|
||||
optimizeChunkOrder: new SyncHook(["chunks"]),
|
||||
/** @type {SyncHook<Chunk[]>} */
|
||||
beforeChunkIds: new SyncHook(["chunks"]),
|
||||
/** @type {SyncHook<Chunk[]>} */
|
||||
optimizeChunkIds: new SyncHook(["chunks"]),
|
||||
/** @type {SyncHook<Chunk[]>} */
|
||||
afterOptimizeChunkIds: new SyncHook(["chunks"]),
|
||||
|
||||
/** @type {SyncHook<Module[], any>} */
|
||||
recordModules: new SyncHook(["modules", "records"]),
|
||||
/** @type {SyncHook<Chunk[], any>} */
|
||||
recordChunks: new SyncHook(["chunks", "records"]),
|
||||
|
||||
/** @type {SyncHook} */
|
||||
beforeHash: new SyncHook([]),
|
||||
/** @type {SyncHook<Chunk>} */
|
||||
contentHash: new SyncHook(["chunk"]),
|
||||
/** @type {SyncHook} */
|
||||
afterHash: new SyncHook([]),
|
||||
|
||||
/** @type {SyncHook<any>} */
|
||||
recordHash: new SyncHook(["records"]),
|
||||
|
||||
/** @type {SyncHook<Compilation, any>} */
|
||||
record: new SyncHook(["compilation", "records"]),
|
||||
|
||||
/** @type {SyncHook} */
|
||||
beforeModuleAssets: new SyncHook([]),
|
||||
/** @type {SyncBailHook} */
|
||||
shouldGenerateChunkAssets: new SyncBailHook([]),
|
||||
/** @type {SyncHook} */
|
||||
beforeChunkAssets: new SyncHook([]),
|
||||
/** @type {SyncHook<Chunk[]>} */
|
||||
additionalChunkAssets: new SyncHook(["chunks"]),
|
||||
|
||||
/** @type {AsyncSeriesHook} */
|
||||
additionalAssets: new AsyncSeriesHook([]),
|
||||
/** @type {AsyncSeriesHook<Chunk[]>} */
|
||||
optimizeChunkAssets: new AsyncSeriesHook(["chunks"]),
|
||||
/** @type {SyncHook<Chunk[]>} */
|
||||
afterOptimizeChunkAssets: new SyncHook(["chunks"]),
|
||||
/** @type {AsyncSeriesHook<CompilationAssets>} */
|
||||
optimizeAssets: new AsyncSeriesHook(["assets"]),
|
||||
/** @type {SyncHook<CompilationAssets>} */
|
||||
afterOptimizeAssets: new SyncHook(["assets"]),
|
||||
|
||||
/** @type {SyncBailHook} */
|
||||
needAdditionalSeal: new SyncBailHook([]),
|
||||
/** @type {AsyncSeriesHook} */
|
||||
afterSeal: new AsyncSeriesHook([]),
|
||||
|
||||
/** @type {SyncHook<Chunk, any>} */
|
||||
chunkHash: new SyncHook(["chunk", "chunkHash"]),
|
||||
/** @type {SyncHook<Module, string>} */
|
||||
moduleAsset: new SyncHook(["module", "filename"]),
|
||||
/** @type {SyncHook<Chunk, string>} */
|
||||
chunkAsset: new SyncHook(["chunk", "filename"]),
|
||||
|
||||
/** @type {SyncWaterfallHook<string, any>} */
|
||||
assetPath: new SyncWaterfallHook(["filename", "data"]), // TODO MainTemplate
|
||||
|
||||
/** @type {SyncBailHook} */
|
||||
needAdditionalPass: new SyncBailHook([]),
|
||||
|
||||
/** @type {SyncHook<Compiler, string, number>} */
|
||||
childCompiler: new SyncHook([
|
||||
"childCompiler",
|
||||
"compilerName",
|
||||
|
@ -190,11 +362,16 @@ class Compilation extends Tapable {
|
|||
|
||||
// TODO the following hooks are weirdly located here
|
||||
// TODO move them for webpack 5
|
||||
/** @type {SyncHook<string, Module>} */
|
||||
normalModuleLoader: new SyncHook(["loaderContext", "module"]),
|
||||
|
||||
/** @type {SyncBailHook<Chunk[]>} */
|
||||
optimizeExtractedChunksBasic: new SyncBailHook(["chunks"]),
|
||||
/** @type {SyncBailHook<Chunk[]>} */
|
||||
optimizeExtractedChunks: new SyncBailHook(["chunks"]),
|
||||
/** @type {SyncBailHook<Chunk[]>} */
|
||||
optimizeExtractedChunksAdvanced: new SyncBailHook(["chunks"]),
|
||||
/** @type {SyncHook<Chunk[]>} */
|
||||
afterOptimizeExtractedChunks: new SyncHook(["chunks"])
|
||||
};
|
||||
this._pluginCompat.tap("Compilation", options => {
|
||||
|
@ -208,7 +385,9 @@ class Compilation extends Tapable {
|
|||
break;
|
||||
}
|
||||
});
|
||||
/** @type {string=} */
|
||||
this.name = undefined;
|
||||
/** @type {Compiler} */
|
||||
this.compiler = compiler;
|
||||
this.resolverFactory = compiler.resolverFactory;
|
||||
this.inputFileSystem = compiler.inputFileSystem;
|
||||
|
@ -216,6 +395,7 @@ class Compilation extends Tapable {
|
|||
|
||||
const options = (this.options = compiler.options);
|
||||
this.outputOptions = options && options.output;
|
||||
/** @type {boolean=} */
|
||||
this.bail = options && options.bail;
|
||||
this.profile = options && options.profile;
|
||||
this.performance = options && options.performance;
|
||||
|
@ -237,34 +417,56 @@ class Compilation extends Tapable {
|
|||
this.semaphore = new Semaphore(options.parallelism || 100);
|
||||
|
||||
this.entries = [];
|
||||
/** @private @type {{name: string, request: string, module: Module}[]} */
|
||||
this._preparedEntrypoints = [];
|
||||
this.entrypoints = new Map();
|
||||
/** @type {Chunk[]} */
|
||||
this.chunks = [];
|
||||
/** @type {ChunkGroup[]} */
|
||||
this.chunkGroups = [];
|
||||
/** @type {Map<string, ChunkGroup>} */
|
||||
this.namedChunkGroups = new Map();
|
||||
/** @type {Map<string, Chunk>} */
|
||||
this.namedChunks = new Map();
|
||||
/** @type {Module[]} */
|
||||
this.modules = [];
|
||||
/** @private @type {Map<string, Module>} */
|
||||
this._modules = new Map();
|
||||
this.cache = null;
|
||||
this.records = null;
|
||||
/** @type {number=} */
|
||||
this.nextFreeModuleIndex = undefined;
|
||||
/** @type {number=} */
|
||||
this.nextFreeModuleIndex2 = undefined;
|
||||
/** @type {string[]} */
|
||||
this.additionalChunkAssets = [];
|
||||
/** @type {CompilationAssets} */
|
||||
this.assets = {};
|
||||
/** @type {WebpackError[]} */
|
||||
this.errors = [];
|
||||
/** @type {WebpackError[]} */
|
||||
this.warnings = [];
|
||||
/** @type {Compilation[]} */
|
||||
this.children = [];
|
||||
/** @type {Map<DepConstructor, ModuleFactory>} */
|
||||
this.dependencyFactories = new Map();
|
||||
/** @type {Map<DepConstructor|string, DependencyTemplate|string>} */
|
||||
this.dependencyTemplates = new Map();
|
||||
this.dependencyTemplates.set("hash", "");
|
||||
this.childrenCounters = {};
|
||||
/** @type {Set<number>} */
|
||||
this.usedChunkIds = null;
|
||||
/** @type {Set<number>} */
|
||||
this.usedModuleIds = null;
|
||||
/** @type {Map<string, number>=} */
|
||||
this.fileTimestamps = undefined;
|
||||
/** @type {Map<string, number>=} */
|
||||
this.contextTimestamps = undefined;
|
||||
/** @type {Set} */
|
||||
this.compilationDependencies = undefined;
|
||||
|
||||
/** @private @type {Map<Module, any>} */
|
||||
this._buildingModules = new Map();
|
||||
/** @private @type {Map<Module, any>} */
|
||||
this._rebuildingModules = new Map();
|
||||
}
|
||||
|
||||
|
@ -272,6 +474,12 @@ class Compilation extends Tapable {
|
|||
return new Stats(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Module} module module to be added that was created
|
||||
* @param {any=} cacheGroup cacheGroup it is apart of
|
||||
* @returns {{module: Module, issuer: boolean, build: boolean, dependencies: boolean}} returns meta about whether or not the module had built
|
||||
* had an issuer, or any dependnecies
|
||||
*/
|
||||
addModule(module, cacheGroup) {
|
||||
const identifier = module.identifier();
|
||||
const alreadyAddedModule = this._modules.get(identifier);
|
||||
|
@ -327,15 +535,30 @@ class Compilation extends Tapable {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a module from a compilation by its identifier
|
||||
* @param {Module} module the module provided
|
||||
* @returns {Module} the module requested
|
||||
*/
|
||||
getModule(module) {
|
||||
const identifier = module.identifier();
|
||||
return this._modules.get(identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to search for a module by its identifier
|
||||
* @param {string} identifier identifier (usually path) for module
|
||||
* @returns {Module|undefined} attempt to search for module and return it, else undefined
|
||||
*/
|
||||
findModule(identifier) {
|
||||
return this._modules.get(identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Module} module module with its callback list
|
||||
* @param {any} callback the callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
waitForBuildingFinished(module, callback) {
|
||||
let callbackList = this._buildingModules.get(module);
|
||||
if (callbackList) {
|
||||
|
@ -345,6 +568,16 @@ class Compilation extends Tapable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the module object
|
||||
*
|
||||
* @param {Module} module module to be built
|
||||
* @param {boolean} optional optional flag
|
||||
* @param {Module=} origin origin module this module build was requested from
|
||||
* @param {Dependency[]=} dependencies optional dependencies from the module to be built
|
||||
* @param {any} thisCallback the callback
|
||||
* @returns {any} returns the callback function with results
|
||||
*/
|
||||
buildModule(module, optional, origin, dependencies, thisCallback) {
|
||||
let callbackList = this._buildingModules.get(module);
|
||||
if (callbackList) {
|
||||
|
@ -396,6 +629,11 @@ class Compilation extends Tapable {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Module} module to be processed for deps
|
||||
* @param {*} callback callback to be triggered
|
||||
* @returns {void}
|
||||
*/
|
||||
processModuleDependencies(module, callback) {
|
||||
const dependencies = new Map();
|
||||
|
||||
|
@ -457,6 +695,15 @@ class Compilation extends Tapable {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Module} module module to add deps to
|
||||
* @param {SortedDependency[]} dependencies set of sorted dependencies to iterate through
|
||||
* @param {(boolean|null)=} bail whether to bail or not
|
||||
* @param {any} cacheGroup optional cacheGroup
|
||||
* @param {boolean} recursive whether it is recursive traversal
|
||||
* @param {function} callback callback for when dependencies are finished being added
|
||||
* @returns {void}
|
||||
*/
|
||||
addModuleDependencies(
|
||||
module,
|
||||
dependencies,
|
||||
|
@ -623,6 +870,14 @@ class Compilation extends Tapable {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} context context string path
|
||||
* @param {Dependency} dependency dependency used to create Module chain
|
||||
* @param {OnModuleCallback} onModule function invoked on modules creation
|
||||
* @param {ModuleChainCallback} callback callback for when module chain is complete
|
||||
* @returns {void|never} will throw if dependency instance is not a valid Dependency
|
||||
*/
|
||||
_addModuleChain(context, dependency, onModule, callback) {
|
||||
const start = this.profile && Date.now();
|
||||
const currentProfile = this.profile && {};
|
||||
|
@ -644,7 +899,10 @@ class Compilation extends Tapable {
|
|||
) {
|
||||
throw new Error("Parameter 'dependency' must be a Dependency");
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
// TODO: Not sure how to handle the
|
||||
// dependency.constructor error,
|
||||
// maybe I typed it wrong
|
||||
const moduleFactory = this.dependencyFactories.get(dependency.constructor);
|
||||
if (!moduleFactory) {
|
||||
throw new Error(
|
||||
|
@ -655,6 +913,7 @@ class Compilation extends Tapable {
|
|||
}
|
||||
|
||||
this.semaphore.acquire(() => {
|
||||
/** @type {ModuleFactory} */
|
||||
moduleFactory.create(
|
||||
{
|
||||
contextInfo: {
|
||||
|
@ -731,12 +990,25 @@ class Compilation extends Tapable {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} context context path for entry
|
||||
* @param {PossibleEntryDependencies} entry entry dependency being created
|
||||
* @param {string} name name of entry
|
||||
* @param {ModuleCallback} callback callback function
|
||||
* @returns {void} returns
|
||||
*/
|
||||
addEntry(context, entry, name, callback) {
|
||||
const slot = {
|
||||
name: name,
|
||||
request: entry.request,
|
||||
request: null,
|
||||
module: null
|
||||
};
|
||||
|
||||
if (entry instanceof SingleEntryDependency) {
|
||||
slot.request = entry.request;
|
||||
}
|
||||
|
||||
this._preparedEntrypoints.push(slot);
|
||||
this._addModuleChain(
|
||||
context,
|
||||
|
@ -760,6 +1032,12 @@ class Compilation extends Tapable {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} context context path string
|
||||
* @param {PossibleEntryDependencies} dependency dep used to create module
|
||||
* @param {ModuleCallback} callback module callback sending module up a level
|
||||
* @returns {void}
|
||||
*/
|
||||
prefetch(context, dependency, callback) {
|
||||
this._addModuleChain(
|
||||
context,
|
||||
|
@ -831,6 +1109,10 @@ class Compilation extends Tapable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {CompilationSealCallback} callback signals when the seal method is finishes
|
||||
* @returns {void}
|
||||
*/
|
||||
seal(callback) {
|
||||
this.hooks.seal.call();
|
||||
|
||||
|
@ -970,10 +1252,19 @@ class Compilation extends Tapable {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Module[]} modules the modules array on compilation to perform the sort for
|
||||
* @returns {void}
|
||||
*/
|
||||
sortModules(modules) {
|
||||
modules.sort(byIndexOrIdentifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Module} module moulde to report from
|
||||
* @param {DependenciesBlock[]} blocks blocks to report from
|
||||
* @returns {void}
|
||||
*/
|
||||
reportDependencyErrorsAndWarnings(module, blocks) {
|
||||
for (let indexBlock = 0; indexBlock < blocks.length; indexBlock++) {
|
||||
const block = blocks[indexBlock];
|
||||
|
@ -1006,6 +1297,13 @@ class Compilation extends Tapable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} groupOptions options provided for group
|
||||
* @param {Module} module module in question
|
||||
* @param {SourceLocation} loc source location reference
|
||||
* @param {string} request request string
|
||||
* @returns {ChunkGroup} the chunk group added inside
|
||||
*/
|
||||
addChunkInGroup(groupOptions, module, loc, request) {
|
||||
if (typeof groupOptions === "string") {
|
||||
groupOptions = { name: groupOptions };
|
||||
|
@ -1034,6 +1332,13 @@ class Compilation extends Tapable {
|
|||
return chunkGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method first looks to see if a name is provided for a new chunk,
|
||||
* and first looks to see if any named chunks already exist and reuse that chunk instead.
|
||||
*
|
||||
* @param {string=} name optional chunk name to be provided
|
||||
* @returns {Chunk} create a chunk (invoked during seal event)
|
||||
*/
|
||||
addChunk(name) {
|
||||
if (name) {
|
||||
const chunk = this.namedChunks.get(name);
|
||||
|
@ -1049,7 +1354,15 @@ class Compilation extends Tapable {
|
|||
return chunk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Module} module index will be assigned to this module
|
||||
* @returns {void}
|
||||
*/
|
||||
assignIndex(module) {
|
||||
/**
|
||||
* @param {Module} module assign index to the module
|
||||
* @returns {void}
|
||||
*/
|
||||
const assignIndexToModule = module => {
|
||||
// enter module
|
||||
if (typeof module.index !== "number") {
|
||||
|
@ -1069,11 +1382,23 @@ class Compilation extends Tapable {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {DependenciesBlock} block to assign index to
|
||||
* @returns {void}
|
||||
*/
|
||||
const assignIndexToDependencyBlock = block => {
|
||||
let allDependencies = [];
|
||||
|
||||
/**
|
||||
* @param {Dependency} d iterator over dependencies
|
||||
* @returns {number} returned push function value (side-effect)
|
||||
*/
|
||||
const iteratorDependency = d => allDependencies.push(d);
|
||||
|
||||
/**
|
||||
* @param {DependenciesBlock} b blocks to iterate
|
||||
* @returns {number} returned push value from queue (side-effect)
|
||||
*/
|
||||
const iteratorBlock = b =>
|
||||
queue.push(() => assignIndexToDependencyBlock(b));
|
||||
|
||||
|
@ -1104,6 +1429,10 @@ class Compilation extends Tapable {
|
|||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* @param {(Dependency|DependenciesBlockVariable)[]} d all dependencies of a block being added to queue
|
||||
* @returns {void}
|
||||
*/
|
||||
const iteratorAllDependencies = d => {
|
||||
queue.push(() => assignIndexToDependency(d));
|
||||
};
|
||||
|
@ -1113,12 +1442,20 @@ class Compilation extends Tapable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Module} module module to assign depth
|
||||
* @returns {void}
|
||||
*/
|
||||
assignDepth(module) {
|
||||
const queue = new Set([module]);
|
||||
let depth;
|
||||
|
||||
module.depth = 0;
|
||||
|
||||
/**
|
||||
* @param {Module} module module for processeing
|
||||
* @returns {void}
|
||||
*/
|
||||
const enqueueJob = module => {
|
||||
const d = module.depth;
|
||||
if (typeof d === "number" && d <= depth) return;
|
||||
|
@ -1126,12 +1463,20 @@ class Compilation extends Tapable {
|
|||
module.depth = depth;
|
||||
};
|
||||
|
||||
const assignDepthToDependency = (dependency, depth) => {
|
||||
/**
|
||||
* @param {Dependency} dependency dependency to assign depth to
|
||||
* @returns {void}
|
||||
*/
|
||||
const assignDepthToDependency = dependency => {
|
||||
if (dependency.module) {
|
||||
enqueueJob(dependency.module);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {DependenciesBlock} block block to assign depth to
|
||||
* @returns {void}
|
||||
*/
|
||||
const assignDepthToDependencyBlock = block => {
|
||||
if (block.variables) {
|
||||
iterationBlockVariable(block.variables, assignDepthToDependency);
|
||||
|
@ -1156,6 +1501,10 @@ class Compilation extends Tapable {
|
|||
}
|
||||
|
||||
// This method creates the Chunk graph from the Module graph
|
||||
/**
|
||||
* @param {TODO} inputChunkGroups input chunkGroups to be processed
|
||||
* @returns {void}
|
||||
*/
|
||||
processDependenciesBlocksForChunkGroups(inputChunkGroups) {
|
||||
// Process is splitting into two parts:
|
||||
// Part one traverse the module graph and builds a very basic chunks graph
|
||||
|
@ -1169,8 +1518,13 @@ class Compilation extends Tapable {
|
|||
const allCreatedChunkGroups = new Set();
|
||||
|
||||
// PREPARE
|
||||
/** @type {Map<DependenciesBlock, {modules: Set<Module>, blocks: AsyncDependenciesBlock[]}>} */
|
||||
const blockInfoMap = new Map();
|
||||
|
||||
/**
|
||||
* @param {Dependency} d dependency to iterate over
|
||||
* @returns {void}
|
||||
*/
|
||||
const iteratorDependency = d => {
|
||||
// We skip Dependencies without Reference
|
||||
const ref = d.getReference();
|
||||
|
@ -1190,12 +1544,23 @@ class Compilation extends Tapable {
|
|||
blockInfoModules.add(refModule);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {AsyncDependenciesBlock} b blocks to prepare
|
||||
* @returns {void}
|
||||
*/
|
||||
const iteratorBlockPrepare = b => {
|
||||
blockInfoBlocks.push(b);
|
||||
blockQueue.push(b);
|
||||
};
|
||||
|
||||
let block, blockQueue, blockInfoModules, blockInfoBlocks;
|
||||
/** @type {DependenciesBlock} */
|
||||
let block;
|
||||
/** @type {DependenciesBlock[]} */
|
||||
let blockQueue;
|
||||
/** @type {Set<Module>} */
|
||||
let blockInfoModules;
|
||||
/** @type {AsyncDependenciesBlock[]} */
|
||||
let blockInfoBlocks;
|
||||
for (const module of this.modules) {
|
||||
blockQueue = [module];
|
||||
while (blockQueue.length > 0) {
|
||||
|
@ -1224,10 +1589,12 @@ class Compilation extends Tapable {
|
|||
}
|
||||
|
||||
// PART ONE
|
||||
|
||||
/** @type {Map<DependenciesBlock, ChunkGroup>} */
|
||||
const blockChunkGroups = new Map();
|
||||
|
||||
// Start with the provided modules/chunks
|
||||
/** @type {{block: DependenciesBlock, module: Module, chunk: Chunk, chunkGroup: ChunkGroup}[]} */
|
||||
|
||||
const queue = inputChunkGroups.map(chunkGroup => ({
|
||||
block: chunkGroup.chunks[0].entryModule,
|
||||
module: chunkGroup.chunks[0].entryModule,
|
||||
|
@ -1235,9 +1602,18 @@ class Compilation extends Tapable {
|
|||
chunkGroup
|
||||
}));
|
||||
|
||||
let module, chunk, chunkGroup;
|
||||
/** @type {Module} */
|
||||
let module;
|
||||
/** @type {Chunk} */
|
||||
let chunk;
|
||||
/** @type {ChunkGroup} */
|
||||
let chunkGroup;
|
||||
|
||||
// For each async Block in graph
|
||||
/**
|
||||
* @param {AsyncDependenciesBlock} b iterating over each Async DepBlock
|
||||
* @returns {void}
|
||||
*/
|
||||
const iteratorBlock = b => {
|
||||
// 1. We create a chunk for this Block
|
||||
// but only once (blockChunkGroups map)
|
||||
|
@ -1315,9 +1691,10 @@ class Compilation extends Tapable {
|
|||
}
|
||||
|
||||
// PART TWO
|
||||
|
||||
/** @type {Set<Module>} */
|
||||
let availableModules;
|
||||
let newAvailableModules;
|
||||
/** @type {Queue<AvailableModulesChunkGroupMapping>} */
|
||||
const queue2 = new Queue(
|
||||
inputChunkGroups.map(chunkGroup => ({
|
||||
chunkGroup,
|
||||
|
@ -1325,7 +1702,13 @@ class Compilation extends Tapable {
|
|||
}))
|
||||
);
|
||||
|
||||
// Helper function to check if all modules of a chunk are available
|
||||
/**
|
||||
* Helper function to check if all modules of a chunk are available
|
||||
*
|
||||
* @param {ChunkGroup} chunkGroup the chunkGroup to scan
|
||||
* @param {Set<Module>} availableModules the comparitor set
|
||||
* @returns {boolean} return true if all modules of a chunk are available
|
||||
*/
|
||||
const areModulesAvailable = (chunkGroup, availableModules) => {
|
||||
for (const chunk of chunkGroup.chunks) {
|
||||
for (const module of chunk.modulesIterable) {
|
||||
|
@ -1336,14 +1719,18 @@ class Compilation extends Tapable {
|
|||
};
|
||||
|
||||
// For each edge in the basic chunk graph
|
||||
/**
|
||||
* @param {TODO} dep the dependency used for filtering
|
||||
* @returns {boolean} used to filter "edges" (aka Dependencies) that were pointing
|
||||
* to modules that are already available. Also filters circular dependencies in the chunks graph
|
||||
*/
|
||||
const filterFn = dep => {
|
||||
// Filter egdes that are not needed because all modules are already available
|
||||
// This also filters circular dependencies in the chunks graph
|
||||
const depChunkGroup = dep.chunkGroup;
|
||||
if (areModulesAvailable(depChunkGroup, newAvailableModules)) return false; // break all modules are already available
|
||||
return true;
|
||||
};
|
||||
|
||||
/** @type {Map<ChunkGroup, Set<Module>>} */
|
||||
const minAvailableModulesMap = new Map();
|
||||
|
||||
// Iterative traversing of the basic chunk graph
|
||||
|
@ -1425,6 +1812,12 @@ class Compilation extends Tapable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Module} module module relationship for removal
|
||||
* @param {DependenciesBlock} block //TODO: good description
|
||||
* @returns {void}
|
||||
*/
|
||||
removeReasonsOfDependencyBlock(module, block) {
|
||||
const iteratorDependency = d => {
|
||||
if (!d.module) {
|
||||
|
@ -1452,6 +1845,11 @@ class Compilation extends Tapable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Module} module module to patch tie
|
||||
* @param {Chunk} chunk chunk to patch tie
|
||||
* @returns {void}
|
||||
*/
|
||||
patchChunksAfterReasonRemoval(module, chunk) {
|
||||
if (!module.hasReasons()) {
|
||||
this.removeReasonsOfDependencyBlock(module, module);
|
||||
|
@ -1463,6 +1861,12 @@ class Compilation extends Tapable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {DependenciesBlock} block block tie for Chunk
|
||||
* @param {Chunk} chunk chunk to remove from dep
|
||||
* @returns {void}
|
||||
*/
|
||||
removeChunkFromDependencies(block, chunk) {
|
||||
const iteratorDependency = d => {
|
||||
if (!d.module) {
|
||||
|
@ -1473,12 +1877,15 @@ class Compilation extends Tapable {
|
|||
|
||||
const blocks = block.blocks;
|
||||
for (let indexBlock = 0; indexBlock < blocks.length; indexBlock++) {
|
||||
const chunks = blocks[indexBlock].chunks;
|
||||
// Grab all chunks from the first Block's AsyncDepBlock
|
||||
const chunks = blocks[indexBlock].chunkGroup.chunks;
|
||||
// For each chunk in chunkGroup
|
||||
for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
|
||||
const blockChunk = chunks[indexChunk];
|
||||
chunk.removeChunk(blockChunk);
|
||||
blockChunk.removeParent(chunk);
|
||||
this.removeChunkFromDependencies(chunks, blockChunk);
|
||||
const iteratedChunk = chunks[indexChunk];
|
||||
block.chunkGroup.removeChunk(iteratedChunk);
|
||||
block.chunkGroup.removeParent(iteratedChunk);
|
||||
// Recurse
|
||||
this.removeChunkFromDependencies(block, iteratedChunk);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1539,6 +1946,7 @@ class Compilation extends Tapable {
|
|||
}
|
||||
|
||||
applyChunkIds() {
|
||||
/** @type {Set<number|string>} */
|
||||
const usedIds = new Set();
|
||||
|
||||
// Get used ids from usedChunkIds property (i. e. from records)
|
||||
|
@ -1568,11 +1976,15 @@ class Compilation extends Tapable {
|
|||
// Calculate maximum assigned chunk id
|
||||
let nextFreeChunkId = -1;
|
||||
for (const id of usedIds) {
|
||||
if (typeof id !== "number") {
|
||||
continue;
|
||||
}
|
||||
nextFreeChunkId = Math.max(nextFreeChunkId, id);
|
||||
}
|
||||
nextFreeChunkId++;
|
||||
|
||||
// Determine free chunk ids from 0 to maximum
|
||||
/** @type {number[]} */
|
||||
const unusedIds = [];
|
||||
if (nextFreeChunkId > 0) {
|
||||
let index = nextFreeChunkId;
|
||||
|
@ -1630,6 +2042,16 @@ class Compilation extends Tapable {
|
|||
chunks[indexChunk].sortItems(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to sort errors and warnings in compilation. this.warnings, and
|
||||
* this.errors contribute to the compilation hash and therefore shoudl be
|
||||
* updated whenever other references (having a chunk id) are sorted. This preserves the hash
|
||||
* integrity
|
||||
*
|
||||
* @param {WebpackError} a first WebpackError instance (including subclasses)
|
||||
* @param {WebpackError} b second WebpackError instance (including subclasses)
|
||||
* @returns {-1|0|1} sort order index
|
||||
*/
|
||||
const byMessage = (a, b) => {
|
||||
const ma = `${a.message}`;
|
||||
const mb = `${b.message}`;
|
||||
|
@ -1746,6 +2168,10 @@ class Compilation extends Tapable {
|
|||
this.hash = this.fullHash.substr(0, hashDigestLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TODO} update //TODO (update hash function?)
|
||||
* @returns {void}
|
||||
*/
|
||||
modifyHash(update) {
|
||||
const outputOptions = this.outputOptions;
|
||||
const hashFunction = outputOptions.hashFunction;
|
||||
|
@ -1839,12 +2265,27 @@ class Compilation extends Tapable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} filename used to get asset path with hash
|
||||
* @param {TODO=} data // TODO: figure out this param type
|
||||
* @returns {TODO} figure out this return type
|
||||
*/
|
||||
getPath(filename, data) {
|
||||
data = data || {};
|
||||
data.hash = data.hash || this.hash;
|
||||
return this.mainTemplate.getAssetPath(filename, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function allows you to run another instance of webpack inside of webpack however as
|
||||
* a child with different settings and configurations (if desired) applied. It copies all hooks, plugins
|
||||
* from parent (or top level compiler) and creates a child Compilation
|
||||
*
|
||||
* @param {string} name name of the child compiler
|
||||
* @param {TODO} outputOptions // Need to convert config schema to types for this
|
||||
* @param {Plugin[]} plugins webpack plugins that will be applied
|
||||
* @returns {Compiler} creates a child Compiler instance
|
||||
*/
|
||||
createChildCompiler(name, outputOptions, plugins) {
|
||||
const idx = this.childrenCounters[name] || 0;
|
||||
this.childrenCounters[name] = idx + 1;
|
||||
|
@ -1858,6 +2299,7 @@ class Compilation extends Tapable {
|
|||
}
|
||||
|
||||
checkConstraints() {
|
||||
/** @type {Set<number|string>} */
|
||||
const usedIds = new Set();
|
||||
|
||||
const modules = this.modules;
|
||||
|
|
|
@ -26,38 +26,92 @@ const RequestShortener = require("./RequestShortener");
|
|||
const { makePathsRelative } = require("./util/identifier");
|
||||
const ConcurrentCompilationError = require("./ConcurrentCompilationError");
|
||||
|
||||
/**
|
||||
* @typedef {Object} CompilationParams
|
||||
* @property {NormalModuleFactory} normalModuleFactory
|
||||
* @property {ContextModuleFactory} contextModuleFactory
|
||||
* @property {Set<any>} compilationDependencies
|
||||
*/
|
||||
|
||||
/** @typedef {string|string[]} EntryValues */
|
||||
/** @typedef {{[entryKey: string]: EntryValues}} EntryOptionValues */
|
||||
/** @typedef {(() => EntryOptionValues) | EntryOptionValues | EntryValues} EntryOptions */
|
||||
|
||||
class Compiler extends Tapable {
|
||||
constructor(context) {
|
||||
super();
|
||||
this.hooks = {
|
||||
/** @type {SyncBailHook<Compilation>} */
|
||||
shouldEmit: new SyncBailHook(["compilation"]),
|
||||
|
||||
/** @type {AsyncSeriesHook<Stats>} */
|
||||
done: new AsyncSeriesHook(["stats"]),
|
||||
|
||||
/** @type {AsyncSeriesHook<>} */
|
||||
additionalPass: new AsyncSeriesHook([]),
|
||||
beforeRun: new AsyncSeriesHook(["compilation"]),
|
||||
run: new AsyncSeriesHook(["compilation"]),
|
||||
|
||||
/** @type {AsyncSeriesHook<Compiler>} */
|
||||
beforeRun: new AsyncSeriesHook(["compiler"]),
|
||||
|
||||
/** @type {AsyncSeriesHook<Compiler>} */
|
||||
run: new AsyncSeriesHook(["compiler"]),
|
||||
|
||||
/** @type {AsyncSeriesHook<Compilation>} */
|
||||
emit: new AsyncSeriesHook(["compilation"]),
|
||||
|
||||
/** @type {AsyncSeriesHook<Compilation>} */
|
||||
afterEmit: new AsyncSeriesHook(["compilation"]),
|
||||
|
||||
/** @type {SyncHook<Compilation, CompilationParams>} */
|
||||
thisCompilation: new SyncHook(["compilation", "params"]),
|
||||
|
||||
/** @type {SyncHook<Compilation, CompilationParams>} */
|
||||
compilation: new SyncHook(["compilation", "params"]),
|
||||
|
||||
/** @type {SyncHook<NormalModuleFactory>} */
|
||||
normalModuleFactory: new SyncHook(["normalModuleFactory"]),
|
||||
|
||||
/** @type {SyncHook<ContextModuleFactory>} */
|
||||
contextModuleFactory: new SyncHook(["contextModulefactory"]),
|
||||
|
||||
/** @type {AsyncSeriesHook<CompilationParams>} */
|
||||
beforeCompile: new AsyncSeriesHook(["params"]),
|
||||
|
||||
/** @type {SyncHook<CompilationParams>} */
|
||||
compile: new SyncHook(["params"]),
|
||||
|
||||
/** @type {AsyncParallelHook<Compilation>} */
|
||||
make: new AsyncParallelHook(["compilation"]),
|
||||
|
||||
/** @type {AsyncSeriesHook<Compilation>} */
|
||||
afterCompile: new AsyncSeriesHook(["compilation"]),
|
||||
|
||||
/** @type {AsyncSeriesHook<Compiler>} */
|
||||
watchRun: new AsyncSeriesHook(["compiler"]),
|
||||
|
||||
/** @type {SyncHook<Error>} */
|
||||
failed: new SyncHook(["error"]),
|
||||
|
||||
/** @type {SyncHook<string, string>} */
|
||||
invalid: new SyncHook(["filename", "changeTime"]),
|
||||
|
||||
/** @type {SyncHook} */
|
||||
watchClose: new SyncHook([]),
|
||||
|
||||
// TODO the following hooks are weirdly located here
|
||||
// TODO move them for webpack 5
|
||||
/** @type {SyncHook} */
|
||||
environment: new SyncHook([]),
|
||||
/** @type {SyncHook} */
|
||||
afterEnvironment: new SyncHook([]),
|
||||
/** @type {SyncHook<Compiler>} */
|
||||
afterPlugins: new SyncHook(["compiler"]),
|
||||
/** @type {SyncHook<Compiler>} */
|
||||
afterResolvers: new SyncHook(["compiler"]),
|
||||
/** @type {SyncBailHook<string, EntryOptions>} */
|
||||
entryOption: new SyncBailHook(["context", "entry"])
|
||||
};
|
||||
|
||||
this._pluginCompat.tap("Compiler", options => {
|
||||
switch (options.name) {
|
||||
case "additional-pass":
|
||||
|
@ -74,19 +128,26 @@ class Compiler extends Tapable {
|
|||
}
|
||||
});
|
||||
|
||||
/** @type {string=} */
|
||||
this.name = undefined;
|
||||
/** @type {Compilation=} */
|
||||
this.parentCompilation = undefined;
|
||||
/** @type {string} */
|
||||
this.outputPath = "";
|
||||
|
||||
this.outputFileSystem = null;
|
||||
this.inputFileSystem = null;
|
||||
|
||||
/** @type {string|null} */
|
||||
this.recordsInputPath = null;
|
||||
/** @type {string|null} */
|
||||
this.recordsOutputPath = null;
|
||||
this.records = {};
|
||||
|
||||
/** @type {Map<string, number>} */
|
||||
this.fileTimestamps = new Map();
|
||||
/** @type {Map<string, number>} */
|
||||
this.contextTimestamps = new Map();
|
||||
|
||||
/** @type {ResolverFactory} */
|
||||
this.resolverFactory = new ResolverFactory();
|
||||
|
||||
// TODO remove in webpack 5
|
||||
|
@ -135,6 +196,7 @@ class Compiler extends Tapable {
|
|||
|
||||
this.requestShortener = new RequestShortener(context);
|
||||
|
||||
/** @type {boolean} */
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ const util = require("util");
|
|||
const { OriginalSource, RawSource } = require("webpack-sources");
|
||||
const Module = require("./Module");
|
||||
const AsyncDependenciesBlock = require("./AsyncDependenciesBlock");
|
||||
const ModuleDependency = require("./dependencies/ModuleDependency");
|
||||
const Template = require("./Template");
|
||||
|
||||
class ContextModule extends Module {
|
||||
|
@ -645,10 +646,10 @@ webpackEmptyAsyncContext.id = ${JSON.stringify(id)};`;
|
|||
const initialSize = 160;
|
||||
|
||||
// if we dont have dependencies we stop here.
|
||||
return this.dependencies.reduce(
|
||||
(size, dependency) => size + 5 + dependency.userRequest.length,
|
||||
initialSize
|
||||
);
|
||||
return this.dependencies.reduce((size, dependency) => {
|
||||
if (dependency instanceof ModuleDependency)
|
||||
return size + 5 + dependency.userRequest.length;
|
||||
}, initialSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ const WebpackMissingModule = require("./dependencies/WebpackMissingModule");
|
|||
const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency");
|
||||
const DelegatedExportsDependency = require("./dependencies/DelegatedExportsDependency");
|
||||
|
||||
/** @typedef {import("./dependencies/ModuleDependency")} ModuleDependency */
|
||||
|
||||
class DelegatedModule extends Module {
|
||||
constructor(sourceRequest, data, type, userRequest, originalRequest) {
|
||||
super("javascript/dynamic", null);
|
||||
|
@ -48,6 +50,8 @@ class DelegatedModule extends Module {
|
|||
this.built = true;
|
||||
this.buildMeta = Object.assign({}, this.delegateData.buildMeta);
|
||||
this.buildInfo = {};
|
||||
/** @type {ModuleDependency[]=} */
|
||||
this.dependencies = [];
|
||||
this.addDependency(new DelegatedSourceDependency(this.sourceRequest));
|
||||
this.addDependency(
|
||||
new DelegatedExportsDependency(this, this.delegateData.exports || true)
|
||||
|
|
|
@ -6,23 +6,46 @@
|
|||
|
||||
const DependenciesBlockVariable = require("./DependenciesBlockVariable");
|
||||
|
||||
/** @typedef {import("./ChunkGroup")} ChunkGroup */
|
||||
/**
|
||||
* @typedef {import("./ChunkGroup")} ChunkGroup
|
||||
* @typedef {import("./Dependency")} Dependency
|
||||
* @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock
|
||||
* @typedef {import("./DependenciesBlockVariable")} DependenciesBlockVariable
|
||||
* @typedef {(d: Dependency) => boolean} DependencyFilterFunction
|
||||
* @typedef {import("crypto").Hash} Hash
|
||||
*/
|
||||
|
||||
class DependenciesBlock {
|
||||
constructor() {
|
||||
/** @type {Dependency[]} */
|
||||
this.dependencies = [];
|
||||
/** @type {AsyncDependenciesBlock[]} */
|
||||
this.blocks = [];
|
||||
/** @type {DependenciesBlockVariable[]} */
|
||||
this.variables = [];
|
||||
// TODO remove this line, it's wrong
|
||||
/** @type {ChunkGroup=} */
|
||||
this.chunkGroup = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a DependencyBlock to DependencyBlock relationship.
|
||||
* This is used for when a Module has a AsyncDependencyBlock tie (for code-splitting)
|
||||
*
|
||||
* @param {AsyncDependenciesBlock} block block being added
|
||||
* @returns {void}
|
||||
*/
|
||||
addBlock(block) {
|
||||
this.blocks.push(block);
|
||||
block.parent = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name name of dependency
|
||||
* @param {string} expression expression string for variable
|
||||
* @param {Dependency[]} dependencies dependency instances tied to variable
|
||||
* @returns {void}
|
||||
*/
|
||||
addVariable(name, expression, dependencies) {
|
||||
for (let v of this.variables) {
|
||||
if (v.name === name && v.expression === expression) {
|
||||
|
@ -34,15 +57,28 @@ class DependenciesBlock {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Dependency} dependency dependency being tied to block.
|
||||
* This is an "edge" pointing to another "node" on module graph.
|
||||
* @returns {void}
|
||||
*/
|
||||
addDependency(dependency) {
|
||||
this.dependencies.push(dependency);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Dependency} dependency dependency being removed
|
||||
* @returns {void}
|
||||
*/
|
||||
removeDependency(dependency) {
|
||||
const idx = this.dependencies.indexOf(dependency);
|
||||
if (idx >= 0) this.dependencies.splice(idx, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Hash} hash the hash used to track dependencies, from "crypto" module
|
||||
* @returns {void}
|
||||
*/
|
||||
updateHash(hash) {
|
||||
for (const dep of this.dependencies) dep.updateHash(hash);
|
||||
for (const block of this.blocks) block.updateHash(hash);
|
||||
|
@ -59,6 +95,10 @@ class DependenciesBlock {
|
|||
for (const block of this.blocks) block.unseal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DependencyFilterFunction} filter filter function for dependencies, gets passed all dependency ties from current instance
|
||||
* @returns {boolean} returns boolean for filter
|
||||
*/
|
||||
hasDependencies(filter) {
|
||||
if (filter) {
|
||||
for (const dep of this.dependencies) {
|
||||
|
|
|
@ -6,13 +6,29 @@
|
|||
|
||||
const { RawSource, ReplaceSource } = require("webpack-sources");
|
||||
|
||||
/** @typedef {import("./Dependency")} Dependency */
|
||||
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
|
||||
/** @typedef {import("crypto").Hash} Hash */
|
||||
/** @typedef {(d: Dependency) => boolean} DependencyFilterFunction */
|
||||
/** @typedef {Map<Dependency["constructor"], any>} DependencyFactoryConstruction */
|
||||
|
||||
class DependenciesBlockVariable {
|
||||
/**
|
||||
* Creates an instance of DependenciesBlockVariable.
|
||||
* @param {string} name name of DependenciesBlockVariable
|
||||
* @param {string} expression expression string
|
||||
* @param {Dependency[]=} dependencies dependencies tied to this varaiable
|
||||
*/
|
||||
constructor(name, expression, dependencies) {
|
||||
this.name = name;
|
||||
this.expression = expression;
|
||||
this.dependencies = dependencies || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Hash} hash hash for instance to update
|
||||
* @returns {void}
|
||||
*/
|
||||
updateHash(hash) {
|
||||
hash.update(this.name);
|
||||
hash.update(this.expression);
|
||||
|
@ -21,8 +37,13 @@ class DependenciesBlockVariable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DependencyFactoryConstruction} dependencyTemplates Dependency constructors and templates Map.
|
||||
* @param {RuntimeTemplate} runtimeTemplate runtimeTemplate to generate expression souce
|
||||
* @returns {ReplaceSource} returns constructed source for expression via templates
|
||||
*/
|
||||
expressionSource(dependencyTemplates, runtimeTemplate) {
|
||||
const source = new ReplaceSource(new RawSource(this.expression));
|
||||
const source = new ReplaceSource(new RawSource(this.expression), null);
|
||||
for (const dep of this.dependencies) {
|
||||
const template = dependencyTemplates.get(dep.constructor);
|
||||
if (!template)
|
||||
|
|
|
@ -7,8 +7,11 @@
|
|||
const compareLocations = require("./compareLocations");
|
||||
const DependencyReference = require("./dependencies/DependencyReference");
|
||||
|
||||
/** @typedef {import("./Module")} Module */
|
||||
|
||||
class Dependency {
|
||||
constructor() {
|
||||
/** @type {Module|null} */
|
||||
this.module = null;
|
||||
this.weak = false;
|
||||
this.optional = false;
|
||||
|
|
|
@ -10,12 +10,25 @@ const MultiModuleFactory = require("./MultiModuleFactory");
|
|||
const MultiEntryPlugin = require("./MultiEntryPlugin");
|
||||
const SingleEntryPlugin = require("./SingleEntryPlugin");
|
||||
|
||||
/** @typedef {import("./Compiler")} Compiler */
|
||||
/** @typedef {string|string[]} EntryValues */
|
||||
/** @typedef {{[entryKey: string]: EntryValues | EntryValues}} EntryOptionValues */
|
||||
/** @typedef {(() => (EntryOptionValues|EntryValues))} EntryOptionValuesFunction */
|
||||
|
||||
class DynamicEntryPlugin {
|
||||
/**
|
||||
* @param {string} context the context path
|
||||
* @param {EntryOptionValuesFunction} entry the entry value
|
||||
*/
|
||||
constructor(context, entry) {
|
||||
this.context = context;
|
||||
this.entry = entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Compiler} compiler the compiler instance
|
||||
* @returns {void}
|
||||
*/
|
||||
apply(compiler) {
|
||||
compiler.hooks.compilation.tap(
|
||||
"DynamicEntryPlugin",
|
||||
|
@ -36,6 +49,11 @@ class DynamicEntryPlugin {
|
|||
compiler.hooks.make.tapAsync(
|
||||
"DynamicEntryPlugin",
|
||||
(compilation, callback) => {
|
||||
/**
|
||||
* @param {string|string[]} entry entry value or array of entry values
|
||||
* @param {string} name name of entry
|
||||
* @returns {Promise<any>} returns the promise resolving the Compilation#addEntry function
|
||||
*/
|
||||
const addEntry = (entry, name) => {
|
||||
const dep = DynamicEntryPlugin.createDependency(entry, name);
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -63,7 +81,11 @@ class DynamicEntryPlugin {
|
|||
}
|
||||
|
||||
module.exports = DynamicEntryPlugin;
|
||||
|
||||
/**
|
||||
* @param {string|string[]} entry entry value or array of entry paths
|
||||
* @param {string} name name of entry
|
||||
* @returns {SingleEntryDependency|MultiEntryDependency} returns dep
|
||||
*/
|
||||
DynamicEntryPlugin.createDependency = (entry, name) => {
|
||||
if (Array.isArray(entry))
|
||||
return MultiEntryPlugin.createDependency(entry, name);
|
||||
|
|
|
@ -8,6 +8,14 @@ const SingleEntryPlugin = require("./SingleEntryPlugin");
|
|||
const MultiEntryPlugin = require("./MultiEntryPlugin");
|
||||
const DynamicEntryPlugin = require("./DynamicEntryPlugin");
|
||||
|
||||
/** @typedef {import("./Compiler")} Compiler */
|
||||
|
||||
/**
|
||||
* @param {string} context context path
|
||||
* @param {string | string[]} item entry array or single path
|
||||
* @param {string} name entry key name
|
||||
* @returns {SingleEntryPlugin | MultiEntryPlugin} returns either a single or multi entry plugin
|
||||
*/
|
||||
const itemToPlugin = (context, item, name) => {
|
||||
if (Array.isArray(item)) {
|
||||
return new MultiEntryPlugin(context, item, name);
|
||||
|
@ -16,6 +24,10 @@ const itemToPlugin = (context, item, name) => {
|
|||
};
|
||||
|
||||
module.exports = class EntryOptionPlugin {
|
||||
/**
|
||||
* @param {Compiler} compiler the compiler instance one is tapping into
|
||||
* @returns {void}
|
||||
*/
|
||||
apply(compiler) {
|
||||
compiler.hooks.entryOption.tap("EntryOptionPlugin", (context, entry) => {
|
||||
if (typeof entry === "string" || Array.isArray(entry)) {
|
||||
|
|
|
@ -18,7 +18,7 @@ class JavascriptGenerator {
|
|||
return new RawSource("throw new Error('No source available');");
|
||||
}
|
||||
|
||||
const source = new ReplaceSource(originalSource);
|
||||
const source = new ReplaceSource(originalSource, null);
|
||||
|
||||
this.sourceBlock(
|
||||
module,
|
||||
|
|
|
@ -11,8 +11,14 @@ const ModuleReason = require("./ModuleReason");
|
|||
const SortableSet = require("./util/SortableSet");
|
||||
const Template = require("./Template");
|
||||
|
||||
<<<<<<< HEAD
|
||||
/** @typedef {import("./Chunk")} Chunk */
|
||||
/** @typedef {import("./RequestShortener")} RequestShortener */
|
||||
=======
|
||||
/** @typedef {typeof import("./Chunk")} Chunk */
|
||||
/** @typedef {typeof import("./RequestShortener")} RequestShortener */
|
||||
/** @typedef {import("./WebpackError")} WebpackError */
|
||||
>>>>>>> 206d1a6... chore(types): add Compiler and Compilation type support
|
||||
|
||||
const EMPTY_RESOLVE_OPTIONS = {};
|
||||
|
||||
|
@ -47,15 +53,15 @@ class Module extends DependenciesBlock {
|
|||
this.renderedHash = undefined;
|
||||
|
||||
// Info from Factory
|
||||
/** @type {object} */
|
||||
/** @type {any} */
|
||||
this.resolveOptions = EMPTY_RESOLVE_OPTIONS;
|
||||
/** @type {object} */
|
||||
this.factoryMeta = {};
|
||||
|
||||
// Info from Build
|
||||
/** @type {Error[]} */
|
||||
/** @type {WebpackError[]} */
|
||||
this.warnings = [];
|
||||
/** @type {Error[]} */
|
||||
/** @type {WebpackError[]} */
|
||||
this.errors = [];
|
||||
/** @type {object} */
|
||||
this.buildMeta = undefined;
|
||||
|
|
|
@ -8,13 +8,25 @@ const MultiEntryDependency = require("./dependencies/MultiEntryDependency");
|
|||
const SingleEntryDependency = require("./dependencies/SingleEntryDependency");
|
||||
const MultiModuleFactory = require("./MultiModuleFactory");
|
||||
|
||||
module.exports = class MultiEntryPlugin {
|
||||
/** @typedef {import("./Compiler")} Compiler */
|
||||
|
||||
class MultiEntryPlugin {
|
||||
/**
|
||||
* The MultiEntryPlugin is invoked whenever this.options.entry value is an array of paths
|
||||
* @param {string} context context path
|
||||
* @param {string[]} entries array of entry paths
|
||||
* @param {string} name entry key name
|
||||
*/
|
||||
constructor(context, entries, name) {
|
||||
this.context = context;
|
||||
this.entries = entries;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Compiler} compiler the compiler instance
|
||||
* @returns {void}
|
||||
*/
|
||||
apply(compiler) {
|
||||
compiler.hooks.compilation.tap(
|
||||
"MultiEntryPlugin",
|
||||
|
@ -43,6 +55,11 @@ module.exports = class MultiEntryPlugin {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} entries each entry path string
|
||||
* @param {string} name name of the entry
|
||||
* @return {MultiEntryDependency} returns a constructed Dependency
|
||||
*/
|
||||
static createDependency(entries, name) {
|
||||
return new MultiEntryDependency(
|
||||
entries.map((e, idx) => {
|
||||
|
@ -55,4 +72,6 @@ module.exports = class MultiEntryPlugin {
|
|||
name
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = MultiEntryPlugin;
|
||||
|
|
|
@ -218,6 +218,8 @@ class NormalModule extends Module {
|
|||
}
|
||||
|
||||
if (Buffer.isBuffer(source)) {
|
||||
// @ts-ignore
|
||||
// TODO We need to fix @types/webpack-sources to allow RawSource to take a Buffer | string
|
||||
return new RawSource(source);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,27 @@
|
|||
"use strict";
|
||||
const SingleEntryDependency = require("./dependencies/SingleEntryDependency");
|
||||
|
||||
/** @typedef {import("./Compiler")} Compiler */
|
||||
|
||||
class SingleEntryPlugin {
|
||||
/**
|
||||
* An entry plugin which will handle
|
||||
* creation of the SingleEntryDependency
|
||||
*
|
||||
* @param {string} context context path
|
||||
* @param {string} entry entry path
|
||||
* @param {string} name entry key name
|
||||
*/
|
||||
constructor(context, entry, name) {
|
||||
this.context = context;
|
||||
this.entry = entry;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Compiler} compiler the compiler instance
|
||||
* @returns {void}
|
||||
*/
|
||||
apply(compiler) {
|
||||
compiler.hooks.compilation.tap(
|
||||
"SingleEntryPlugin",
|
||||
|
|
|
@ -4,11 +4,16 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
module.exports = class WebpackError extends Error {
|
||||
class WebpackError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
|
||||
this.details = undefined;
|
||||
this.missing = undefined;
|
||||
this.origin = undefined;
|
||||
this.dependencies = undefined;
|
||||
this.module = undefined;
|
||||
this.message = undefined;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
@ -16,4 +21,6 @@ module.exports = class WebpackError extends Error {
|
|||
inspect() {
|
||||
return this.stack + (this.details ? `\n${this.details}` : "");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = WebpackError;
|
||||
|
|
|
@ -4,7 +4,16 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
/** @typedef {import('../Module')} Module */
|
||||
|
||||
class DependencyReference {
|
||||
/**
|
||||
* Creates an instance of DependencyReference.
|
||||
* @param {Module} module module there reference comes from
|
||||
* @param {string[]|boolean} importedNames imported names or boolean
|
||||
* @param {boolean} weak is weak reference or not
|
||||
* @memberof DependencyReference
|
||||
*/
|
||||
constructor(module, importedNames, weak) {
|
||||
this.module = module;
|
||||
// true: full object
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"use strict";
|
||||
|
||||
const LoaderDependency = require("./LoaderDependency");
|
||||
const NormalModule = require("../NormalModule");
|
||||
|
||||
class LoaderPlugin {
|
||||
apply(compiler) {
|
||||
|
@ -51,11 +52,10 @@ class LoaderPlugin {
|
|||
err => {
|
||||
compilation.semaphore.acquire(() => {
|
||||
if (err) return callback(err);
|
||||
|
||||
if (!dep.module)
|
||||
return callback(new Error("Cannot load the module"));
|
||||
|
||||
if (dep.module.error) return callback(dep.module.error);
|
||||
if (dep.module instanceof NormalModule && dep.module.error)
|
||||
return callback(dep.module.error);
|
||||
if (!dep.module._source)
|
||||
throw new Error(
|
||||
"The module created for a LoaderDependency must have a property _source"
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
const Dependency = require("../Dependency");
|
||||
|
||||
class ModuleDependency extends Dependency {
|
||||
/**
|
||||
* @param {string} request request path which needs resolving
|
||||
*/
|
||||
constructor(request) {
|
||||
super();
|
||||
this.request = request;
|
||||
|
|
|
@ -3,9 +3,14 @@
|
|||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
/** @typedef {import("./SingleEntryDependency")} SingleEntryDependency */
|
||||
const Dependency = require("../Dependency");
|
||||
|
||||
class MultiEntryDependency extends Dependency {
|
||||
/**
|
||||
* @param {SingleEntryDependency[]} dependencies an array of SingleEntryDependencies
|
||||
* @param {string} name entry name
|
||||
*/
|
||||
constructor(dependencies, name) {
|
||||
super();
|
||||
this.dependencies = dependencies;
|
||||
|
|
|
@ -6,8 +6,12 @@
|
|||
const ModuleDependency = require("./ModuleDependency");
|
||||
|
||||
class SingleEntryDependency extends ModuleDependency {
|
||||
/**
|
||||
* @param {string} request request path for entry
|
||||
*/
|
||||
constructor(request) {
|
||||
super(request);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
get type() {
|
||||
|
|
|
@ -621,7 +621,7 @@ class ConcatenatedModule extends Module {
|
|||
});
|
||||
const globalScope = scopeManager.acquire(ast);
|
||||
const moduleScope = globalScope.childScopes[0];
|
||||
const resultSource = new ReplaceSource(source);
|
||||
const resultSource = new ReplaceSource(source, null);
|
||||
info.ast = ast;
|
||||
info.internalSource = source;
|
||||
info.source = resultSource;
|
||||
|
|
|
@ -5,12 +5,24 @@
|
|||
"use strict";
|
||||
|
||||
class Semaphore {
|
||||
/**
|
||||
* Creates an instance of Semaphore.
|
||||
*
|
||||
* @param {number} available the amount available number of "tasks"
|
||||
* in the Semaphore
|
||||
*/
|
||||
constructor(available) {
|
||||
this.available = available;
|
||||
/** @type {(() => void)[]} */
|
||||
this.waiters = [];
|
||||
/** @private */
|
||||
this._continue = this._continue.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {function(): void} callback function block to capture and run
|
||||
* @returns {void}
|
||||
*/
|
||||
acquire(callback) {
|
||||
if (this.available > 0) {
|
||||
this.available--;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
"devDependencies": {
|
||||
"@types/node": "^9.6.4",
|
||||
"@types/tapable": "^1.0.1",
|
||||
"@types/webpack-sources": "^0.1.4",
|
||||
"benchmark": "^2.1.1",
|
||||
"bundle-loader": "~0.5.0",
|
||||
"codacy-coverage": "^2.0.1",
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
/* Basic Options */
|
||||
"target": "ES2017", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
"lib": ["es2017", "dom"], /* Specify library files to be included in the compilation. */
|
||||
"allowJs": true, /* Allow javascript files to be compiled. */
|
||||
"checkJs": true, /* Report errors in .js files. */
|
||||
"target":
|
||||
"ES2017" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
|
||||
"module":
|
||||
"commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
|
||||
"lib": [
|
||||
"es2017",
|
||||
"dom"
|
||||
] /* Specify library files to be included in the compilation. */,
|
||||
"allowJs": true /* Allow javascript files to be compiled. */,
|
||||
"checkJs": true /* Report errors in .js files. */,
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
|
@ -13,19 +18,19 @@
|
|||
// "outDir": "./", /* Redirect output structure to the directory. */
|
||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
"noEmit": true, /* Do not emit outputs. */
|
||||
"noEmit": true /* Do not emit outputs. */,
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": false, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
"strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
"strict": false /* Enable all strict type-checking options. */,
|
||||
// "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
|
||||
// "strictNullChecks": true /* Enable strict null checks. */,
|
||||
// "strictFunctionTypes": true /* Enable strict checking of function types. */,
|
||||
// "strictPropertyInitialization": true /* Enable strict checking of property initialization in classes. */,
|
||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
"alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
"alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,
|
||||
|
||||
/* Additional Checks */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
|
@ -39,7 +44,9 @@
|
|||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
"types": ["node"], /* Type declaration files to be included in compilation. */
|
||||
"types": [
|
||||
"node"
|
||||
] /* Type declaration files to be included in compilation. */,
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
|
@ -54,9 +61,5 @@
|
|||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
},
|
||||
"include": [
|
||||
"declarations.d.ts",
|
||||
"bin/*.js",
|
||||
"lib/**/*.js"
|
||||
]
|
||||
"include": ["declarations.d.ts", "bin/*.js", "lib/**/*.js"]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue