Skip to content

Fix GIF recording crash when a dweet reassigns c - #547

Open
MattNotarangelo wants to merge 1 commit into
lionleaf:masterfrom
MattNotarangelo:fix-recording-clobbered-canvas
Open

Fix GIF recording crash when a dweet reassigns c#547
MattNotarangelo wants to merge 1 commit into
lionleaf:masterfrom
MattNotarangelo:fix-recording-clobbered-canvas

Conversation

@MattNotarangelo

@MattNotarangelo MattNotarangelo commented Apr 27, 2026

Copy link
Copy Markdown

What

A dweet that reassigns the global c (the canvas) breaks GIF recording. Example offender — uses c as a scratch variable inside fillRect:

for(a=i=981;i--;x.fillRect(X,Y,c=8+15*b,c))x.fillStyle=R(T(d=T(X=T(Y=T(T=_=>t--*t*i%a))*9)<40)*d,T(b=(X-a)**2<Y*Y/9-a)*(d+b/6),d*!b*a)

Trying to record this dweet throws:

Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D':
The provided value is not of type '(CSSImageValue or HTMLCanvasElement or ...)'.

…because c=8+15*b falls through to window.c (the dweet body runs as new Function("t", …), where free identifiers resolve via the global object), overwriting the canvas reference with a number. The recording loop then calls gifctx.drawImage(c, …) with that number.

Fix

Capture the canvas in a script-scope const __c next to the existing var c = document.querySelector("#c"). const declarations at script top level live in script scope and are not properties of window, so they're invisible to new Function(…) bodies and can't be reassigned by dweets. The recording path uses __c instead of c.

The dweet's own use of c as a scratch variable still works exactly as before — window.c remains writable, the dweet's math is unchanged, only the page's recording path is hardened.

Diff

3 substantive changes, 7 lines added / 3 removed:

  1. const __c = c; next to the canvas grab
  2. Math.max(__c.width, …) in the GIF-record start handler
  3. gifctx.drawImage(__c, …) in the per-frame recorder

Testing

Tested locally

A dweet that reassigns the global `c` (e.g. using it as a scratch
variable inside an expression like `x.fillRect(X,Y,c=8+15*b,c)`)
overwrites `window.c` with a non-canvas value. Recording then fails
because `gifctx.drawImage(c, ...)` is called with a number instead of
the canvas element, throwing:

    Uncaught TypeError: Failed to execute 'drawImage' on
    'CanvasRenderingContext2D': The provided value is not of type
    '(CSSImageValue or HTMLCanvasElement or ...)'.

Capture the canvas in a script-scope `const __c` (invisible to dweet
`new Function(...)` bodies) and use that for recording. The dweet's
own use of `c` as a scratch variable still works as before; only the
recording path is hardened.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant