move to nodestuff

This commit is contained in:
avivkeller 2025-10-07 13:08:06 -04:00
parent 015468be71
commit 5cc506d5b6
No known key found for this signature in database
GPG Key ID: FB5D4500627F7285
3 changed files with 108 additions and 67 deletions

View File

@ -16,7 +16,8 @@ const ConstDependency = require("./dependencies/ConstDependency");
const ExternalModuleDependency = require("./dependencies/ExternalModuleDependency");
const {
evaluateToString,
expressionIsUnsupported
expressionIsUnsupported,
toConstantDependency
} = require("./javascript/JavascriptParserHelpers");
const { relative } = require("./util/fs");
const { parseResource } = require("./util/identifier");
@ -102,6 +103,57 @@ class NodeStuffPlugin {
});
}
/**
* Helper function to define import.meta properties
* @param {string} propertyName The full property name (e.g., "import.meta.dirname")
* @param {() => string} valueGetter Function to get the property value
* @param {string=} warning The warning, if applicable
*/
const defineImportMetaProperty = (
propertyName,
valueGetter,
warning
) => {
// typeof import.meta.property
parser.hooks.typeof
.for(propertyName)
.tap(
PLUGIN_NAME,
toConstantDependency(parser, JSON.stringify("string"))
);
// import.meta.property expression
parser.hooks.expression
.for(propertyName)
.tap(PLUGIN_NAME, (expr) => {
const dep = new ConstDependency(
JSON.stringify(valueGetter()),
/** @type {Range} */ (expr.range)
);
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
parser.state.module.addPresentationalDependency(dep);
if (warning) {
parser.state.module.addWarning(
new NodeStuffInWebError(dep.loc, propertyName, warning)
);
}
return true;
});
// evaluateTypeof
parser.hooks.evaluateTypeof
.for(propertyName)
.tap(PLUGIN_NAME, evaluateToString("string"));
// evaluateIdentifier
parser.hooks.evaluateIdentifier
.for(propertyName)
.tap(PLUGIN_NAME, (expr) =>
evaluateToString(valueGetter())(expr)
);
};
/**
* @param {string} expressionName expression name
* @param {(module: NormalModule) => string} fn function
@ -211,6 +263,35 @@ class NodeStuffPlugin {
return evaluateToString(resource.path)(expr);
});
}
// Handle import.meta.filename
if (localOptions.__filename) {
switch (localOptions.__filename) {
case "mock":
defineImportMetaProperty(
"import.meta.filename",
() => "/index.js"
);
break;
case "warn-mock":
defineImportMetaProperty(
"import.meta.filename",
() => "/index.js",
"import.meta.filename is a Node.js feature and isn't available in browsers."
);
break;
case true:
defineImportMetaProperty("import.meta.filename", () =>
relative(
/** @type {InputFileSystem} */ (compiler.inputFileSystem),
context,
parser.state.module.resource
)
);
break;
}
}
if (localOptions.__dirname) {
switch (localOptions.__dirname) {
case "mock":
@ -254,6 +335,31 @@ class NodeStuffPlugin {
)(expr);
});
}
// Handle import.meta.dirname
if (localOptions.__dirname) {
switch (localOptions.__dirname) {
case "mock":
defineImportMetaProperty("import.meta.dirname", () => "/");
break;
case "warn-mock":
defineImportMetaProperty(
"import.meta.dirname",
() => "/",
"import.meta.dirname is a Node.js feature and isn't available in browsers."
);
break;
case true:
defineImportMetaProperty("import.meta.dirname", () =>
relative(
/** @type {InputFileSystem} */ (compiler.inputFileSystem),
context,
/** @type {string} */ (parser.state.module.context)
)
);
break;
}
}
parser.hooks.expression
.for("require.extensions")
.tap(

View File

@ -19,7 +19,6 @@ const {
evaluateToString,
toConstantDependency
} = require("../javascript/JavascriptParserHelpers");
const { parseResource } = require("../util/identifier");
const memoize = require("../util/memoize");
const propertyAccess = require("../util/propertyAccess");
const ConstDependency = require("./ConstDependency");
@ -197,68 +196,6 @@ class ImportMetaPlugin {
.setRange(/** @type {Range} */ (expr.range))
);
// import.meta.dirname
parser.hooks.typeof
.for("import.meta.dirname")
.tap(
PLUGIN_NAME,
toConstantDependency(parser, JSON.stringify("string"))
);
parser.hooks.expression
.for("import.meta.dirname")
.tap(PLUGIN_NAME, (expr) => {
const dep = new ConstDependency(
JSON.stringify(
/** @type {string} */ (parser.state.module.context)
),
/** @type {Range} */ (expr.range)
);
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
parser.state.module.addPresentationalDependency(dep);
return true;
});
parser.hooks.evaluateTypeof
.for("import.meta.dirname")
.tap(PLUGIN_NAME, evaluateToString("string"));
parser.hooks.evaluateIdentifier
.for("import.meta.dirname")
.tap(PLUGIN_NAME, (expr) =>
evaluateToString(
/** @type {string} */
(parser.state.module.context)
)(expr)
);
// import.meta.filename
parser.hooks.typeof
.for("import.meta.filename")
.tap(
PLUGIN_NAME,
toConstantDependency(parser, JSON.stringify("string"))
);
parser.hooks.expression
.for("import.meta.filename")
.tap(PLUGIN_NAME, (expr) => {
const resource = parseResource(parser.state.module.resource);
const dep = new ConstDependency(
JSON.stringify(resource.path),
/** @type {Range} */ (expr.range)
);
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
parser.state.module.addPresentationalDependency(dep);
return true;
});
parser.hooks.evaluateTypeof
.for("import.meta.filename")
.tap(PLUGIN_NAME, evaluateToString("string"));
parser.hooks.evaluateIdentifier
.for("import.meta.filename")
.tap(PLUGIN_NAME, (expr) =>
new BasicEvaluatedExpression()
.setString(parseResource(parser.state.module.resource).path)
.setRange(/** @type {Range} */ (expr.range))
);
// import.meta.webpack
parser.hooks.typeof
.for("import.meta.webpack")

View File

@ -1,5 +1,4 @@
const fs = require("fs");
const path = require("path");
const path = require("path/posix");
it("should be a string (import.meta.filename)", function() {
expect(import.meta.filename).toBeTypeOf("string");
@ -16,5 +15,4 @@ it("should be a string (import.meta.dirname)", function() {
it("should be able to be used to get this file", function() {
const filePath = path.join(import.meta.dirname, "index.js");
expect(filePath).toBe(import.meta.filename);
expect(fs.existsSync(filePath)).toBe(true);
});