| 156 | } |
| 157 | |
| 158 | export class ExtensionMessageConnect implements MessageConnect { |
| 159 | private readonly listenerId = `${uuidv4()}`; // 使用 uuidv4 确保唯一 |
| 160 | private con: chrome.runtime.Port | null; |
| 161 | private isSelfDisconnected = false; |
| 162 | |
| 163 | constructor(con: chrome.runtime.Port) { |
| 164 | this.con = con; // 强引用 |
| 165 | const handler = (msg: TMessage, _con: chrome.runtime.Port) => { |
| 166 | listenerMgr.emit(`onMessage:${this.listenerId}`, msg); |
| 167 | }; |
| 168 | const cleanup = () => { |
| 169 | const con = this.con; |
| 170 | if (con !== null) { |
| 171 | this.con = null; |
| 172 | listenerMgr.removeAllListeners(`cleanup:${this.listenerId}`); |
| 173 | con.onMessage.removeListener(handler); |
| 174 | con.onDisconnect.removeListener(cleanup); |
| 175 | listenerMgr.emit(`onDisconnect:${this.listenerId}`, this.isSelfDisconnected); |
| 176 | listenerMgr.removeAllListeners(`onDisconnect:${this.listenerId}`); |
| 177 | listenerMgr.removeAllListeners(`onMessage:${this.listenerId}`); |
| 178 | } |
| 179 | }; |
| 180 | con.onMessage.addListener(handler); |
| 181 | con.onDisconnect.addListener(cleanup); |
| 182 | listenerMgr.once(`cleanup:${this.listenerId}`, cleanup); |
| 183 | } |
| 184 | |
| 185 | sendMessage(data: TMessage) { |
| 186 | if (!this.con) { |
| 187 | console.warn("Attempted to sendMessage on a disconnected port."); |
| 188 | // 無法 sendMessage 不应该屏蔽错误 |
| 189 | throw new Error("Attempted to sendMessage on a disconnected port."); |
| 190 | } |
| 191 | this.con.postMessage(data); |
| 192 | } |
| 193 | |
| 194 | onMessage(callback: (data: TMessage) => void) { |
| 195 | if (!this.con) { |
| 196 | console.error("onMessage Invalid Port"); |
| 197 | // 無法監聽的話不应该屏蔽错误 |
| 198 | throw new Error("onMessage Invalid Port"); |
| 199 | } |
| 200 | listenerMgr.addListener(`onMessage:${this.listenerId}`, callback); |
| 201 | } |
| 202 | |
| 203 | disconnect(ignoreAlreadyDisconnected?: boolean) { |
| 204 | if (!this.con) { |
| 205 | if (ignoreAlreadyDisconnected) return; |
| 206 | console.warn("Attempted to disconnect on a disconnected port."); |
| 207 | // 重复 disconnect() 不应该屏蔽错误 |
| 208 | throw new Error("Attempted to disconnect on a disconnected port."); |
| 209 | } |
| 210 | this.isSelfDisconnected = true; |
| 211 | this.con?.disconnect(); |
| 212 | // Note: .disconnect() will NOT automatically trigger the 'cleanup' listener |
| 213 | listenerMgr.emit(`cleanup:${this.listenerId}`); |
| 214 | } |
| 215 |
nothing calls this directly
no outgoing calls
no test coverage detected