summaryrefslogtreecommitdiffstats
path: root/node_modules/webpack/lib/ContextModuleFactory.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/webpack/lib/ContextModuleFactory.js')
-rw-r--r--node_modules/webpack/lib/ContextModuleFactory.js262
1 files changed, 262 insertions, 0 deletions
diff --git a/node_modules/webpack/lib/ContextModuleFactory.js b/node_modules/webpack/lib/ContextModuleFactory.js
new file mode 100644
index 0000000..f594112
--- /dev/null
+++ b/node_modules/webpack/lib/ContextModuleFactory.js
@@ -0,0 +1,262 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+
+const asyncLib = require("neo-async");
+const path = require("path");
+
+const {
+ Tapable,
+ AsyncSeriesWaterfallHook,
+ SyncWaterfallHook
+} = require("tapable");
+const ContextModule = require("./ContextModule");
+const ContextElementDependency = require("./dependencies/ContextElementDependency");
+
+/** @typedef {import("./Module")} Module */
+
+const EMPTY_RESOLVE_OPTIONS = {};
+
+module.exports = class ContextModuleFactory extends Tapable {
+ constructor(resolverFactory) {
+ super();
+ this.hooks = {
+ /** @type {AsyncSeriesWaterfallHook<TODO>} */
+ beforeResolve: new AsyncSeriesWaterfallHook(["data"]),
+ /** @type {AsyncSeriesWaterfallHook<TODO>} */
+ afterResolve: new AsyncSeriesWaterfallHook(["data"]),
+ /** @type {SyncWaterfallHook<string[]>} */
+ contextModuleFiles: new SyncWaterfallHook(["files"]),
+ /** @type {SyncWaterfallHook<TODO[]>} */
+ alternatives: new AsyncSeriesWaterfallHook(["modules"])
+ };
+ this._pluginCompat.tap("ContextModuleFactory", options => {
+ switch (options.name) {
+ case "before-resolve":
+ case "after-resolve":
+ case "alternatives":
+ options.async = true;
+ break;
+ }
+ });
+ this.resolverFactory = resolverFactory;
+ }
+
+ create(data, callback) {
+ const context = data.context;
+ const dependencies = data.dependencies;
+ const resolveOptions = data.resolveOptions;
+ const dependency = dependencies[0];
+ this.hooks.beforeResolve.callAsync(
+ Object.assign(
+ {
+ context: context,
+ dependencies: dependencies,
+ resolveOptions
+ },
+ dependency.options
+ ),
+ (err, beforeResolveResult) => {
+ if (err) return callback(err);
+
+ // Ignored
+ if (!beforeResolveResult) return callback();
+
+ const context = beforeResolveResult.context;
+ const request = beforeResolveResult.request;
+ const resolveOptions = beforeResolveResult.resolveOptions;
+
+ let loaders,
+ resource,
+ loadersPrefix = "";
+ const idx = request.lastIndexOf("!");
+ if (idx >= 0) {
+ let loadersRequest = request.substr(0, idx + 1);
+ let i;
+ for (
+ i = 0;
+ i < loadersRequest.length && loadersRequest[i] === "!";
+ i++
+ ) {
+ loadersPrefix += "!";
+ }
+ loadersRequest = loadersRequest
+ .substr(i)
+ .replace(/!+$/, "")
+ .replace(/!!+/g, "!");
+ if (loadersRequest === "") {
+ loaders = [];
+ } else {
+ loaders = loadersRequest.split("!");
+ }
+ resource = request.substr(idx + 1);
+ } else {
+ loaders = [];
+ resource = request;
+ }
+
+ const contextResolver = this.resolverFactory.get(
+ "context",
+ resolveOptions || EMPTY_RESOLVE_OPTIONS
+ );
+ const loaderResolver = this.resolverFactory.get(
+ "loader",
+ EMPTY_RESOLVE_OPTIONS
+ );
+
+ asyncLib.parallel(
+ [
+ callback => {
+ contextResolver.resolve(
+ {},
+ context,
+ resource,
+ {},
+ (err, result) => {
+ if (err) return callback(err);
+ callback(null, result);
+ }
+ );
+ },
+ callback => {
+ asyncLib.map(
+ loaders,
+ (loader, callback) => {
+ loaderResolver.resolve(
+ {},
+ context,
+ loader,
+ {},
+ (err, result) => {
+ if (err) return callback(err);
+ callback(null, result);
+ }
+ );
+ },
+ callback
+ );
+ }
+ ],
+ (err, result) => {
+ if (err) return callback(err);
+
+ this.hooks.afterResolve.callAsync(
+ Object.assign(
+ {
+ addon:
+ loadersPrefix +
+ result[1].join("!") +
+ (result[1].length > 0 ? "!" : ""),
+ resource: result[0],
+ resolveDependencies: this.resolveDependencies.bind(this)
+ },
+ beforeResolveResult
+ ),
+ (err, result) => {
+ if (err) return callback(err);
+
+ // Ignored
+ if (!result) return callback();
+
+ return callback(
+ null,
+ new ContextModule(result.resolveDependencies, result)
+ );
+ }
+ );
+ }
+ );
+ }
+ );
+ }
+
+ resolveDependencies(fs, options, callback) {
+ const cmf = this;
+ let resource = options.resource;
+ let resourceQuery = options.resourceQuery;
+ let recursive = options.recursive;
+ let regExp = options.regExp;
+ let include = options.include;
+ let exclude = options.exclude;
+ if (!regExp || !resource) return callback(null, []);
+
+ const addDirectory = (directory, callback) => {
+ fs.readdir(directory, (err, files) => {
+ if (err) return callback(err);
+ files = cmf.hooks.contextModuleFiles.call(files);
+ if (!files || files.length === 0) return callback(null, []);
+ asyncLib.map(
+ files.filter(p => p.indexOf(".") !== 0),
+ (segment, callback) => {
+ const subResource = path.join(directory, segment);
+
+ if (!exclude || !subResource.match(exclude)) {
+ fs.stat(subResource, (err, stat) => {
+ if (err) {
+ if (err.code === "ENOENT") {
+ // ENOENT is ok here because the file may have been deleted between
+ // the readdir and stat calls.
+ return callback();
+ } else {
+ return callback(err);
+ }
+ }
+
+ if (stat.isDirectory()) {
+ if (!recursive) return callback();
+ addDirectory.call(this, subResource, callback);
+ } else if (
+ stat.isFile() &&
+ (!include || subResource.match(include))
+ ) {
+ const obj = {
+ context: resource,
+ request:
+ "." +
+ subResource.substr(resource.length).replace(/\\/g, "/")
+ };
+
+ this.hooks.alternatives.callAsync(
+ [obj],
+ (err, alternatives) => {
+ if (err) return callback(err);
+ alternatives = alternatives
+ .filter(obj => regExp.test(obj.request))
+ .map(obj => {
+ const dep = new ContextElementDependency(
+ obj.request + resourceQuery,
+ obj.request
+ );
+ dep.optional = true;
+ return dep;
+ });
+ callback(null, alternatives);
+ }
+ );
+ } else {
+ callback();
+ }
+ });
+ } else {
+ callback();
+ }
+ },
+ (err, result) => {
+ if (err) return callback(err);
+
+ if (!result) return callback(null, []);
+
+ callback(
+ null,
+ result.filter(Boolean).reduce((a, i) => a.concat(i), [])
+ );
+ }
+ );
+ });
+ };
+
+ addDirectory(resource, callback);
+ }
+};