Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
titaniumnetwork-dev
GitHub Repository: titaniumnetwork-dev/Ultraviolet
Path: blob/main/src/client/message.js
304 views
1
import EventEmitter from "events";
2
import HookEvent from "./hook.js";
3
4
/**
5
* @typedef {import('./index').default} Ultraviolet
6
*/
7
8
class MessageApi extends EventEmitter {
9
/**
10
*
11
* @param {Ultraviolet} ctx
12
*/
13
constructor(ctx) {
14
super();
15
this.ctx = ctx;
16
this.window = this.ctx.window;
17
this.postMessage = this.window.postMessage;
18
this.MessageEvent = this.window.MessageEvent || {};
19
this.MessagePort = this.window.MessagePort || {};
20
this.mpProto = this.MessagePort.prototype || {};
21
this.mpPostMessage = this.mpProto.postMessage;
22
this.messageProto = this.MessageEvent.prototype || {};
23
this.messageData = ctx.nativeMethods.getOwnPropertyDescriptor(
24
this.messageProto,
25
"data"
26
);
27
this.messageOrigin = ctx.nativeMethods.getOwnPropertyDescriptor(
28
this.messageProto,
29
"origin"
30
);
31
}
32
overridePostMessage() {
33
this.ctx.override(this.window, "postMessage", (target, that, args) => {
34
if (!args.length) return target.apply(that, args);
35
36
let message;
37
let origin;
38
let transfer;
39
40
if (!this.ctx.worker) {
41
[message, origin, transfer = []] = args;
42
} else {
43
[message, transfer = []] = args;
44
}
45
46
const event = new HookEvent(
47
{ message, origin, transfer, worker: this.ctx.worker },
48
target,
49
that
50
);
51
this.emit("postMessage", event);
52
53
if (event.intercepted) return event.returnValue;
54
return this.ctx.worker
55
? event.target.call(event.that, event.data.message, event.data.transfer)
56
: event.target.call(
57
event.that,
58
event.data.message,
59
event.data.origin,
60
event.data.transfer
61
);
62
});
63
}
64
wrapPostMessage(obj, prop, noOrigin = false) {
65
return this.ctx.wrap(obj, prop, (target, that, args) => {
66
if (this.ctx.worker ? !args.length : 2 > args)
67
return target.apply(that, args);
68
let message;
69
let origin;
70
let transfer;
71
72
if (!noOrigin) {
73
[message, origin, transfer = []] = args;
74
} else {
75
[message, transfer = []] = args;
76
origin = null;
77
}
78
79
const event = new HookEvent(
80
{ message, origin, transfer, worker: this.ctx.worker },
81
target,
82
obj
83
);
84
this.emit("postMessage", event);
85
86
if (event.intercepted) return event.returnValue;
87
return noOrigin
88
? event.target.call(event.that, event.data.message, event.data.transfer)
89
: event.target.call(
90
event.that,
91
event.data.message,
92
event.data.origin,
93
event.data.transfer
94
);
95
});
96
}
97
overrideMessageOrigin() {
98
this.ctx.overrideDescriptor(this.messageProto, "origin", {
99
get: (target, that) => {
100
const event = new HookEvent({ value: target.call(that) }, target, that);
101
this.emit("origin", event);
102
103
if (event.intercepted) return event.returnValue;
104
return event.data.value;
105
},
106
});
107
}
108
overrideMessageData() {
109
this.ctx.overrideDescriptor(this.messageProto, "data", {
110
get: (target, that) => {
111
const event = new HookEvent({ value: target.call(that) }, target, that);
112
this.emit("data", event);
113
114
if (event.intercepted) return event.returnValue;
115
return event.data.value;
116
},
117
});
118
}
119
}
120
121
export default MessageApi;
122
123