From 3171e2266af003fe19463b458486d089e9eae61f Mon Sep 17 00:00:00 2001 From: Chris Lorenzo Date: Mon, 29 Jun 2026 12:36:19 -0400 Subject: [PATCH] fix(shaders): don't re-convert raw canvas shaders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Raw Canvas shaders (CanvasShaderNode) expose `render`, not `program`, so the `!props.shader.program` guard let them fall through and re-run through `convertToShader`, corrupting an already-built shader. WebGL worked only because WebGlShaderNode happens to have `program`. Both backends' shader nodes extend CoreShaderNode, which always carries a `shaderType`, as does the DOM-renderer test fake. A raw StyleEffects props object never does. Switch the guard to a single `'shaderType' in shader` check that covers WebGL, Canvas, and the DOM test path uniformly — and won't need another `|| '...' in shader` clause when a new backend lands. Co-Authored-By: Claude Opus 4.8 --- src/core/elementNode.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/core/elementNode.ts b/src/core/elementNode.ts index edd3df60..bb727338 100644 --- a/src/core/elementNode.ts +++ b/src/core/elementNode.ts @@ -1620,7 +1620,10 @@ export class ElementNode { } // Can you put effects on Text nodes? Need to confirm... - if (SHADERS_ENABLED && props.shader && !props.shader.program) { + // A built shader node (WebGL, Canvas, or the DOM test fake) always has a + // `shaderType`; a raw StyleEffects props object never does. Only convert + // the latter — a built shader is already ready to render. + if (SHADERS_ENABLED && props.shader && !('shaderType' in props.shader)) { props.shader = Config.convertToShader(node, props.shader); } @@ -1692,7 +1695,7 @@ export class ElementNode { } } - if (SHADERS_ENABLED && props.shader && !props.shader.program) { + if (SHADERS_ENABLED && props.shader && !('shaderType' in props.shader)) { props.shader = Config.convertToShader(node, props.shader); }