Skip to content

Commit b58c6c8

Browse files
[Web] Fix Webkit leak caused by the position reporting audio worklets
Co-authored-by: PizzaLovers007 <[email protected]>
1 parent 88b9932 commit b58c6c8

File tree

2 files changed

+20
-21
lines changed

2 files changed

+20
-21
lines changed

platform/web/js/libs/audio.position.worklet.js

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,40 +28,31 @@
2828
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
2929
/**************************************************************************/
3030

31-
const POST_THRESHOLD_S = 0.1;
32-
3331
class GodotPositionReportingProcessor extends AudioWorkletProcessor {
3432
constructor(...args) {
3533
super(...args);
36-
this.lastPostTime = currentTime;
3734
this.position = 0;
38-
this.ended = false;
3935

4036
this.port.onmessage = (event) => {
41-
if (event?.data?.type === 'ended') {
42-
this.ended = true;
37+
switch (event?.data?.type) {
38+
case 'reset':
39+
this.position = 0;
40+
break;
41+
default:
42+
// Do nothing.
4343
}
4444
};
4545
}
4646

4747
process(inputs, _outputs, _parameters) {
48-
if (this.ended) {
49-
return false;
50-
}
51-
5248
if (inputs.length > 0) {
5349
const input = inputs[0];
5450
if (input.length > 0) {
5551
this.position += input[0].length;
52+
this.port.postMessage({ type: 'position', data: this.position });
5653
}
5754
}
5855

59-
// Posting messages is expensive. Let's limit the number of posts.
60-
if (currentTime - this.lastPostTime > POST_THRESHOLD_S) {
61-
this.lastPostTime = currentTime;
62-
this.port.postMessage({ type: 'position', data: this.position });
63-
}
64-
6556
return true;
6657
}
6758
}

platform/web/js/libs/library_godot_audio.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -635,10 +635,14 @@ class SampleNode {
635635
if (this._positionWorklet != null) {
636636
return this._positionWorklet;
637637
}
638-
this._positionWorklet = new AudioWorkletNode(
639-
GodotAudio.ctx,
640-
'godot-position-reporting-processor'
641-
);
638+
if (GodotAudio.audioPositionWorkletNodes.length > 0) {
639+
this._positionWorklet = GodotAudio.audioPositionWorkletNodes.pop();
640+
} else {
641+
this._positionWorklet = new AudioWorkletNode(
642+
GodotAudio.ctx,
643+
'godot-position-reporting-processor'
644+
);
645+
}
642646
this._positionWorklet.port.onmessage = (event) => {
643647
switch (event.data['type']) {
644648
case 'position':
@@ -648,6 +652,7 @@ class SampleNode {
648652
// Do nothing.
649653
}
650654
};
655+
this._positionWorklet.port.postMessage('reset');
651656
return this._positionWorklet;
652657
}
653658

@@ -678,7 +683,7 @@ class SampleNode {
678683
if (this._positionWorklet) {
679684
this._positionWorklet.disconnect();
680685
this._positionWorklet.port.onmessage = null;
681-
this._positionWorklet.port.postMessage({ type: 'ended' });
686+
GodotAudio.audioPositionWorkletNodes.push(this._positionWorklet);
682687
this._positionWorklet = null;
683688
}
684689

@@ -1198,6 +1203,8 @@ const _GodotAudio = {
11981203

11991204
/** @type {Promise} */
12001205
audioPositionWorkletPromise: null,
1206+
/** @type {Array<AudioWorkletNode>} */
1207+
audioPositionWorkletNodes: null,
12011208

12021209
/**
12031210
* Converts linear volume to Db.
@@ -1224,6 +1231,7 @@ const _GodotAudio = {
12241231
GodotAudio.sampleNodes = new Map();
12251232
GodotAudio.buses = [];
12261233
GodotAudio.busSolo = null;
1234+
GodotAudio.audioPositionWorkletNodes = [];
12271235

12281236
const opts = {};
12291237
// If mix_rate is 0, let the browser choose.

0 commit comments

Comments
 (0)