Most appropriate sub-area of p5.js?
p5.js version
2.3.2 (p5.js Web Editor)
Web browser and version
151.0.7922.138 (Official Build) (arm64)
Operating system
macOS Tahoe 26.6.1
Steps to reproduce this
Steps to reproduce this
bezierOrder() is documented as taking 2 or 3, but the value is stored without validation. Values not in range reach the renderers intact, and the 2D and WebGL converters then handle them differently — none of the two reporting anything to the user.
The sketches below use console.log('bezierOrder() reports:', bezierOrder()) to show that the out-of-range value is stored rather than rejected or clamped.
Control: bezierOrder(3) renders the same curve in both renderers
function setup() {
createCanvas(200, 200);
background(220);
noFill();
stroke(0);
strokeWeight(2);
bezierOrder(3);
beginShape();
vertex(20, 100);
bezierVertex(60, 20);
bezierVertex(100, 180);
bezierVertex(140, 20);
endShape();
}
The same sketch with createCanvas(200, 200, WEBGL) and translate(-100, -100) after background():
The translate(-100, -100) only aligns the WEBGL origin with the 2D one so the coordinates match. The two render identically, so anything that differs below is down to the order value and not the setup.
1. bezierOrder(4) in 2D — draws nothing
function setup() {
createCanvas(200, 200);
background(220);
noFill();
stroke(0);
strokeWeight(2);
bezierOrder(4);
console.log('bezierOrder() reports:', bezierOrder());
beginShape();
vertex(20, 100);
bezierVertex(60, 20);
bezierVertex(100, 180);
bezierVertex(140, 20);
bezierVertex(180, 100);
endShape();
}
Result: blank canvas. No error, no warning. bezierOrder() reports 4.
2. The same sketch in WEBGL — draws a different curve
function setup() {
createCanvas(200, 200, WEBGL);
background(220);
translate(-100, -100);
noFill();
stroke(0);
strokeWeight(2);
bezierOrder(4);
console.log('bezierOrder() reports:', bezierOrder());
beginShape();
vertex(20, 100);
bezierVertex(60, 20);
bezierVertex(100, 180);
bezierVertex(140, 20);
bezierVertex(180, 100);
endShape();
}
Result: a curve is drawn, but it ends near (100, 180) — the third of the five points. The last two control points are silently discarded. Again no error or warning.
3. bezierOrder(1) — silent in 2D, throws in WEBGL
Both sketches again with bezierOrder(1).
In 2D: blank canvas, nothing logged beyond the order value.
In WEBGL:
TypeError: Cannot read properties of undefined (reading 'map')
at Shape.arrayScale
at Shape.evaluateQuadraticBezier
at PrimitiveToVerticesConverter.visitBezierSegment
The friendly error that follows points at a line inside the bundled p5.js and suggests checking a variable the user never wrote. Nothing in the message mentions bezierOrder.
Summary of observed behaviour
| |
2D |
WebGL |
| bezierOrder(4) |
draws nothing, silently |
draws a quadratic through the first 3 points, silently |
| bezierOrder(1) |
draws nothing, silently |
TypeError from p5 internals |
The difference between the two renderers comes from the shape of the code rather than any choice of it. The 2D switch has a natural do-nothing path when no case matches, therefore the segment is skipped. The ternary has no third branch, so anything that isn't 3 is actively evaluated as a quadratic — with the extra control points dropped by the destructure at order 4, and with a missing one at order 1 causing the TypeError.
Notes
There look to be a few possible directions here — validating in bezierOrder(), emitting a friendly error, or adding a default: to both converters — and they differ quite a bit in scope, so I haven't assumed one.
I also noticed custom_shapes.js carries a // TODO shapes refactor comment; if this is already covered by work in progress, happy to close this.
Happy to fix this myself once an approach is agreed on.
Most appropriate sub-area of p5.js?
p5.js version
2.3.2 (p5.js Web Editor)
Web browser and version
151.0.7922.138 (Official Build) (arm64)
Operating system
macOS Tahoe 26.6.1
Steps to reproduce this
Steps to reproduce this
bezierOrder()is documented as taking 2 or 3, but the value is stored without validation. Values not in range reach the renderers intact, and the 2D and WebGL converters then handle them differently — none of the two reporting anything to the user.The sketches below use
console.log('bezierOrder() reports:', bezierOrder())to show that the out-of-range value is stored rather than rejected or clamped.Control:
bezierOrder(3)renders the same curve in both renderersThe same sketch with
createCanvas(200, 200, WEBGL)andtranslate(-100, -100)afterbackground():The
translate(-100, -100)only aligns the WEBGL origin with the 2D one so the coordinates match. The two render identically, so anything that differs below is down to the order value and not the setup.1.
bezierOrder(4)in 2D — draws nothingResult: blank canvas. No error, no warning.
bezierOrder()reports4.2. The same sketch in WEBGL — draws a different curve
Result: a curve is drawn, but it ends near (100, 180) — the third of the five points. The last two control points are silently discarded. Again no error or warning.
3.
bezierOrder(1)— silent in 2D, throws in WEBGLBoth sketches again with
bezierOrder(1).In 2D: blank canvas, nothing logged beyond the order value.
In WEBGL:
The friendly error that follows points at a line inside the bundled p5.js and suggests checking a variable the user never wrote. Nothing in the message mentions
bezierOrder.Summary of observed behaviour
The difference between the two renderers comes from the shape of the code rather than any choice of it. The 2D
switchhas a natural do-nothing path when no case matches, therefore the segment is skipped. The ternary has no third branch, so anything that isn't 3 is actively evaluated as a quadratic — with the extra control points dropped by the destructure at order 4, and with a missing one at order 1 causing the TypeError.Notes
There look to be a few possible directions here — validating in
bezierOrder(), emitting a friendly error, or adding adefault:to both converters — and they differ quite a bit in scope, so I haven't assumed one.I also noticed
custom_shapes.jscarries a// TODO shapes refactorcomment; if this is already covered by work in progress, happy to close this.Happy to fix this myself once an approach is agreed on.