File tree Expand file tree Collapse file tree 2 files changed +37
-6
lines changed Expand file tree Collapse file tree 2 files changed +37
-6
lines changed Original file line number Diff line number Diff line change @@ -453,12 +453,16 @@ impl Graph {
453
453
// Nodes are only dropped when they do not have incoming connections.
454
454
// But they may have AudioParams feeding into them, these can de dropped too.
455
455
nodes. retain ( |id, n| {
456
- id. 0 < 2 // never drop Listener and Destination node
457
- || !n
458
- . borrow ( )
459
- . outgoing_edges
460
- . iter ( )
461
- . any ( |e| e. other_id == * index)
456
+ // Check if this node was connected to the dropped node. In that case, it is
457
+ // either an AudioParam (which can be dropped), or the AudioListener that feeds
458
+ // into a PannerNode (which can be disconnected).
459
+ let outgoing_edges = & mut n. borrow_mut ( ) . outgoing_edges ;
460
+ let prev_len = outgoing_edges. len ( ) ;
461
+ outgoing_edges. retain ( |e| e. other_id != * index) ;
462
+ let was_connected = outgoing_edges. len ( ) != prev_len;
463
+
464
+ let special = id. 0 < 2 ; // never drop Listener and Destination node
465
+ special || !was_connected
462
466
} ) ;
463
467
}
464
468
} ) ;
Original file line number Diff line number Diff line change @@ -121,3 +121,30 @@ fn test_channels() {
121
121
context. destination ( ) . set_channel_count ( 5 ) ;
122
122
assert_eq ! ( context. destination( ) . channel_count( ) , 5 ) ;
123
123
}
124
+
125
+ #[ test]
126
+ fn test_panner_node_drop_panic ( ) {
127
+ // https://github.com/orottier/web-audio-api-rs/issues/369
128
+ let options = AudioContextOptions {
129
+ sink_id : "none" . into ( ) ,
130
+ ..AudioContextOptions :: default ( )
131
+ } ;
132
+ let context = AudioContext :: new ( options) ;
133
+
134
+ // create a new panner and drop it
135
+ let panner = context. create_panner ( ) ;
136
+ drop ( panner) ;
137
+
138
+ // allow the audio render thread to boot and handle adding and dropping the panner
139
+ std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 200 ) ) ;
140
+
141
+ // creating a new panner node should not crash the render thread
142
+ let mut _panner = context. create_panner ( ) ;
143
+
144
+ // A crashed thread will not fail the test (only if the main thread panics).
145
+ // Instead inspect if there is progression of time in the audio context.
146
+
147
+ let time = context. current_time ( ) ;
148
+ std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 200 ) ) ;
149
+ assert ! ( context. current_time( ) >= time + 0.15 ) ;
150
+ }
You can’t perform that action at this time.
0 commit comments