UNPKG

node-web-mvc

Version:
178 lines (177 loc) 6.42 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const crypto_1 = require("crypto"); class WorkerInvoker { static serializeRequest(req) { return { url: req.url, method: req.method, rawHeaders: req.rawHeaders, rawTrailers: req.rawTrailers, httpVersion: req.httpVersion, httpVersionMajor: req.httpVersionMajor, httpVersionMinor: req.httpVersionMinor, readableEncoding: req.readableEncoding, socket: { address: req.socket.address(), }, }; } constructor(port) { this.port = port; } static bindCallback(port, id, name) { return (...values) => { const transfer = values.filter((m) => m instanceof Uint8Array).map((m) => m.buffer); port.postMessage({ callbackValues: values, callbackId: id, type: 'callback', }, transfer); }; } static onInvoke(info, port, request, response) { const invoke = info.invoke; const name = invoke.target + '.' + invoke.method; const callback = this.bindCallback(port, invoke.id, name); const args = invoke.args; const socket = invoke.target == 'responseSocket' ? response.socket : request.socket; switch (name) { case 'response.write': response.write(args[0], args[1], callback); break; case 'response.writeHead': response.writeHead(args[0], args[1], args[2]); callback(); break; case 'response.setHeader': response.setHeader(args[0], args[1]); callback(); break; case 'response.end': response.end(args[0], args[1], callback); break; case 'responseSocket.setKeepAlive': case 'requestSocket.setKeepAlive': socket.setKeepAlive(...args); callback(); break; case 'responseSocket.setNoDelay': case 'requestSocket.setNoDelay': socket.setNoDelay(args[0]); callback(); break; case 'responseSocket.setEncoding': case 'requestSocket.setEncoding': socket.setEncoding(args[0]); callback(); break; case 'responseSocket.pause': case 'requestSocket.pause': socket.pause(); callback(); break; case 'responseSocket.resume': case 'requestSocket.resume': socket.resume(); callback(); case 'responseSocket.ref': case 'requestSocket.ref': socket.ref(); callback(); break; case 'responseSocket.unref': case 'requestSocket.unref': socket.unref(); callback(); case 'request.read': request.read(args[0]); break; default: callback(); break; } } static bindEventListener(info, port, request, response) { const mappings = { 'response': response, 'request': request, 'responseSocket': response.socket, 'requestSocket': request.socket, }; const event = info.event; const id = event.id; const obj = mappings[event.target]; const name = `event:${event.target}.${event.name}`; const handler = this.bindCallback(port, id, name); obj.addListener(event.name, handler); const onRemove = (info) => { var _a; const data = info.data; if (data.type == 'remove-event' && ((_a = data.event) === null || _a === void 0 ? void 0 : _a.id) == event.id) { obj.removeListener(event.name, handler); port.removeEventListener('message', onRemove); } }; port.addEventListener('message', onRemove); } /** * 执行主线程对象方法 * @param target 要执行的对象名 * @param method 要执行的方法名 * @param args 参数 * @returns */ invoke(target, method, args) { return new Promise((resolve, reject) => { const id = (0, crypto_1.randomUUID)(); const transfer = args.filter((m) => m instanceof Uint8Array).map((m) => m.buffer); const onCallback = (ev) => { const data = ev.data; if (data.callbackId !== id && data.type == 'callback') return; this.port.removeEventListener('message', onCallback); resolve(data.callbackValues); }; this.port.addEventListener('message', onCallback); this.port.postMessage({ type: 'invoke', invoke: { id: id, target, method, args, }, }, transfer); }); } addEventListener(target, event, handler, once) { if (!handler) { return; } const id = `${event}_${(0, crypto_1.randomUUID)()}`; const invokeHandler = (e) => { const data = (e.data || {}); if (data.type == 'callback' && data.callbackId == id) { handler(...data.callbackValues); once && this.removeEventListener(target, event, id, handler); } }; handler[`@${event}`] = { id, handler: invokeHandler }; // 监听事件回调 this.port.addEventListener('message', invokeHandler); // 通知绑定事件 this.port.postMessage({ type: 'bind-event', event: { id, name: event, target } }); } removeEventListener(target, event, id, handler) { if (!handler) { return; } const info = handler[`@${event}`]; if (info) { this.port.postMessage({ type: 'remove-event', event: { id, name: event, target } }); this.port.removeEventListener(event, info.handler); } } } exports.default = WorkerInvoker;