Skip to content

Commit 1f3a3ec

Browse files
CodFrmcyfung1031
andauthored
🐛 修复document.write导致消息监听重置的问题 (#1055)
Co-authored-by: cyfung1031 <44498510+cyfung1031@users.noreply.github.com>
1 parent 626e84d commit 1f3a3ec

File tree

9 files changed

+55
-20
lines changed

9 files changed

+55
-20
lines changed

packages/message/custom_event_message.ts

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,23 @@ import LoggerCore from "@App/app/logger/core";
55
import EventEmitter from "eventemitter3";
66
import { DefinedFlags } from "@App/app/service/service_worker/runtime.consts";
77

8+
// 避免页面载入后改动 EventTarget.prototype 的方法导致消息传递失败
9+
const pageDispatchEvent = performance.dispatchEvent.bind(performance);
10+
const pageAddEventListener = performance.addEventListener.bind(performance);
11+
12+
// 避免页面载入后改动全域物件导致消息传递失败
13+
const MouseEventClone = MouseEvent;
14+
const CustomEventClone = CustomEvent;
15+
16+
// 避免页面载入后改动 Map.prototype 导致消息传递失败
17+
const relatedTargetMap = new Map<number, EventTarget>();
18+
relatedTargetMap.set = Map.prototype.set;
19+
relatedTargetMap.get = Map.prototype.get;
20+
relatedTargetMap.delete = Map.prototype.delete;
21+
22+
let relateId = 0;
23+
const maxInteger = Number.MAX_SAFE_INTEGER;
24+
825
export class CustomEventPostMessage implements PostMessage {
926
constructor(private send: CustomEventMessage) {}
1027

@@ -28,10 +45,10 @@ export class CustomEventMessage implements Message {
2845
) {
2946
this.receiveFlag = `evt${messageFlag}${isContent ? DefinedFlags.contentFlag : DefinedFlags.injectFlag}${DefinedFlags.domEvent}`;
3047
this.sendFlag = `evt${messageFlag}${isContent ? DefinedFlags.injectFlag : DefinedFlags.contentFlag}${DefinedFlags.domEvent}`;
31-
window.addEventListener(this.receiveFlag, (event) => {
32-
if (event instanceof MouseEvent && event.movementX && event.relatedTarget) {
33-
this.relatedTarget.set(event.movementX, event.relatedTarget!);
34-
} else if (event instanceof CustomEvent) {
48+
pageAddEventListener(this.receiveFlag, (event) => {
49+
if (event instanceof MouseEventClone && event.movementX && event.relatedTarget) {
50+
relatedTargetMap.set(event.movementX, event.relatedTarget!);
51+
} else if (event instanceof CustomEventClone) {
3552
this.messageHandle(event.detail, new CustomEventPostMessage(this));
3653
}
3754
});
@@ -100,10 +117,10 @@ export class CustomEventMessage implements Message {
100117
}
101118
}
102119

103-
const ev = new CustomEvent(this.sendFlag, {
120+
const ev = new CustomEventClone(this.sendFlag, {
104121
detail,
105122
});
106-
window.dispatchEvent(ev);
123+
pageDispatchEvent(ev);
107124
}
108125

109126
sendMessage<T = any>(data: TMessage): Promise<T> {
@@ -146,24 +163,22 @@ export class CustomEventMessage implements Message {
146163
return ret;
147164
}
148165

149-
relateId = 0;
150-
151166
sendRelatedTarget(target: EventTarget): number {
152167
// 特殊处理relatedTarget,返回id进行关联
153168
// 先将relatedTarget转换成id发送过去
154-
const id = ++this.relateId;
169+
const id = (relateId = relateId === maxInteger ? 1 : relateId + 1);
155170
// 可以使用此种方式交互element
156-
const ev = new MouseEvent(this.sendFlag, {
171+
const ev = new MouseEventClone(this.sendFlag, {
157172
movementX: id,
158173
relatedTarget: target,
159174
});
160-
window.dispatchEvent(ev);
175+
pageDispatchEvent(ev);
161176
return id;
162177
}
163178

164179
getAndDelRelatedTarget(id: number) {
165-
const target = this.relatedTarget.get(id);
166-
this.relatedTarget.delete(id);
180+
const target = relatedTargetMap.get(id);
181+
relatedTargetMap.delete(id);
167182
return target;
168183
}
169184
}

packages/message/extension_message.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ export class ExtensionContentMessageSend implements MessageSend {
180180

181181
sendMessage<T = any>(data: TMessage): Promise<T> {
182182
return new Promise((resolve) => {
183-
if (!this.options?.documentId || this.options?.frameId) {
183+
if (!this.options?.documentId && !this.options?.frameId) {
184184
// 发送给指定的tab
185185
chrome.tabs.sendMessage(this.tabId, data, (resp: T) => {
186186
const lastError = chrome.runtime.lastError;

src/app/service/content/content.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import type { MessageSend } from "@Packages/message/types";
55
import type { ScriptExecutor } from "./script_executor";
66
import { RuntimeClient } from "../service_worker/client";
77
import type { GMInfoEnv } from "./types";
8+
import type { Logger } from "@App/app/repo/logger";
9+
import LoggerCore from "@App/app/logger/core";
810

911
// content页的处理
1012
export default class ContentRuntime {
@@ -36,6 +38,9 @@ export default class ContentRuntime {
3638
this.scriptExecutor.valueUpdate(data);
3739
return sendMessage(this.senderToInject, "inject/runtime/valueUpdate", data);
3840
});
41+
this.server.on("logger", (data: Logger) => {
42+
LoggerCore.logger().log(data.level, data.message, data.label);
43+
});
3944
forwardMessage("serviceWorker", "script/isInstalled", this.server, this.senderToExt);
4045
forwardMessage(
4146
"serviceWorker",

src/app/service/content/script_executor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export class ScriptExecutor {
9090
const envLoadCompleteEvtName = `${eventNamePrefix}${DefinedFlags.envLoadComplete}`;
9191
// 监听 脚本加载
9292
// 适用于此「通知环境加载完成」代码执行后的脚本加载
93-
window.addEventListener(scriptLoadCompleteEvtName, (ev) => {
93+
performance.addEventListener(scriptLoadCompleteEvtName, (ev) => {
9494
const detail = (ev as CustomEvent).detail;
9595
const scriptFlag = detail?.scriptFlag;
9696
if (typeof scriptFlag === "string") {
@@ -101,7 +101,7 @@ export class ScriptExecutor {
101101
// 通知 环境 加载完成
102102
// 适用于此「通知环境加载完成」代码执行前的脚本加载
103103
const ev = new CustomEvent(envLoadCompleteEvtName);
104-
window.dispatchEvent(ev);
104+
performance.dispatchEvent(ev);
105105
}
106106

107107
execEarlyScript(flag: string, scriptInfo: TScriptInfo, envInfo: GMInfoEnv) {

src/app/service/content/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,9 @@ export function compilePreInjectScript(
150150
return `window['${flag}'] = function(){${autoDeleteMountCode}${scriptCode}};
151151
{
152152
let o = { cancelable: true, detail: { scriptFlag: '${flag}', scriptInfo: (${scriptInfoJSON}) } },
153-
f = () => window.dispatchEvent(new CustomEvent('${evScriptLoad}', o)),
153+
f = () => performance.dispatchEvent(new CustomEvent('${evScriptLoad}', o)),
154154
needWait = f();
155-
if (needWait) window.addEventListener('${evEnvLoad}', f, { once: true });
155+
if (needWait) performance.addEventListener('${evEnvLoad}', f, { once: true });
156156
}
157157
`;
158158
}

src/app/service/service_worker/value.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ export class ValueService {
101101
await this.valueDAO.save(storageName, valueModel);
102102
return true;
103103
});
104+
104105
this.pushValueToTab({
105106
id,
106107
entries: encodeMessage([[key, value, oldValue]]),

src/content.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ if (typeof chrome?.runtime?.onMessage?.addListener !== "function") {
1818
const extMsgComm: Message = new ExtensionMessage(false);
1919
// 初始化日志组件
2020
const loggerCore = new LoggerCore({
21-
writer: new MessageWriter(extMsgComm),
21+
writer: new MessageWriter(extMsgComm, "serviceWorker/logger"),
2222
labels: { env: "content" },
2323
});
2424

src/inject.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ const msg: Message = new CustomEventMessage(MessageFlag, false);
1414

1515
// 加载logger组件
1616
const logger = new LoggerCore({
17-
writer: new MessageWriter(msg),
17+
writer: new MessageWriter(msg, "content/logger"),
18+
consoleLevel: "none", // 只让日志在content环境中打印
1819
labels: { env: "inject", href: window.location.href },
1920
});
2021

tests/vitest.setup.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,16 @@ vi.stubGlobal("define", "特殊关键字不能穿透沙盒");
227227
if (!URL.createObjectURL) URL.createObjectURL = undefined;
228228
//@ts-expect-error
229229
if (!URL.revokeObjectURL) URL.revokeObjectURL = undefined;
230+
231+
// 测试环境使用 window 代替 performance 作为 EventTarget
232+
performance.addEventListener = function (type: string, listener: any, options?: any) {
233+
return window.addEventListener(type, listener, options);
234+
};
235+
236+
performance.removeEventListener = function (type: string, listener: any, options?: any) {
237+
return window.removeEventListener(type, listener, options);
238+
};
239+
240+
performance.dispatchEvent = function (event: Event) {
241+
return window.dispatchEvent(event);
242+
};

0 commit comments

Comments
 (0)