Skip to content

Commit e9c0d06

Browse files
committed
refactor filesystem interfaces
add Compiler.intermediateFileSystem avoid using `path` and `fs` module when possible move `join`, `mkdirp` and `dirname` into utils join and dirname is optional in FileSystem interface remove mkdirp from Filesystem interface
1 parent 224daec commit e9c0d06

39 files changed

+450
-184
lines changed

bin/webpack.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const cli = {
6161

6262
if (!cli.installed) {
6363
const path = require("path");
64-
const fs = require("fs");
64+
const fs = require("graceful-fs");
6565
const readLine = require("readline");
6666

6767
const notify =

lib/Compiler.js

+25-22
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
const parseJson = require("json-parse-better-errors");
99
const asyncLib = require("neo-async");
10-
const path = require("path");
1110
const {
1211
SyncHook,
1312
SyncBailHook,
@@ -25,6 +24,7 @@ const RequestShortener = require("./RequestShortener");
2524
const ResolverFactory = require("./ResolverFactory");
2625
const Stats = require("./Stats");
2726
const Watching = require("./Watching");
27+
const { join, dirname, mkdirp } = require("./util/fs");
2828
const { makePathsRelative } = require("./util/identifier");
2929

3030
/** @typedef {import("webpack-sources").Source} Source */
@@ -36,6 +36,9 @@ const { makePathsRelative } = require("./util/identifier");
3636
/** @typedef {import("./Chunk")} Chunk */
3737
/** @typedef {import("./FileSystemInfo").FileSystemInfoEntry} FileSystemInfoEntry */
3838
/** @typedef {import("./Module")} Module */
39+
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
40+
/** @typedef {import("./util/fs").IntermediateFileSystem} IntermediateFileSystem */
41+
/** @typedef {import("./util/fs").OutputFileSystem} OutputFileSystem */
3942

4043
/**
4144
* @typedef {Object} CompilationParams
@@ -151,7 +154,11 @@ class Compiler {
151154
/** @type {string} */
152155
this.outputPath = "";
153156

157+
/** @type {OutputFileSystem} */
154158
this.outputFileSystem = null;
159+
/** @type {IntermediateFileSystem} */
160+
this.intermediateFileSystem = null;
161+
/** @type {InputFileSystem} */
155162
this.inputFileSystem = null;
156163
this.watchFileSystem = null;
157164

@@ -353,7 +360,8 @@ class Compiler {
353360

354361
const writeOut = err => {
355362
if (err) return callback(err);
356-
const targetPath = this.outputFileSystem.join(
363+
const targetPath = join(
364+
this.outputFileSystem,
357365
outputPath,
358366
targetFile
359367
);
@@ -424,11 +432,9 @@ class Compiler {
424432
};
425433

426434
if (targetFile.match(/\/|\\/)) {
427-
const dir = path.dirname(targetFile);
428-
this.outputFileSystem.mkdirp(
429-
this.outputFileSystem.join(outputPath, dir),
430-
writeOut
431-
);
435+
const fs = this.outputFileSystem;
436+
const dir = dirname(fs, join(fs, outputPath, targetFile));
437+
mkdirp(fs, dir, writeOut);
432438
} else {
433439
writeOut();
434440
}
@@ -448,7 +454,7 @@ class Compiler {
448454
this.hooks.emit.callAsync(compilation, err => {
449455
if (err) return callback(err);
450456
outputPath = compilation.getPath(this.outputPath, {});
451-
this.outputFileSystem.mkdirp(outputPath, emitFiles);
457+
mkdirp(this.outputFileSystem, outputPath, emitFiles);
452458
});
453459
}
454460

@@ -458,14 +464,6 @@ class Compiler {
458464
*/
459465
emitRecords(callback) {
460466
if (!this.recordsOutputPath) return callback();
461-
const idx1 = this.recordsOutputPath.lastIndexOf("/");
462-
const idx2 = this.recordsOutputPath.lastIndexOf("\\");
463-
let recordsOutputPathDirectory = null;
464-
if (idx1 > idx2) {
465-
recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx1);
466-
} else if (idx1 < idx2) {
467-
recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx2);
468-
}
469467

470468
const writeFile = () => {
471469
this.outputFileSystem.writeFile(
@@ -491,10 +489,14 @@ class Compiler {
491489
);
492490
};
493491

492+
const recordsOutputPathDirectory = dirname(
493+
this.outputFileSystem,
494+
this.recordsOutputPath
495+
);
494496
if (!recordsOutputPathDirectory) {
495497
return writeFile();
496498
}
497-
this.outputFileSystem.mkdirp(recordsOutputPathDirectory, err => {
499+
mkdirp(this.outputFileSystem, recordsOutputPathDirectory, err => {
498500
if (err) return callback(err);
499501
writeFile();
500502
});
@@ -630,11 +632,12 @@ class Compiler {
630632
}
631633

632634
createNormalModuleFactory() {
633-
const normalModuleFactory = new NormalModuleFactory(
634-
this.options.context,
635-
this.resolverFactory,
636-
this.options.module || {}
637-
);
635+
const normalModuleFactory = new NormalModuleFactory({
636+
context: this.options.context,
637+
fs: this.inputFileSystem,
638+
resolverFactory: this.resolverFactory,
639+
options: this.options.module || {}
640+
});
638641
this.hooks.normalModuleFactory.call(normalModuleFactory);
639642
return normalModuleFactory;
640643
}

lib/ContextModuleFactory.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@
66
"use strict";
77

88
const asyncLib = require("neo-async");
9-
const path = require("path");
10-
119
const { AsyncSeriesWaterfallHook, SyncWaterfallHook } = require("tapable");
1210
const ContextModule = require("./ContextModule");
1311
const ModuleFactory = require("./ModuleFactory");
1412
const ContextElementDependency = require("./dependencies/ContextElementDependency");
13+
const { join } = require("./util/fs");
1514

1615
/** @typedef {import("./Module")} Module */
1716
/** @typedef {import("./ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */
@@ -195,7 +194,7 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
195194
asyncLib.map(
196195
files.filter(p => p.indexOf(".") !== 0),
197196
(segment, callback) => {
198-
const subResource = path.join(directory, segment);
197+
const subResource = join(fs, directory, segment);
199198

200199
if (!exclude || !subResource.match(exclude)) {
201200
fs.stat(subResource, (err, stat) => {

lib/ContextReplacementPlugin.js

+24-4
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
"use strict";
77

8-
const path = require("path");
98
const ContextElementDependency = require("./dependencies/ContextElementDependency");
9+
const { join } = require("./util/fs");
1010

1111
class ContextReplacementPlugin {
1212
constructor(
@@ -84,7 +84,18 @@ class ContextReplacementPlugin {
8484
if (!result) return;
8585
if (resourceRegExp.test(result.resource)) {
8686
if (newContentResource !== undefined) {
87-
result.resource = path.resolve(result.resource, newContentResource);
87+
if (
88+
newContentResource.startsWith("/") ||
89+
(newContentResource.length > 1 && newContentResource[1] === ":")
90+
) {
91+
result.resource = newContentResource;
92+
} else {
93+
result.resource = join(
94+
compiler.inputFileSystem,
95+
result.resource,
96+
newContentResource
97+
);
98+
}
8899
}
89100
if (newContentRecursive !== undefined) {
90101
result.recursive = newContentRecursive;
@@ -100,8 +111,17 @@ class ContextReplacementPlugin {
100111
if (typeof newContentCallback === "function") {
101112
const origResource = result.resource;
102113
newContentCallback(result);
103-
if (result.resource !== origResource) {
104-
result.resource = path.resolve(origResource, result.resource);
114+
if (
115+
result.resource !== origResource &&
116+
!result.resource.startsWith("/") &&
117+
(result.resource.length <= 1 || result.resource[1] !== ":")
118+
) {
119+
// When the function changed it to an relative path
120+
result.resource = join(
121+
compiler.inputFileSystem,
122+
origResource,
123+
result.resource
124+
);
105125
}
106126
} else {
107127
for (const d of result.dependencies) {

lib/JavascriptParserHelpers.js

-10
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,10 @@
55

66
"use strict";
77

8-
const path = require("path");
9-
108
const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
119
const UnsupportedFeatureWarning = require("./UnsupportedFeatureWarning");
1210
const ConstDependency = require("./dependencies/ConstDependency");
1311

14-
exports.getModulePath = (context, pathToModule) => {
15-
let moduleJsPath = path.relative(context, pathToModule);
16-
if (!/^[A-Z]:/i.test(moduleJsPath)) {
17-
moduleJsPath = "./" + moduleJsPath.replace(/\\/g, "/");
18-
}
19-
return moduleJsPath;
20-
};
21-
2212
exports.toConstantDependency = (parser, value, runtimeRequirements) => {
2313
return function constDependency(expr) {
2414
const dep = new ConstDependency(value, expr.range, runtimeRequirements);

lib/LibManifestPlugin.js

+13-9
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
"use strict";
77

88
const asyncLib = require("neo-async");
9-
const path = require("path");
109
const EntryDependency = require("./dependencies/EntryDependency");
1110
const { compareModulesById } = require("./util/comparators");
11+
const { dirname, mkdirp } = require("./util/fs");
1212

1313
/** @typedef {import("./Compiler")} Compiler */
1414

@@ -99,14 +99,18 @@ class LibManifestPlugin {
9999
? JSON.stringify(manifest, null, 2)
100100
: JSON.stringify(manifest);
101101
const content = Buffer.from(manifestContent, "utf8");
102-
compiler.outputFileSystem.mkdirp(path.dirname(targetPath), err => {
103-
if (err) return callback(err);
104-
compiler.outputFileSystem.writeFile(
105-
targetPath,
106-
content,
107-
callback
108-
);
109-
});
102+
mkdirp(
103+
compiler.intermediateFileSystem,
104+
dirname(compiler.intermediateFileSystem, targetPath),
105+
err => {
106+
if (err) return callback(err);
107+
compiler.intermediateFileSystem.writeFile(
108+
targetPath,
109+
content,
110+
callback
111+
);
112+
}
113+
);
110114
},
111115
callback
112116
);

lib/MultiCompiler.js

+22
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ const MultiWatching = require("./MultiWatching");
1717
/** @typedef {import("./Compiler")} Compiler */
1818
/** @typedef {import("./Stats")} Stats */
1919
/** @typedef {import("./Watching")} Watching */
20+
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
21+
/** @typedef {import("./util/fs").IntermediateFileSystem} IntermediateFileSystem */
22+
/** @typedef {import("./util/fs").OutputFileSystem} OutputFileSystem */
2023

2124
/** @typedef {number} CompilerStatus */
2225

@@ -117,18 +120,37 @@ module.exports = class MultiCompiler {
117120
throw new Error("Cannot read outputFileSystem of a MultiCompiler");
118121
}
119122

123+
get intermediateFileSystem() {
124+
throw new Error("Cannot read outputFileSystem of a MultiCompiler");
125+
}
126+
127+
/**
128+
* @param {InputFileSystem} value the new input file system
129+
*/
120130
set inputFileSystem(value) {
121131
for (const compiler of this.compilers) {
122132
compiler.inputFileSystem = value;
123133
}
124134
}
125135

136+
/**
137+
* @param {OutputFileSystem} value the new output file system
138+
*/
126139
set outputFileSystem(value) {
127140
for (const compiler of this.compilers) {
128141
compiler.outputFileSystem = value;
129142
}
130143
}
131144

145+
/**
146+
* @param {IntermediateFileSystem} value the new intermediate file system
147+
*/
148+
set intermediateFileSystem(value) {
149+
for (const compiler of this.compilers) {
150+
compiler.intermediateFileSystem = value;
151+
}
152+
}
153+
132154
/**
133155
* @param {Compiler} compiler the child compiler
134156
* @param {string[]} dependencies its dependencies

lib/NodeStuffPlugin.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55

66
"use strict";
77

8-
const path = require("path");
98
const {
109
evaluateToString,
1110
expressionIsUnsupported
1211
} = require("./JavascriptParserHelpers");
1312
const CachedConstDependency = require("./dependencies/CachedConstDependency");
13+
const { relative } = require("./util/fs");
1414

1515
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
1616
/** @typedef {import("./Compiler")} Compiler */
@@ -65,7 +65,7 @@ class NodeStuffPlugin {
6565
setConstant("__filename", "/index.js");
6666
} else {
6767
setModuleConstant("__filename", module =>
68-
path.relative(context, module.resource)
68+
relative(compiler.inputFileSystem, context, module.resource)
6969
);
7070
}
7171
parser.hooks.evaluateIdentifier
@@ -84,7 +84,7 @@ class NodeStuffPlugin {
8484
setConstant("__dirname", "/");
8585
} else {
8686
setModuleConstant("__dirname", module =>
87-
path.relative(context, module.context)
87+
relative(compiler.inputFileSystem, context, module.context)
8888
);
8989
}
9090
parser.hooks.evaluateIdentifier

lib/NormalModuleFactory.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"use strict";
77

88
const asyncLib = require("neo-async");
9-
const path = require("path");
109
const {
1110
AsyncSeriesBailHook,
1211
SyncWaterfallHook,
@@ -23,6 +22,7 @@ const BasicMatcherRulePlugin = require("./rules/BasicMatcherRulePlugin");
2322
const RuleSetCompiler = require("./rules/RuleSetCompiler");
2423
const UseEffectRulePlugin = require("./rules/UseEffectRulePlugin");
2524
const { cachedCleverMerge } = require("./util/cleverMerge");
25+
const { join } = require("./util/fs");
2626

2727
/** @typedef {import("./ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */
2828
/** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
@@ -123,7 +123,7 @@ const ruleSetCompiler = new RuleSetCompiler([
123123
]);
124124

125125
class NormalModuleFactory extends ModuleFactory {
126-
constructor(context, resolverFactory, options) {
126+
constructor({ context, fs, resolverFactory, options }) {
127127
super();
128128
this.hooks = Object.freeze({
129129
/** @type {AsyncSeriesBailHook<[ResolveData], TODO>} */
@@ -162,6 +162,7 @@ class NormalModuleFactory extends ModuleFactory {
162162
? options.unsafeCache
163163
: () => true;
164164
this.context = context || "";
165+
this.fs = fs;
165166
this.parserCache = Object.create(null);
166167
this.generatorCache = Object.create(null);
167168
this.hooks.factorize.tapAsync(
@@ -250,7 +251,7 @@ class NormalModuleFactory extends ModuleFactory {
250251
(secondChar === 46 && matchResource.charCodeAt(2) === 47)
251252
) {
252253
// if matchResources startsWith ../ or ./
253-
matchResource = path.join(context, matchResource);
254+
matchResource = join(this.fs, context, matchResource);
254255
}
255256
}
256257
requestWithoutMatchResource = request.substr(

0 commit comments

Comments
 (0)