fix(cloudflare/workers): enable strictExecutionOrder to prevent cross-chunk TDZ at startup - #940
Merged
Merged
Conversation
…-chunk TDZ at startup Rolldown's default chunking can split top-level initializer modules (e.g. Drizzle pgTable schemas) away from the classes they read, so workerd evaluates a reader before its imported binding is initialized and the script fails Cloudflare startup validation with ScriptStartupError. strictExecutionOrder wraps cross-chunk modules so evaluation follows ESM semantics regardless of chunk boundaries. Closes #749 Co-authored-by: Cursor <cursoragent@cursor.com>
Contributor
|
Install the packages built from this commit: alchemy bun add alchemy@https://pkg.ing/alchemy/40bf479@alchemy.run/better-auth bun add @alchemy.run/better-auth@https://pkg.ing/@alchemy.run/better-auth/40bf479@alchemy.run/pr-package bun add @alchemy.run/pr-package@https://pkg.ing/@alchemy.run/pr-package/40bf479 |
…build props `build.output` merges over WorkerBundle's default output options so chunking (`codeSplitting`) is controllable per Worker. The #749 regression test now deploys a conventional stack that forces the bad schema/drizzle chunk split through the real Worker build path and asserts it serves. Co-authored-by: Cursor <cursoragent@cursor.com>
john-royal
marked this pull request as ready for review
July 24, 2026 16:57
…est actually regresses The previous two-group split was acyclic (worker -> auth -> drizzle), which plain ESM import order evaluates correctly — the deploy passed even with strictExecutionOrder disabled. The bug needs the cyclic layout from the issue (drizzle left in the entry chunk, worker.js <-> auth-*.js), which requires includeDependenciesRecursively: false and therefore preserveEntrySignatures, now exposed on Worker build props. With the cycle in place, strictExecutionOrder: false restores the exact ScriptStartupError from the issue. Co-authored-by: Cursor <cursoragent@cursor.com>
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.
Closes #749
Rolldown's chunking can split top-level initializer modules (e.g. Drizzle
pgTableschemas) into a chunk that forms a cycle with the entry chunk (worker.js -> auth-*.js -> worker.jswhendrizzle-ormstays in the entry). ESM evaluation then runs the schema chunk before drizzle's class bindings initialize, and the script fails Cloudflare startup validation:The fix enables rolldown's
strictExecutionOrderonWorkerBundle's output options, which wraps cross-chunk modules so evaluation follows ESM semantics regardless of chunk boundaries:const outputOptions: rolldown.OutputOptions = { format: "esm", sourcemap: "hidden", minify: true, keepNames: true, + strictExecutionOrder: true, dir: `.alchemy/bundles/${options.id}`, };Lambda's
codeSplitting: falseapproach is not safe for Workers: Worker bundles rely on chunks to keep dynamically-imported Node/Bun-only modules from evaluating eagerly in workerd.strictExecutionOrderkeeps the chunks and fixes only the evaluation order. This makes the user-sideadvancedChunksgrouping workaround from the issue unnecessary.WorkerProps.buildnow also forwards rolldown output overrides (merged overWorkerBundle's defaults) pluspreserveEntrySignatures— the issue's other ask, chunking was previously uncontrollable per Worker:Group
testpatterns are strings (compiled to regexes by rolldown) — RegExp literals don't survive props serialization.Repro / tests
test/Cloudflare/Workers/DrizzleSchemaChunks.test.ts+fixtures/drizzle-schema-chunks/mirror the reporter's monorepo shape (dbschema/*+ auth package tables with top-levelpgTable(...)cross-imports). The test deploys a stack whoseCloudflare.Workerforces the cyclic chunk layout viabuildoptions. Cloudflare's startup validation runs on exactly those chunks at upload, so the deploy is itself the regression assertion; the test also verifies the cyclic layout on disk (auth-*.jsimporting./worker.jsback) and fetches the worker.The cycle is essential: an acyclic split (e.g. drizzle in its own chunk imported by the schema chunk) evaluates correctly under plain import order and never triggers the bug. Verified live that flipping
strictExecutionOrder: falseon the stack restores the exactScriptStartupErrorabove.Passes live, plus
WorkerBundle.test.ts(CJS-require conversion + deploy integration) andRandomEnvLocal.test.ts(local workerd path) are green with the new default.