🐛 Fix NotReadableError in rasterizer during thumbnail generation

The rasterizer's create-image function was clearing image.src in its
Rx teardown cleanup. This caused the decoded pixel data to be discarded
before downstream operators (drawImage / createImageBitmap) could read
it, resulting in a browser NotReadableError.

Changes:
- Remove image.src = "" from cleanup; the image element will be
  garbage collected naturally. Event handler nulling is kept to break
  circular references.
- Add dimension validation in svg-get-adjusted-size to return nil for
  zero/NaN dimensions instead of producing invalid sizes.
- Add fallback in svg-set-intrinsic-size! to use [max max] when SVG
  dimensions can't be determined.

Error occurred in production (2.16.0-RC10) during thumbnail generation
in the workspace.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
This commit is contained in:
Andrey Antukh 2026-06-11 13:23:50 +00:00 committed by Alonso Torres
parent 5f21ebd08d
commit 2e1839f898

View File

@ -49,7 +49,14 @@
:hint "operation aborted")))
(obj/set! image "src" uri)
(fn []
(obj/set! image "src" "")
;; NOTE: We intentionally do NOT set `image.src = ""` here.
;; Doing so discards the decoded pixel data immediately when this
;; observable completes, but downstream operators (e.g. drawImage /
;; createImageBitmap in `render-image-bitmap`) still need to read
;; the pixel data after the image is emitted. Clearing `src` before
;; the downstream pipeline finishes causes a NotReadableError
;; ("The requested file could not be read..."). The image element
;; will be garbage collected naturally when no references remain.
(obj/set! image "onload" nil)
(obj/set! image "onerror" nil)
(obj/set! image "onabort" nil))))))
@ -57,10 +64,13 @@
(defn- svg-get-adjusted-size
"Returns the adjusted size of an SVG."
[width height max]
(let [ratio (/ width height)]
(if (< width height)
[max (* max (/ 1 ratio))]
[(* max ratio) max])))
;; Guard against zero/NaN dimensions that would cause division by zero
;; or produce invalid sizes, leading to createImageBitmap failures.
(when (and (pos? width) (pos? height))
(let [ratio (/ width height)]
(if (< width height)
[max (* max (/ 1 ratio))]
[(* max ratio) max]))))
(defn- svg-get-size-from-viewbox
"Returns the size of an SVG from its viewbox."
@ -101,7 +111,10 @@
"Sets the intrinsic size of an SVG to the given max size."
[^js svg max]
(let [doc (get-document-element svg)
[w h] (svg-get-size svg max)]
[w h] (or (svg-get-size svg max)
;; Fallback: if we can't determine size from viewBox or
;; intrinsic attributes, use the max size as a square.
[max max])]
(dom/set-attribute! doc "width" (dm/str w))
(dom/set-attribute! doc "height" (dm/str h)))
svg)