Merge branch 'next' into feat_afterDone_hook

This commit is contained in:
mc-zone 2019-01-13 11:24:32 +08:00
commit 4f3e0d27b5
50 changed files with 1276 additions and 924 deletions

View File

@ -62,6 +62,7 @@ const { arrayToSetDeprecation } = require("./util/deprecation");
/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */ /** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
/** @typedef {import("./DependencyTemplate")} DependencyTemplate */ /** @typedef {import("./DependencyTemplate")} DependencyTemplate */
/** @typedef {import("./Module")} Module */ /** @typedef {import("./Module")} Module */
/** @typedef {import("./ModuleFactory")} ModuleFactory */
/** @typedef {import("./RuntimeModule")} RuntimeModule */ /** @typedef {import("./RuntimeModule")} RuntimeModule */
/** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry */ /** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry */
/** @typedef {import("./WebpackError")} WebpackError */ /** @typedef {import("./WebpackError")} WebpackError */
@ -99,25 +100,6 @@ const { arrayToSetDeprecation } = require("./util/deprecation");
/** @typedef {new (...args: any[]) => Dependency} DepConstructor */ /** @typedef {new (...args: any[]) => Dependency} DepConstructor */
/** @typedef {Record<string, Source>} CompilationAssets */ /** @typedef {Record<string, Source>} CompilationAssets */
/**
* @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} AvailableModulesChunkGroupMapping * @typedef {Object} AvailableModulesChunkGroupMapping
* @property {ChunkGroup} chunkGroup * @property {ChunkGroup} chunkGroup
@ -552,8 +534,6 @@ class Compilation {
this.usedChunkIds = null; this.usedChunkIds = null;
/** @type {Set<number>} */ /** @type {Set<number>} */
this.usedModuleIds = null; this.usedModuleIds = null;
/** @type {Set<string>=} */
this.compilationDependencies = undefined;
/** @type {boolean} */ /** @type {boolean} */
this.needAdditionalPass = false; this.needAdditionalPass = false;
/** @type {WeakSet<Module>} */ /** @type {WeakSet<Module>} */
@ -562,6 +542,12 @@ class Compilation {
this._rebuildingModules = new Map(); this._rebuildingModules = new Map();
/** @type {WeakSet<Source>} */ /** @type {WeakSet<Source>} */
this.emittedAssets = new WeakSet(); this.emittedAssets = new WeakSet();
/** @type {SortableSet<string>} */
this.fileDependencies = new SortableSet();
/** @type {SortableSet<string>} */
this.contextDependencies = new SortableSet();
/** @type {SortableSet<string>} */
this.missingDependencies = new SortableSet();
} }
getStats() { getStats() {
@ -822,6 +808,12 @@ class Compilation {
} }
} }
if (sortedDependencies.length === 0) {
callback();
return;
}
process.nextTick(() => {
// This is nested so we need to allow one additional task // This is nested so we need to allow one additional task
this.processDependenciesQueue.increaseParallelism(); this.processDependenciesQueue.increaseParallelism();
@ -853,6 +845,7 @@ class Compilation {
return callback(err); return callback(err);
} }
); );
});
} }
/** /**
@ -999,7 +992,23 @@ class Compilation {
: this.compiler.context, : this.compiler.context,
dependencies: dependencies dependencies: dependencies
}, },
(err, newModule) => { (err, result) => {
if (result) {
const {
fileDependencies,
contextDependencies,
missingDependencies
} = result;
if (fileDependencies) {
addAllToSet(this.fileDependencies, fileDependencies);
}
if (contextDependencies) {
addAllToSet(this.contextDependencies, contextDependencies);
}
if (missingDependencies) {
addAllToSet(this.missingDependencies, missingDependencies);
}
}
if (err) { if (err) {
const notFoundError = new ModuleNotFoundError( const notFoundError = new ModuleNotFoundError(
originModule, originModule,
@ -1008,6 +1017,10 @@ class Compilation {
); );
return callback(notFoundError); return callback(notFoundError);
} }
if (!result) {
return callback();
}
const newModule = result.module;
if (!newModule) { if (!newModule) {
return callback(); return callback();
} }
@ -2190,10 +2203,6 @@ class Compilation {
} }
summarizeDependencies() { summarizeDependencies() {
this.fileDependencies = new SortableSet(this.compilationDependencies);
this.contextDependencies = new SortableSet();
this.missingDependencies = new SortableSet();
for ( for (
let indexChildren = 0; let indexChildren = 0;
indexChildren < this.children.length; indexChildren < this.children.length;
@ -2207,16 +2216,20 @@ class Compilation {
} }
for (const module of this.modules) { for (const module of this.modules) {
if (module.buildInfo.fileDependencies) { const fileDependencies = module.buildInfo.fileDependencies;
addAllToSet(this.fileDependencies, module.buildInfo.fileDependencies); const contextDependencies = module.buildInfo.contextDependencies;
const missingDependencies = module.buildInfo.missingDependencies;
if (fileDependencies) {
addAllToSet(this.fileDependencies, fileDependencies);
} }
if (module.buildInfo.contextDependencies) { if (contextDependencies) {
addAllToSet( addAllToSet(this.contextDependencies, contextDependencies);
this.contextDependencies, }
module.buildInfo.contextDependencies if (missingDependencies) {
); addAllToSet(this.missingDependencies, missingDependencies);
} }
} }
for (const error of this.errors) { for (const error of this.errors) {
if ( if (
typeof error.missing === "object" && typeof error.missing === "object" &&
@ -2226,6 +2239,7 @@ class Compilation {
addAllToSet(this.missingDependencies, error.missing); addAllToSet(this.missingDependencies, error.missing);
} }
} }
this.fileDependencies.sort(); this.fileDependencies.sort();
this.contextDependencies.sort(); this.contextDependencies.sort();
this.missingDependencies.sort(); this.missingDependencies.sort();

View File

@ -40,7 +40,6 @@ const { makePathsRelative } = require("./util/identifier");
* @typedef {Object} CompilationParams * @typedef {Object} CompilationParams
* @property {NormalModuleFactory} normalModuleFactory * @property {NormalModuleFactory} normalModuleFactory
* @property {ContextModuleFactory} contextModuleFactory * @property {ContextModuleFactory} contextModuleFactory
* @property {Set<string>} compilationDependencies
*/ */
/** /**
@ -141,9 +140,9 @@ class Compiler {
this.records = {}; this.records = {};
/** @type {Set<string>} */ /** @type {Set<string>} */
this.removedFiles = new Set(); this.removedFiles = new Set();
/** @type {Map<string, FileSystemInfoEntry>} */ /** @type {Map<string, FileSystemInfoEntry | null>} */
this.fileTimestamps = new Map(); this.fileTimestamps = new Map();
/** @type {Map<string, FileSystemInfoEntry>} */ /** @type {Map<string, FileSystemInfoEntry | null>} */
this.contextTimestamps = new Map(); this.contextTimestamps = new Map();
/** @type {ResolverFactory} */ /** @type {ResolverFactory} */
this.resolverFactory = new ResolverFactory(); this.resolverFactory = new ResolverFactory();
@ -193,7 +192,9 @@ class Compiler {
const finalCallback = (err, stats) => { const finalCallback = (err, stats) => {
this.cache.beginIdle(); this.cache.beginIdle();
this.running = false; this.running = false;
if (err) {
this.hooks.failed.call(err);
}
if (callback !== undefined) callback(err, stats); if (callback !== undefined) callback(err, stats);
this.hooks.afterDone.call(stats); this.hooks.afterDone.call(stats);
}; };
@ -216,6 +217,7 @@ class Compiler {
return; return;
} }
process.nextTick(() => {
this.emitAssets(compilation, err => { this.emitAssets(compilation, err => {
if (err) return finalCallback(err); if (err) return finalCallback(err);
@ -248,6 +250,7 @@ class Compiler {
}); });
}); });
}); });
});
}; };
this.cache.endIdle(err => { this.cache.endIdle(err => {
@ -525,7 +528,6 @@ class Compiler {
const compilation = this.createCompilation(); const compilation = this.createCompilation();
compilation.name = this.name; compilation.name = this.name;
compilation.records = this.records; compilation.records = this.records;
compilation.compilationDependencies = params.compilationDependencies;
this.hooks.thisCompilation.call(compilation, params); this.hooks.thisCompilation.call(compilation, params);
this.hooks.compilation.call(compilation, params); this.hooks.compilation.call(compilation, params);
return compilation; return compilation;
@ -550,8 +552,7 @@ class Compiler {
newCompilationParams() { newCompilationParams() {
const params = { const params = {
normalModuleFactory: this.createNormalModuleFactory(), normalModuleFactory: this.createNormalModuleFactory(),
contextModuleFactory: this.createContextModuleFactory(), contextModuleFactory: this.createContextModuleFactory()
compilationDependencies: new Set()
}; };
return params; return params;
} }
@ -572,6 +573,7 @@ class Compiler {
this.hooks.make.callAsync(compilation, err => { this.hooks.make.callAsync(compilation, err => {
if (err) return callback(err); if (err) return callback(err);
process.nextTick(() => {
compilation.finish(err => { compilation.finish(err => {
if (err) return callback(err); if (err) return callback(err);
@ -587,6 +589,7 @@ class Compiler {
}); });
}); });
}); });
});
} }
/** /**

View File

@ -10,14 +10,19 @@ const path = require("path");
const { AsyncSeriesWaterfallHook, SyncWaterfallHook } = require("tapable"); const { AsyncSeriesWaterfallHook, SyncWaterfallHook } = require("tapable");
const ContextModule = require("./ContextModule"); const ContextModule = require("./ContextModule");
const ModuleFactory = require("./ModuleFactory");
const ContextElementDependency = require("./dependencies/ContextElementDependency"); const ContextElementDependency = require("./dependencies/ContextElementDependency");
/** @typedef {import("./Module")} Module */ /** @typedef {import("./Module")} Module */
/** @typedef {import("./ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */
/** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
/** @typedef {import("./dependencies/ContextDependency")} ContextDependency */
const EMPTY_RESOLVE_OPTIONS = {}; const EMPTY_RESOLVE_OPTIONS = {};
module.exports = class ContextModuleFactory { module.exports = class ContextModuleFactory extends ModuleFactory {
constructor(resolverFactory) { constructor(resolverFactory) {
super();
this.hooks = Object.freeze({ this.hooks = Object.freeze({
/** @type {AsyncSeriesWaterfallHook<TODO>} */ /** @type {AsyncSeriesWaterfallHook<TODO>} */
beforeResolve: new AsyncSeriesWaterfallHook(["data"]), beforeResolve: new AsyncSeriesWaterfallHook(["data"]),
@ -31,17 +36,28 @@ module.exports = class ContextModuleFactory {
this.resolverFactory = resolverFactory; this.resolverFactory = resolverFactory;
} }
/**
* @param {ModuleFactoryCreateData} data data object
* @param {function(Error=, ModuleFactoryResult=): void} callback callback
* @returns {void}
*/
create(data, callback) { create(data, callback) {
const context = data.context; const context = data.context;
const dependencies = data.dependencies; const dependencies = data.dependencies;
const resolveOptions = data.resolveOptions; const resolveOptions = data.resolveOptions;
const dependency = dependencies[0]; const dependency = /** @type {ContextDependency} */ (dependencies[0]);
const fileDependencies = new Set();
const missingDependencies = new Set();
const contextDependencies = new Set();
this.hooks.beforeResolve.callAsync( this.hooks.beforeResolve.callAsync(
Object.assign( Object.assign(
{ {
context: context, context: context,
dependencies: dependencies, dependencies: dependencies,
resolveOptions resolveOptions,
fileDependencies,
missingDependencies,
contextDependencies
}, },
dependency.options dependency.options
), ),
@ -147,10 +163,12 @@ module.exports = class ContextModuleFactory {
// Ignored // Ignored
if (!result) return callback(); if (!result) return callback();
return callback( return callback(null, {
null, module: new ContextModule(result.resolveDependencies, result),
new ContextModule(result.resolveDependencies, result) fileDependencies,
); missingDependencies,
contextDependencies
});
} }
); );
} }

View File

@ -27,11 +27,14 @@ class RuntimeValue {
} }
exec(parser) { exec(parser) {
const buildInfo = parser.state.module.buildInfo;
if (this.fileDependencies === true) { if (this.fileDependencies === true) {
parser.state.module.buildInfo.cacheable = false; buildInfo.cacheable = false;
} else { } else {
for (const fileDependency of this.fileDependencies) { for (const fileDependency of this.fileDependencies) {
parser.state.module.buildInfo.fileDependencies.add(fileDependency); buildInfo.fileDependencies.add(fileDependency);
if (!buildInfo.snapshot.fileTimestamps.has(fileDependency))
buildInfo.snapshot.fileTimestamps.set(fileDependency, {});
} }
} }

View File

@ -28,9 +28,9 @@ class DelegatedModuleFactoryPlugin {
apply(normalModuleFactory) { apply(normalModuleFactory) {
const scope = this.options.scope; const scope = this.options.scope;
if (scope) { if (scope) {
normalModuleFactory.hooks.factory.tap( normalModuleFactory.hooks.factorize.tapAsync(
"DelegatedModuleFactoryPlugin", "DelegatedModuleFactoryPlugin",
factory => (data, callback) => { (data, callback) => {
const dependency = data.dependencies[0]; const dependency = data.dependencies[0];
const request = dependency.request; const request = dependency.request;
if (request && request.indexOf(scope + "/") === 0) { if (request && request.indexOf(scope + "/") === 0) {
@ -67,7 +67,7 @@ class DelegatedModuleFactoryPlugin {
} }
} }
} }
return factory(data, callback); return callback();
} }
); );
} else { } else {

View File

@ -6,17 +6,31 @@
"use strict"; "use strict";
const DllModule = require("./DllModule"); const DllModule = require("./DllModule");
const ModuleFactory = require("./ModuleFactory");
class DllModuleFactory { /** @typedef {import("./ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */
/** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
/** @typedef {import("./dependencies/DllEntryDependency")} DllEntryDependency */
class DllModuleFactory extends ModuleFactory {
constructor() { constructor() {
super();
this.hooks = Object.freeze({}); this.hooks = Object.freeze({});
} }
/**
* @param {ModuleFactoryCreateData} data data object
* @param {function(Error=, ModuleFactoryResult=): void} callback callback
* @returns {void}
*/
create(data, callback) { create(data, callback) {
const dependency = data.dependencies[0]; const dependency = /** @type {DllEntryDependency} */ (data.dependencies[0]);
callback( callback(null, {
null, module: new DllModule(
new DllModule(data.context, dependency.dependencies, dependency.name) data.context,
); dependency.dependencies,
dependency.name
)
});
} }
} }

View File

@ -27,6 +27,8 @@ class DllReferencePlugin {
constructor(options) { constructor(options) {
validateOptions(schema, options, "Dll Reference Plugin"); validateOptions(schema, options, "Dll Reference Plugin");
this.options = options; this.options = options;
/** @type {WeakMap<Object, {path: string, data: DllReferencePluginOptionsManifest?, error: Error?}>} */
this._compilationData = new WeakMap();
} }
apply(compiler) { apply(compiler) {
@ -50,15 +52,17 @@ class DllReferencePlugin {
if ("manifest" in this.options) { if ("manifest" in this.options) {
const manifest = this.options.manifest; const manifest = this.options.manifest;
if (typeof manifest === "string") { if (typeof manifest === "string") {
params.compilationDependencies.add(manifest);
compiler.inputFileSystem.readFile(manifest, (err, result) => { compiler.inputFileSystem.readFile(manifest, (err, result) => {
if (err) return callback(err); if (err) return callback(err);
const data = {
path: manifest,
data: undefined,
error: undefined
};
// Catch errors parsing the manifest so that blank // Catch errors parsing the manifest so that blank
// or malformed manifest files don't kill the process. // or malformed manifest files don't kill the process.
try { try {
params["dll reference " + manifest] = parseJson( data.data = parseJson(result.toString("utf-8"));
result.toString("utf-8")
);
} catch (e) { } catch (e) {
// Store the error in the params so that it can // Store the error in the params so that it can
// be added as a compilation error later on. // be added as a compilation error later on.
@ -67,10 +71,9 @@ class DllReferencePlugin {
manifest, manifest,
compiler.root compiler.root
); );
params[ data.error = new DllManifestError(manifestPath, e.message);
"dll reference parse error " + manifest
] = new DllManifestError(manifestPath, e.message);
} }
this._compilationData.set(params, data);
return callback(); return callback();
}); });
return; return;
@ -89,16 +92,14 @@ class DllReferencePlugin {
let manifestParameter = this.options.manifest; let manifestParameter = this.options.manifest;
let manifest; let manifest;
if (typeof manifestParameter === "string") { if (typeof manifestParameter === "string") {
const data = this._compilationData.get(params);
// If there was an error parsing the manifest // If there was an error parsing the manifest
// file, exit now because the error will be added // file, exit now because the error will be added
// as a compilation error in the "compilation" hook. // as a compilation error in the "compilation" hook.
if (params["dll reference parse error " + manifestParameter]) { if (data.error) {
return; return;
} }
manifest = manifest = data.data;
/** @type {DllReferencePluginOptionsManifest} */ (params[
"dll reference " + manifestParameter
]);
} else { } else {
manifest = manifestParameter; manifest = manifestParameter;
} }
@ -131,12 +132,13 @@ class DllReferencePlugin {
if ("manifest" in this.options) { if ("manifest" in this.options) {
let manifest = this.options.manifest; let manifest = this.options.manifest;
if (typeof manifest === "string") { if (typeof manifest === "string") {
const data = this._compilationData.get(params);
// If there was an error parsing the manifest file, add the // If there was an error parsing the manifest file, add the
// error as a compilation error to make the compilation fail. // error as a compilation error to make the compilation fail.
let e = params["dll reference parse error " + manifest]; if (data.error) {
if (e) { compilation.errors.push(data.error);
compilation.errors.push(e);
} }
compilation.fileDependencies.add(manifest);
} }
} }
} }

View File

@ -15,9 +15,9 @@ class ExternalModuleFactoryPlugin {
apply(normalModuleFactory) { apply(normalModuleFactory) {
const globalType = this.type; const globalType = this.type;
normalModuleFactory.hooks.factory.tap( normalModuleFactory.hooks.factorize.tapAsync(
"ExternalModuleFactoryPlugin", "ExternalModuleFactoryPlugin",
factory => (data, callback) => { (data, callback) => {
const context = data.context; const context = data.context;
const dependency = data.dependencies[0]; const dependency = data.dependencies[0];
@ -30,7 +30,7 @@ class ExternalModuleFactoryPlugin {
const handleExternal = (value, type, callback) => { const handleExternal = (value, type, callback) => {
if (value === false) { if (value === false) {
// Not externals, fallback to original factory // Not externals, fallback to original factory
return factory(data, callback); return callback();
} }
/** @type {string} */ /** @type {string} */
let externalConfig; let externalConfig;
@ -126,11 +126,7 @@ class ExternalModuleFactoryPlugin {
callback(); callback();
}; };
handleExternals(this.externals, (err, module) => { handleExternals(this.externals, callback);
if (err) return callback(err);
if (!module) return handleExternal(false, undefined, callback);
return callback(null, module);
});
} }
); );
} }

View File

@ -26,7 +26,9 @@ const applyMtime = mtime => {
class FileSystemInfo { class FileSystemInfo {
constructor(fs) { constructor(fs) {
this.fs = fs; this.fs = fs;
/** @type {Map<string, FileSystemInfoEntry | null>} */
this._fileTimestamps = new Map(); this._fileTimestamps = new Map();
/** @type {Map<string, FileSystemInfoEntry | null>} */
this._contextTimestamps = new Map(); this._contextTimestamps = new Map();
this.fileTimestampQueue = new AsyncQueue({ this.fileTimestampQueue = new AsyncQueue({
name: "file timestamp", name: "file timestamp",
@ -41,7 +43,7 @@ class FileSystemInfo {
} }
/** /**
* @param {Map<string, FileSystemInfoEntry>} map timestamps * @param {Map<string, FileSystemInfoEntry | null>} map timestamps
* @returns {void} * @returns {void}
*/ */
addFileTimestamps(map) { addFileTimestamps(map) {
@ -51,7 +53,7 @@ class FileSystemInfo {
} }
/** /**
* @param {Map<string, FileSystemInfoEntry>} map timestamps * @param {Map<string, FileSystemInfoEntry | null>} map timestamps
* @returns {void} * @returns {void}
*/ */
addContextTimestamps(map) { addContextTimestamps(map) {
@ -82,6 +84,165 @@ class FileSystemInfo {
this.contextTimestampQueue.add(path, callback); this.contextTimestampQueue.add(path, callback);
} }
createSnapshot(startTime, files, directories, missing, options, callback) {
const fileTimestamps = new Map();
const contextTimestamps = new Map();
const missingTimestamps = new Map();
let jobs = 1;
const jobDone = () => {
if (--jobs === 0) {
callback(null, {
startTime,
fileTimestamps,
contextTimestamps,
missingTimestamps
});
}
};
if (files) {
for (const path of files) {
const cache = this._fileTimestamps.get(path);
if (cache !== undefined) {
fileTimestamps.set(path, cache);
} else {
jobs++;
this.fileTimestampQueue.add(path, (err, entry) => {
if (err) {
fileTimestamps.set(path, "error");
} else {
fileTimestamps.set(path, entry);
}
jobDone();
});
}
}
}
if (directories) {
for (const path of directories) {
contextTimestamps.set(path, "error");
// TODO: getContextTimestamp is not implemented yet
}
}
if (missing) {
for (const path of missing) {
const cache = this._fileTimestamps.get(path);
if (cache !== undefined) {
missingTimestamps.set(path, cache);
} else {
jobs++;
this.fileTimestampQueue.add(path, (err, entry) => {
if (err) {
missingTimestamps.set(path, "error");
} else {
missingTimestamps.set(path, entry);
}
jobDone();
});
}
}
}
jobDone();
}
checkSnapshotValid(snapshot, callback) {
const {
startTime,
fileTimestamps,
contextTimestamps,
missingTimestamps
} = snapshot;
let jobs = 1;
const jobDone = () => {
if (--jobs === 0) {
callback(null, true);
}
};
const invalid = () => {
if (jobs > 0) {
jobs = NaN;
callback(null, false);
}
};
const checkExistance = (current, snap) => {
if (snap === "error") {
// If there was an error while snapshotting (i. e. EBUSY)
// we can't compare further data and assume it's invalid
return false;
}
return !current === !snap;
};
const checkFile = (current, snap) => {
if (snap === "error") {
// If there was an error while snapshotting (i. e. EBUSY)
// we can't compare further data and assume it's invalid
return false;
}
if (current && current.safeTime > startTime) {
// If a change happened after starting reading the item
// this may no longer be valid
return false;
}
if (!current !== !snap) {
// If existance of item differs
// it's invalid
return false;
}
if (current) {
// For existing items only
if (
snap.timestamp !== undefined &&
current.timestamp !== snap.timestamp
) {
// If we have a timestamp (it was a file or symlink) and it differs from current timestamp
// it's invalid
return false;
}
}
return true;
};
for (const [path, ts] of fileTimestamps) {
const cache = this._fileTimestamps.get(path);
if (cache !== undefined) {
if (!checkFile(cache, ts)) {
invalid();
}
} else {
jobs++;
this.fileTimestampQueue.add(path, (err, entry) => {
if (err) return invalid();
if (!checkFile(entry, ts)) {
invalid();
} else {
jobDone();
}
});
}
}
if (contextTimestamps.size > 0) {
// TODO: getContextTimestamp is not implemented yet
invalid();
}
for (const [path, ts] of missingTimestamps) {
const cache = this._fileTimestamps.get(path);
if (cache !== undefined) {
if (!checkExistance(cache, ts)) {
invalid();
}
} else {
jobs++;
this.fileTimestampQueue.add(path, (err, entry) => {
if (err) return invalid();
if (!checkExistance(entry, ts)) {
invalid();
} else {
jobDone();
}
});
}
}
jobDone();
}
// TODO getFileHash(path, callback) // TODO getFileHash(path, callback)
_readFileTimestamp(path, callback) { _readFileTimestamp(path, callback) {
@ -94,12 +255,13 @@ class FileSystemInfo {
return callback(err); return callback(err);
} }
if (stat.mtime) applyMtime(+stat.mtime); const mtime = +stat.mtime;
if (mtime) applyMtime(mtime);
const mtime = +stat.mtime || Infinity;
const ts = { const ts = {
safeTime: mtime + FS_ACCURACY, safeTime: mtime ? mtime + FS_ACCURACY : Infinity,
timestamp: mtime timestamp: stat.isDirectory() ? undefined : mtime
}; };
this._fileTimestamps.set(path, ts); this._fileTimestamps.set(path, ts);

View File

@ -11,6 +11,22 @@ const Template = require("./Template");
/** @typedef {import("./ModuleTemplate")} ModuleTemplate */ /** @typedef {import("./ModuleTemplate")} ModuleTemplate */
const joinIterableWithComma = iterable => {
// This is more performant than Array.from().join(", ")
// as it doesn't create an array
let str = "";
let first = true;
for (const item of iterable) {
str += item;
if (first) {
first = false;
} else {
str += ", ";
}
}
return str;
};
class FunctionModuleTemplatePlugin { class FunctionModuleTemplatePlugin {
constructor({ compilation }) { constructor({ compilation }) {
this.compilation = compilation; this.compilation = compilation;
@ -62,9 +78,11 @@ class FunctionModuleTemplatePlugin {
const req = module.readableIdentifier( const req = module.readableIdentifier(
moduleTemplate.runtimeTemplate.requestShortener moduleTemplate.runtimeTemplate.requestShortener
); );
source.add("/*!****" + req.replace(/./g, "*") + "****!*\\\n"); const reqStr = req.replace(/\*\//g, "*_/");
source.add(" !*** " + req.replace(/\*\//g, "*_/") + " ***!\n"); const reqStrStar = "*".repeat(reqStr.length);
source.add(" \\****" + req.replace(/./g, "*") + "****/\n"); source.add("/*!****" + reqStrStar + "****!*\\\n");
source.add(" !*** " + reqStr + " ***!\n");
source.add(" \\****" + reqStrStar + "****/\n");
const providedExports = moduleGraph.getProvidedExports(module); const providedExports = moduleGraph.getProvidedExports(module);
if (Array.isArray(providedExports)) { if (Array.isArray(providedExports)) {
if (providedExports.length === 0) { if (providedExports.length === 0) {
@ -81,9 +99,9 @@ class FunctionModuleTemplatePlugin {
} }
source.add( source.add(
Template.toComment( Template.toComment(
`runtime requirements: ${Array.from( `runtime requirements: ${joinIterableWithComma(
chunkGraph.getModuleRuntimeRequirements(module) chunkGraph.getModuleRuntimeRequirements(module)
).join(", ")}` )}`
) + "\n" ) + "\n"
); );
const usedExports = moduleGraph.getUsedExports(module); const usedExports = moduleGraph.getUsedExports(module);
@ -97,7 +115,7 @@ class FunctionModuleTemplatePlugin {
} else { } else {
source.add( source.add(
Template.toComment( Template.toComment(
"exports used: " + Array.from(usedExports).join(", ") "exports used: " + joinIterableWithComma(usedExports)
) + "\n" ) + "\n"
); );
} }

View File

@ -10,6 +10,7 @@ const schema = require("../schemas/plugins/IgnorePlugin.json");
/** @typedef {import("../declarations/plugins/IgnorePlugin").IgnorePluginOptions} IgnorePluginOptions */ /** @typedef {import("../declarations/plugins/IgnorePlugin").IgnorePluginOptions} IgnorePluginOptions */
/** @typedef {import("./Compiler")} Compiler */ /** @typedef {import("./Compiler")} Compiler */
/** @typedef {import("./NormalModuleFactory").ResolveData} ResolveData */
class IgnorePlugin { class IgnorePlugin {
/** /**
@ -27,44 +28,40 @@ class IgnorePlugin {
* Note that if "contextRegExp" is given, both the "resourceRegExp" * Note that if "contextRegExp" is given, both the "resourceRegExp"
* and "contextRegExp" have to match. * and "contextRegExp" have to match.
* *
* @param {TODO} result result * @param {ResolveData} resolveData resolve data
* @returns {TODO|null} returns result or null if result should be ignored * @returns {false|undefined} returns false when the request should be ignored, otherwise undefined
*/ */
checkIgnore(result) { checkIgnore(resolveData) {
if (!result) return result;
if ( if (
"checkResource" in this.options && "checkResource" in this.options &&
this.options.checkResource && this.options.checkResource &&
this.options.checkResource(result.request, result.context) this.options.checkResource(resolveData.request, resolveData.context)
) { ) {
// TODO webpack 5 remove checkContext, as checkResource already gets context // TODO webpack 5 remove checkContext, as checkResource already gets context
if ("checkContext" in this.options && this.options.checkContext) { if ("checkContext" in this.options && this.options.checkContext) {
if (this.options.checkContext(result.context)) { if (this.options.checkContext(resolveData.context)) {
return null; return false;
} }
} else { } else {
return null; return false;
} }
} }
if ( if (
"resourceRegExp" in this.options && "resourceRegExp" in this.options &&
this.options.resourceRegExp && this.options.resourceRegExp &&
this.options.resourceRegExp.test(result.request) this.options.resourceRegExp.test(resolveData.request)
) { ) {
if ("contextRegExp" in this.options && this.options.contextRegExp) { if ("contextRegExp" in this.options && this.options.contextRegExp) {
// if "contextRegExp" is given, // if "contextRegExp" is given,
// both the "resourceRegExp" and "contextRegExp" have to match. // both the "resourceRegExp" and "contextRegExp" have to match.
if (this.options.contextRegExp.test(result.context)) { if (this.options.contextRegExp.test(resolveData.context)) {
return null; return false;
} }
} else { } else {
return null; return false;
} }
} }
return result;
} }
/** /**

View File

@ -495,6 +495,20 @@ class JavascriptParser {
res.setNumber(~argument.number); res.setNumber(~argument.number);
res.setRange(expr.range); res.setRange(expr.range);
return res; return res;
} else if (expr.operator === "+") {
const argument = this.evaluateExpression(expr.argument);
if (!argument) return;
if (argument.isNumber()) {
const res = new BasicEvaluatedExpression();
res.setNumber(+argument.number);
res.setRange(expr.range);
return res;
} else if (argument.isString()) {
const res = new BasicEvaluatedExpression();
res.setNumber(+argument.string);
res.setRange(expr.range);
return res;
}
} }
}); });
this.hooks.evaluateTypeof.for("undefined").tap("JavascriptParser", expr => { this.hooks.evaluateTypeof.for("undefined").tap("JavascriptParser", expr => {

44
lib/ModuleFactory.js Normal file
View File

@ -0,0 +1,44 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./Dependency")} Dependency */
/** @typedef {import("./Module")} Module */
/**
* @typedef {Object} ModuleFactoryResult
* @property {Module=} module the created module or unset if no module was created
* @property {Set<string>=} fileDependencies
* @property {Set<string>=} contextDependencies
* @property {Set<string>=} missingDependencies
*/
/**
* @typedef {Object} ModuleFactoryCreateDataContextInfo
* @property {string} issuer
* @property {string} compiler
*/
/**
* @typedef {Object} ModuleFactoryCreateData
* @property {ModuleFactoryCreateDataContextInfo} contextInfo
* @property {any=} resolveOptions
* @property {string} context
* @property {Dependency[]} dependencies
*/
class ModuleFactory {
/**
* @param {ModuleFactoryCreateData} data data object
* @param {function(Error=, ModuleFactoryResult=): void} callback callback
* @returns {void}
*/
create(data, callback) {
throw new Error("ModuleFactory.create must be overridden");
}
}
module.exports = ModuleFactory;

View File

@ -6,7 +6,6 @@
"use strict"; "use strict";
const { getContext, runLoaders } = require("loader-runner"); const { getContext, runLoaders } = require("loader-runner");
const asyncLib = require("neo-async");
const { SyncHook } = require("tapable"); const { SyncHook } = require("tapable");
const { const {
CachedSource, CachedSource,
@ -51,8 +50,6 @@ const makeSerializable = require("./util/makeSerializable");
* @property {TODO} options * @property {TODO} options
*/ */
const EARLY_RETURN_ERROR = new Error("flags early return is not an error");
/** /**
* @param {string | Buffer} input the input * @param {string | Buffer} input the input
* @returns {string} the converted string * @returns {string} the converted string
@ -163,8 +160,6 @@ class NormalModule extends Module {
this.error = null; this.error = null;
/** @private @type {Source=} */ /** @private @type {Source=} */
this._source = null; this._source = null;
/** @type {number=} */
this.buildTimestamp = undefined;
/** @private @type {Map<string, GenerateSourceResult & CachedSourceEntry>} */ /** @private @type {Map<string, GenerateSourceResult & CachedSourceEntry>} */
this._cachedSources = new Map(); this._cachedSources = new Map();
@ -337,11 +332,10 @@ class NormalModule extends Module {
/** /**
* @param {string | Buffer} content the content * @param {string | Buffer} content the content
* @param {string | Buffer} resourceBuffer TODO
* @param {string | TODO} sourceMap an optional source map * @param {string | TODO} sourceMap an optional source map
* @returns {Source} the created source * @returns {Source} the created source
*/ */
createSource(content, resourceBuffer, sourceMap) { createSource(content, sourceMap) {
if (Buffer.isBuffer(content)) { if (Buffer.isBuffer(content)) {
// @ts-ignore // @ts-ignore
// TODO We need to fix @types/webpack-sources to allow RawSource to take a Buffer | string // TODO We need to fix @types/webpack-sources to allow RawSource to take a Buffer | string
@ -371,22 +365,9 @@ class NormalModule extends Module {
fs fs
); );
runLoaders( const startTime = Date.now();
{
resource: this.resource,
loaders: this.loaders,
context: loaderContext,
readResource: fs.readFile.bind(fs)
},
(err, result) => {
if (result) {
this.buildInfo.cacheable = result.cacheable;
this.buildInfo.fileDependencies = new Set(result.fileDependencies);
this.buildInfo.contextDependencies = new Set(
result.contextDependencies
);
}
const processResult = (err, result) => {
if (err) { if (err) {
if (!(err instanceof Error)) { if (!(err instanceof Error)) {
err = new NonErrorEmittedError(err); err = new NonErrorEmittedError(err);
@ -402,10 +383,9 @@ class NormalModule extends Module {
return callback(error); return callback(error);
} }
const resourceBuffer = result.resourceBuffer; const source = result[0];
const source = result.result[0]; const sourceMap = result.length >= 1 ? result[1] : null;
const sourceMap = result.result.length >= 1 ? result.result[1] : null; const extraInfo = result.length >= 2 ? result[2] : null;
const extraInfo = result.result.length >= 2 ? result.result[2] : null;
if (!Buffer.isBuffer(source) && typeof source !== "string") { if (!Buffer.isBuffer(source) && typeof source !== "string") {
const currentLoader = this.getCurrentLoader(loaderContext, 0); const currentLoader = this.getCurrentLoader(loaderContext, 0);
@ -424,7 +404,6 @@ class NormalModule extends Module {
this._source = this.createSource( this._source = this.createSource(
this.binary ? asBuffer(source) : asString(source), this.binary ? asBuffer(source) : asString(source),
resourceBuffer,
sourceMap sourceMap
); );
this._ast = this._ast =
@ -434,6 +413,46 @@ class NormalModule extends Module {
? extraInfo.webpackAST ? extraInfo.webpackAST
: null; : null;
return callback(); return callback();
};
runLoaders(
{
resource: this.resource,
loaders: this.loaders,
context: loaderContext,
readResource: fs.readFile.bind(fs)
},
(err, result) => {
if (!result) {
processResult(
err || new Error("No result from loader-runner processing"),
null
);
}
this.buildInfo.fileDependencies = new Set(result.fileDependencies);
this.buildInfo.contextDependencies = new Set(
result.contextDependencies
);
this.buildInfo.missingDependencies = new Set(
result.missingDependencies
);
if (!result.cacheable) {
this.buildInfo.cacheable = false;
processResult(err, result.result);
return;
}
this.buildInfo.cacheable = true;
compilation.fileSystemInfo.createSnapshot(
startTime,
result.fileDependencies,
result.contextDependencies,
result.missingDependencies,
null,
(err2, snapshot) => {
this.buildInfo.snapshot = snapshot;
processResult(err || err2, result.result);
}
);
} }
); );
} }
@ -515,7 +534,6 @@ class NormalModule extends Module {
* @returns {void} * @returns {void}
*/ */
build(options, compilation, resolver, fs, callback) { build(options, compilation, resolver, fs, callback) {
this.buildTimestamp = Date.now();
this._forceBuild = false; this._forceBuild = false;
this._source = null; this._source = null;
this._ast = null; this._ast = null;
@ -530,6 +548,7 @@ class NormalModule extends Module {
parsed: true, parsed: true,
fileDependencies: undefined, fileDependencies: undefined,
contextDependencies: undefined, contextDependencies: undefined,
missingDependencies: undefined,
hash: undefined, hash: undefined,
assets: undefined assets: undefined
}; };
@ -717,41 +736,10 @@ class NormalModule extends Module {
// always build when module is not cacheable // always build when module is not cacheable
if (!this.buildInfo.cacheable) return callback(null, true); if (!this.buildInfo.cacheable) return callback(null, true);
// Check timestamps of all dependencies // check snapshot for validity
// Missing timestamp -> need build fileSystemInfo.checkSnapshotValid(this.buildInfo.snapshot, (err, valid) => {
// Timestamp bigger than buildTimestamp -> need build callback(err, !valid);
asyncLib.parallel(
[
callback =>
asyncLib.each(
this.buildInfo.fileDependencies,
(file, callback) => {
fileSystemInfo.getFileTimestamp(file, (err, info) => {
if (err) return callback(err);
if (!info || info.safeTime >= this.buildTimestamp)
return callback(EARLY_RETURN_ERROR);
callback();
}); });
},
callback
),
callback =>
asyncLib.each(
this.buildInfo.contextDependencies,
(context, callback) => {
fileSystemInfo.getContextTimestamp(context, (err, info) => {
if (err) return callback(err);
if (!info || info.safeTime >= this.buildTimestamp)
return callback(EARLY_RETURN_ERROR);
callback();
});
},
callback
)
],
err =>
err === EARLY_RETURN_ERROR ? callback(null, true) : callback(err, false)
);
} }
/** /**
@ -788,7 +776,6 @@ class NormalModule extends Module {
write(this.resource); write(this.resource);
// deserialize // deserialize
write(this._source); write(this._source);
write(this.buildTimestamp);
write(this.error); write(this.error);
write(this._cachedSources); write(this._cachedSources);
write(this._lastSuccessfulBuildMeta); write(this._lastSuccessfulBuildMeta);
@ -818,7 +805,6 @@ class NormalModule extends Module {
deserialize(context) { deserialize(context) {
const { read } = context; const { read } = context;
this._source = read(); this._source = read();
this.buildTimestamp = read();
this.error = read(); this.error = read();
this._cachedSources = read(); this._cachedSources = read();
this._lastSuccessfulBuildMeta = read(); this._lastSuccessfulBuildMeta = read();

View File

@ -8,17 +8,36 @@
const asyncLib = require("neo-async"); const asyncLib = require("neo-async");
const path = require("path"); const path = require("path");
const { const {
AsyncSeriesWaterfallHook, AsyncSeriesBailHook,
SyncWaterfallHook, SyncWaterfallHook,
SyncBailHook, SyncBailHook,
SyncHook, SyncHook,
HookMap HookMap
} = require("tapable"); } = require("tapable");
const Module = require("./Module");
const ModuleFactory = require("./ModuleFactory");
const NormalModule = require("./NormalModule"); const NormalModule = require("./NormalModule");
const RawModule = require("./RawModule"); const RawModule = require("./RawModule");
const RuleSet = require("./RuleSet"); const RuleSet = require("./RuleSet");
const cachedMerge = require("./util/cachedMerge"); const cachedMerge = require("./util/cachedMerge");
/** @typedef {import("./ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */
/** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
/** @typedef {import("./dependencies/ModuleDependency")} ModuleDependency */
/**
* @typedef {Object} ResolveData
* @property {ModuleFactoryCreateData["contextInfo"]} contextInfo
* @property {ModuleFactoryCreateData["resolveOptions"]} resolveOptions
* @property {string} context
* @property {string} request
* @property {ModuleDependency[]} dependencies
* @property {Object} createData
* @property {Set<string>} fileDependencies
* @property {Set<string>} missingDependencies
* @property {Set<string>} contextDependencies
*/
const EMPTY_RESOLVE_OPTIONS = {}; const EMPTY_RESOLVE_OPTIONS = {};
const MATCH_RESOURCE_REGEX = /^([^!]+)!=!/; const MATCH_RESOURCE_REGEX = /^([^!]+)!=!/;
@ -39,6 +58,14 @@ const loaderToIdent = data => {
return data.loader + "?" + JSON.stringify(data.options); return data.loader + "?" + JSON.stringify(data.options);
}; };
const stringifyLoadersAndResource = (loaders, resource) => {
let str = "";
for (const loader of loaders) {
str += loaderToIdent(loader) + "!";
}
return str + resource;
};
const identToLoaderRequest = resultString => { const identToLoaderRequest = resultString => {
const idx = resultString.indexOf("?"); const idx = resultString.indexOf("?");
if (idx >= 0) { if (idx >= 0) {
@ -56,17 +83,42 @@ const identToLoaderRequest = resultString => {
} }
}; };
const needCalls = (times, callback) => {
return err => {
if (--times === 0) {
return callback(err);
}
if (err && times > 0) {
times = NaN;
return callback(err);
}
};
};
// TODO webpack 6 remove
const deprecationChangedHookMessage = name =>
`NormalModuleFactory.${name} is no longer a waterfall hook, but a bailing hook instead. ` +
"Do not return the passed object, but modify it instead. " +
"Returning false will ignore the request and results in no module created.";
const dependencyCache = new WeakMap(); const dependencyCache = new WeakMap();
class NormalModuleFactory { class NormalModuleFactory extends ModuleFactory {
constructor(context, resolverFactory, options) { constructor(context, resolverFactory, options) {
super();
this.hooks = Object.freeze({ this.hooks = Object.freeze({
resolver: new SyncWaterfallHook(["resolver"]), /** @type {AsyncSeriesBailHook<ResolveData>} */
factory: new SyncWaterfallHook(["factory"]), resolve: new AsyncSeriesBailHook(["resolveData"]),
beforeResolve: new AsyncSeriesWaterfallHook(["data"]), /** @type {AsyncSeriesBailHook<ResolveData>} */
afterResolve: new AsyncSeriesWaterfallHook(["data"]), factorize: new AsyncSeriesBailHook(["resolveData"]),
createModule: new SyncBailHook(["data"]), /** @type {AsyncSeriesBailHook<ResolveData>} */
module: new SyncWaterfallHook(["module", "data"]), beforeResolve: new AsyncSeriesBailHook(["resolveData"]),
/** @type {AsyncSeriesBailHook<ResolveData>} */
afterResolve: new AsyncSeriesBailHook(["resolveData"]),
/** @type {SyncBailHook<ResolveData>} */
createModule: new SyncBailHook(["resolveData"]),
/** @type {SyncWaterfallHook<Module, ResolveData["createData"], ResolveData>} */
module: new SyncWaterfallHook(["module", "createData", "resolveData"]),
createParser: new HookMap(() => new SyncBailHook(["parserOptions"])), createParser: new HookMap(() => new SyncBailHook(["parserOptions"])),
parser: new HookMap(() => new SyncHook(["parser", "parserOptions"])), parser: new HookMap(() => new SyncHook(["parser", "parserOptions"])),
createGenerator: new HookMap( createGenerator: new HookMap(
@ -86,111 +138,127 @@ class NormalModuleFactory {
this.context = context || ""; this.context = context || "";
this.parserCache = Object.create(null); this.parserCache = Object.create(null);
this.generatorCache = Object.create(null); this.generatorCache = Object.create(null);
this.hooks.factory.tap("NormalModuleFactory", () => (result, callback) => { this.hooks.factorize.tapAsync(
let resolver = this.hooks.resolver.call(null); /** @type {TODO} */ ({
name: "NormalModuleFactory",
// Ignored stage: 100
if (!resolver) return callback(); }),
(resolveData, callback) => {
resolver(result, (err, data) => { this.hooks.resolve.callAsync(resolveData, (err, result) => {
if (err) return callback(err); if (err) return callback(err);
// Ignored // Ignored
if (!data) return callback(); if (result === false) return callback();
// direct module // direct module
if (typeof data.source === "function") return callback(null, data); if (result instanceof Module) return callback(null, result);
this.hooks.afterResolve.callAsync(data, (err, result) => { if (typeof result === "object")
throw new Error(
deprecationChangedHookMessage("resolve") +
" Returning a Module object will result in this module used as result."
);
this.hooks.afterResolve.callAsync(resolveData, (err, result) => {
if (err) return callback(err); if (err) return callback(err);
// Ignored if (typeof result === "object")
if (!result) return callback(); throw new Error(deprecationChangedHookMessage("afterResolve"));
let createdModule = this.hooks.createModule.call(result); // Ignored
if (result === false) return callback();
const createData = resolveData.createData;
let createdModule = this.hooks.createModule.call(createData);
if (!createdModule) { if (!createdModule) {
if (!result.request) { if (!resolveData.request) {
return callback(new Error("Empty dependency (no request)")); return callback(new Error("Empty dependency (no request)"));
} }
createdModule = new NormalModule(result); createdModule = new NormalModule(createData);
} }
createdModule = this.hooks.module.call(createdModule, result); createdModule = this.hooks.module.call(
createdModule,
createData,
resolveData
);
return callback(null, createdModule); return callback(null, createdModule);
}); });
}); });
}); }
this.hooks.resolver.tap("NormalModuleFactory", () => (data, callback) => { );
const contextInfo = data.contextInfo; this.hooks.resolve.tapAsync(
const context = data.context; /** @type {TODO} */ ({
const request = data.request; name: "NormalModuleFactory",
stage: 100
}),
(data, callback) => {
const {
contextInfo,
context,
request,
resolveOptions,
fileDependencies,
missingDependencies,
contextDependencies
} = data;
const loaderResolver = this.getResolver("loader"); const loaderResolver = this.getResolver("loader");
const normalResolver = this.getResolver("normal", data.resolveOptions); const normalResolver = this.getResolver("normal", resolveOptions);
/** @type {string} */
let matchResource = undefined; let matchResource = undefined;
/** @type {string} */
let requestWithoutMatchResource = request; let requestWithoutMatchResource = request;
const matchResourceMatch = MATCH_RESOURCE_REGEX.exec(request); const matchResourceMatch = MATCH_RESOURCE_REGEX.exec(request);
if (matchResourceMatch) { if (matchResourceMatch) {
matchResource = matchResourceMatch[1]; matchResource = matchResourceMatch[1];
if (/^\.\.?\//.test(matchResource)) { if (matchResource.charCodeAt(0) === 46) {
// 46 === ".", 47 === "/"
const secondChar = matchResource.charCodeAt(1);
if (
secondChar === 47 ||
(secondChar === 46 && matchResource.charCodeAt(2) === 47)
) {
// if matchResources startsWith ../ or ./
matchResource = path.join(context, matchResource); matchResource = path.join(context, matchResource);
} }
}
requestWithoutMatchResource = request.substr( requestWithoutMatchResource = request.substr(
matchResourceMatch[0].length matchResourceMatch[0].length
); );
} }
const noPreAutoLoaders = requestWithoutMatchResource.startsWith("-!"); const firstChar = requestWithoutMatchResource.charCodeAt(0);
const noAutoLoaders = const secondChar = requestWithoutMatchResource.charCodeAt(1);
noPreAutoLoaders || requestWithoutMatchResource.startsWith("!"); const noPreAutoLoaders = firstChar === 45 && secondChar === 33; // startsWith "-!"
const noPrePostAutoLoaders = requestWithoutMatchResource.startsWith("!!"); const noAutoLoaders = noPreAutoLoaders || firstChar === 33; // startsWith "!"
let elements = requestWithoutMatchResource const noPrePostAutoLoaders = firstChar === 33 && secondChar === 33; // startsWith "!!";
.replace(/^-?!+/, "") const rawElements = requestWithoutMatchResource
.replace(/!!+/g, "!") .slice(
.split("!"); noPreAutoLoaders || noPrePostAutoLoaders ? 2 : noAutoLoaders ? 1 : 0
let resource = elements.pop(); )
elements = elements.map(identToLoaderRequest); .split(/!+/);
const unresolvedResource = rawElements.pop();
const elements = rawElements.map(identToLoaderRequest);
asyncLib.parallel( const resolveContext = {
[ fileDependencies,
callback => missing: missingDependencies,
this.resolveRequestArray( missingDependencies,
contextInfo, contextDependencies
context, };
elements,
loaderResolver,
callback
),
callback => {
if (resource === "" || resource[0] === "?") {
return callback(null, {
resource
});
}
normalResolver.resolve( /** @type {string | false} */
contextInfo, let resource;
context, let resourceResolveData;
resource, let loaders;
{},
(err, resource, resourceResolveData) => { const continueCallback = needCalls(2, err => {
if (err) return callback(err); if (err) return callback(err);
callback(null, {
resourceResolveData,
resource
});
}
);
}
],
(err, results) => {
if (err) return callback(err);
let loaders = results[0];
const resourceResolveData = results[1].resourceResolveData;
resource = results[1].resource;
// translate option idents // translate option idents
try { try {
@ -219,10 +287,7 @@ class NormalModuleFactory {
const userRequest = const userRequest =
(matchResource !== undefined ? `${matchResource}!=!` : "") + (matchResource !== undefined ? `${matchResource}!=!` : "") +
loaders stringifyLoadersAndResource(loaders, resource);
.map(loaderToIdent)
.concat([resource])
.join("!");
let resourcePath = let resourcePath =
matchResource !== undefined ? matchResource : resource; matchResource !== undefined ? matchResource : resource;
@ -275,46 +340,24 @@ class NormalModuleFactory {
settings[r.type] = r.value; settings[r.type] = r.value;
} }
} }
asyncLib.parallel(
[ let postLoaders, normalLoaders, preLoaders;
this.resolveRequestArray.bind(
this, const continueCallback = needCalls(3, err => {
contextInfo, if (err) {
this.context, return callback(err);
useLoadersPost, }
loaderResolver const allLoaders = postLoaders;
), for (const loader of loaders) allLoaders.push(loader);
this.resolveRequestArray.bind( for (const loader of normalLoaders) allLoaders.push(loader);
this, for (const loader of preLoaders) allLoaders.push(loader);
contextInfo,
this.context,
useLoaders,
loaderResolver
),
this.resolveRequestArray.bind(
this,
contextInfo,
this.context,
useLoadersPre,
loaderResolver
)
],
(err, results) => {
if (err) return callback(err);
loaders = results[0].concat(loaders, results[1], results[2]);
process.nextTick(() => {
const type = settings.type; const type = settings.type;
const resolveOptions = settings.resolve; const resolveOptions = settings.resolve;
callback(null, { Object.assign(data.createData, {
context: context, request: stringifyLoadersAndResource(allLoaders, resource),
request: loaders
.map(loaderToIdent)
.concat([resource])
.join("!"),
dependencies: data.dependencies,
userRequest, userRequest,
rawRequest: request, rawRequest: request,
loaders, loaders: allLoaders,
resource, resource,
matchResource, matchResource,
resourceResolveData, resourceResolveData,
@ -324,60 +367,157 @@ class NormalModuleFactory {
generator: this.getGenerator(type, settings.generator), generator: this.getGenerator(type, settings.generator),
resolveOptions resolveOptions
}); });
callback();
}); });
this.resolveRequestArray(
contextInfo,
this.context,
useLoadersPost,
loaderResolver,
resolveContext,
(err, result) => {
postLoaders = result;
continueCallback(err);
} }
); );
this.resolveRequestArray(
contextInfo,
this.context,
useLoaders,
loaderResolver,
resolveContext,
(err, result) => {
normalLoaders = result;
continueCallback(err);
}
);
this.resolveRequestArray(
contextInfo,
this.context,
useLoadersPre,
loaderResolver,
resolveContext,
(err, result) => {
preLoaders = result;
continueCallback(err);
} }
); );
}); });
this.resolveRequestArray(
contextInfo,
context,
elements,
loaderResolver,
resolveContext,
(err, result) => {
if (err) return continueCallback(err);
loaders = result;
continueCallback();
}
);
if (
unresolvedResource === "" ||
unresolvedResource.charCodeAt(0) === 63
) {
// 63 === "?"
resource = unresolvedResource;
return continueCallback();
} }
normalResolver.resolve(
contextInfo,
context,
unresolvedResource,
resolveContext,
(err, resolvedResource, resolvedResourceResolveData) => {
if (err) return continueCallback(err);
// TODO remove this when enhanced-resolve supports fileDependencies
if (resolvedResource) {
fileDependencies.add(resolvedResource);
}
resource = resolvedResource;
resourceResolveData = resolvedResourceResolveData;
continueCallback();
}
);
}
);
}
/**
* @param {ModuleFactoryCreateData} data data object
* @param {function(Error=, ModuleFactoryResult=): void} callback callback
* @returns {void}
*/
create(data, callback) { create(data, callback) {
const dependencies = data.dependencies; const dependencies = /** @type {ModuleDependency[]} */ (data.dependencies);
if (this.unsafeCache) { if (this.unsafeCache) {
const cacheEntry = dependencyCache.get(dependencies[0]); const cacheEntry = dependencyCache.get(dependencies[0]);
if (cacheEntry) return callback(null, cacheEntry); if (cacheEntry) return callback(null, cacheEntry);
} }
const context = data.context || this.context; const context = data.context || this.context;
const resolveOptions = data.resolveOptions || EMPTY_RESOLVE_OPTIONS; const resolveOptions = data.resolveOptions || EMPTY_RESOLVE_OPTIONS;
const request = dependencies[0].request; const dependency = dependencies[0];
const contextInfo = data.contextInfo || {}; const request = dependency.request;
this.hooks.beforeResolve.callAsync( const contextInfo = data.contextInfo;
{ const fileDependencies = new Set();
const missingDependencies = new Set();
const contextDependencies = new Set();
/** @type {ResolveData} */
const resolveData = {
contextInfo, contextInfo,
resolveOptions, resolveOptions,
context, context,
request, request,
dependencies dependencies,
}, fileDependencies,
(err, result) => { missingDependencies,
contextDependencies,
createData: {}
};
this.hooks.beforeResolve.callAsync(resolveData, (err, result) => {
if (err) return callback(err); if (err) return callback(err);
// Ignored // Ignored
if (!result) return callback(); if (result === false) return callback();
const factory = this.hooks.factory.call(null); if (typeof result === "object")
throw new Error(deprecationChangedHookMessage("beforeResolve"));
// Ignored this.hooks.factorize.callAsync(resolveData, (err, module) => {
if (!factory) return callback();
factory(result, (err, module) => {
if (err) return callback(err); if (err) return callback(err);
const factoryResult = {
module,
fileDependencies,
missingDependencies,
contextDependencies
};
if (this.unsafeCache && module && this.cachePredicate(module)) { if (this.unsafeCache && module && this.cachePredicate(module)) {
for (const d of dependencies) { for (const d of dependencies) {
dependencyCache.set(d, module); dependencyCache.set(d, factoryResult);
} }
} }
callback(null, module); callback(null, factoryResult);
});
}); });
} }
);
}
resolveRequestArray(contextInfo, context, array, resolver, callback) { resolveRequestArray(
if (array.length === 0) return callback(null, []); contextInfo,
context,
array,
resolver,
resolveContext,
callback
) {
if (array.length === 0) return callback(null, array);
asyncLib.map( asyncLib.map(
array, array,
(item, callback) => { (item, callback) => {
@ -385,7 +525,7 @@ class NormalModuleFactory {
contextInfo, contextInfo,
context, context,
item.loader, item.loader,
{}, resolveContext,
(err, result) => { (err, result) => {
if ( if (
err && err &&
@ -396,7 +536,7 @@ class NormalModuleFactory {
contextInfo, contextInfo,
context, context,
item.loader + "-loader", item.loader + "-loader",
{}, resolveContext,
err2 => { err2 => {
if (!err2) { if (!err2) {
err.message = err.message =
@ -414,15 +554,22 @@ class NormalModuleFactory {
} }
if (err) return callback(err); if (err) return callback(err);
const optionsOnly = item.options const parsedResult = identToLoaderRequest(result);
? { const resolved = {
options: item.options loader: parsedResult.loader,
options:
item.options === undefined
? parsedResult.options
: item.options,
ident: item.options === undefined ? undefined : item.ident
};
// TODO remove this when enhanced-resolve supports fileDependencies
if (resolved.loader) {
resolveContext.fileDependencies.add(resolved.loader);
} }
: undefined;
return callback( return callback(null, resolved);
null,
Object.assign({}, item, identToLoaderRequest(result), optionsOnly)
);
} }
); );
}, },

View File

@ -33,7 +33,6 @@ class NormalModuleReplacementPlugin {
"NormalModuleReplacementPlugin", "NormalModuleReplacementPlugin",
nmf => { nmf => {
nmf.hooks.beforeResolve.tap("NormalModuleReplacementPlugin", result => { nmf.hooks.beforeResolve.tap("NormalModuleReplacementPlugin", result => {
if (!result) return;
if (resourceRegExp.test(result.request)) { if (resourceRegExp.test(result.request)) {
if (typeof newResource === "function") { if (typeof newResource === "function") {
newResource(result); newResource(result);
@ -44,13 +43,13 @@ class NormalModuleReplacementPlugin {
return result; return result;
}); });
nmf.hooks.afterResolve.tap("NormalModuleReplacementPlugin", result => { nmf.hooks.afterResolve.tap("NormalModuleReplacementPlugin", result => {
if (!result) return; const createData = result.createData;
if (resourceRegExp.test(result.resource)) { if (resourceRegExp.test(createData.resource)) {
if (typeof newResource === "function") { if (typeof newResource === "function") {
newResource(result); newResource(result);
} else { } else {
result.resource = path.resolve( createData.resource = path.resolve(
path.dirname(result.resource), path.dirname(createData.resource),
newResource newResource
); );
} }

View File

@ -5,7 +5,17 @@
"use strict"; "use strict";
class NullFactory { const ModuleFactory = require("./ModuleFactory");
/** @typedef {import("./ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */
/** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
class NullFactory extends ModuleFactory {
/**
* @param {ModuleFactoryCreateData} data data object
* @param {function(Error=, ModuleFactoryResult=): void} callback callback
* @returns {void}
*/
create(data, callback) { create(data, callback) {
return callback(); return callback();
} }

View File

@ -34,15 +34,7 @@ class IgnoringWatchFileSystem {
missing, missing,
startTime, startTime,
options, options,
( (err, fileTimestamps, dirTimestamps, removedFiles) => {
err,
filesModified,
dirsModified,
missingModified,
fileTimestamps,
dirTimestamps,
removedFiles
) => {
if (err) return callback(err); if (err) return callback(err);
for (const path of ignoredFiles) { for (const path of ignoredFiles) {
fileTimestamps.set(path, 1); fileTimestamps.set(path, 1);
@ -52,15 +44,7 @@ class IgnoringWatchFileSystem {
dirTimestamps.set(path, 1); dirTimestamps.set(path, 1);
} }
callback( callback(err, fileTimestamps, dirTimestamps, removedFiles);
err,
filesModified,
dirsModified,
missingModified,
fileTimestamps,
dirTimestamps,
removedFiles
);
}, },
callbackUndelayed callbackUndelayed
); );
@ -68,15 +52,15 @@ class IgnoringWatchFileSystem {
return { return {
close: () => watcher.close(), close: () => watcher.close(),
pause: () => watcher.pause(), pause: () => watcher.pause(),
getContextTimestamps: () => { getContextInfoEntries: () => {
const dirTimestamps = watcher.getContextTimestamps(); const dirTimestamps = watcher.getContextInfoEntries();
for (const path of ignoredDirs) { for (const path of ignoredDirs) {
dirTimestamps.set(path, 1); dirTimestamps.set(path, 1);
} }
return dirTimestamps; return dirTimestamps;
}, },
getFileTimestamps: () => { getFileTimeInfoEntries: () => {
const fileTimestamps = watcher.getFileTimestamps(); const fileTimestamps = watcher.getFileTimeInfoEntries();
for (const path of ignoredFiles) { for (const path of ignoredFiles) {
fileTimestamps.set(path, 1); fileTimestamps.set(path, 1);
} }

View File

@ -19,15 +19,6 @@ const Stats = require("./Stats");
* @param {T=} result * @param {T=} result
*/ */
// TODO refactor watchpack to report timestamps in the correct format
const toFileSystemInfoEntryMap = timestamps => {
const map = new Map();
for (const [key, ts] of timestamps) {
map.set(key, { safeTime: ts });
}
return map;
};
class Watching { class Watching {
/** /**
* @param {Compiler} compiler the compiler * @param {Compiler} compiler the compiler
@ -77,6 +68,7 @@ class Watching {
return this._done(null, compilation); return this._done(null, compilation);
} }
process.nextTick(() => {
this.compiler.emitAssets(compilation, err => { this.compiler.emitAssets(compilation, err => {
if (err) return this._done(err); if (err) return this._done(err);
if (this.invalid) return this._done(); if (this.invalid) return this._done();
@ -103,6 +95,7 @@ class Watching {
return this._done(null, compilation); return this._done(null, compilation);
}); });
}); });
});
}; };
this.compiler.compile(onCompiled); this.compiler.compile(onCompiled);
}); });
@ -140,6 +133,7 @@ class Watching {
this.compiler.hooks.done.callAsync(stats, () => { this.compiler.hooks.done.callAsync(stats, () => {
this.compiler.cache.beginIdle(); this.compiler.cache.beginIdle();
this.handler(null, stats); this.handler(null, stats);
process.nextTick(() => {
if (!this.closed) { if (!this.closed) {
this.watch( this.watch(
Array.from(compilation.fileDependencies), Array.from(compilation.fileDependencies),
@ -147,6 +141,7 @@ class Watching {
Array.from(compilation.missingDependencies) Array.from(compilation.missingDependencies)
); );
} }
});
for (const cb of this.callbacks) cb(); for (const cb of this.callbacks) cb();
this.callbacks.length = 0; this.callbacks.length = 0;
this.compiler.hooks.afterDone.call(stats); this.compiler.hooks.afterDone.call(stats);
@ -161,24 +156,14 @@ class Watching {
missing, missing,
this.startTime, this.startTime,
this.watchOptions, this.watchOptions,
( (err, fileTimeInfoEntries, contextTimeInfoEntries, removedFiles) => {
err,
filesModified,
contextModified,
missingModified,
fileTimestamps,
contextTimestamps,
removedFiles
) => {
this.pausedWatcher = this.watcher; this.pausedWatcher = this.watcher;
this.watcher = null; this.watcher = null;
if (err) { if (err) {
return this.handler(err); return this.handler(err);
} }
this.compiler.fileTimestamps = toFileSystemInfoEntryMap(fileTimestamps); this.compiler.fileTimestamps = fileTimeInfoEntries;
this.compiler.contextTimestamps = toFileSystemInfoEntryMap( this.compiler.contextTimestamps = contextTimeInfoEntries;
contextTimestamps
);
this.compiler.removedFiles = removedFiles; this.compiler.removedFiles = removedFiles;
this._invalidate(); this._invalidate();
}, },
@ -197,12 +182,8 @@ class Watching {
this.callbacks.push(callback); this.callbacks.push(callback);
} }
if (this.watcher) { if (this.watcher) {
this.compiler.fileTimestamps = toFileSystemInfoEntryMap( this.compiler.fileTimestamps = this.watcher.getFileTimeInfoEntries();
this.watcher.getFileTimestamps() this.compiler.contextTimestamps = this.watcher.getContextTimeInfoEntries();
);
this.compiler.contextTimestamps = toFileSystemInfoEntryMap(
this.watcher.getContextTimestamps()
);
} }
this._invalidate(); this._invalidate();
} }

View File

@ -451,7 +451,7 @@ class WebpackOptionsApply extends OptionsApply {
if (options.optimization.minimize) { if (options.optimization.minimize) {
for (const minimizer of options.optimization.minimizer) { for (const minimizer of options.optimization.minimizer) {
if (typeof minimizer === "function") { if (typeof minimizer === "function") {
minimizer.apply(compiler); minimizer.call(compiler, compiler);
} else { } else {
minimizer.apply(compiler); minimizer.apply(compiler);
} }

View File

@ -203,7 +203,7 @@ class WebpackOptionsDefaulter extends OptionsDefaulter {
return Object.assign({}, value); return Object.assign({}, value);
} }
}); });
this.set("node.global", false); this.set("node.global", true);
this.set("node.__filename", "mock"); this.set("node.__filename", "mock");
this.set("node.__dirname", "mock"); this.set("node.__dirname", "mock");

View File

@ -10,8 +10,7 @@ const WebpackError = require("./WebpackError");
const getSchemaPart = (path, parents, additionalPath) => { const getSchemaPart = (path, parents, additionalPath) => {
parents = parents || 0; parents = parents || 0;
path = path.split("/"); path = path.split("/", path.length - parents);
path = path.slice(0, path.length - parents);
if (additionalPath) { if (additionalPath) {
additionalPath = additionalPath.split("/"); additionalPath = additionalPath.split("/");
path = path.concat(additionalPath); path = path.concat(additionalPath);

View File

@ -5,13 +5,22 @@
"use strict"; "use strict";
const asyncLib = require("neo-async");
/** @typedef {import("enhanced-resolve/lib/Resolver")} Resolver */ /** @typedef {import("enhanced-resolve/lib/Resolver")} Resolver */
/** @typedef {import("../Compiler")} Compiler */ /** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../FileSystemInfo")} FileSystemInfo */ /** @typedef {import("../FileSystemInfo")} FileSystemInfo */
const INVALID = {}; const requestToString = request => {
let str = "";
for (const key in request) {
const value = request[key];
if (typeof value === "object" && value !== null) {
str += `/${key}={${requestToString(value)}}`;
} else {
str += `/${key}=${value}`;
}
}
return str;
};
class ResolverCachePlugin { class ResolverCachePlugin {
/** /**
@ -63,68 +72,37 @@ class ResolverCachePlugin {
propagate("fileDependencies"); propagate("fileDependencies");
propagate("contextDependencies"); propagate("contextDependencies");
if (err) return callback(err); if (err) return callback(err);
const fileDependencies = new Set(newResolveContext.fileDependencies); const fileDependencies = newResolveContext.fileDependencies;
if (newResolveContext.missing) { const contextDependencies = newResolveContext.contextDependencies;
for (const missing of newResolveContext.missing) { const missingDependencies = newResolveContext.missing;
fileDependencies.add(missing); // TODO remove this when enhanced-resolve supports fileDependencies
}
}
const contextDependencies = new Set(
newResolveContext.contextDependencies
);
if (result && result.path) { if (result && result.path) {
fileDependencies.add(result.path); fileDependencies.add(result.path);
} }
const fileTimestamps = new Map(); fileSystemInfo.createSnapshot(
const contextTimestamps = new Map(); resolveTime,
const store = () => { fileDependencies,
contextDependencies,
missingDependencies,
null,
(err, snapshot) => {
if (err) return callback(err);
cache.store( cache.store(
identifier, identifier,
null, null,
{ {
result, result,
resolveTime, missing: newResolveContext.missing,
fileTimestamps, fileDependencies: newResolveContext.fileDependencies,
contextTimestamps contextDependencies: newResolveContext.contextDependencies,
snapshot
}, },
restoreErr => { storeErr => {
if (restoreErr) return callback(restoreErr); if (storeErr) return callback(storeErr);
if (result) return callback(null, result); if (result) return callback(null, result);
callback(); callback();
} }
); );
};
asyncLib.parallel(
[
asyncLib.each.bind(
asyncLib,
fileDependencies,
(dep, callback) => {
fileSystemInfo.getFileTimestamp(dep, (err, entry) => {
if (err) {
fileTimestamps.set(dep, "error");
} else {
fileTimestamps.set(dep, entry && entry.timestamp);
}
callback();
});
}
),
asyncLib.each.bind(
asyncLib,
contextDependencies,
(dep, callback) => {
fileSystemInfo.getContextTimestamp(dep, (err, entry) => {
contextTimestamps.set(dep, "error");
// TODO: getContextTimestamp is not implemented yet
callback();
});
}
)
],
err => {
if (err) return callback(err);
store();
} }
); );
} }
@ -150,76 +128,17 @@ class ResolverCachePlugin {
if (request._ResolverCachePluginCacheMiss || !fileSystemInfo) { if (request._ResolverCachePluginCacheMiss || !fileSystemInfo) {
return callback(); return callback();
} }
const identifier = `/resolve/${type}/${JSON.stringify( const identifier = `/resolve/${type}${requestToString(
request request
)}`; )}`;
cache.get(identifier, null, (err, cacheEntry) => { const processCacheResult = (err, cacheEntry) => {
if (err) return callback(err); if (err) return callback(err);
if (cacheEntry) { if (cacheEntry) {
const { fileSystemInfo.checkSnapshotValid(
result, cacheEntry.snapshot,
resolveTime, (err, valid) => {
fileTimestamps, if (err || !valid) {
contextTimestamps
} = cacheEntry;
asyncLib.parallel(
[
asyncLib.each.bind(
asyncLib,
fileTimestamps,
([dep, ts], callback) => {
fileSystemInfo.getFileTimestamp(
dep,
(err, entry) => {
if (err) return callback(err);
if (ts === "error") {
return callback(
!entry || entry.safeTime > resolveTime
? INVALID
: null
);
}
if (!entry !== !ts) return callback(INVALID);
if (entry && entry.timestamp) {
return callback(
entry.timestamp !== ts ? INVALID : null
);
}
callback();
}
);
}
),
asyncLib.each.bind(
asyncLib,
contextTimestamps,
([dep, ts], callback) => {
fileSystemInfo.getContextTimestamp(
dep,
(err, entry) => {
if (err) return callback(err);
if (ts === "error") {
return callback(
!entry || entry.safeTime > resolveTime
? INVALID
: null
);
}
if (!entry !== !ts) return callback(INVALID);
if (entry && entry.timestamp) {
return callback(
entry.timestamp !== ts ? INVALID : null
);
}
callback();
}
);
}
)
],
err => {
if (err) {
return doRealResolve( return doRealResolve(
identifier, identifier,
type, type,
@ -229,7 +148,22 @@ class ResolverCachePlugin {
callback callback
); );
} }
callback(null, result); if (resolveContext.missing) {
for (const item of cacheEntry.missing) {
resolveContext.missing.add(item);
}
}
if (resolveContext.fileDependencies) {
for (const item of cacheEntry.fileDependencies) {
resolveContext.fileDependencies.add(item);
}
}
if (resolveContext.contextDependencies) {
for (const item of cacheEntry.contextDependencies) {
resolveContext.contextDependencies.add(item);
}
}
callback(null, cacheEntry.result);
} }
); );
} else { } else {
@ -242,7 +176,8 @@ class ResolverCachePlugin {
callback callback
); );
} }
}); };
cache.get(identifier, null, processCacheResult);
} }
); );
} }

View File

@ -13,9 +13,13 @@ module.exports = class HarmonyDetectionParserPlugin {
const isStrictHarmony = parser.state.module.type === "javascript/esm"; const isStrictHarmony = parser.state.module.type === "javascript/esm";
const isHarmony = const isHarmony =
isStrictHarmony || isStrictHarmony ||
ast.body.some(statement => { ast.body.some(
return /^(Import|Export).*Declaration$/.test(statement.type); statement =>
}); statement.type === "ImportDeclaration" ||
statement.type === "ExportDefaultDeclaration" ||
statement.type === "ExportNamedDeclaration" ||
statement.type === "ExportAllDeclaration"
);
if (isHarmony) { if (isHarmony) {
const module = parser.state.module; const module = parser.state.module;
const compatDep = new HarmonyCompatibilityDependency(); const compatDep = new HarmonyCompatibilityDependency();

View File

@ -23,6 +23,10 @@ class NodeTemplatePlugin {
* @returns {void} * @returns {void}
*/ */
apply(compiler) { apply(compiler) {
const ChunkLoadingRuntimeModule = this.asyncChunkLoading
? ReadFileChunkLoadingRuntimeModule
: RequireChunkLoadingRuntimeModule;
compiler.hooks.thisCompilation.tap("NodeTemplatePlugin", compilation => { compiler.hooks.thisCompilation.tap("NodeTemplatePlugin", compilation => {
new NodeChunkTemplatePlugin(compilation).apply(compilation.chunkTemplate); new NodeChunkTemplatePlugin(compilation).apply(compilation.chunkTemplate);
@ -31,17 +35,10 @@ class NodeTemplatePlugin {
if (onceForChunkSet.has(chunk)) return; if (onceForChunkSet.has(chunk)) return;
onceForChunkSet.add(chunk); onceForChunkSet.add(chunk);
set.add(RuntimeGlobals.moduleFactories); set.add(RuntimeGlobals.moduleFactories);
if (this.asyncChunkLoading) {
compilation.addRuntimeModule( compilation.addRuntimeModule(
chunk, chunk,
new ReadFileChunkLoadingRuntimeModule(chunk, set) new ChunkLoadingRuntimeModule(chunk, set)
); );
} else {
compilation.addRuntimeModule(
chunk,
new RequireChunkLoadingRuntimeModule(chunk, set)
);
}
}; };
compilation.hooks.runtimeRequirementInTree compilation.hooks.runtimeRequirementInTree

View File

@ -6,7 +6,6 @@
"use strict"; "use strict";
const Watchpack = require("watchpack"); const Watchpack = require("watchpack");
const objectToMap = require("../util/objectToMap");
class NodeWatchFileSystem { class NodeWatchFileSystem {
constructor(inputFileSystem) { constructor(inputFileSystem) {
@ -48,31 +47,19 @@ class NodeWatchFileSystem {
const cachedFiles = files; const cachedFiles = files;
const cachedDirs = dirs; const cachedDirs = dirs;
this.watcher.once("aggregated", (changes, removals) => { this.watcher.once("aggregated", (changes, removals) => {
changes = changes.concat(removals);
if (this.inputFileSystem && this.inputFileSystem.purge) { if (this.inputFileSystem && this.inputFileSystem.purge) {
this.inputFileSystem.purge(changes); for (const item of changes) {
this.inputFileSystem.purge(item);
} }
const times = objectToMap(this.watcher.getTimes()); for (const item of removals) {
files = new Set(files); this.inputFileSystem.purge(item);
dirs = new Set(dirs); }
missing = new Set(missing); }
removals = new Set(removals.filter(file => files.has(file))); const times = this.watcher.getTimeInfoEntries();
callback( callback(null, times, times, removals);
null,
changes.filter(file => files.has(file)).sort(),
changes.filter(file => dirs.has(file)).sort(),
changes.filter(file => missing.has(file)).sort(),
times,
times,
removals
);
}); });
this.watcher.watch( this.watcher.watch(cachedFiles.concat(missing), cachedDirs, startTime);
cachedFiles.concat(missing),
cachedDirs.concat(missing),
startTime
);
if (oldWatcher) { if (oldWatcher) {
oldWatcher.close(); oldWatcher.close();
@ -89,16 +76,16 @@ class NodeWatchFileSystem {
this.watcher.pause(); this.watcher.pause();
} }
}, },
getFileTimestamps: () => { getFileTimeInfoEntries: () => {
if (this.watcher) { if (this.watcher) {
return objectToMap(this.watcher.getTimes()); return this.watcher.getTimeInfoEntries();
} else { } else {
return new Map(); return new Map();
} }
}, },
getContextTimestamps: () => { getContextInfoEntries: () => {
if (this.watcher) { if (this.watcher) {
return objectToMap(this.watcher.getTimes()); return this.watcher.getTimeInfoEntries();
} else { } else {
return new Map(); return new Map();
} }

View File

@ -52,6 +52,7 @@ class SideEffectsFlagPlugin {
} else if (data.settings.sideEffects === true) { } else if (data.settings.sideEffects === true) {
module.factoryMeta.sideEffectFree = false; module.factoryMeta.sideEffectFree = false;
} }
return module;
}); });
}); });
compiler.hooks.compilation.tap("SideEffectsFlagPlugin", compilation => { compiler.hooks.compilation.tap("SideEffectsFlagPlugin", compilation => {

View File

@ -16,7 +16,8 @@ const {
compareIds, compareIds,
concatComparators, concatComparators,
compareSelect, compareSelect,
compareModulesById compareModulesById,
compareModulesByIdOrIdentifier
} = require("../util/comparators"); } = require("../util/comparators");
/** @typedef {import("webpack-sources").Source} Source */ /** @typedef {import("webpack-sources").Source} Source */
@ -509,6 +510,15 @@ const SIMPLE_EXTRACTORS = {
moduleName: reason.originModule moduleName: reason.originModule
? reason.originModule.readableIdentifier(requestShortener) ? reason.originModule.readableIdentifier(requestShortener)
: null, : null,
resolvedModuleId: reason.resolvedOriginModule
? chunkGraph.getModuleId(reason.resolvedOriginModule)
: null,
resolvedModuleIdentifier: reason.resolvedOriginModule
? reason.resolvedOriginModule.identifier()
: null,
resolvedModule: reason.resolvedOriginModule
? reason.resolvedOriginModule.readableIdentifier(requestShortener)
: null,
type: reason.dependency ? reason.dependency.type : null, type: reason.dependency ? reason.dependency.type : null,
explanation: reason.explanation, explanation: reason.explanation,
userRequest: userRequest:
@ -796,6 +806,12 @@ const SORTERS = {
comparators.push( comparators.push(
compareSelect(x => x.originModule, compareModulesById(chunkGraph)) compareSelect(x => x.originModule, compareModulesById(chunkGraph))
); );
comparators.push(
compareSelect(
x => x.resolvedOriginModule,
compareModulesByIdOrIdentifier(chunkGraph)
)
);
comparators.push( comparators.push(
compareSelect( compareSelect(
x => x.dependency, x => x.dependency,

View File

@ -246,6 +246,7 @@ const SIMPLE_PRINTERS = {
"moduleReason.module": (module, { magenta }) => magenta(module), "moduleReason.module": (module, { magenta }) => magenta(module),
"moduleReason.loc": loc => loc, "moduleReason.loc": loc => loc,
"moduleReason.explanation": (explanation, { cyan }) => cyan(explanation), "moduleReason.explanation": (explanation, { cyan }) => cyan(explanation),
"moduleReason.resolvedModule": (module, { magenta }) => magenta(module),
"module.profile.total": (value, { formatTime }) => formatTime(value), "module.profile.total": (value, { formatTime }) => formatTime(value),
"module.profile.resolving": (value, { formatTime }) => "module.profile.resolving": (value, { formatTime }) =>
@ -509,6 +510,7 @@ const PREFERED_ORDERS = {
"userRequest", "userRequest",
"moduleId", "moduleId",
"module", "module",
"resolvedModule",
"loc", "loc",
"explanation" "explanation"
], ],
@ -762,6 +764,11 @@ const SIMPLE_ELEMENT_JOINERS = {
case "module": case "module":
if (hasName) return false; if (hasName) return false;
break; break;
case "resolvedModule":
return (
moduleReason.module !== moduleReason.resolvedModule &&
item.content
);
} }
return true; return true;
}) })

View File

@ -7,6 +7,10 @@
const { SyncHook, AsyncSeriesHook } = require("tapable"); const { SyncHook, AsyncSeriesHook } = require("tapable");
const QUEUED_STATE = 0;
const PROCESSING_STATE = 1;
const DONE_STATE = 2;
/** /**
* @template T * @template T
* @callback Callback<T> * @callback Callback<T>
@ -14,6 +18,28 @@ const { SyncHook, AsyncSeriesHook } = require("tapable");
* @param {T=} result * @param {T=} result
*/ */
/**
* @template T
* @template K
* @template R
*/
class AsyncQueueEntry {
/**
* @param {T} item the item
* @param {Callback<R>} callback the callback
*/
constructor(item, callback) {
this.item = item;
/** @type {typeof QUEUED_STATE | typeof PROCESSING_STATE | typeof DONE_STATE} */
this.state = QUEUED_STATE;
this.callback = callback;
/** @type {Callback<R>[] | undefined} */
this.callbacks = undefined;
this.result = undefined;
this.error = undefined;
}
}
/** /**
* @template T * @template T
* @template K * @template K
@ -33,14 +59,10 @@ class AsyncQueue {
this._processor = processor; this._processor = processor;
this._getKey = this._getKey =
getKey || /** @type {(T) => K} */ (item => /** @type {any} */ (item)); getKey || /** @type {(T) => K} */ (item => /** @type {any} */ (item));
/** @type {Map<K, Callback<R>[]>} */ /** @type {Map<K, AsyncQueueEntry<T, K, R>>} */
this._callbacks = new Map(); this._entries = new Map();
/** @type {Set<T>} */ /** @type {AsyncQueueEntry<T, K, R>[]} */
this._queued = new Set(); this._queued = [];
/** @type {Set<K>} */
this._processing = new Set();
/** @type {Map<K, [Error, R]>} */
this._results = new Map();
this._activeTasks = 0; this._activeTasks = 0;
this._willEnsureProcessing = false; this._willEnsureProcessing = false;
this._stopped = false; this._stopped = false;
@ -69,24 +91,25 @@ class AsyncQueue {
return; return;
} }
const key = this._getKey(item); const key = this._getKey(item);
const result = this._results.get(key); const entry = this._entries.get(key);
if (result !== undefined) { if (entry !== undefined) {
process.nextTick(() => callback(result[0], result[1])); if (entry.state === DONE_STATE) {
process.nextTick(() => callback(entry.error, entry.result));
} else if (entry.callbacks === undefined) {
entry.callbacks = [callback];
} else {
entry.callbacks.push(callback);
}
return; return;
} }
let callbacks = this._callbacks.get(key); const newEntry = new AsyncQueueEntry(item, callback);
if (callbacks !== undefined) {
callbacks.push(callback);
return;
}
callbacks = [callback];
this._callbacks.set(key, callbacks);
if (this._stopped) { if (this._stopped) {
this.hooks.added.call(item); this.hooks.added.call(item);
this._activeTasks++; this._activeTasks++;
this._handleResult(item, new Error("Queue was stopped")); this._handleResult(newEntry, new Error("Queue was stopped"));
} else { } else {
this._queued.add(item); this._entries.set(key, newEntry);
this._queued.push(newEntry);
if (this._willEnsureProcessing === false) { if (this._willEnsureProcessing === false) {
this._willEnsureProcessing = true; this._willEnsureProcessing = true;
process.nextTick(this._ensureProcessing); process.nextTick(this._ensureProcessing);
@ -102,7 +125,14 @@ class AsyncQueue {
*/ */
invalidate(item) { invalidate(item) {
const key = this._getKey(item); const key = this._getKey(item);
this._results.delete(key); const entry = this._entries.get(key);
this._entries.delete(key);
if (entry.state === QUEUED_STATE) {
const idx = this._queued.indexOf(entry);
if (idx >= 0) {
this._queued.splice(idx, 1);
}
}
} }
/** /**
@ -110,10 +140,12 @@ class AsyncQueue {
*/ */
stop() { stop() {
this._stopped = true; this._stopped = true;
for (const item of this._queued) { const queue = this._queued;
this._queued = [];
for (const entry of queue) {
this._entries.delete(this._getKey(entry.item));
this._activeTasks++; this._activeTasks++;
this._queued.delete(item); this._handleResult(entry, new Error("Queue was stopped"));
this._handleResult(item, new Error("Queue was stopped"));
} }
} }
@ -122,7 +154,7 @@ class AsyncQueue {
*/ */
increaseParallelism() { increaseParallelism() {
this._parallelism++; this._parallelism++;
if (this._willEnsureProcessing === false && this._queued.size > 0) { if (this._willEnsureProcessing === false && this._queued.length > 0) {
this._willEnsureProcessing = true; this._willEnsureProcessing = true;
process.nextTick(this._ensureProcessing); process.nextTick(this._ensureProcessing);
} }
@ -141,7 +173,8 @@ class AsyncQueue {
*/ */
isProcessing(item) { isProcessing(item) {
const key = this._getKey(item); const key = this._getKey(item);
return this._processing.has(key); const entry = this._entries.get(key);
return entry !== undefined && entry.state === PROCESSING_STATE;
} }
/** /**
@ -149,7 +182,9 @@ class AsyncQueue {
* @returns {boolean} true, if the item is currently queued * @returns {boolean} true, if the item is currently queued
*/ */
isQueued(item) { isQueued(item) {
return this._queued.has(item); const key = this._getKey(item);
const entry = this._entries.get(key);
return entry !== undefined && entry.state === QUEUED_STATE;
} }
/** /**
@ -158,79 +193,79 @@ class AsyncQueue {
*/ */
isDone(item) { isDone(item) {
const key = this._getKey(item); const key = this._getKey(item);
return this._results.has(key); const entry = this._entries.get(key);
return entry !== undefined && entry.state === DONE_STATE;
} }
/** /**
* @returns {void} * @returns {void}
*/ */
_ensureProcessing() { _ensureProcessing() {
if (this._activeTasks >= this._parallelism) { while (this._activeTasks < this._parallelism && this._queued.length > 0) {
this._willEnsureProcessing = false; const entry = this._queued.pop();
return;
}
for (const item of this._queued) {
this._activeTasks++; this._activeTasks++;
const key = this._getKey(item); entry.state = PROCESSING_STATE;
this._queued.delete(item); this._startProcessing(entry);
this._processing.add(key);
this._startProcessing(item);
if (this._activeTasks >= this._parallelism) {
this._willEnsureProcessing = false;
return;
}
} }
this._willEnsureProcessing = false; this._willEnsureProcessing = false;
} }
/** /**
* @param {T} item an item * @param {AsyncQueueEntry<T, K, R>} entry the entry
* @returns {void} * @returns {void}
*/ */
_startProcessing(item) { _startProcessing(entry) {
this.hooks.beforeStart.callAsync(item, err => { this.hooks.beforeStart.callAsync(entry.item, err => {
if (err) { if (err) {
this._handleResult(item, err); this._handleResult(entry, err);
return; return;
} }
let inCallback = false;
try { try {
this._processor(item, (e, r) => { this._processor(entry.item, (e, r) => {
process.nextTick(() => { inCallback = true;
this._handleResult(item, e, r); this._handleResult(entry, e, r);
});
}); });
} catch (err) { } catch (err) {
this._handleResult(item, err, null); if (inCallback) throw err;
this._handleResult(entry, err, null);
} }
this.hooks.started.call(item); this.hooks.started.call(entry.item);
}); });
} }
/** /**
* @param {T} item an item * @param {AsyncQueueEntry<T, K, R>} entry the entry
* @param {Error=} err error, if any * @param {Error=} err error, if any
* @param {R=} result result, if any * @param {R=} result result, if any
* @returns {void} * @returns {void}
*/ */
_handleResult(item, err, result) { _handleResult(entry, err, result) {
this.hooks.result.callAsync(item, err, result, hookError => { this.hooks.result.callAsync(entry.item, err, result, hookError => {
const error = hookError || err; const error = hookError || err;
const key = this._getKey(item); const callback = entry.callback;
const callbacks = this._callbacks.get(key); const callbacks = entry.callbacks;
this._processing.delete(key); entry.state = DONE_STATE;
this._results.set(key, [error, result]); entry.callback = undefined;
this._callbacks.delete(key); entry.callbacks = undefined;
entry.result = result;
entry.error = error;
this._activeTasks--; this._activeTasks--;
if (this._willEnsureProcessing === false && this._queued.size > 0) { if (this._willEnsureProcessing === false && this._queued.length > 0) {
this._willEnsureProcessing = true; this._willEnsureProcessing = true;
process.nextTick(this._ensureProcessing); process.nextTick(this._ensureProcessing);
} }
process.nextTick(() => {
callback(error, result);
if (callbacks !== undefined) {
for (const callback of callbacks) { for (const callback of callbacks) {
callback(error, result); callback(error, result);
} }
}
});
}); });
} }
} }

View File

@ -66,7 +66,7 @@ class DebugHash {
if (data.startsWith("debug-digest-")) { if (data.startsWith("debug-digest-")) {
data = Buffer.from(data.slice("debug-digest-".length), "hex").toString(); data = Buffer.from(data.slice("debug-digest-".length), "hex").toString();
} }
this.string += `[${data}](${new Error().stack.split("\n")[2]})\n`; this.string += `[${data}](${new Error().stack.split("\n", 3)[2]})\n`;
return this; return this;
} }

View File

@ -176,7 +176,9 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
]), ]),
"}", "}",
prefetchChunks && prefetchChunks.length > 0 prefetchChunks && prefetchChunks.length > 0
? prefetchChunks.map(c => `\nprefetchChunk(${c});`) ? prefetchChunks
.map(c => `prefetchChunk(${JSON.stringify(c)});`)
.join("\n")
: "" : ""
]) ])
: "// no prefetching", : "// no prefetching",

View File

@ -1,6 +1,6 @@
{ {
"name": "webpack", "name": "webpack",
"version": "5.0.0-alpha.3", "version": "5.0.0-alpha.5",
"author": "Tobias Koppers @sokra", "author": "Tobias Koppers @sokra",
"description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.", "description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",
"license": "MIT", "license": "MIT",
@ -28,7 +28,7 @@
"schema-utils": "^0.4.4", "schema-utils": "^0.4.4",
"tapable": "^1.1.0", "tapable": "^1.1.0",
"terser-webpack-plugin": "^1.2.1", "terser-webpack-plugin": "^1.2.1",
"watchpack": "^1.5.0", "watchpack": "2.0.0-beta.2",
"webpack-sources": "^1.3.0" "webpack-sources": "^1.3.0"
}, },
"devDependencies": { "devDependencies": {

View File

@ -683,4 +683,25 @@ describe("Compiler", () => {
}); });
}); });
}); });
it("should call the failed-hook on error", done => {
const failedSpy = jest.fn();
const compiler = webpack({
bail: true,
context: __dirname,
mode: "production",
entry: "./missing",
output: {
path: "/",
filename: "bundle.js"
},
});
compiler.hooks.failed.tap('CompilerTest', failedSpy);
compiler.outputFileSystem = new MemoryFs();
compiler.run((err, stats) => {
expect(err).toBeTruthy();
expect(failedSpy).toHaveBeenCalledTimes(1);
expect(failedSpy).toHaveBeenCalledWith(err);
done();
});
});
}); });

View File

@ -6,6 +6,8 @@ const webpack = require("../");
const rimraf = require("rimraf"); const rimraf = require("rimraf");
describe("Profiling Plugin", function() { describe("Profiling Plugin", function() {
jest.setTimeout(15000);
it("should handle output path with folder creation", done => { it("should handle output path with folder creation", done => {
const finalPath = "test/js/profilingPath/events.json"; const finalPath = "test/js/profilingPath/events.json";
const outputPath = path.join(__dirname, "/js/profilingPath"); const outputPath = path.join(__dirname, "/js/profilingPath");

View File

@ -88,7 +88,7 @@ describe("StatsTestCases", () => {
if (/error$/.test(testName)) { if (/error$/.test(testName)) {
expect(stats.hasErrors()).toBe(true); expect(stats.hasErrors()).toBe(true);
} else if (stats.hasErrors()) { } else if (stats.hasErrors()) {
return done(new Error(stats.toJson().errors.join("\n\n"))); return done(new Error(stats.toString({ all: false, errors: true })));
} }
let toStringOptions = { let toStringOptions = {
context: path.join(base, testName), context: path.join(base, testName),

View File

@ -181,13 +181,17 @@ const describeCases = config => {
rimraf(cacheDirectory, done); rimraf(cacheDirectory, done);
}); });
if (config.cache) { if (config.cache) {
it(`${testName} should pre-compile to fill disk cache`, done => { it(`${testName} should pre-compile to fill disk cache (1st)`, done => {
const compiler = webpack(options, err => { webpack(options, err => {
if (err) return done(err); if (err) return done(err);
compiler.close(() => {
done(); done();
}); });
}); });
it(`${testName} should pre-compile to fill disk cache (2nd)`, done => {
webpack(options, err => {
if (err) return done(err);
done();
});
}); });
} }
it( it(

View File

@ -1452,6 +1452,21 @@ If you don't want to include a polyfill, you can use an empty module like this:
" "
`; `;
exports[`StatsTestCases should print correct stats for module-reasons 1`] = `
"Hash: 3584c47f06ef83e85f02
Time: Xms
Built at: Thu Jan 01 1970 00:00:00 GMT
Asset Size Chunks Chunk Names
main.js 2.75 KiB {404} [emitted] main
Entrypoint main = main.js
[523] ./index.js + 2 modules 102 bytes {404} [built]
entry ./index main
[911] ./c.js 8 bytes {404} [built]
cjs require ./c [523] ./index.js + 2 modules ./a.js 1:0-14
cjs require ./c [523] ./index.js + 2 modules ./b.js 1:0-14
+ 2 hidden modules"
`;
exports[`StatsTestCases should print correct stats for module-trace-disabled-in-error 1`] = ` exports[`StatsTestCases should print correct stats for module-trace-disabled-in-error 1`] = `
"Time: Xms "Time: Xms
Built at: Thu Jan 01 1970 00:00:00 GMT Built at: Thu Jan 01 1970 00:00:00 GMT
@ -2357,20 +2372,20 @@ Entrypoint main = main.js
| ./main.js 144 bytes [built] | ./main.js 144 bytes [built]
[1] ./components/src/CompAB/CompA.js 89 bytes {0} [built] [1] ./components/src/CompAB/CompA.js 89 bytes {0} [built]
[only some exports used: default] [only some exports used: default]
harmony import specifier ./components [0] ./main.js + 1 modules 3:15-20 (skipped side-effect-free modules) harmony import specifier ./components [0] ./main.js + 1 modules ./main.js 3:15-20 (skipped side-effect-free modules)
harmony import specifier ./components [3] ./foo.js 3:20-25 (skipped side-effect-free modules) harmony import specifier ./components [3] ./foo.js 3:20-25 (skipped side-effect-free modules)
harmony side effect evaluation ./CompA ./components/src/CompAB/index.js 1:0-43 harmony side effect evaluation ./CompA ./components/src/CompAB/index.js 1:0-43
harmony export imported specifier ./CompA ./components/src/CompAB/index.js 1:0-43 harmony export imported specifier ./CompA ./components/src/CompAB/index.js 1:0-43
[2] ./components/src/CompAB/utils.js 97 bytes {0} [built] [2] ./components/src/CompAB/utils.js 97 bytes {0} [built]
harmony side effect evaluation ./utils [0] ./main.js + 1 modules 1:0-30 harmony side effect evaluation ./utils [0] ./main.js + 1 modules ./components/src/CompAB/CompB.js 1:0-30
harmony import specifier ./utils [0] ./main.js + 1 modules 5:2-5 harmony import specifier ./utils [0] ./main.js + 1 modules ./components/src/CompAB/CompB.js 5:2-5
harmony side effect evaluation ./utils [1] ./components/src/CompAB/CompA.js 1:0-35 harmony side effect evaluation ./utils [1] ./components/src/CompAB/CompA.js 1:0-35
harmony import specifier ./utils [1] ./components/src/CompAB/CompA.js 5:5-12 harmony import specifier ./utils [1] ./components/src/CompAB/CompA.js 5:5-12
[3] ./foo.js 101 bytes {1} [built] [3] ./foo.js 101 bytes {1} [built]
import() ./foo [0] ./main.js + 1 modules 6:0-15 import() ./foo [0] ./main.js + 1 modules ./main.js 6:0-15
./components/src/index.js 84 bytes [orphan] [built] ./components/src/index.js 84 bytes [orphan] [built]
[module unused] [module unused]
harmony side effect evaluation ./components [0] ./main.js + 1 modules 1:0-44 harmony side effect evaluation ./components [0] ./main.js + 1 modules ./main.js 1:0-44
harmony side effect evaluation ./components [3] ./foo.js 1:0-37 harmony side effect evaluation ./components [3] ./foo.js 1:0-37
./components/src/CompAB/index.js 87 bytes [orphan] [built] ./components/src/CompAB/index.js 87 bytes [orphan] [built]
[module unused] [module unused]
@ -2409,14 +2424,14 @@ Entrypoint main = main.js
| ./index.js 55 bytes [built] | ./index.js 55 bytes [built]
./node_modules/pmodule/a.js 60 bytes [orphan] [built] ./node_modules/pmodule/a.js 60 bytes [orphan] [built]
[module unused] [module unused]
harmony side effect evaluation ./a [690] ./index.js + 2 modules 1:0-20 harmony side effect evaluation ./a [690] ./index.js + 2 modules ./node_modules/pmodule/index.js 1:0-20
harmony export imported specifier ./a [690] ./index.js + 2 modules 1:0-20 harmony export imported specifier ./a [690] ./index.js + 2 modules ./node_modules/pmodule/index.js 1:0-20
./node_modules/pmodule/b.js 69 bytes [orphan] [built] ./node_modules/pmodule/b.js 69 bytes [orphan] [built]
[module unused] [module unused]
harmony side effect evaluation ./b [690] ./index.js + 2 modules 2:0-30 harmony side effect evaluation ./b [690] ./index.js + 2 modules ./node_modules/pmodule/index.js 2:0-30
harmony export imported specifier ./b [690] ./index.js + 2 modules 2:0-30 harmony export imported specifier ./b [690] ./index.js + 2 modules ./node_modules/pmodule/index.js 2:0-30
harmony export imported specifier ./b [690] ./index.js + 2 modules 2:0-30 harmony export imported specifier ./b [690] ./index.js + 2 modules ./node_modules/pmodule/index.js 2:0-30
harmony export imported specifier ./b [690] ./index.js + 2 modules 2:0-30 harmony export imported specifier ./b [690] ./index.js + 2 modules ./node_modules/pmodule/index.js 2:0-30
+ 2 hidden modules" + 2 hidden modules"
`; `;

View File

@ -0,0 +1,3 @@
it("should compile a long module chain fine", () => {
require.resolveWeak("./module?800"); // this is orphan
});

View File

@ -0,0 +1,5 @@
if(__resourceQuery === "?0") {
module.exports = "module";
} else {
module.exports = require("./module?" + (+__resourceQuery.substr(1) - 1));
}

View File

@ -0,0 +1 @@
it("should compile", () => {})

View File

@ -0,0 +1,18 @@
const Compiler = require('../../../../lib/Compiler');
module.exports = {
optimization: {
minimize: true,
minimizer: [
{
apply(compiler) {
expect(compiler).toBeInstanceOf(Compiler);
},
},
function(compiler) {
expect(compiler).toBe(this);
expect(compiler).toBeInstanceOf(Compiler);
}
],
},
};

View File

@ -1,8 +1,5 @@
module.exports = { module.exports = {
target: "web", target: "web",
node: {
global: true
},
performance: { performance: {
hints: false hints: false
} }

View File

@ -1,6 +1,3 @@
module.exports = { module.exports = {
target: "web", target: "web"
node: {
global: true
}
}; };

View File

@ -0,0 +1,2 @@
require("./c");
export const a = "a";

View File

@ -0,0 +1,2 @@
require("./c");
export const b = "b";

View File

@ -0,0 +1 @@
// empty

View File

@ -0,0 +1,2 @@
import "./a";
import "./b";

View File

@ -0,0 +1,8 @@
module.exports = {
mode: "production",
entry: "./index",
stats: {
modules: true,
reasons: true,
}
};

121
yarn.lock
View File

@ -550,11 +550,6 @@ astral-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
async-each@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
integrity sha1-GdOGodntxufByF04iu28xW0zYC0=
async-limiter@~1.0.0: async-limiter@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
@ -839,11 +834,6 @@ big.js@^3.1.3:
resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e"
integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==
binary-extensions@^1.0.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205"
integrity sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=
bluebird@^3.5.0, bluebird@^3.5.x: bluebird@^3.5.0, bluebird@^3.5.x:
version "3.5.1" version "3.5.1"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
@ -878,7 +868,7 @@ braces@^1.8.2:
preserve "^0.2.0" preserve "^0.2.0"
repeat-element "^1.1.2" repeat-element "^1.1.2"
braces@^2.3.0, braces@^2.3.1: braces@^2.3.1:
version "2.3.2" version "2.3.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==
@ -1081,25 +1071,6 @@ chardet@^0.7.0:
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
chokidar@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.3.tgz#dcbd4f6cbb2a55b4799ba8a840ac527e5f4b1176"
integrity sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==
dependencies:
anymatch "^2.0.0"
async-each "^1.0.0"
braces "^2.3.0"
glob-parent "^3.1.0"
inherits "^2.0.1"
is-binary-path "^1.0.0"
is-glob "^4.0.0"
normalize-path "^2.1.1"
path-is-absolute "^1.0.0"
readdirp "^2.0.0"
upath "^1.0.0"
optionalDependencies:
fsevents "^1.1.2"
chownr@^1.0.1, chownr@^1.1.1: chownr@^1.0.1, chownr@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
@ -2555,14 +2526,6 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
fsevents@^1.1.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.2.tgz#4f598f0f69b273188ef4a62ca4e9e08ace314bbf"
integrity sha512-iownA+hC4uHFp+7gwP/y5SzaiUo7m2vpa0dhpzw8YuKtiZsz7cIXsFbXpLEeBM6WuCQyw1MH4RRe6XI8GFUctQ==
dependencies:
nan "^2.9.2"
node-pre-gyp "^0.9.0"
fsevents@^1.2.3: fsevents@^1.2.3:
version "1.2.4" version "1.2.4"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426"
@ -2658,14 +2621,6 @@ glob-parent@^2.0.0:
dependencies: dependencies:
is-glob "^2.0.0" is-glob "^2.0.0"
glob-parent@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=
dependencies:
is-glob "^3.1.0"
path-dirname "^1.0.0"
glob@^5.0.15: glob@^5.0.15:
version "5.0.15" version "5.0.15"
resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
@ -3094,13 +3049,6 @@ is-arrayish@^0.2.1:
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
is-binary-path@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=
dependencies:
binary-extensions "^1.0.0"
is-buffer@^1.1.5: is-buffer@^1.1.5:
version "1.1.6" version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
@ -3211,7 +3159,7 @@ is-extglob@^1.0.0:
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=
is-extglob@^2.1.0, is-extglob@^2.1.1: is-extglob@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
@ -3247,13 +3195,6 @@ is-glob@^2.0.0, is-glob@^2.0.1:
dependencies: dependencies:
is-extglob "^1.0.0" is-extglob "^1.0.0"
is-glob@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=
dependencies:
is-extglob "^2.1.0"
is-glob@^4.0.0: is-glob@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0"
@ -4697,7 +4638,7 @@ mimic-fn@^1.0.0:
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: "minimatch@2 || 3", minimatch@^3.0.3, minimatch@^3.0.4:
version "3.0.4" version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@ -4828,7 +4769,7 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
needle@^2.2.0, needle@^2.2.1: needle@^2.2.1:
version "2.2.1" version "2.2.1"
resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d"
integrity sha512-t/ZswCM9JTWjAdXS9VpvqhI2Ct2sL2MdY4fUXqGJaGBk13ge99ObqRksRTbBE56K+wxUXwwfZYOuZHifFW9q+Q== integrity sha512-t/ZswCM9JTWjAdXS9VpvqhI2Ct2sL2MdY4fUXqGJaGBk13ge99ObqRksRTbBE56K+wxUXwwfZYOuZHifFW9q+Q==
@ -4891,22 +4832,6 @@ node-pre-gyp@^0.10.0:
semver "^5.3.0" semver "^5.3.0"
tar "^4" tar "^4"
node-pre-gyp@^0.9.0:
version "0.9.1"
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.9.1.tgz#f11c07516dd92f87199dbc7e1838eab7cd56c9e0"
integrity sha1-8RwHUW3ZL4cZnbx+GDjqt81WyeA=
dependencies:
detect-libc "^1.0.2"
mkdirp "^0.5.1"
needle "^2.2.0"
nopt "^4.0.1"
npm-packlist "^1.1.6"
npmlog "^4.0.2"
rc "^1.1.7"
rimraf "^2.6.1"
semver "^5.3.0"
tar "^4"
nopt@3.x: nopt@3.x:
version "3.0.6" version "3.0.6"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
@ -5249,11 +5174,6 @@ pascalcase@^0.1.1:
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=
path-dirname@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=
path-exists@^2.0.0: path-exists@^2.0.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
@ -5946,7 +5866,7 @@ raw-loader@~0.5.0, raw-loader@~0.5.1:
resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-0.5.1.tgz#0c3d0beaed8a01c966d9787bf778281252a979aa" resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-0.5.1.tgz#0c3d0beaed8a01c966d9787bf778281252a979aa"
integrity sha1-DD0L6u2KAclm2Xh793goElKpeao= integrity sha1-DD0L6u2KAclm2Xh793goElKpeao=
rc@^1.1.7, rc@^1.2.7: rc@^1.2.7:
version "1.2.8" version "1.2.8"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
@ -6003,7 +5923,7 @@ read-pkg@^4.0.1:
parse-json "^4.0.0" parse-json "^4.0.0"
pify "^3.0.0" pify "^3.0.0"
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@~2.3.6: "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@~2.3.6:
version "2.3.6" version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
@ -6016,16 +5936,6 @@ read-pkg@^4.0.1:
string_decoder "~1.1.1" string_decoder "~1.1.1"
util-deprecate "~1.0.1" util-deprecate "~1.0.1"
readdirp@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78"
integrity sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=
dependencies:
graceful-fs "^4.1.2"
minimatch "^3.0.2"
readable-stream "^2.0.2"
set-immediate-shim "^1.0.1"
realpath-native@^1.0.0: realpath-native@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.0.1.tgz#07f40a0cce8f8261e2e8b7ebebf5c95965d7b633" resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.0.1.tgz#07f40a0cce8f8261e2e8b7ebebf5c95965d7b633"
@ -6458,11 +6368,6 @@ set-blocking@^2.0.0, set-blocking@~2.0.0:
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
set-immediate-shim@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=
set-value@^0.4.3: set-value@^0.4.3:
version "0.4.3" version "0.4.3"
resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1"
@ -7212,11 +7117,6 @@ unset-value@^1.0.0:
has-value "^0.3.1" has-value "^0.3.1"
isobject "^3.0.0" isobject "^3.0.0"
upath@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/upath/-/upath-1.0.5.tgz#02cab9ecebe95bbec6d5fc2566325725ab6d1a73"
integrity sha512-qbKn90aDQ0YEwvXoLqj0oiuUYroLX2lVHZ+b+xwjozFasAOC4GneDq5+OaIG5Zj+jFmbz/uO+f7a9qxjktJQww==
uri-js@^4.2.2: uri-js@^4.2.2:
version "4.2.2" version "4.2.2"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
@ -7327,12 +7227,11 @@ watch@~0.18.0:
exec-sh "^0.2.0" exec-sh "^0.2.0"
minimist "^1.2.0" minimist "^1.2.0"
watchpack@^1.5.0: watchpack@2.0.0-beta.2:
version "1.6.0" version "2.0.0-beta.2"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.0.0-beta.2.tgz#357ed627767dd16ed80500f49c5d4029b49248cb"
integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== integrity sha512-dzFk3sOzcuIC9s+6Qek6Y0cQmk+N8VvUSY1BtB9wCEpfbcUFOQS7tlD1wRnwq2gv+orBYB/td4hO59Z4lg6ELQ==
dependencies: dependencies:
chokidar "^2.0.2"
graceful-fs "^4.1.2" graceful-fs "^4.1.2"
neo-async "^2.5.0" neo-async "^2.5.0"