fixes
This commit is contained in:
parent
d6d6fb584d
commit
0ee3a992e8
|
@ -24,8 +24,6 @@ const { parseResource } = require("./util/identifier");
|
|||
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
|
||||
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
|
||||
|
||||
const fileURLToPathTag = Symbol("fileURLToPath");
|
||||
|
||||
class NodeStuffPlugin {
|
||||
/**
|
||||
* @param {NodeOptions} options options
|
||||
|
@ -116,33 +114,20 @@ class NodeStuffPlugin {
|
|||
});
|
||||
};
|
||||
|
||||
let moduleInCache;
|
||||
let functionNameCached;
|
||||
|
||||
const setUrlModuleConstant = (expressionName, fn) => {
|
||||
parser.hooks.expression
|
||||
.for(expressionName)
|
||||
.tap("NodeStuffPlugin", expr => {
|
||||
if (moduleInCache !== parser.state.current) {
|
||||
moduleInCache = parser.state.current;
|
||||
if (parser.isVariableDefined("fileURLToPath")) {
|
||||
for (let i = 0; i < 30; i++) {
|
||||
const name = `fileURLToPath${i}`;
|
||||
if (!parser.isVariableDefined(name)) {
|
||||
functionNameCached = name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
functionNameCached = "fileURLToPath";
|
||||
}
|
||||
parser.tagVariable(functionNameCached, fileURLToPathTag, {});
|
||||
}
|
||||
|
||||
const dep = new ExternalModuleDependency(
|
||||
"url",
|
||||
[{ name: "fileURLToPath", value: functionNameCached }],
|
||||
fn(functionNameCached),
|
||||
[
|
||||
{
|
||||
name: "fileURLToPath",
|
||||
value: "__webpack_fileURLToPath__"
|
||||
}
|
||||
],
|
||||
undefined,
|
||||
fn("__webpack_fileURLToPath__"),
|
||||
expr.range,
|
||||
expressionName
|
||||
);
|
||||
|
@ -205,7 +190,8 @@ class NodeStuffPlugin {
|
|||
case "node-module":
|
||||
setUrlModuleConstant(
|
||||
"__dirname",
|
||||
functionName => `${functionName}(import.meta.url + "/..")`
|
||||
functionName =>
|
||||
`${functionName}(import.meta.url + "/..").slice(0, -1)`
|
||||
);
|
||||
break;
|
||||
case true:
|
||||
|
@ -231,15 +217,6 @@ class NodeStuffPlugin {
|
|||
"require.extensions is not supported by webpack. Use a loader instead."
|
||||
)
|
||||
);
|
||||
|
||||
if (
|
||||
localOptions.__dirname === "node-module" ||
|
||||
localOptions.__filename === "node-module"
|
||||
)
|
||||
parser.hooks.finish.tap(
|
||||
"NodeStuffPlugin",
|
||||
() => (moduleInCache = undefined)
|
||||
);
|
||||
};
|
||||
|
||||
normalModuleFactory.hooks.parser
|
||||
|
|
|
@ -30,6 +30,13 @@ class CachedConstDependency extends NullDependency {
|
|||
this._hashUpdate = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string} hash update
|
||||
*/
|
||||
_createHashUpdate() {
|
||||
return `${this.identifier}${this.range}${this.expression}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the hash
|
||||
* @param {Hash} hash hash to be updated
|
||||
|
@ -38,7 +45,7 @@ class CachedConstDependency extends NullDependency {
|
|||
*/
|
||||
updateHash(hash, context) {
|
||||
if (this._hashUpdate === undefined)
|
||||
this._hashUpdate = "" + this.identifier + this.range + this.expression;
|
||||
this._hashUpdate = this._createHashUpdate();
|
||||
hash.update(this._hashUpdate);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const InitFragment = require("../InitFragment");
|
||||
const makeSerializable = require("../util/makeSerializable");
|
||||
const CachedConstDependency = require("./CachedConstDependency");
|
||||
const ExternalModuleInitFragment = require("./ExternalModuleInitFragment");
|
||||
|
||||
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
|
||||
/** @typedef {import("../Dependency")} Dependency */
|
||||
|
@ -17,40 +17,44 @@ const CachedConstDependency = require("./CachedConstDependency");
|
|||
/** @typedef {import("../util/Hash")} Hash */
|
||||
|
||||
class ExternalModuleDependency extends CachedConstDependency {
|
||||
constructor(module, imports, expression, range, identifier) {
|
||||
constructor(
|
||||
module,
|
||||
importSpecifiers,
|
||||
defaultImport,
|
||||
expression,
|
||||
range,
|
||||
identifier
|
||||
) {
|
||||
super(expression, range, identifier);
|
||||
|
||||
if (imports.length === 0) throw new Error("Imports should be provided");
|
||||
this.importedModule = module;
|
||||
this.imports = imports;
|
||||
this.specifiers = importSpecifiers;
|
||||
this.default = defaultImport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the hash
|
||||
* @param {Hash} hash hash to be updated
|
||||
* @param {UpdateHashContext} context context
|
||||
* @returns {void}
|
||||
* @returns {string} hash update
|
||||
*/
|
||||
updateHash(hash, context) {
|
||||
if (!this._hashUpdate)
|
||||
this._hashUpdate = `${this.importedModule}${JSON.stringify(
|
||||
this.imports
|
||||
)}${this.identifier}${this.range}${this.expression}`;
|
||||
hash.update(this._hashUpdate);
|
||||
_createHashUpdate() {
|
||||
return `${this.importedModule}${JSON.stringify(this.specifiers)}${
|
||||
this.default || "null"
|
||||
}${super._createHashUpdate()}`;
|
||||
}
|
||||
|
||||
serialize(context) {
|
||||
super.serialize(context);
|
||||
const { write } = context;
|
||||
write(this.importedModule);
|
||||
write(this.imports);
|
||||
write(this.specifiers);
|
||||
write(this.default);
|
||||
}
|
||||
|
||||
deserialize(context) {
|
||||
super.deserialize(context);
|
||||
const { read } = context;
|
||||
this.importedModule = read();
|
||||
this.imports = read();
|
||||
this.specifiers = read();
|
||||
this.default = read();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,32 +77,11 @@ ExternalModuleDependency.Template = class ExternalModuleDependencyTemplate exten
|
|||
const dep = /** @type {ExternalModuleDependency} */ (dependency);
|
||||
const { chunkInitFragments } = templateContext;
|
||||
|
||||
let importsString;
|
||||
const namedImports = [];
|
||||
|
||||
for (const { name, value } of dep.imports) {
|
||||
if (name === "default") {
|
||||
importsString = value || dep.importedModule;
|
||||
} else {
|
||||
namedImports.push(value !== name ? `${name} as ${value}` : name);
|
||||
}
|
||||
}
|
||||
|
||||
if (namedImports.length > 0) {
|
||||
const named = `{${namedImports.join(",")}}`;
|
||||
importsString = importsString ? `${importsString}, ${named}` : named;
|
||||
}
|
||||
|
||||
importsString = `import ${importsString} from ${JSON.stringify(
|
||||
dep.importedModule
|
||||
)};`;
|
||||
|
||||
chunkInitFragments.push(
|
||||
new InitFragment(
|
||||
importsString,
|
||||
InitFragment.STAGE_CONSTANTS,
|
||||
0,
|
||||
importsString
|
||||
new ExternalModuleInitFragment(
|
||||
dep.importedModule,
|
||||
dep.specifiers,
|
||||
dep.default
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Ivan Kopeykin @vankop
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const InitFragment = require("../InitFragment");
|
||||
const makeSerializable = require("../util/makeSerializable");
|
||||
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
/** @typedef {import("../Generator").GenerateContext} Context */
|
||||
|
||||
/** @typedef {Map<string, Set<string>>} ImportSpecifiers */
|
||||
|
||||
class ExternalModuleInitFragment extends InitFragment {
|
||||
/**
|
||||
* @param {string} importedModule imported module
|
||||
* @param {Array<{ name: string, value?: string }>|ImportSpecifiers} specifiers import specifiers
|
||||
* @param {string=} defaultImport default import
|
||||
*/
|
||||
constructor(importedModule, specifiers, defaultImport) {
|
||||
super(
|
||||
undefined,
|
||||
InitFragment.STAGE_CONSTANTS,
|
||||
0,
|
||||
`external module imports|${importedModule}|${defaultImport || "null"}`
|
||||
);
|
||||
this.importedModule = importedModule;
|
||||
if (Array.isArray(specifiers)) {
|
||||
/** @type {ImportSpecifiers} */
|
||||
this.specifiers = new Map();
|
||||
for (const { name, value } of specifiers) {
|
||||
let specifiers = this.specifiers.get(name);
|
||||
if (!specifiers) {
|
||||
specifiers = new Set();
|
||||
this.specifiers.set(name, specifiers);
|
||||
}
|
||||
specifiers.add(value || name);
|
||||
}
|
||||
} else {
|
||||
this.specifiers = specifiers;
|
||||
}
|
||||
this.defaultImport = defaultImport;
|
||||
}
|
||||
|
||||
merge(other) {
|
||||
const newSpecifiersMap = new Map(this.specifiers);
|
||||
for (const [name, specifiers] of other.specifiers) {
|
||||
if (newSpecifiersMap.has(name)) {
|
||||
const currentSpecifiers = newSpecifiersMap.get(name);
|
||||
for (const spec of specifiers) currentSpecifiers.add(spec);
|
||||
} else {
|
||||
newSpecifiersMap.set(name, specifiers);
|
||||
}
|
||||
}
|
||||
return new ExternalModuleInitFragment(
|
||||
this.importedModule,
|
||||
newSpecifiersMap,
|
||||
this.defaultImport
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Context} context context
|
||||
* @returns {string|Source} the source code that will be included as initialization code
|
||||
*/
|
||||
getContent({ runtimeRequirements }) {
|
||||
const namedImports = [];
|
||||
|
||||
for (const [name, specifiers] of this.specifiers) {
|
||||
for (const spec of specifiers) {
|
||||
if (spec === name) {
|
||||
namedImports.push(name);
|
||||
} else {
|
||||
namedImports.push(`${name} as ${spec}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let importsString =
|
||||
namedImports.length > 0 ? `{${namedImports.join(",")}}` : "";
|
||||
|
||||
if (this.defaultImport) {
|
||||
importsString = `${this.defaultImport}${
|
||||
importsString ? `, ${importsString}` : ""
|
||||
}`;
|
||||
}
|
||||
|
||||
return `import ${importsString} from ${JSON.stringify(
|
||||
this.importedModule
|
||||
)};`;
|
||||
}
|
||||
|
||||
serialize(context) {
|
||||
super.serialize(context);
|
||||
const { write } = context;
|
||||
write(this.importedModule);
|
||||
write(this.specifiers);
|
||||
write(this.defaultImport);
|
||||
}
|
||||
|
||||
deserialize(context) {
|
||||
super.deserialize(context);
|
||||
const { read } = context;
|
||||
this.importedModule = read();
|
||||
this.specifiers = read();
|
||||
this.defaultImport = read();
|
||||
}
|
||||
}
|
||||
|
||||
makeSerializable(
|
||||
ExternalModuleInitFragment,
|
||||
"webpack/lib/dependencies/ExternalModuleInitFragment"
|
||||
);
|
||||
|
||||
module.exports = ExternalModuleInitFragment;
|
|
@ -47,6 +47,8 @@ module.exports = {
|
|||
require("../dependencies/CachedConstDependency"),
|
||||
"dependencies/ExternalModuleDependency": () =>
|
||||
require("../dependencies/ExternalModuleDependency"),
|
||||
"dependencies/ExternalModuleInitFragment": () =>
|
||||
require("../dependencies/ExternalModuleInitFragment"),
|
||||
"dependencies/CreateScriptUrlDependency": () =>
|
||||
require("../dependencies/CreateScriptUrlDependency"),
|
||||
"dependencies/CommonJsRequireContextDependency": () =>
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
const fileURLToPath = "";
|
||||
const file = __filename;
|
||||
const dir = __dirname;
|
||||
const dir2 = `${__dirname}/`;
|
||||
|
||||
module.exports = { file, dir };
|
||||
module.exports = { file, dir, dir2 };
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import { dir, file } from './cjs/file.js'
|
||||
import { dir, dir2, file } from './cjs/file.js'
|
||||
|
||||
it("should generate correct __dirname", () => {
|
||||
const match = dir.match(/[\\/][^\\/]+[\\/]$/);
|
||||
expect(match && match[0]).toMatch(/[\\/]node-globals[\\/]/);
|
||||
expect(dir).toMatch(/[\\/]node-globals$/);
|
||||
expect(dir2).toMatch(/[\\/]node-globals\/$/);
|
||||
});
|
||||
|
||||
it("should generate correct __filename", () => {
|
||||
const match = file.match(/[\\/][^\\/]+$/);
|
||||
expect(match && match[0]).toMatch(/[\\/]main.mjs$/);
|
||||
expect(file).toMatch(/[\\/]main.mjs$/);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue