# UNDF: UNDF-2026-000000311 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();