@@ -134,6 +134,64 @@ export const MAX_WIDTH = "400px";
134134
135135const ICON_URL = `data:image/svg+xml;utf8,${ encodeURIComponent ( WHITE_LOGO_SVG ) } ` ;
136136
137+ const isAtomReactionCycleError = ( error : unknown ) : error is Error =>
138+ error instanceof Error &&
139+ / c a n n o t c h a n g e a t o m s d u r i n g r e a c t i o n c y c l e / i. test ( error . message ) ;
140+
141+ const installSafeHintingSetter = ( {
142+ app,
143+ title,
144+ pageUid,
145+ } : {
146+ app : Editor ;
147+ title ?: string ;
148+ pageUid ?: string ;
149+ } ) : void => {
150+ const originalSetHintingShapes = app . setHintingShapes . bind ( app ) ;
151+
152+ app . setHintingShapes = ( ( shapeIds : TLShapeId [ ] ) => {
153+ try {
154+ return originalSetHintingShapes ( shapeIds ) ;
155+ } catch ( error ) {
156+ if ( ! isAtomReactionCycleError ( error ) ) {
157+ throw error ;
158+ }
159+
160+ internalError ( {
161+ error,
162+ type : "Canvas Atom Reaction Cycle Error" ,
163+ context : {
164+ phase : "setHintingShapes.sync" ,
165+ title,
166+ pageUid,
167+ } ,
168+ sendEmail : false ,
169+ } ) ;
170+
171+ app . timers . setTimeout ( ( ) => {
172+ try {
173+ originalSetHintingShapes ( shapeIds ) ;
174+ } catch ( deferredError ) {
175+ if ( isAtomReactionCycleError ( deferredError ) ) {
176+ internalError ( {
177+ error : deferredError ,
178+ type : "Canvas Atom Reaction Cycle Error" ,
179+ context : {
180+ phase : "setHintingShapes.deferred" ,
181+ title,
182+ pageUid,
183+ } ,
184+ sendEmail : false ,
185+ } ) ;
186+ }
187+ }
188+ } , 0 ) ;
189+
190+ return app ;
191+ }
192+ } ) as Editor [ "setHintingShapes" ] ;
193+ } ;
194+
137195/** Valid file size for asset props; undefined when unknown (e.g. Roam/file API not a real File) to avoid persisting null. */
138196const getValidFileSize = ( file : { size ?: number } ) : number | undefined =>
139197 typeof file . size === "number" && Number . isFinite ( file . size ) && file . size > 0
@@ -704,6 +762,7 @@ const TldrawCanvas = ({ title }: { title: string }) => {
704762 }
705763
706764 appRef . current = app ;
765+ installSafeHintingSetter ( { app, title, pageUid } ) ;
707766
708767 app . on ( "change" , ( entry ) => {
709768 lastActionsRef . current . push ( entry ) ;
0 commit comments