├── .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 |
--------------------------------------------------------------------------------