├── .gitignore ├── LICENSE ├── README.md ├── test.html └── window-monitor-bypass ├── README.md ├── main.js └── test.html /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 JavaScript Reverse Engineering Infrastructure 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # javascript逆向开发基础组件: window监听器 2 | 3 | # 一、 简介 4 | 5 | 用于监听window的变化,目前只有新增全局变量监控,最初是为了用在javascript hook库中实现对window变量的proxy功能。 6 | 7 | # 二、Example 8 | 9 | ```js 10 | (async () => { 11 | 12 | const monitor = new WindowMonitor(); 13 | // 在window新增变量时会触发此处传入的Listener函数,Listener函数可以有多个 14 | await monitor.addWindowListener(key => { 15 | console.log(new Date(), key); 16 | }); 17 | // 启动监控器,其实就是个while循环不断的检查window上是否有新增变量 18 | await monitor.startWindowMonitor(); 19 | 20 | })(); 21 | 22 | const chars = "ABCDEFGHJKMNPQRSTWXYZ" 23 | 24 | function randomString(length) { 25 | length = length || 100; 26 | const charArray = []; 27 | for (let i = 0; i < length; i++) { 28 | charArray.push(chars.charAt(Math.floor(Math.random() * chars.length))); 29 | } 30 | return charArray.join(""); 31 | } 32 | 33 | function genGlobalVars() { 34 | window[randomString(40)] = randomString(6); 35 | setTimeout(genGlobalVars, Math.random() * 10) 36 | } 37 | 38 | setTimeout(() => { 39 | genGlobalVars(); 40 | }, Math.random() * 10) 41 | 42 | ``` 43 | 44 | # 三、原理 45 | 46 | 其实原理简单粗暴,就是每隔一段时间遍历window对其所有属性做一个快照,然后前后快照做diff,就能够找出来新增的变量或者删除的变量,对于第一个快照会认为是初始化,这样就能够把默认的属性给识别出来不触发新增事件。 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test 5 | 6 | 7 | 8 | 9 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /window-monitor-bypass/README.md: -------------------------------------------------------------------------------- 1 | # javascript逆向开发基础组件: window监听器 2 | 3 | # 一、 简介 4 | 5 | 用于监听`window`上的全局变量的变化,目前支持的事件类型: 6 | 7 | - 新增变量 8 | - 删除变量 9 | - 变量的值被修改 10 | 11 | 最初是为了用在`javascript hook`库中实现对`window`变量的`proxy`功能。 12 | 13 | # 二、示例代码 14 | 15 | ```js 16 | 17 | function eventCallback() { 18 | console.log(new Date(), JSON.stringify(arguments)); 19 | } 20 | 21 | (async () => { 22 | 23 | const monitor = new WindowMonitor(); 24 | await monitor.addWindowListener(eventCallback); 25 | await monitor.startWindowMonitor(); 26 | 27 | })(); 28 | 29 | const chars = "ABCDEFGHJKMNPQRSTWXYZ" 30 | 31 | function randomString(length) { 32 | length = length || 100; 33 | const charArray = []; 34 | for (let i = 0; i < length; i++) { 35 | charArray.push(chars.charAt(Math.floor(Math.random() * chars.length))); 36 | } 37 | return charArray.join(""); 38 | } 39 | 40 | function genGlobalVars() { 41 | const variableName = randomString(2); 42 | const variableValue = randomString(10); 43 | if (Math.random() < 0.3) { 44 | delete window[variableName]; 45 | } else { 46 | window[variableName] = variableValue; 47 | } 48 | setTimeout(genGlobalVars, Math.random() * 100) 49 | } 50 | 51 | setTimeout(() => { 52 | genGlobalVars(); 53 | }, Math.random() * 100) 54 | ``` 55 | 56 | 效果大概是这样子的: 57 | 58 | ```bash 59 | Mon Feb 12 2024 01:21:03 GMT+0800 (中国标准时间) '{"0":"add","1":"FJ","2":"XXHPASGPNM"}' 60 | Mon Feb 12 2024 01:21:03 GMT+0800 (中国标准时间) '{"0":"add","1":"TR","2":"GQRFMERYPC"}' 61 | Mon Feb 12 2024 01:21:03 GMT+0800 (中国标准时间) '{"0":"add","1":"GA","2":"KGKZFMJFPQ"}' 62 | Mon Feb 12 2024 01:21:03 GMT+0800 (中国标准时间) '{"0":"add","1":"DM","2":"DDCHTFFXKC"}' 63 | Mon Feb 12 2024 01:21:03 GMT+0800 (中国标准时间) '{"0":"add","1":"EN","2":"QACZMJQWHS"}' 64 | Mon Feb 12 2024 01:21:04 GMT+0800 (中国标准时间) '{"0":"add","1":"YR","2":"DGMXDYJBPK"}' 65 | Mon Feb 12 2024 01:21:04 GMT+0800 (中国标准时间) '{"0":"add","1":"FS","2":"CTGYPNZFYM"}' 66 | Mon Feb 12 2024 01:21:04 GMT+0800 (中国标准时间) '{"0":"add","1":"WW","2":"DQKTHTYETA"}' 67 | Mon Feb 12 2024 01:21:04 GMT+0800 (中国标准时间) '{"0":"add","1":"KR","2":"GHMBFNJMDR"}' 68 | Mon Feb 12 2024 01:21:04 GMT+0800 (中国标准时间) '{"0":"add","1":"MM","2":"RHEMJXJSWQ"}' 69 | Mon Feb 12 2024 01:21:04 GMT+0800 (中国标准时间) '{"0":"add","1":"WZ","2":"SGMPJZWAGT"}' 70 | Mon Feb 12 2024 01:21:04 GMT+0800 (中国标准时间) '{"0":"add","1":"WE","2":"YSAHHBKZHD"}' 71 | Mon Feb 12 2024 01:21:04 GMT+0800 (中国标准时间) '{"0":"delete","1":"EW","2":"XRZKANRJYK"}' 72 | Mon Feb 12 2024 01:21:04 GMT+0800 (中国标准时间) '{"0":"add","1":"GG","2":"CCCKHTDKJM"}' 73 | Mon Feb 12 2024 01:21:04 GMT+0800 (中国标准时间) '{"0":"add","1":"FP","2":"EJHFACQNJT"}' 74 | Mon Feb 12 2024 01:21:04 GMT+0800 (中国标准时间) '{"0":"add","1":"GM","2":"QSDYMWTZAJ"}' 75 | Mon Feb 12 2024 01:21:04 GMT+0800 (中国标准时间) '{"0":"add","1":"CH","2":"WRAETDQZWP"}' 76 | Mon Feb 12 2024 01:21:04 GMT+0800 (中国标准时间) '{"0":"add","1":"DY","2":"WTJRMKMCTX"}' 77 | Mon Feb 12 2024 01:21:05 GMT+0800 (中国标准时间) '{"0":"value-change","1":"FJ","2":"TPDKFFKHYP","3":"XXHPASGPNM"}' 78 | Mon Feb 12 2024 01:21:05 GMT+0800 (中国标准时间) '{"0":"add","1":"XW","2":"BMJETGFMYG"}' 79 | Mon Feb 12 2024 01:21:05 GMT+0800 (中国标准时间) '{"0":"add","1":"EW","2":"KRWCHSZDJG"}' 80 | Mon Feb 12 2024 01:21:05 GMT+0800 (中国标准时间) '{"0":"add","1":"GK","2":"ZCEJAQTXRF"}' 81 | Mon Feb 12 2024 01:21:05 GMT+0800 (中国标准时间) '{"0":"add","1":"QA","2":"XXKFHYGMTE"}' 82 | Mon Feb 12 2024 01:21:05 GMT+0800 (中国标准时间) '{"0":"add","1":"SG","2":"CJBAGADFYN"}' 83 | Mon Feb 12 2024 01:21:05 GMT+0800 (中国标准时间) '{"0":"add","1":"GJ","2":"XQHWWHBDDC"}' 84 | Mon Feb 12 2024 01:21:05 GMT+0800 (中国标准时间) '{"0":"add","1":"JF","2":"YQSSKTFNGY"}' 85 | Mon Feb 12 2024 01:21:05 GMT+0800 (中国标准时间) '{"0":"add","1":"MG","2":"EGXQANXHFZ"}' 86 | Mon Feb 12 2024 01:21:05 GMT+0800 (中国标准时间) '{"0":"add","1":"SY","2":"ZXNGRKKQWQ"}' 87 | Mon Feb 12 2024 01:21:06 GMT+0800 (中国标准时间) '{"0":"add","1":"FH","2":"MEZHWWYCTW"}' 88 | Mon Feb 12 2024 01:21:06 GMT+0800 (中国标准时间) '{"0":"add","1":"HT","2":"TYHNWZTZJP"}' 89 | Mon Feb 12 2024 01:21:06 GMT+0800 (中国标准时间) '{"0":"add","1":"JY","2":"JBXCGQNCAE"}' 90 | Mon Feb 12 2024 01:21:06 GMT+0800 (中国标准时间) '{"0":"value-change","1":"GJ","2":"XMGTXTAGXF","3":"XQHWWHBDDC"}' 91 | Mon Feb 12 2024 01:21:06 GMT+0800 (中国标准时间) '{"0":"add","1":"SH","2":"SFPEBHHAMG"}' 92 | Mon Feb 12 2024 01:21:06 GMT+0800 (中国标准时间) '{"0":"add","1":"MP","2":"YTWZZYCZJP"}' 93 | Mon Feb 12 2024 01:21:06 GMT+0800 (中国标准时间) '{"0":"add","1":"SQ","2":"BNZCCECGMT"}' 94 | Mon Feb 12 2024 01:21:06 GMT+0800 (中国标准时间) '{"0":"add","1":"BN","2":"GXFTFYKHQH"}' 95 | Mon Feb 12 2024 01:21:06 GMT+0800 (中国标准时间) '{"0":"value-change","1":"QA","2":"MSSZRDFSBR","3":"XXKFHYGMTE"}' 96 | Mon Feb 12 2024 01:21:06 GMT+0800 (中国标准时间) '{"0":"add","1":"ZP","2":"ZCAPWBWSEZ"}' 97 | Mon Feb 12 2024 01:21:06 GMT+0800 (中国标准时间) '{"0":"add","1":"WN","2":"GZNCTBTQHN"}' 98 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"add","1":"QP","2":"YSRSPGSCSP"}' 99 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"add","1":"BB","2":"QQQSPZNEEP"}' 100 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"add","1":"YD","2":"YQXGXWHECD"}' 101 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"add","1":"CB","2":"GGWFNKPGDP"}' 102 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"add","1":"CR","2":"YMZRBKYZPW"}' 103 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"delete","1":"SG","2":"CJBAGADFYN"}' 104 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"delete","1":"JF","2":"YQSSKTFNGY"}' 105 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"value-change","1":"WZ","2":"CANXENXHZT","3":"SGMPJZWAGT"}' 106 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"add","1":"ZC","2":"GBQCNPRMKT"}' 107 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"add","1":"RW","2":"PMBSMJNWNF"}' 108 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"add","1":"PH","2":"BCSKPSRXHN"}' 109 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"value-change","1":"SH","2":"ZFXDQACCXN","3":"SFPEBHHAMG"}' 110 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"add","1":"CS","2":"PFEKTSZRSC"}' 111 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"add","1":"QQ","2":"FTWNMGZMQJ"}' 112 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"add","1":"MW","2":"ZWARCYJXYJ"}' 113 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"add","1":"BG","2":"NNDQKGWSEW"}' 114 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"add","1":"FB","2":"WSRGMGAANN"}' 115 | Mon Feb 12 2024 01:21:07 GMT+0800 (中国标准时间) '{"0":"add","1":"ND","2":"CEHRCZHFAZ"}' 116 | Mon Feb 12 2024 01:21:08 GMT+0800 (中国标准时间) '{"0":"value-change","1":"GM","2":"BHGSSSQQZC","3":"QSDYMWTZAJ"}' 117 | Mon Feb 12 2024 01:21:08 GMT+0800 (中国标准时间) '{"0":"add","1":"YK","2":"RTFTKQANRK"}' 118 | Mon Feb 12 2024 01:21:08 GMT+0800 (中国标准时间) '{"0":"add","1":"SR","2":"QEXKTYCXTC"}' 119 | Mon Feb 12 2024 01:21:08 GMT+0800 (中国标准时间) '{"0":"add","1":"BZ","2":"YZZXJPDPJQ"}' 120 | Mon Feb 12 2024 01:21:08 GMT+0800 (中国标准时间) '{"0":"add","1":"HM","2":"EKCRGTBQWF"}' 121 | Mon Feb 12 2024 01:21:08 GMT+0800 (中国标准时间) '{"0":"value-change","1":"BZ","2":"EAZAJRNNDB","3":"YZZXJPDPJQ"}' 122 | Mon Feb 12 2024 01:21:08 GMT+0800 (中国标准时间) '{"0":"add","1":"YJ","2":"YRDFRAHYEQ"}' 123 | Mon Feb 12 2024 01:21:08 GMT+0800 (中国标准时间) '{"0":"add","1":"CK","2":"ZCZQHDCWXD"}' 124 | Mon Feb 12 2024 01:21:08 GMT+0800 (中国标准时间) '{"0":"add","1":"EC","2":"JKSHFGMQNA"}' 125 | Mon Feb 12 2024 01:21:08 GMT+0800 (中国标准时间) '{"0":"add","1":"KF","2":"SDEQJPKBXH"}' 126 | Mon Feb 12 2024 01:21:08 GMT+0800 (中国标准时间) '{"0":"add","1":"JN","2":"FSAQKDBDTT"}' 127 | Mon Feb 12 2024 01:21:08 GMT+0800 (中国标准时间) '{"0":"add","1":"MX","2":"YJNXZNPGCZ"}' 128 | Mon Feb 12 2024 01:21:08 GMT+0800 (中国标准时间) '{"0":"delete","1":"SR","2":"QEXKTYCXTC"}' 129 | Mon Feb 12 2024 01:21:09 GMT+0800 (中国标准时间) '{"0":"value-change","1":"EW","2":"CQJCQCZASD","3":"KRWCHSZDJG"}' 130 | Mon Feb 12 2024 01:21:09 GMT+0800 (中国标准时间) '{"0":"add","1":"PX","2":"ZFKJJGSSKF"}' 131 | Mon Feb 12 2024 01:21:09 GMT+0800 (中国标准时间) '{"0":"add","1":"EY","2":"XFBJSTQJDY"}' 132 | Mon Feb 12 2024 01:21:09 GMT+0800 (中国标准时间) '{"0":"add","1":"NG","2":"TNRWJWAAEP"}' 133 | Mon Feb 12 2024 01:21:09 GMT+0800 (中国标准时间) '{"0":"add","1":"DR","2":"FSNPRPDMYP"}' 134 | Mon Feb 12 2024 01:21:09 GMT+0800 (中国标准时间) '{"0":"add","1":"SB","2":"ESZEGWGJCA"}' 135 | Mon Feb 12 2024 01:21:09 GMT+0800 (中国标准时间) '{"0":"add","1":"BP","2":"NKGAFNPTPG"}' 136 | Mon Feb 12 2024 01:21:09 GMT+0800 (中国标准时间) '{"0":"add","1":"NK","2":"MAQHETWQET"}' 137 | Mon Feb 12 2024 01:21:09 GMT+0800 (中国标准时间) '{"0":"add","1":"RH","2":"QSDXRYMWKX"}' 138 | Mon Feb 12 2024 01:21:09 GMT+0800 (中国标准时间) '{"0":"add","1":"PQ","2":"HSGNRDKTMJ"}' 139 | Mon Feb 12 2024 01:21:09 GMT+0800 (中国标准时间) '{"0":"delete","1":"HM","2":"EKCRGTBQWF"}' 140 | Mon Feb 12 2024 01:21:09 GMT+0800 (中国标准时间) '{"0":"value-change","1":"NG","2":"QPMAYAXGTH","3":"TNRWJWAAEP"}' 141 | Mon Feb 12 2024 01:21:09 GMT+0800 (中国标准时间) '{"0":"add","1":"BA","2":"EBNTSBMZNQ"}' 142 | Mon Feb 12 2024 01:21:09 GMT+0800 (中国标准时间) '{"0":"add","1":"JQ","2":"NWFMSATFDH"}' 143 | ``` 144 | 145 | 测试用例详见`test.html`文件,或者在线预览效果,点进下面的链接然后打开开发者工具查看: 146 | 147 | [https://htmlpreview.github.io/?https://github.com/JSREI/javascript-window-listener-library/blob/main/window-monitor-bypass/test.html](https://htmlpreview.github.io/?https://github.com/JSREI/javascript-window-listener-library/blob/main/window-monitor-bypass/test.html) 148 | 149 | # 三、原理 150 | 151 | 其实原理简单粗暴,就是每隔一段时间遍历`window`对其所有属性做一个快照,然后前后快照做`diff`,就能够找出来新增的变量或者删除的变量,对于第一个快照会认为是初始化,这样就能够把默认的属性给识别出来不触发新增事件。 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /window-monitor-bypass/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * window监控器,封装了监控相关的逻辑 3 | */ 4 | class WindowMonitor { 5 | 6 | // ---------------------------------------------------------------------------------------------------------------- 7 | 8 | /** 9 | * window上增加了一个变量 10 | * 11 | * @type {string} 12 | */ 13 | static WINDOW_EVENT_VARIABLE_ADD = "add"; 14 | 15 | /** 16 | * window上删除了一个变量 17 | * 18 | * @type {string} 19 | */ 20 | static WINDOW_EVENT_VARIABLE_DELETE = "delete"; 21 | 22 | /** 23 | * window上某个变量的值发生了变化 24 | * 25 | * @type {string} 26 | */ 27 | static WINDOW_EVENT_VARIABLE_VALUE_CHANGE = "value-change"; 28 | 29 | // ---------------------------------------------------------------------------------------------------------------- 30 | 31 | constructor() { 32 | this.windowAttributeMap = new Map(); 33 | this.windowListenerQueue = []; 34 | } 35 | 36 | /** 37 | * 增加一个window上新增或者删除变量时的监听器回调函数 38 | * 39 | * @param windowListener 40 | * @returns {Promise} 41 | */ 42 | async addWindowListener(windowListener) { 43 | this.windowListenerQueue.push(windowListener); 44 | } 45 | 46 | /** 47 | * 启动window监控器,其实就是异步移动一个while循环每隔 intervalMils 秒去检查一下window上是否有变量变化 48 | * 49 | * @param intervalMils 间隔多少毫秒检查一次,默认为300毫秒 50 | * @returns {Promise} 51 | */ 52 | async startWindowMonitor(intervalMils = 300) { 53 | 54 | // 第一次的认为是原生携带的,不触发事件 55 | await this.#screenshotWindow(true); 56 | 57 | // 之后的才触发事件 58 | while (true) { 59 | await this.#screenshotWindow(false); 60 | await this.#sleep(intervalMils); 61 | } 62 | } 63 | 64 | /** 65 | * 对window上的变量做快照,如果有必要的话,则会与上一次的快照做diff尝试触发事件 66 | * 67 | * @param isInit 是否是第一次初始化,如果是初始化则只对window上的变量做快照,否则会与前一次的变量快照做diff尝试触发事件 68 | * @returns {Promise} 69 | */ 70 | async #screenshotWindow(isInit) { 71 | 72 | const newWindowAttributeMap = new Map(); 73 | for (let key in window) { 74 | newWindowAttributeMap.set(key, window[key]); 75 | } 76 | 77 | // 如果不是第一次的话,则比对快照 78 | if (!isInit) { 79 | this.#diff(this.windowAttributeMap, newWindowAttributeMap); 80 | } 81 | 82 | // 最后,把快照整个替换一下 83 | this.windowAttributeMap = newWindowAttributeMap; 84 | 85 | } 86 | 87 | #diff(oldWindowAttributeMap, newWindowAttributeMap) { 88 | for (let key of newWindowAttributeMap.keys()) { 89 | 90 | const newValue = newWindowAttributeMap.get(key); 91 | 92 | // 新增变量,new map有但是old map没有 93 | if (!oldWindowAttributeMap.has(key)) { 94 | // 触发变量新增事件 95 | this.#applyEvent(WindowMonitor.WINDOW_EVENT_VARIABLE_ADD, key, newValue); 96 | continue; 97 | } 98 | 99 | // 新的map有,老的map也有,但是值并不一样,说明是值发生了变化 100 | const oldValue = oldWindowAttributeMap.get(key); 101 | if (newValue !== oldValue) { 102 | // 触发变量值变化的事件 103 | this.#applyEvent(WindowMonitor.WINDOW_EVENT_VARIABLE_VALUE_CHANGE, key, newValue, oldValue); 104 | } 105 | 106 | } 107 | 108 | // 删除变量 109 | for (let key of oldWindowAttributeMap.keys()) { 110 | if (newWindowAttributeMap.has(key)) { 111 | continue; 112 | } 113 | const oldValue = oldWindowAttributeMap.get(key); 114 | // 触发变量删除事件 115 | this.#applyEvent(WindowMonitor.WINDOW_EVENT_VARIABLE_DELETE, key, oldValue); 116 | } 117 | } 118 | 119 | /** 120 | * 触发变量事件,传递给事件回调函数的参数通过此函数的arguments传递,会被原样传递给回调函数 121 | */ 122 | #applyEvent() { 123 | for (let callback of this.windowListenerQueue) { 124 | // 不能因为某个callback执行失败而影响到后续的callback的执行 125 | try { 126 | callback.apply(this, arguments); 127 | } catch (e) { 128 | console.error(e); 129 | } 130 | } 131 | } 132 | 133 | /** 134 | * 休眠给定的毫秒数 135 | * 136 | * @param mils 要休眠的毫秒数 137 | * @returns {Promise} 138 | */ 139 | async #sleep(mils) { 140 | return new Promise((resolve) => setTimeout(resolve, mils)); 141 | } 142 | 143 | } 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /window-monitor-bypass/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test 5 | 6 | 7 | 8 | 9 | 50 | 51 | 按F12打开开发者工具查看效果 52 | 53 | 54 | --------------------------------------------------------------------------------