From c23d1c0febae41bb0f3da99c47aa259f97dc17ff Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Wed, 13 May 2026 09:37:31 -0400 Subject: [PATCH] Don't use push(...arr) in GeometryBuilder for long vertex arrays --- src/webgl/GeometryBuilder.js | 24 +++++++++++++++--------- test/unit/webgl/p5.RendererGL.js | 17 +++++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/webgl/GeometryBuilder.js b/src/webgl/GeometryBuilder.js index b59548bf67..777feb838e 100644 --- a/src/webgl/GeometryBuilder.js +++ b/src/webgl/GeometryBuilder.js @@ -64,11 +64,15 @@ class GeometryBuilder { } let startIdx = this.geometry.vertices.length; - this.geometry.vertices.push(...this.transformVertices(input.vertices)); - this.geometry.vertexNormals.push( - ...this.transformNormals(input.vertexNormals) - ); - this.geometry.uvs.push(...input.uvs); + for (const v of this.transformVertices(input.vertices)) { + this.geometry.vertices.push(v); + } + for (const vn of this.transformNormals(input.vertexNormals)) { + this.geometry.vertexNormals.push(vn); + } + for (const val of input.uvs) { + this.geometry.uvs.push(val); + } const inputUserVertexProps = input.userVertexProperties; const builtUserVertexProps = this.geometry.userVertexProperties; @@ -103,15 +107,17 @@ class GeometryBuilder { ); } if (this.renderer.states.strokeColor) { - this.geometry.edges.push( - ...input.edges.map(edge => edge.map(idx => idx + startIdx)) - ); + for (const edge of input.edges.map(edge => edge.map(idx => idx + startIdx))) { + this.geometry.edges.push(edge); + } } const vertexColors = [...input.vertexColors]; while (vertexColors.length < input.vertices.length * 4) { vertexColors.push(...this.renderer.states.curFillColor); } - this.geometry.vertexColors.push(...vertexColors); + for (const c of vertexColors) { + this.geometry.vertexColors.push(c); + } } /** diff --git a/test/unit/webgl/p5.RendererGL.js b/test/unit/webgl/p5.RendererGL.js index 1b6b59c78f..aaa229bcec 100644 --- a/test/unit/webgl/p5.RendererGL.js +++ b/test/unit/webgl/p5.RendererGL.js @@ -3089,6 +3089,23 @@ suite('p5.RendererGL', function() { myp5.model(geom); expect(myp5.get(5, 5)).toEqual([255, 0, 0, 255]); }); + test('does not throw with a large number of vertices', function() { + myp5.createCanvas(10, 10, myp5.WEBGL); + // Enough triangles to exceed the ~65k argument limit of Function.prototype.apply, + // which would cause a stack overflow if vertices were spread into push() calls. + const numTriangles = 30000; + expect(() => { + myp5.buildGeometry(() => { + myp5.beginShape(myp5.TRIANGLES); + for (let i = 0; i < numTriangles; i++) { + myp5.vertex(0, 0, 0); + myp5.vertex(1, 0, 0); + myp5.vertex(0, 1, 0); + } + myp5.endShape(); + }); + }).not.toThrow(); + }); }); suite('fontWidth', function() {