node-web-mvc
Version:
node spring mvc
178 lines (177 loc) • 6.42 kB
JavaScript
;
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;