Files
reverse-skills-max/vendor-new/xbsReverseSkill/web-reverse-env/scripts/build-worker-module.js

196 lines
6.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { scaffoldModule } = require("./scaffold-module");
function normalizeWorkerSeed(seed = {}) {
const workerSeed = seed.worker && typeof seed.worker === "object" ? seed.worker : seed;
return {
scriptBaseUrl: workerSeed.scriptBaseUrl || "https://example.invalid/assets/",
inlineScripts: Object.assign({}, workerSeed.inlineScripts || {}),
sharedWorkerName: workerSeed.sharedWorkerName || "env-shared-worker",
broadcastChannels: Array.isArray(workerSeed.broadcastChannels)
? workerSeed.broadcastChannels.slice()
: ["env-sync"],
};
}
function renderWorkerPatch(seed) {
const serializedSeed = JSON.stringify(seed, null, 2);
return `(
function installWorkerModule(globalObject) {
const seed = ${serializedSeed};
const protector = globalObject.__envNativeProtector || null;
const sharedChannels = Object.create(null);
function applyEventTarget(target) {
target._listeners = Object.create(null);
target.addEventListener = function addEventListener(type, listener) {
if (!this._listeners[type]) this._listeners[type] = [];
this._listeners[type].push(listener);
};
target.removeEventListener = function removeEventListener(type, listener) {
const list = this._listeners[type] || [];
this._listeners[type] = list.filter(function filterItem(item) {
return item !== listener;
});
};
target.dispatchEvent = function dispatchEvent(event) {
const list = (this._listeners[event.type] || []).slice();
for (const listener of list) listener.call(this, event);
const handler = this["on" + event.type];
if (typeof handler === "function") handler.call(this, event);
return true;
};
}
function createMessageEvent(data) {
return { type: "message", data: data };
}
function MessagePort() {
applyEventTarget(this);
this._entangledPort = null;
this._started = false;
}
MessagePort.prototype.postMessage = function postMessage(data) {
if (this._entangledPort) this._entangledPort.dispatchEvent(createMessageEvent(data));
};
MessagePort.prototype.start = function start() {
this._started = true;
};
MessagePort.prototype.close = function close() {
this._entangledPort = null;
this._started = false;
};
function createMessageChannel() {
const port1 = new MessagePort();
const port2 = new MessagePort();
port1._entangledPort = port2;
port2._entangledPort = port1;
return { port1: port1, port2: port2 };
}
function Worker(scriptUrl) {
applyEventTarget(this);
this.scriptURL = scriptUrl || "";
this.baseUrl = seed.scriptBaseUrl;
this.inlineSource = seed.inlineScripts[scriptUrl] || "";
}
Worker.prototype.postMessage = function postMessage(data) {
this.dispatchEvent(createMessageEvent(data));
};
Worker.prototype.terminate = function terminate() {
this._terminated = true;
};
function SharedWorker(scriptUrl, name) {
applyEventTarget(this);
this.scriptURL = scriptUrl || "";
this.name = name || seed.sharedWorkerName;
const channel = createMessageChannel();
this.port = channel.port1;
this._workerPort = channel.port2;
}
function BroadcastChannel(name) {
applyEventTarget(this);
this.name = name || "";
if (!sharedChannels[this.name]) sharedChannels[this.name] = [];
sharedChannels[this.name].push(this);
}
BroadcastChannel.prototype.postMessage = function postMessage(data) {
const peers = sharedChannels[this.name] || [];
for (const peer of peers) {
if (peer !== this) peer.dispatchEvent(createMessageEvent(data));
}
};
BroadcastChannel.prototype.close = function close() {
const peers = sharedChannels[this.name] || [];
sharedChannels[this.name] = peers.filter(function filterPeer(item) {
return item !== this;
}, this);
};
if (protector && protector.repairFunctionMeta) {
protector.repairFunctionMeta(MessagePort, { name: "MessagePort", length: 0 });
protector.repairFunctionMeta(Worker, { name: "Worker", length: 1 });
protector.repairFunctionMeta(SharedWorker, { name: "SharedWorker", length: 2 });
protector.repairFunctionMeta(BroadcastChannel, { name: "BroadcastChannel", length: 1 });
}
if (protector && protector.protectFunction) {
protector.protectFunction(MessagePort, "MessagePort");
protector.protectFunction(Worker, "Worker");
protector.protectFunction(SharedWorker, "SharedWorker");
protector.protectFunction(BroadcastChannel, "BroadcastChannel");
}
Object.defineProperty(globalObject, "MessagePort", {
configurable: true,
enumerable: false,
writable: true,
value: MessagePort
});
Object.defineProperty(globalObject, "MessageChannel", {
configurable: true,
enumerable: false,
writable: true,
value: function MessageChannel() {
return createMessageChannel();
}
});
Object.defineProperty(globalObject, "Worker", {
configurable: true,
enumerable: false,
writable: true,
value: Worker
});
Object.defineProperty(globalObject, "SharedWorker", {
configurable: true,
enumerable: false,
writable: true,
value: SharedWorker
});
Object.defineProperty(globalObject, "BroadcastChannel", {
configurable: true,
enumerable: false,
writable: true,
value: BroadcastChannel
});
return { Worker: Worker, SharedWorker: SharedWorker, BroadcastChannel: BroadcastChannel };
})(typeof globalThis !== "undefined" ? globalThis : window);
`;
}
function buildWorkerModule(seed = {}) {
const module = scaffoldModule("worker-module");
const normalizedSeed = normalizeWorkerSeed(seed);
module.patchPlan = [
"补出 Worker/SharedWorker/MessagePort/MessageChannel/BroadcastChannel 构造器。",
"用最小事件系统模拟 postMessage/onmessage 通路。",
"把 worker 脚本路径、inline source、广播频道名称外置为种子,而不是写死在补丁里。",
];
module.patchCode = renderWorkerPatch(normalizedSeed);
module.runtimeState = { worker: normalizedSeed };
module.validation = [
"检查 typeof Worker/SharedWorker/BroadcastChannel === 'function'。",
"执行 new Worker('/worker.js').postMessage({ping:1}),确认 message 事件能被触发。",
"执行 new SharedWorker('/shared.js').port.postMessage('x'),确认端口存在。",
"执行两个同名 BroadcastChannel 互发消息,确认消息广播通路正常。",
];
module.residualRisk = [
"这里只模拟消息通路,不提供真实线程、importScripts、URL.createObjectURL 等完整能力。",
"若目标站点依赖 Worker 全局作用域、自定义事件循环或二进制消息通路,仍需继续扩展。",
];
return module;
}
module.exports = {
buildWorkerModule,
normalizeWorkerSeed,
};