Found while building the minified-kernel loop simplification (2c8a8b4 follow-up). Two distinct pre-existing GL failures on the same shape, neither introduced by the de-minification pass:
1. Crash on expression init. astForStatement reads statement.init.declarations unconditionally (src/backend/web-gl/function-node.js:661), so an init that is a SequenceExpression (or any expression, likely) rather than a VariableDeclaration throws Cannot read properties of undefined (reading 'length'):
gpu.createKernel(function (a) {
let s = 0; let i = 0; let j = 0;
for (i = 0, j = 1; i < 4; i++) { s += a[j]; }
return s;
}, { output: [4] });
// cpu: [8, 8, 8, 8] webgl/webgl2/headlessgl: TypeError
2. Declaration/assignment typing disagreement. If the init is instead hoisted to plain assignment statements before the loop (which is how the webgpu backend now handles it), GL emits int user_i = 0; for the declaration — the tracer types it as a loop counter via the for-test heuristic — but the generic assignment path emits user_i = 0.0;, a float literal, and the shader fails with 'assign' : cannot convert from 'const float' to 'lowp int'. Reproduces with hand-written code too:
// let i = 0; i = 0; for (; i < 4; i++) ... → same compile error
Because of (2), the loop-simplification init hoist is gated to the WGSL backend (requiresSequenceFreeForInit); fixing both would let the gate come off and make the shape uniform across backends. Low urgency: esbuild's minifier prefers hoisted declarations with an empty init, so this shape mostly appears in hand-written code.
Found while building the minified-kernel loop simplification (2c8a8b4 follow-up). Two distinct pre-existing GL failures on the same shape, neither introduced by the de-minification pass:
1. Crash on expression init.
astForStatementreadsstatement.init.declarationsunconditionally (src/backend/web-gl/function-node.js:661), so an init that is aSequenceExpression(or any expression, likely) rather than aVariableDeclarationthrowsCannot read properties of undefined (reading 'length'):2. Declaration/assignment typing disagreement. If the init is instead hoisted to plain assignment statements before the loop (which is how the webgpu backend now handles it), GL emits
int user_i = 0;for the declaration — the tracer types it as a loop counter via the for-test heuristic — but the generic assignment path emitsuser_i = 0.0;, a float literal, and the shader fails with'assign' : cannot convert from 'const float' to 'lowp int'. Reproduces with hand-written code too:// let i = 0; i = 0; for (; i < 4; i++) ... → same compile errorBecause of (2), the loop-simplification init hoist is gated to the WGSL backend (
requiresSequenceFreeForInit); fixing both would let the gate come off and make the shape uniform across backends. Low urgency: esbuild's minifier prefers hoisted declarations with an empty init, so this shape mostly appears in hand-written code.