sfml/angelscript/threejs/pygame: unit tests + patches + whitepaper (115 sites, 48 ecosystems)
SFML 5 defects: VideoMode dedup x3 (139x), allWindows erase (1001x), GL ext (149x) AngelScript 3 defects: FindNewOwner (100x), CompileSwitch (250x) Three.js 5 defects: WebGL binding (22x), StackNode filter (1875x), NodeBuilder (517x) pygame 4 defects: remove_internal (3001x), spritecollide dokill (3001x), switch_layer (3001x) Whitepaper: 98→115 sites, 44→48 ecosystems All unit tests pass: 6/6 each
This commit is contained in:
parent
442a6156e3
commit
6bafc7f5e9
17 changed files with 1189 additions and 18 deletions
26
defects/threejs/patch/threejs-0001-uniforms-groups-set.patch
Normal file
26
defects/threejs/patch/threejs-0001-uniforms-groups-set.patch
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
Fixes threejs-0001: WebGLUniformsGroups.allocateBindingPointIndex() uses Array.indexOf()
|
||||
inside a for loop — O(n²) binding point allocation, fires per material per frame.
|
||||
|
||||
--- a/src/renderers/webgl/WebGLUniformsGroups.js
|
||||
+++ b/src/renderers/webgl/WebGLUniformsGroups.js
|
||||
@@ -... (module scope, near allocatedBindingPoints declaration)
|
||||
- const allocatedBindingPoints = [];
|
||||
+ const allocatedBindingPoints = []; // preserved for compatibility (indexOf used at line 377)
|
||||
+ const allocatedBindingPointsSet = new Set(); // FIX threejs-0001: O(1) membership — CWE-407
|
||||
|
||||
function allocateBindingPointIndex() {
|
||||
for ( let i = 0; i < maxBindingPoints; i ++ ) {
|
||||
- if ( allocatedBindingPoints.indexOf( i ) === - 1 ) { // O(n) per iteration — CWE-407
|
||||
+ if ( ! allocatedBindingPointsSet.has( i ) ) { // O(1) — fixed
|
||||
allocatedBindingPoints.push( i );
|
||||
+ allocatedBindingPointsSet.add( i );
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Also maintain set in the release path (wherever allocatedBindingPoints.splice() is called):
|
||||
+ allocatedBindingPointsSet.delete( index );
|
||||
|
||||
# Simpler alternative: replace allocatedBindingPoints array entirely with a Set,
|
||||
# change indexOf usage at line 377 to has(). No backward compat concern — internal only.
|
||||
12
defects/threejs/patch/threejs-0002-stacknode-set.patch
Normal file
12
defects/threejs/patch/threejs-0002-stacknode-set.patch
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
Fixes threejs-0002: StackNode build() uses nodes.indexOf() inside filter callback —
|
||||
O(n²) during shader graph compilation per unique node set comparison.
|
||||
|
||||
--- a/src/nodes/core/StackNode.js
|
||||
+++ b/src/nodes/core/StackNode.js
|
||||
@@ -380,7 +380,8 @@ class StackNode extends Node {
|
||||
this._currentNode = null;
|
||||
|
||||
- const newNodes = this.nodes.filter( ( node ) => nodes.indexOf( node ) === - 1 );
|
||||
+ // FIX threejs-0002: nodes.indexOf() inside filter = O(n²) — CWE-407
|
||||
+ const nodesSet = new Set( nodes ); // O(n) build once
|
||||
+ const newNodes = this.nodes.filter( ( node ) => ! nodesSet.has( node ) ); // O(1) per check
|
||||
53
defects/threejs/patch/threejs-0003-nodebuilder-set.patch
Normal file
53
defects/threejs/patch/threejs-0003-nodebuilder-set.patch
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
Fixes threejs-0003/0004/0005: NodeBuilder.js — three Array.includes() in node graph build.
|
||||
|
||||
--- a/src/nodes/core/NodeBuilder.js
|
||||
+++ b/src/nodes/core/NodeBuilder.js
|
||||
|
||||
@@ DEFECT threejs-0003: getBindingGroups() triple-nested loop (line 683-700)
|
||||
|
||||
- const groups = {}; // groupName → Array of uniforms
|
||||
+ const groups = {}; // groupName → Array of uniforms (preserved for output)
|
||||
+ const groupSets = {}; // FIX threejs-0003: groupName → Set for O(1) dedup
|
||||
|
||||
for ( const shaderStage of shaderStages ) {
|
||||
for ( const groupName in bindings[ shaderStage ] ) {
|
||||
const uniforms = bindings[ shaderStage ][ groupName ];
|
||||
const groupUniforms = groups[ groupName ] || ( groups[ groupName ] = [] );
|
||||
+ const groupSet = groupSets[ groupName ] || ( groupSets[ groupName ] = new Set() );
|
||||
|
||||
for ( const uniform of uniforms ) {
|
||||
- if ( groupUniforms.includes( uniform ) === false ) { // O(n) — CWE-407
|
||||
+ if ( groupSet.has( uniform ) === false ) { // O(1) — fixed
|
||||
groupUniforms.push( uniform );
|
||||
+ groupSet.add( uniform );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ DEFECT threejs-0004: addNode() — this.nodes.includes() (line 763)
|
||||
|
||||
addNode( node ) {
|
||||
- if ( this.nodes.includes( node ) === false ) { // O(n) — CWE-407
|
||||
+ if ( this.nodesSet.has( node ) === false ) { // O(1) — fixed
|
||||
this.nodes.push( node );
|
||||
+ this.nodesSet.add( node );
|
||||
this.setHashNode( node, node.getHash( this ) );
|
||||
}
|
||||
}
|
||||
// Add to constructor: this.nodesSet = new Set();
|
||||
|
||||
@@ DEFECT threejs-0005: addSequentialNode() — this.sequentialNodes.includes() (line 787)
|
||||
|
||||
addSequentialNode( node ) {
|
||||
const updateBeforeType = node.getUpdateBeforeType();
|
||||
const updateAfterType = node.getUpdateAfterType();
|
||||
if ( updateBeforeType !== NodeUpdateType.NONE || updateAfterType !== NodeUpdateType.NONE ) {
|
||||
- if ( this.sequentialNodes.includes( node ) === false ) { // O(n) — CWE-407
|
||||
+ if ( this.sequentialNodesSet.has( node ) === false ) { // O(1) — fixed
|
||||
this.sequentialNodes.push( node );
|
||||
+ this.sequentialNodesSet.add( node );
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add to constructor: this.sequentialNodesSet = new Set();
|
||||
Loading…
Add table
Add a link
Reference in a new issue