Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/base/browser/broadcast.ts
3292 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { mainWindow } from './window.js';
7
import { getErrorMessage } from '../common/errors.js';
8
import { Emitter } from '../common/event.js';
9
import { Disposable, toDisposable } from '../common/lifecycle.js';
10
11
export class BroadcastDataChannel<T> extends Disposable {
12
13
private broadcastChannel: BroadcastChannel | undefined;
14
15
private readonly _onDidReceiveData = this._register(new Emitter<T>());
16
readonly onDidReceiveData = this._onDidReceiveData.event;
17
18
constructor(private readonly channelName: string) {
19
super();
20
21
// Use BroadcastChannel
22
if ('BroadcastChannel' in mainWindow) {
23
try {
24
this.broadcastChannel = new BroadcastChannel(channelName);
25
const listener = (event: MessageEvent) => {
26
this._onDidReceiveData.fire(event.data);
27
};
28
this.broadcastChannel.addEventListener('message', listener);
29
this._register(toDisposable(() => {
30
if (this.broadcastChannel) {
31
this.broadcastChannel.removeEventListener('message', listener);
32
this.broadcastChannel.close();
33
}
34
}));
35
} catch (error) {
36
console.warn('Error while creating broadcast channel. Falling back to localStorage.', getErrorMessage(error));
37
}
38
}
39
40
// BroadcastChannel is not supported. Use storage.
41
if (!this.broadcastChannel) {
42
this.channelName = `BroadcastDataChannel.${channelName}`;
43
this.createBroadcastChannel();
44
}
45
}
46
47
private createBroadcastChannel(): void {
48
const listener = (event: StorageEvent) => {
49
if (event.key === this.channelName && event.newValue) {
50
this._onDidReceiveData.fire(JSON.parse(event.newValue));
51
}
52
};
53
mainWindow.addEventListener('storage', listener);
54
this._register(toDisposable(() => mainWindow.removeEventListener('storage', listener)));
55
}
56
57
/**
58
* Sends the data to other BroadcastChannel objects set up for this channel. Data can be structured objects, e.g. nested objects and arrays.
59
* @param data data to broadcast
60
*/
61
postData(data: T): void {
62
if (this.broadcastChannel) {
63
this.broadcastChannel.postMessage(data);
64
} else {
65
// remove previous changes so that event is triggered even if new changes are same as old changes
66
localStorage.removeItem(this.channelName);
67
localStorage.setItem(this.channelName, JSON.stringify(data));
68
}
69
}
70
}
71
72