@@ -89,19 +89,26 @@ impl Node {
8989 return false ;
9090 }
9191
92- // Drop when the node does not have any inputs and outputs
93- if !self . has_inputs_connected && self . outgoing_edges . is_empty ( ) {
94- return true ;
92+ // When the nodes has no incoming connections:
93+ if !self . has_inputs_connected {
94+ // Drop when the processor reports it won't yield output.
95+ if !tail_time {
96+ return true ;
97+ }
98+
99+ // Drop when the node does not have any inputs and outputs
100+ if self . outgoing_edges . is_empty ( ) {
101+ return true ;
102+ }
95103 }
96104
97- // Drop when the node does not have any inputs connected,
98- // and if the processor reports it won't yield output.
99- if !self . has_inputs_connected && !tail_time {
105+ // Node has no control handle and does have inputs connected.
106+ // Drop when the processor when it has no outpus connected and does not have side effects
107+ if !self . processor . has_side_effects ( ) && self . outgoing_edges . is_empty ( ) {
100108 return true ;
101109 }
102110
103111 // Otherwise, do not drop the node.
104- // (Even if it has no outputs connected, it may have side effects)
105112 false
106113 }
107114
@@ -503,31 +510,14 @@ impl Graph {
503510
504511 // Nodes are only dropped when they do not have incoming connections.
505512 // But they may have AudioParams feeding into them, these can de dropped too.
506- self . nodes . retain ( |id, node| {
507- let node = node. get_mut ( ) ; // unwrap the RefCell
508-
513+ self . nodes . values_mut ( ) . for_each ( |node| {
509514 // Check if this node was connected to the dropped node. In that case, it is
510- // either an AudioParam (which can be dropped), or the AudioListener that feeds
511- // into a PannerNode (which can be disconnected).
512- let was_connected = {
513- let outgoing_edges = & mut node. outgoing_edges ;
514- let prev_len = outgoing_edges. len ( ) ;
515- outgoing_edges. retain ( |e| e. other_id != * index) ;
516- outgoing_edges. len ( ) != prev_len
517- } ;
518-
519- // Retain when
520- // - special node (destination = id 0, listener = id 1), or
521- // - not connected to this dropped node, or
522- // - if the control thread still has a handle to it.
523- let retain = id. 0 < 2 || !was_connected || !node. control_handle_dropped ;
524-
525- if !retain {
526- self . reclaim_id_channel
527- . push ( node. reclaim_id . take ( ) . unwrap ( ) ) ;
528- }
529- retain
530- } )
515+ // either an AudioParam or the AudioListener that feeds into a PannerNode.
516+ // These should be disconnected
517+ node. get_mut ( )
518+ . outgoing_edges
519+ . retain ( |e| e. other_id != * index) ;
520+ } ) ;
531521 }
532522 } ) ;
533523
@@ -819,7 +809,10 @@ mod tests {
819809 node_id : std:: cell:: Cell :: new ( AudioNodeId ( 0 ) ) ,
820810 event_sender : None ,
821811 } ;
822- graph. render ( & scope) ;
812+
813+ // render twice
814+ graph. render ( & scope) ; // node is dropped
815+ graph. render ( & scope) ; // param is dropped
823816
824817 // First the regular node should be dropped, then the audioparam
825818 assert_eq ! ( node_id_consumer. pop( ) . unwrap( ) . 0 , 2 ) ;
@@ -870,6 +863,11 @@ mod tests {
870863 let signal = Box :: new ( TestNode { tail_time : true } ) ;
871864 add_node ( & mut graph, 4 , signal) ;
872865 add_edge ( & mut graph, 4 , 3 ) ;
866+ // Mark the node as 'detached from the control thread', so it is allowed to drop
867+ graph
868+ . nodes
869+ . get_unchecked_mut ( AudioNodeId ( 4 ) )
870+ . control_handle_dropped = true ;
873871
874872 // Render a single quantum
875873 let scope = AudioWorkletGlobalScope {
@@ -879,7 +877,10 @@ mod tests {
879877 node_id : std:: cell:: Cell :: new ( AudioNodeId ( 0 ) ) ,
880878 event_sender : None ,
881879 } ;
882- graph. render ( & scope) ;
880+
881+ // render twice
882+ graph. render ( & scope) ; // node is dropped
883+ graph. render ( & scope) ; // param is dropped
883884
884885 // First the regular node should be dropped, then the audioparam
885886 assert_eq ! ( node_id_consumer. pop( ) . unwrap( ) . 0 , 2 ) ;
@@ -889,7 +890,8 @@ mod tests {
889890 assert ! ( node_id_consumer. pop( ) . is_none( ) ) ;
890891
891892 // Render again
892- graph. render ( & scope) ;
893+ graph. render ( & scope) ; // param signal source is dropped
894+ assert_eq ! ( node_id_consumer. pop( ) . unwrap( ) . 0 , 4 ) ;
893895 }
894896
895897 #[ test]
0 commit comments