Originally posted here:
Related:
- My initial debugging started here: jehna/humanify#343 (comment)
- Upstream pkgroll bug report: privatenumber/pkgroll#115
- Minimal repro repo: https://github.com/0xdevalias/min-repro-pkgroll-2-10-0-regression
Shared on socials/etc here:
- https://x.com/_devalias/status/1894999383890071723
- https://bsky.app/profile/devalias.net/post/3lj5bp4wxdc2t
- https://www.linkedin.com/posts/glenn-devalias-grant_prettier-createrequire-the-argument-filename-activity-7300766878421987330-EZAi
The root cause of this is likely having your esbuild --target set to lower than es2020 (or an equivalent engine version alias (eg. node9)).
If you set your --target to something higher than that, it should transpile correctly, and leave import.meta as is; e.g.
esbuild app.js --target=es2020If you can't change your --target, then you can override the individual feature support using --supported; e.g. to tell esbuild that import.meta is supported:
esbuild app.js --supported:import-meta=trueI came across this issue recently while debugging a strange build failure due to a pkgroll update (which uses esbuild under the hood), which I ended up making a minimal reproduction of, for this bug report:
node:internal/modules/cjs/loader:1762
throw new ERR_INVALID_ARG_VALUE('filename', filename, createRequireError);
^
TypeError [ERR_INVALID_ARG_VALUE]: The argument 'filename' must be a file URL object, file URL string, or absolute path string. Received undefined
at createRequire (node:internal/modules/cjs/loader:1762:11)
at file:///Users/devalias/dev/tmp/humanify/dist/index.mjs:1374:18 {
code: 'ERR_INVALID_ARG_VALUE'
}The root cause of that bug appears as though it may be the same as the issues being seen here.
esbuild transforms import.meta when the --target is below es2020:
These syntax features are conditionally transformed for older browsers depending on the configured language target:
..snip..
- Syntax transform | Transformed when
--targetis below | Example- ..snip..
import.meta|es2020|import.meta- ..snip..
..snip..
Since the repo I was debugging was using es2017, that explains why it wasn't working there.
While I'm not sure what target Sergio was using in their original question, we can see that James was using node16 in theirs.
While many of the usual sources of JavaScript / browser compatibility data don't seem to have entries for import.meta.url / import.meta.filename / import.meta.dirname; we can see that node has supported the basic import.meta since 10.4.0 (which also includes support for import.meta.url according to the node 10.x docs); and from node 20.x, support for import.meta.dirname and import.meta.filename exists; which seems to have been added in this PR, and released in node 21.2.0, which was later backported to node 20.11.0.
We can see that this esbuild compat-table combines data from kangax, caniuse, mdn, etc, along with manual data for things such as es2020's js.ImportMeta. We can also see that this internal/compat/js_table.go file shows ImportMeta support since Node 10.4.0 and ES 2020.
So at least in theory, I would have expected node16 to have worked with import.meta correctly. Looking at the online esbuild playground, we can see that import.meta with --target=node16 worked as far back as esbuild version 0.8.27:
But that esbuild version 0.8.26 didn't support it:
Options:
{target: ['node16']}Input:
console.log(import.meta.url)Output:
const import_meta = {};
console.log(import_meta.url); > <stdin>:1:12: warning: "import.meta" is not available in the configured target environment and will be empty
1 │ console.log(import.meta.url)
╵ ~~~~~~~~~~~For these versions we need to go back to esbuild's CHANGELOG-2020.md; where in version 0.8.27 we see:
Mark
import.metaas supported innode10.4+(#626)It was previously marked as unsupported due to a typo in
esbuild's compatibility table, which meantesbuildgenerated a shim forimport.metaeven when it's not necessary. It should now be marked as supported in node10.4and above so the shim will no longer be included when using a sufficiently newtargetenvironment such as--target=node10.4.
If we can't set a --target to es2020 or above; then we can still override the feature at an individual level using esbuild's --supported option:
If you need to customize the set of supported syntax features at the individual feature level in addition to or instead of what
targetprovides, you can do that with thesupportedsetting.
This setting lets you customize
esbuild's set of unsupported syntax features at the individual syntax feature level. Usually this is configured for you when you use thetargetsetting, which you should typically be using instead of this setting. If thetargetis specified in addition to this setting, this setting will override whatever is specified by thetarget.
Syntax features are specified using
esbuild-specific feature names. The full set of feature names is as follows:JavaScript:
- ..snip..
- import-meta
- ..snip..
So you could tell esbuild that import.meta is supported and should be left as-is with:
esbuild app.js --supported:import-meta=trueUsing the online esbuild playground, we can see that when we set target to less than es2020, we get a warning:
Options:
{target: ['es2019']}Input:
console.log(import.meta.url)Output:
const import_meta = {};
console.log(import_meta.url);▲ [WARNING] "import.meta" is not available in the configured target environment ("es2019") and will be empty [empty-import-meta]
<stdin>:1:12:
1 │ console.log(import.meta.url)
╵ ~~~~~~~~~~~But if we change that to also use supported, it works as expected and there is no warning:
Options:
{target: ['es2019'], supported: {'import-meta': true}}Input:
console.log(import.meta.url)Output:
console.log(import.meta.url);As for esbuild's import.meta shim being an empty object, there are a number of issues on the esbuild GitHub repo about this/related, including:
import.meta.urlsupport (#1492)import.metais empty (#2249)- has a comment that links to
tsup's polyfill forimport.meta.url
- has a comment that links to
import.meta.urltranspile. (#2441)- Support for
import.meta.resolve(...)(#2866) import.metabehavior inconsistency between targets (#2294)- etc
- https://github.com/0xdevalias
- https://gist.github.com/0xdevalias
- https://github.com/0xdevalias/chatgpt-source-watch : Analyzing the evolution of ChatGPT's codebase through time with curated archives and scripts.
- Deobfuscating / Unminifying Obfuscated Web App Code (0xdevalias' gist)
- Reverse Engineering Webpack Apps (0xdevalias gist)
- React Server Components, Next.js v13+, and Webpack: Notes on Streaming Wire Format (
__next_f, etc) (0xdevalias' gist)) - Fingerprinting Minified JavaScript Libraries / AST Fingerprinting / Source Code Similarity / Etc (0xdevalias' gist)
- Bypassing Cloudflare, Akamai, etc (0xdevalias' gist)
- Debugging Electron Apps (and related memory issues) (0xdevalias' gist)
- devalias' Beeper CSS Hacks (0xdevalias' gist)
- Reverse Engineering Golang (0xdevalias' gist)
- Reverse Engineering on macOS (0xdevalias' gist)
- Editor Frameworks and Collaborative Editing/Conflict Resolution Tech (0xdevalias' gist)

