fix(meta): define build banner globals as writable - #78
Merged
Conversation
The production build banner defined __dirname, __filename, and require on
globalThis with writable: false. Some dependencies ship an esbuild-style
banner of their own that assigns to globalThis['__dirname'] — @prisma/client
does as of 6.19.3, having previously used a module-local const. Once esbuild
inlines such a runtime into the bundle, that assignment runs in module scope,
where a non-writable property throws rather than failing silently:
TypeError: Cannot assign to read only property '__dirname' of object '#<Object>'
The process dies before the app bootstraps. Flipping the three properties to
writable: true makes those later assignments harmless overwrites; in Prisma's
case with an identical value, since both resolve to the dirname of the
executing bundle.
Adds a regression test that bundles a dependency carrying the upstream banner
and boots the result in a subprocess.
Fixes #77
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The globalThis['__dirname'] assignment in @prisma/client's ESM runtime banner landed in 6.19.0, not 6.19.3 as the linked issue reports; 6.19.3 is just where it was first hit downstream. Verified across 6.19.0 through 6.19.3 and 7.x, all of which carry the assignment, against 6.9.0 which uses a module-local const. Also renames a local in the regression test to satisfy cSpell. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #78 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 62 62
Lines 738 739 +1
Branches 125 125
=========================================
+ Hits 738 739 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
🎉 This PR is included in version 8.4.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the crash reported in #77. The production build banner in
src/meta/build.tsdefined__dirname,__filename, andrequireonglobalThisas non-writable. Some dependencies ship an esbuild-style banner of their own that assigns toglobalThis['__dirname']. Once esbuild inlines such a runtime into our bundle, that assignment executes in module scope — where a non-writable property throws instead of failing silently:The process dies before the app bootstraps. Flipping the three properties to
writable: truemakes those later assignments harmless overwrites — in Prisma's case with an identical value, since both resolve to the dirname of the executing bundle.Why we hadn't seen this
@prisma/clientchanged its ESM runtime banner from a module-localconst __dirnametoglobalThis['__dirname'] = …. libnest pins 6.9.0, which still uses the harmless module-local form, so no build in this repo or in our apps has ever inlined the assigning banner. The bug is latent in every libnest release until an app's import graph pulls in a newer Prisma runtime — which is exactly how it surfaced downstream, on OpenDataCapturemain.One correction to the issue: the assignment landed in 6.19.0, not 6.19.3. Verified against the published tarballs — 6.19.0, 6.19.1, 6.19.2, 6.19.3 and current 7.x all carry it; 6.9.0 does not. 6.19.3 is just where the reporter happened to hit it.
Nothing shielded us:
src/meta/plugins/prisma.tsonly appends aPRISMA_QUERY_ENGINE_LIBRARYdefine and copies the engine binary — the runtime.mjsis not in theexternallist, so it does get inlined.Scope
Only
src/meta/build.tsis affected. Thewritable: falseatsrc/meta/dev.ts:24that the issue also points at is unrelated — it applies to user-suppliedconfig.globals, not__dirname/__filename, and dev mode doesn't bundle, so Prisma's runtime loads as its own module where the assignment succeeds. Left as-is.In practice only
__dirnameis implicated: Prisma's__filenameandrequireare module-scopedconsts that esbuild renames on inline. All three are flipped anyway, since Prisma is the instance at hand and not the only possible one.Testing
Adds
src/meta/__tests__/globals-banner.test.ts, which bundles a dependency carrying the upstream banner and boots the result in a subprocess. Confirmed non-vacuous — reverting the fix makes it fail with the exactTypeErrorfrom the issue.npm run lintclean; full suite passes exceptexample/app.test.ts, which fails identically on a clean tree here (local mongod port conflict, exit code 48) and is unrelated to this change.Closes #77