ultraviolet/client/message.js
2022-02-14 00:25:17 -05:00

84 lines
No EOL
3.4 KiB
JavaScript

import EventEmitter from "./events.js";
import HookEvent from "./hook.js";
class MessageApi extends EventEmitter {
constructor(ctx) {
super();
this.ctx = ctx;
this.window = this.ctx.window;
this.postMessage = this.window.postMessage;
this.MessageEvent = this.window.MessageEvent || {};
this.MessagePort = this.window.MessagePort || {};
this.mpProto = this.MessagePort.prototype || {};
this.mpPostMessage = this.mpProto.postMessage;
this.messageProto = this.MessageEvent.prototype || {};
this.messageData = ctx.nativeMethods.getOwnPropertyDescriptor(this.messageProto, 'data');
this.messageOrigin = ctx.nativeMethods.getOwnPropertyDescriptor(this.messageProto, 'origin');
};
overridePostMessage() {
this.ctx.override(this.window, 'postMessage', (target, that, args) => {
if (!args.length) return target.apply(that, args);
let message;
let origin;
let transfer;
if (!this.ctx.worker) {
[ message, origin, transfer = [] ] = args;
} else {
[ message, transfer = [] ] = args;
};
const event = new HookEvent({ message, origin, transfer, worker: this.ctx.worker }, target, that);
this.emit('postMessage', event);
if (event.intercepted) return event.returnValue;
return this.ctx.worker ? event.target.call(event.that, event.data.message, event.data.transfer) : event.target.call(event.that, event.data.message, event.data.origin, event.data.transfer);
});
};
wrapPostMessage(obj, prop, noOrigin = false) {
return this.ctx.wrap(obj, prop, (target, that, args) => {
if (this.ctx.worker ? !args.length : 2 > args) return target.apply(that, args);
let message;
let origin;
let transfer;
if (!noOrigin) {
[ message, origin, transfer = [] ] = args;
} else {
[ message, transfer = [] ] = args;
origin = null;
};
const event = new HookEvent({ message, origin, transfer, worker: this.ctx.worker }, target, obj);
this.emit('postMessage', event);
if (event.intercepted) return event.returnValue;
return noOrigin ? event.target.call(event.that, event.data.message, event.data.transfer) : event.target.call(event.that, event.data.message, event.data.origin, event.data.transfer);
});
};
overrideMessageOrigin() {
this.ctx.overrideDescriptor(this.messageProto, 'origin', {
get: (target, that) => {
const event = new HookEvent({ value: target.call(that) }, target, that);
this.emit('origin', event);
if (event.intercepted) return event.returnValue;
return event.data.value;
}
});
};
overrideMessageData() {
this.ctx.overrideDescriptor(this.messageProto, 'data', {
get: (target, that) => {
const event = new HookEvent({ value: target.call(that) }, target, that);
this.emit('data', event);
if (event.intercepted) return event.returnValue;
return event.data.value;
}
});
};
};
export default MessageApi;