feat: Support import.meta.filename/dirname/resolve#10573
feat: Support import.meta.filename/dirname/resolve#10573magic-akari wants to merge 8 commits intoweb-infra-dev:chore/add-import-meta-desctructuring-hookfrom
import.meta.filename/dirname/resolve#10573Conversation
✅ Deploy Preview for rspack canceled.Built without sensitive environment variables
|
CodSpeed Performance ReportMerging #10573 will not alter performanceComparing Summary
|
|
done. |
|
On Windows CI, - expect('file://<TEST_TOOLS_ROOT>/tests/builtinCases/plugin-javascript/import-meta/index.js').toBe(url);
- expect('file://<TEST_TOOLS_ROOT>/tests/builtinCases/plugin-javascript/import-meta/index.js').toBe(url);
- expect("my" + 'file://<TEST_TOOLS_ROOT>/tests/builtinCases/plugin-javascript/import-meta/index.js').toBe("my" + url);
+ expect('file:///<TEST_TOOLS_ROOT>/tests/builtinCases/plugin-javascript/import-meta/index.js').toBe(url);
+ expect('file:///<TEST_TOOLS_ROOT>/tests/builtinCases/plugin-javascript/import-meta/index.js').toBe(url);
+ expect("my" + 'file:///<TEST_TOOLS_ROOT>/tests/builtinCases/plugin-javascript/import-meta/index.js').toBe("my" + url); |
import.meta.filename and import.meta.dirnameimport.meta.filename/dirname/resolve
52a12d7 to
5837f13
Compare
| "./tests/builtinCases/plugin-javascript/import-meta/index.js", | ||
| ).toString(); | ||
|
|
||
| const filename = "/index.js"; |
There was a problem hiding this comment.
It appears that __filename is handled by crates/rspack_plugin_rstest/src/parser_plugin.rs using a different strategy.
| .to_string() | ||
| } | ||
|
|
||
| // This is the same as the url.fileURLToPath() of the import.meta.url |
There was a problem hiding this comment.
Using PathBuf::from directly might be more efficient. However, considering that the Resource might contain a query string – which can introduce various edge cases like ./x.js?foo=/../y.js – processing it through a URL parser is safer.
rspack/crates/rspack_loader_runner/src/content.rs
Lines 114 to 115 in 561581e
|
@LingyuCoder @h-a-n-a cc~ |
|
@LingyuCoder can you help to review this PR? |
|
LGTM, im not sure if a new experiment option should be added @chenjiahan |
|
@LingyuCoder Can you help to check this issue (webpack/webpack#18320) and provide some advice? |
I just think it should align with the behavior of Node.js and adding an new experiment option to facilitate modifications in case of inconsistent behaviors after the implementation of webpack in the future. |
|
Since this is not a very stable specification, it's uncertain whether it is consistent across bundlers and Node.js. Considering that rspack should currently align with webpack in this behavior, you might consider submitting a PR to webpack and getting their advice too 😊 |
|
A PR has now been merged in webpack: |
561581e to
b3ab478
Compare
There was a problem hiding this comment.
Pull Request Overview
This PR adds support for import.meta.filename, import.meta.dirname, and import.meta.resolve properties to rspack's JavaScript plugin, extending the existing import.meta API implementation to provide Node.js-compatible functionality.
Key Changes:
- Adds three new
import.metaproperties:filename,dirname, andresolvewith full parsing and code generation support - Implements dependency tracking for
import.meta.resolve()calls via newImportMetaResolveDependencyandImportMetaResolveHeaderDependencytypes - Refactors existing conditional logic to use more idiomatic
matchexpressions
Reviewed Changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
packages/rspack-test-tools/tests/builtinCases/plugin-javascript/import-meta/rspack.config.js |
Adds test configuration enabling Node.js externals preset |
packages/rspack-test-tools/tests/builtinCases/plugin-javascript/import-meta/index.js |
Adds comprehensive test cases for the new import.meta properties |
packages/rspack-test-tools/tests/builtinCases/plugin-javascript/import-meta/__snapshots__/output.snap.txt |
Expected output snapshot showing code transformation results |
crates/rspack_plugin_javascript/src/visitors/dependency/util.rs |
Adds constant definitions for new expression names |
crates/rspack_plugin_javascript/src/plugin/impl_plugin_for_js_plugin.rs |
Registers dependency factories and templates for import.meta.resolve |
crates/rspack_plugin_javascript/src/parser_plugin/import_meta_plugin.rs |
Core implementation of new properties and resolve functionality |
crates/rspack_plugin_javascript/src/dependency/esm/mod.rs |
Exports new dependency types |
crates/rspack_plugin_javascript/src/dependency/esm/import_meta_resolve_header_dependency.rs |
Dependency for replacing import.meta.resolve calls with comments |
crates/rspack_plugin_javascript/src/dependency/esm/import_meta_resolve_dependency.rs |
Dependency for resolving module paths in import.meta.resolve |
crates/rspack_plugin_circular_dependencies/src/lib.rs |
Updates circular dependency checker to recognize ImportMetaResolve |
crates/rspack_core/src/dependency/dependency_type.rs |
Adds ImportMetaResolve dependency type |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| parser.add_dependency(import_meta_resolve_header_dependency); | ||
| } else { | ||
| self.process_import_meta_resolve_item(parser, ¶m); | ||
| parser.add_dependency(import_meta_resolve_header_dependency); | ||
| } |
There was a problem hiding this comment.
The import_meta_resolve_header_dependency is added in both branches of the conditional. This code duplication can be eliminated by moving the parser.add_dependency(import_meta_resolve_header_dependency) call after the if-else block to reduce redundancy.
| parser.add_dependency(import_meta_resolve_header_dependency); | |
| } else { | |
| self.process_import_meta_resolve_item(parser, ¶m); | |
| parser.add_dependency(import_meta_resolve_header_dependency); | |
| } | |
| } else { | |
| self.process_import_meta_resolve_item(parser, ¶m); | |
| } | |
| parser.add_dependency(import_meta_resolve_header_dependency); |
| Url::from_file_path(parser.resource_data.resource()) | ||
| .expect("should be a path") | ||
| .to_file_path() | ||
| .expect("should be a path") | ||
| .to_string_lossy() | ||
| .into_owned() |
There was a problem hiding this comment.
The import_meta_filename method performs Url::from_file_path() followed by to_file_path(), which converts a path to URL and back to a path. This is unnecessarily complex and potentially lossy. Consider directly using parser.resource_data.resource().to_string_lossy().into_owned() instead.
| Url::from_file_path(parser.resource_data.resource()) | |
| .expect("should be a path") | |
| .to_file_path() | |
| .expect("should be a path") | |
| .to_string_lossy() | |
| .into_owned() | |
| parser.resource_data.resource().to_string_lossy().into_owned() |
| fn import_meta_dirname(&self, parser: &JavascriptParser) -> String { | ||
| Url::from_file_path(parser.resource_data.resource()) | ||
| .expect("should be a path") | ||
| .to_file_path() | ||
| .expect("should be a path") | ||
| .parent() | ||
| .expect("should have a parent") | ||
| .to_string_lossy() | ||
| .into_owned() | ||
| } |
There was a problem hiding this comment.
Similar to import_meta_filename, this method performs unnecessary URL conversion roundtrip. Consider directly using parser.resource_data.resource().parent().expect(\"should have a parent\").to_string_lossy().into_owned() to simplify the logic.
| const url = pathToFileURL( | ||
| "./tests/builtinCases/plugin-javascript/import-meta/index.js", | ||
| ).toString(); |
There was a problem hiding this comment.
Unused variable url.
| const url = pathToFileURL( | |
| "./tests/builtinCases/plugin-javascript/import-meta/index.js", | |
| ).toString(); |
|
Hi team! 👋 I noticed that webpack's implementation for ✅ What's WorkingI've successfully migrated the member access handling to // Now in NodeStuffPlugin
import.meta.dirname // ✅ Respects node.dirname config
import.meta.filename // ✅ Respects node.filename configThis works well and follows webpack's pattern using the unified Supported Node OptionsThe implementation reuses the existing NodeStuffPlugin logic for CommonJS
|
b3ab478 to
6b6c9cf
Compare
Since the |
|
I'm ok with the current implementation, only thing need to change is ImportMetaPlugin need to read the config from |
d0c1d94 to
71a53d0
Compare
71a53d0 to
944b84e
Compare
|
Just to follow up, is the |
This case is still in use and it should be a test case specific to rspack. |
Webpack
|
| Configuration | import.meta.dirname Output |
|---|---|
node.__dirname: true |
"/relative/path" (from context) |
node.__dirname: false |
import.meta.dirname (preserved) |
node.__dirname: "mock" |
"/" |
node.__dirname: "warn-mock" |
"/" + warning |
node.__dirname: "node-module" |
dirname(fileURLToPath(import.meta.url)) |
node.__dirname: "eval-only" |
import.meta.dirname (ESM) / __dirname (CJS) |
node: false |
import.meta.dirname (preserved) |
parser.javascript.node: false |
import.meta.dirname (preserved) |
|
Hi @LingyuCoder, I expected this PR would automatically rebase onto main after chore/add-import-meta-desctructuring-hook was merged, but it seems to have been closed unexpectedly instead. |
|
Never mind! I've already opened a new PR(#12317) instead. Thanks anyway! |
Summary
import.meta.resolve+ Node Specific Meta Values #8008Checklist