fix(build): keep precompiled Svelte output valid across all of Svelte 5 - #703
Open
berkayozdin wants to merge 1 commit into
Open
fix(build): keep precompiled Svelte output valid across all of Svelte 5#703berkayozdin wants to merge 1 commit into
berkayozdin wants to merge 1 commit into
Conversation
Svelte 5.56 changed the `exclude` argument of the private `rest_props` runtime helper from an array (`exclude.includes(key)`) to a Set (`exclude.has(key)`). Because the Svelte entry points ship precompiled, output built against one side of that change throws on the other, and the published packages abort the render of every Svelte component on Svelte >= 5.56 with `TypeError: exclude.has is not a function`. Route those calls through a wrapper that hands the runtime a Set carrying an `includes` alias, so one build satisfies both contracts across the whole `svelte: ">=5 <6"` peer range. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@berkayozdin is attempting to deploy a commit to the OpenBook Team on Vercel. A member of the Team first needs to authorize it. |
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.
Fixes #702.
Problem
Svelte 5.56.0 changed the
excludeargument of the privaterest_propsruntime helper from an array to aSet(src/internal/client/reactivity/props.js): all four traps ofrest_props_handlerwent fromtarget.exclude.includes(key)totarget.exclude.has(key), and the compiler started hoistingnew Set([...])instead of emitting an array literal at the call site.The
*/svelteentry points ship precompiled component JS.2.14.4was built with the pinnedsvelte@5.50.1, so its output passes an array into a runtime that now calls.has()on it — every EmbedPDF Svelte component throwsTypeError: exclude.has is not a functionat mount on Svelte >= 5.56, and Svelte aborts the render.A rebuild against a newer Svelte alone would only move the failure: the peer range is
svelte: ">=5 <6", and no single precompiled bundle satisfies both sides of the 5.56 boundary.Fix
A small post-compile step in the Svelte build mode (
@embedpdf/build) rewritesto call a wrapper appended to the same module:
A
Setwith anincludesalias satisfies both runtimes: in the non-legacy handlerexcludeis only ever read through.includes/.has— never iterated, sized or mutated — so nothing else needs emulating.legacy_rest_propsis deliberately left alone; its array contract did not change.This keeps
svelte: ">=5 <6"truthful without dropping support for anyone, and it is source-compatible either way: the same rewrite works whether the compiler emits an array (< 5.56) or a hoisted Set (>= 5.56), so it stays correct when you bump the build toolchain.Verification
Same component compiled with each compiler, then mounted (jsdom) against each runtime, asserting rest-prop passthrough and exclusion (the
{...restProps}spread exercises theget,has,ownKeysandgetOwnPropertyDescriptortraps):exclude.has is not a functionexclude.includes is not a functionAlso built for real through the repo's own pipeline (
@embedpdf/build→models→core→plugin-viewport,vite build --mode svelte, on the lockfile'ssvelte@5.50.1):plugin-viewport/dist/svelte/index.jscontains no barerest_propscall site left, andpnpm install --frozen-lockfileis clean.Two notes from working in the repo, unrelated to this PR:
typescript: "latest"at the root now resolves to TypeScript 7, which fails@embedpdf/build'stsc(svelte-dts-resolver.ts) on a fresh install — I pinned 5.9.3 locally to run the build, but left that out of the diff. Andpackages/build'ssvelte: ^5.39.5resolves to 5.56.x on a fresh resolution, so the next lockfile refresh would have shipped Set-form output and broken users below 5.56 — this change makes that safe either way.The longer-term fix
The durable answer is publishing the Svelte layer as uncompiled
.sveltesource (svelte-package+ thesvelteexport condition), so the consuming app's compiler generates internals matching its own Svelte version.svelte/internal/clientis explicitly not a stable API, and 5.56 won't be the last change to it. That's a bigger, all-at-once migration of every*/sveltesubpath (a source-compiled component importing a precompiled one reproduces this exact class of bug), so I kept this PR to the immediate unblock — happy to help with the migration if it's a direction you want to take.I'm happy to add a regression test if you'd like one — I didn't see a test runner wired up in the repo, so I left the verification out of the diff rather than introduce one unasked.
Investigated and prepared with Claude Code; every claim above was verified by running it.