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;