fix(editor): install a structuredClone fallback where lingo is imported (Sentry MONOREPO-EDITOR-FB) - #577
Merged
Merged
Conversation
`@pascal-app/lingo` builds its unit registry at module-eval time and `registerKind` deep-copies each kind definition with `structuredClone`, so a browser without that global (Chromium <98, reported from Honor Browser 9.8 as `ReferenceError: structuredClone is not defined`) fails while the module graph is still evaluating. Sentry MONOREPO-EDITOR-FB. The shim belongs next to the import that makes lingo load-reachable, not in an app entry: `packages/editor` is what the OSS app, the hosted app and every npm consumer all load. An app-level polyfill covers only the app that declares it. Scoped narrowly and documented as such — lingo's kind table is plain JSON, so a JSON round-trip suffices and needs no new dependency. It is not spec-compliant and must not be relied on for real structured-clone semantics.
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.
Supersedes #524, which correctly diagnosed the root cause but installed the polyfill in the wrong place.
Root cause (verified)
@pascal-app/lingo@0.2.0buildsdefaultRegistry = createRegistry(allKinds)at module scope.Registry's constructor callsregisterKindfor each kind, andregisterKinddoesconst copy = structuredClone(def). So on a browser without the global, the throw happens while lingo's module body is still evaluating — no component-level guard can run in time.packages/editor/src/lib/measurement-parser.ts:1imports lingo, which is what makes it load-reachable from the editor bundle. Confirmed by test: importing@pascal-app/lingowithglobalThis.structuredClone = undefinedthrows; with the shim installed it resolves and parses correctly.Sentry MONOREPO-EDITOR-FB (
ReferenceError: structuredClone is not defined, Honor Browser 9.8 / Chromium <98).Why here and not in an app entry
#524 put the polyfill in
apps/editor/instrumentation-client.ts.apps/editorhas no Sentry SDK and noinstrumentation-client.tson main — the app that reports MONOREPO-EDITOR-FB is the hosted app, which has its own instrumentation entry and would never load that file. So the crash would have stayed unfixed for the reporting app, for every npm consumer of@pascal-app/editor, and the Sentry issue would have looked addressed.packages/editoris the layer all three load. Importing the shim for its side effect immediately above the lingo import puts it exactly where the ordering constraint is, and keeps it visible to anyone who later moves that import.Scope
Deliberately a JSON round-trip rather than
@ungap/structured-clone: lingo's kind definitions are plain JSON (strings, numbers, arrays of those), so no dependency is warranted. The file documents that it is not spec-compliant — no Map/Set/Date/ArrayBuffer/cycles, and it throwsTypeErrorrather thanDataCloneError— so nothing else starts leaning on it.packages/core/src/utils/clone-scene-graph.tsalready avoidsstructuredClonefor live runtime nodes for related reasons.Not claimed: that this makes Chromium <98 able to run the editor. Next 16 compiles for a
chrome 111baseline,globals.cssusesoklch()62 times, and the viewer needs WebGL2/WebGPU. This removes one hardReferenceErrorat module load; it is not a browser-support expansion.Verification
bun run checkclean (1589 files)bun run check-types9/9 tasksbun run test12/12 tasks green, including 3 new tests covering native-passthrough, the JSON clone, and lingo importing successfully without the globalNote
Low Risk
Small, guarded polyfill with tests; only affects environments without native
structuredCloneand is scoped to JSON-serializable data lingo needs.Overview
Fixes MONOREPO-EDITOR-FB by ensuring
globalThis.structuredCloneexists before@pascal-app/lingoevaluates. Lingo deep-copies its kind registry at import time; without the global, the editor bundle throws during module load.Adds
structured-clone-fallback.ts, a JSON round-trip shim only when the native API is missing, and imports it for side effect immediately above the lingo import inmeasurement-parser.tsso every@pascal-app/editorconsumer gets the fix—not an app-only entry. The shim is documented as non–spec-compliant and intentionally narrow.Three tests cover native passthrough, JSON cloning behavior, and successful lingo import/parse when
structuredCloneis undefined.Reviewed by Cursor Bugbot for commit 35fc449. Bugbot is set up for automated code reviews on this repo. Configure here.