@viyzhu/boss-cli-fork 0.7.3 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +111 -85
- package/LICENSE +674 -674
- package/README.md +346 -284
- package/dist/browser/cdp_browser.d.ts +170 -170
- package/dist/browser/cdp_browser.js +674 -674
- package/dist/cli/cliRouter.d.ts.map +1 -1
- package/dist/cli/cliRouter.js +119 -67
- package/dist/cli/cliRouter.js.map +1 -1
- package/dist/common/auth.js +49 -49
- package/dist/common/boss_modal.js +42 -42
- package/dist/common/boss_page_guards.js +247 -247
- package/dist/common/boss_paywall_popup.js +87 -87
- package/dist/common/boss_session_page.js +14 -14
- package/dist/common/boss_sidebar_nav.js +24 -24
- package/dist/common/c_resume_capture.js +61 -61
- package/dist/toolset/action.js +232 -232
- package/dist/toolset/chat.js +437 -437
- package/dist/toolset/deep-search.js +570 -570
- package/dist/toolset/index.d.ts +4 -1
- package/dist/toolset/index.d.ts.map +1 -1
- package/dist/toolset/index.js +3 -2
- package/dist/toolset/index.js.map +1 -1
- package/dist/toolset/jd.js +132 -132
- package/dist/toolset/list.js +48 -48
- package/dist/toolset/normal-search.d.ts +167 -1
- package/dist/toolset/normal-search.d.ts.map +1 -1
- package/dist/toolset/normal-search.js +1276 -165
- package/dist/toolset/normal-search.js.map +1 -1
- package/dist/toolset/recommend.js +207 -207
- package/package.json +69 -69
- package/skills/boss-frontend-analysis/SKILL.md +58 -58
- package/skills/boss-frontend-analysis/agents/openai.yaml +4 -4
- package/skills/boss-frontend-analysis/scripts/capture_boss_frontend.mjs +604 -604
|
@@ -126,253 +126,253 @@ function buildNoContentResponseHeaders(headers) {
|
|
|
126
126
|
* `instanceof PluginArray`、对象形态比对等检测一眼分辨。
|
|
127
127
|
* - 不再覆盖 `window.closed`:`close()` 已经被改写为 noop,`closed` 自然保持原生默认值。
|
|
128
128
|
*/
|
|
129
|
-
const BOSS_PAGE_GUARD_SCRIPT_TEMPLATE = `(function() {
|
|
130
|
-
'use strict';
|
|
131
|
-
|
|
132
|
-
var _Object = Object;
|
|
133
|
-
var _defineProperty = _Object.defineProperty;
|
|
134
|
-
var _getOwnPropertyDescriptor = _Object.getOwnPropertyDescriptor;
|
|
135
|
-
var _Function = Function;
|
|
136
|
-
var _origFunctionToString = _Function.prototype.toString;
|
|
137
|
-
var _String = String;
|
|
138
|
-
var _Map = Map;
|
|
139
|
-
|
|
140
|
-
/** 让我们包装的函数对 fn.toString() 返回 "function NAME() { [native code] }"。 */
|
|
141
|
-
var nativeSourceMap = new _Map();
|
|
142
|
-
var fakeToString = function toString() {
|
|
143
|
-
if (this != null) {
|
|
144
|
-
var mapped = nativeSourceMap.get(this);
|
|
145
|
-
if (typeof mapped === 'string') return mapped;
|
|
146
|
-
}
|
|
147
|
-
return _origFunctionToString.call(this);
|
|
148
|
-
};
|
|
149
|
-
nativeSourceMap.set(fakeToString, 'function toString() { [native code] }');
|
|
150
|
-
try {
|
|
151
|
-
_defineProperty(_Function.prototype, 'toString', {
|
|
152
|
-
value: fakeToString,
|
|
153
|
-
writable: true,
|
|
154
|
-
configurable: true,
|
|
155
|
-
enumerable: false,
|
|
156
|
-
});
|
|
157
|
-
} catch (e) {}
|
|
158
|
-
|
|
159
|
-
/** 包装替身函数:把它伪装成 "function NAME() { [native code] }"。 */
|
|
160
|
-
var asNative = function(replacement, nativeName) {
|
|
161
|
-
var src = 'function ' + nativeName + '() { [native code] }';
|
|
162
|
-
nativeSourceMap.set(replacement, src);
|
|
163
|
-
try {
|
|
164
|
-
_defineProperty(replacement, 'name', {
|
|
165
|
-
value: nativeName,
|
|
166
|
-
writable: false,
|
|
167
|
-
configurable: true,
|
|
168
|
-
enumerable: false,
|
|
169
|
-
});
|
|
170
|
-
} catch (e) {}
|
|
171
|
-
return replacement;
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
/** 替换 prototype 上的方法(保持原 descriptor 形态:默认 configurable+writable)。 */
|
|
175
|
-
var replaceProtoMethod = function(proto, key, replacement) {
|
|
176
|
-
try {
|
|
177
|
-
var desc = _getOwnPropertyDescriptor(proto, key);
|
|
178
|
-
if (!desc) return null;
|
|
179
|
-
if (!desc.configurable) return null;
|
|
180
|
-
_defineProperty(proto, key, {
|
|
181
|
-
value: replacement,
|
|
182
|
-
writable: 'writable' in desc ? !!desc.writable : true,
|
|
183
|
-
configurable: true,
|
|
184
|
-
enumerable: !!desc.enumerable,
|
|
185
|
-
});
|
|
186
|
-
return desc.value;
|
|
187
|
-
} catch (e) {
|
|
188
|
-
return null;
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
/** 改写 prototype 上的 accessor:仅替换 getter/setter,保留 configurable/enumerable 形态。 */
|
|
193
|
-
var replaceProtoAccessor = function(proto, key, options) {
|
|
194
|
-
try {
|
|
195
|
-
var desc = _getOwnPropertyDescriptor(proto, key);
|
|
196
|
-
if (!desc || !desc.configurable) return null;
|
|
197
|
-
var nextDesc = {
|
|
198
|
-
configurable: true,
|
|
199
|
-
enumerable: !!desc.enumerable,
|
|
200
|
-
};
|
|
201
|
-
if (options.get || desc.get) nextDesc.get = options.get || desc.get;
|
|
202
|
-
if (options.set || desc.set) nextDesc.set = options.set || desc.set;
|
|
203
|
-
_defineProperty(proto, key, nextDesc);
|
|
204
|
-
return desc;
|
|
205
|
-
} catch (e) {
|
|
206
|
-
return null;
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
// ===== navigator.webdriver:在 Navigator.prototype 上覆盖 getter,保持 accessor 形态 =====
|
|
211
|
-
try {
|
|
212
|
-
var navProto = Object.getPrototypeOf(navigator);
|
|
213
|
-
if (navProto) {
|
|
214
|
-
replaceProtoAccessor(navProto, 'webdriver', {
|
|
215
|
-
get: asNative(function() { return false; }, 'get webdriver'),
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
} catch (e) {}
|
|
219
|
-
|
|
220
|
-
// ===== navigator.languages:仅在为空时回填,使用 prototype getter =====
|
|
221
|
-
try {
|
|
222
|
-
if (!navigator.languages || navigator.languages.length === 0) {
|
|
223
|
-
var navProto2 = Object.getPrototypeOf(navigator);
|
|
224
|
-
if (navProto2) {
|
|
225
|
-
var langs = ['zh-CN', 'zh', 'en'];
|
|
226
|
-
replaceProtoAccessor(navProto2, 'languages', {
|
|
227
|
-
get: asNative(function() { return langs; }, 'get languages'),
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
} catch (e) {}
|
|
232
|
-
|
|
233
|
-
// ===== window.close:改为空函数(保留 native 形态)=====
|
|
234
|
-
try {
|
|
235
|
-
var winProto = Object.getPrototypeOf(window);
|
|
236
|
-
if (winProto) {
|
|
237
|
-
replaceProtoMethod(winProto, 'close', asNative(function close() {}, 'close'));
|
|
238
|
-
}
|
|
239
|
-
} catch (e) {}
|
|
240
|
-
|
|
241
|
-
// ===== history.back / forward / go =====
|
|
242
|
-
try {
|
|
243
|
-
var historyProto = Object.getPrototypeOf(history);
|
|
244
|
-
if (historyProto) {
|
|
245
|
-
var origGo = historyProto.go;
|
|
246
|
-
replaceProtoMethod(historyProto, 'back', asNative(function back() {}, 'back'));
|
|
247
|
-
replaceProtoMethod(historyProto, 'forward', asNative(function forward() {}, 'forward'));
|
|
248
|
-
replaceProtoMethod(historyProto, 'go', asNative(function go(n) {
|
|
249
|
-
if (typeof n === 'number' && n < 0) return undefined;
|
|
250
|
-
return origGo.call(this, n);
|
|
251
|
-
}, 'go'));
|
|
252
|
-
}
|
|
253
|
-
} catch (e) {}
|
|
254
|
-
|
|
255
|
-
// ===== Location.assign / replace / href setter =====
|
|
256
|
-
var BLOCK_PATH = /\\/web\\/common\\/(?:403|nonsupport)\\.html|\\/web\\/user\\/safe\\/verify|\\/web\\/passport\\/(?:zp\\/(?:403|verify|security)\\.html|cm\\/(?:403|verify|security-check)\\.html)/i;
|
|
257
|
-
var isBlockedTarget = function(value) {
|
|
258
|
-
var s = _String(value);
|
|
259
|
-
if (s === 'about:blank') return true;
|
|
260
|
-
return BLOCK_PATH.test(s);
|
|
261
|
-
};
|
|
262
|
-
try {
|
|
263
|
-
var locProto = Location.prototype;
|
|
264
|
-
var origAssign = locProto.assign;
|
|
265
|
-
var origReplace = locProto.replace;
|
|
266
|
-
replaceProtoMethod(locProto, 'assign', asNative(function assign(url) {
|
|
267
|
-
if (isBlockedTarget(url)) return undefined;
|
|
268
|
-
return origAssign.call(this, url);
|
|
269
|
-
}, 'assign'));
|
|
270
|
-
replaceProtoMethod(locProto, 'replace', asNative(function replace(url) {
|
|
271
|
-
if (isBlockedTarget(url)) return undefined;
|
|
272
|
-
return origReplace.call(this, url);
|
|
273
|
-
}, 'replace'));
|
|
274
|
-
|
|
275
|
-
var hrefDesc = _getOwnPropertyDescriptor(locProto, 'href');
|
|
276
|
-
if (hrefDesc && hrefDesc.configurable && hrefDesc.set) {
|
|
277
|
-
var origHrefSet = hrefDesc.set;
|
|
278
|
-
_defineProperty(locProto, 'href', {
|
|
279
|
-
get: hrefDesc.get,
|
|
280
|
-
set: asNative(function(value) {
|
|
281
|
-
if (isBlockedTarget(value)) return undefined;
|
|
282
|
-
return origHrefSet.call(this, value);
|
|
283
|
-
}, 'set href'),
|
|
284
|
-
configurable: true,
|
|
285
|
-
enumerable: !!hrefDesc.enumerable,
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
} catch (e) {}
|
|
289
|
-
|
|
290
|
-
// ===== console.clear:可选替身,原生形态空函数 =====
|
|
291
|
-
if (!__SHOULD_ALLOW_CONSOLE_CLEAR__) {
|
|
292
|
-
try {
|
|
293
|
-
var consoleProtoForClear = Object.getPrototypeOf(console);
|
|
294
|
-
var ownClearDesc = Object.getOwnPropertyDescriptor(console, 'clear');
|
|
295
|
-
var protoClearDesc = consoleProtoForClear
|
|
296
|
-
? _getOwnPropertyDescriptor(consoleProtoForClear, 'clear')
|
|
297
|
-
: null;
|
|
298
|
-
var clearSrcDesc = ownClearDesc || protoClearDesc;
|
|
299
|
-
if (clearSrcDesc && typeof clearSrcDesc.value === 'function') {
|
|
300
|
-
try {
|
|
301
|
-
_defineProperty(console, 'clear', {
|
|
302
|
-
value: asNative(function clear() {}, 'clear'),
|
|
303
|
-
writable: 'writable' in clearSrcDesc ? clearSrcDesc.writable !== false : true,
|
|
304
|
-
configurable: true,
|
|
305
|
-
enumerable: !!clearSrcDesc.enumerable,
|
|
306
|
-
});
|
|
307
|
-
} catch (_) {}
|
|
308
|
-
}
|
|
309
|
-
} catch (e) {}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// ===== console 时间差探测对抗 =====
|
|
313
|
-
// 主包用 \`console.log\` / \`console.table\` 重复打印大对象(典型:50 次 × 0..500 数组),
|
|
314
|
-
// 比较前后 \`performance.now()\`,DevTools 打开时 V8 inspector 会把对象逐一序列化送去,
|
|
315
|
-
// 耗时显著上升即判定 DevTools 打开。对抗手段:把所有对象参数在我们这层先归一化为
|
|
316
|
-
// \`[object Type]\` 这种 O(1) 字符串再交给原生方法,inspector 序列化路径只看到短字符串,
|
|
317
|
-
// 耗时不再随 DevTools 状态变化。代价:DevTools 控制台中对象会显示成 \`[object Type]\`,
|
|
318
|
-
// 失去对象树展开 UX;断点 / Watch / Sources / 调用栈不受影响。
|
|
319
|
-
if (!__SHOULD_ALLOW_VERBOSE_CONSOLE__) {
|
|
320
|
-
try {
|
|
321
|
-
var _objToString = Object.prototype.toString;
|
|
322
|
-
var sanitizeArgs = function(rawArgs) {
|
|
323
|
-
var len = rawArgs.length;
|
|
324
|
-
var out = new Array(len);
|
|
325
|
-
for (var i = 0; i < len; i++) {
|
|
326
|
-
var a = rawArgs[i];
|
|
327
|
-
if (a !== null && typeof a === 'object') {
|
|
328
|
-
try {
|
|
329
|
-
out[i] = _objToString.call(a);
|
|
330
|
-
} catch (_) {
|
|
331
|
-
out[i] = '[object Object]';
|
|
332
|
-
}
|
|
333
|
-
} else if (typeof a === 'function') {
|
|
334
|
-
// 函数也别交给 inspector,避免 toString 串走慢路径
|
|
335
|
-
out[i] = '[Function: ' + (a.name || 'anonymous') + ']';
|
|
336
|
-
} else {
|
|
337
|
-
out[i] = a;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
return out;
|
|
341
|
-
};
|
|
342
|
-
var consoleProtoForLog = Object.getPrototypeOf(console);
|
|
343
|
-
var consoleMethodNames = [
|
|
344
|
-
'log', 'info', 'debug', 'warn', 'error',
|
|
345
|
-
'table', 'dir', 'dirxml', 'trace',
|
|
346
|
-
'group', 'groupCollapsed',
|
|
347
|
-
];
|
|
348
|
-
for (var ci = 0; ci < consoleMethodNames.length; ci++) {
|
|
349
|
-
(function(method) {
|
|
350
|
-
// Chrome 把这些方法挂在 console 实例的 own property 上;
|
|
351
|
-
// 部分浏览器(含历史 Firefox)会挂在 Console.prototype 上。
|
|
352
|
-
// 优先取 own,否则退回 prototype;patch 一律 define 到实例上,
|
|
353
|
-
// 这样既能覆盖 own 写法,又能在 prototype 形态下 shadow 掉原方法。
|
|
354
|
-
var ownDesc = Object.getOwnPropertyDescriptor(console, method);
|
|
355
|
-
var protoDesc = consoleProtoForLog
|
|
356
|
-
? _getOwnPropertyDescriptor(consoleProtoForLog, method)
|
|
357
|
-
: null;
|
|
358
|
-
var srcDesc = ownDesc || protoDesc;
|
|
359
|
-
if (!srcDesc || typeof srcDesc.value !== 'function') return;
|
|
360
|
-
var orig = srcDesc.value;
|
|
361
|
-
var wrapped = asNative(function() {
|
|
362
|
-
return orig.apply(this, sanitizeArgs(arguments));
|
|
363
|
-
}, method);
|
|
364
|
-
try {
|
|
365
|
-
_defineProperty(console, method, {
|
|
366
|
-
value: wrapped,
|
|
367
|
-
writable: 'writable' in srcDesc ? srcDesc.writable !== false : true,
|
|
368
|
-
configurable: true,
|
|
369
|
-
enumerable: !!srcDesc.enumerable,
|
|
370
|
-
});
|
|
371
|
-
} catch (_) {}
|
|
372
|
-
})(consoleMethodNames[ci]);
|
|
373
|
-
}
|
|
374
|
-
} catch (e) {}
|
|
375
|
-
}
|
|
129
|
+
const BOSS_PAGE_GUARD_SCRIPT_TEMPLATE = `(function() {
|
|
130
|
+
'use strict';
|
|
131
|
+
|
|
132
|
+
var _Object = Object;
|
|
133
|
+
var _defineProperty = _Object.defineProperty;
|
|
134
|
+
var _getOwnPropertyDescriptor = _Object.getOwnPropertyDescriptor;
|
|
135
|
+
var _Function = Function;
|
|
136
|
+
var _origFunctionToString = _Function.prototype.toString;
|
|
137
|
+
var _String = String;
|
|
138
|
+
var _Map = Map;
|
|
139
|
+
|
|
140
|
+
/** 让我们包装的函数对 fn.toString() 返回 "function NAME() { [native code] }"。 */
|
|
141
|
+
var nativeSourceMap = new _Map();
|
|
142
|
+
var fakeToString = function toString() {
|
|
143
|
+
if (this != null) {
|
|
144
|
+
var mapped = nativeSourceMap.get(this);
|
|
145
|
+
if (typeof mapped === 'string') return mapped;
|
|
146
|
+
}
|
|
147
|
+
return _origFunctionToString.call(this);
|
|
148
|
+
};
|
|
149
|
+
nativeSourceMap.set(fakeToString, 'function toString() { [native code] }');
|
|
150
|
+
try {
|
|
151
|
+
_defineProperty(_Function.prototype, 'toString', {
|
|
152
|
+
value: fakeToString,
|
|
153
|
+
writable: true,
|
|
154
|
+
configurable: true,
|
|
155
|
+
enumerable: false,
|
|
156
|
+
});
|
|
157
|
+
} catch (e) {}
|
|
158
|
+
|
|
159
|
+
/** 包装替身函数:把它伪装成 "function NAME() { [native code] }"。 */
|
|
160
|
+
var asNative = function(replacement, nativeName) {
|
|
161
|
+
var src = 'function ' + nativeName + '() { [native code] }';
|
|
162
|
+
nativeSourceMap.set(replacement, src);
|
|
163
|
+
try {
|
|
164
|
+
_defineProperty(replacement, 'name', {
|
|
165
|
+
value: nativeName,
|
|
166
|
+
writable: false,
|
|
167
|
+
configurable: true,
|
|
168
|
+
enumerable: false,
|
|
169
|
+
});
|
|
170
|
+
} catch (e) {}
|
|
171
|
+
return replacement;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
/** 替换 prototype 上的方法(保持原 descriptor 形态:默认 configurable+writable)。 */
|
|
175
|
+
var replaceProtoMethod = function(proto, key, replacement) {
|
|
176
|
+
try {
|
|
177
|
+
var desc = _getOwnPropertyDescriptor(proto, key);
|
|
178
|
+
if (!desc) return null;
|
|
179
|
+
if (!desc.configurable) return null;
|
|
180
|
+
_defineProperty(proto, key, {
|
|
181
|
+
value: replacement,
|
|
182
|
+
writable: 'writable' in desc ? !!desc.writable : true,
|
|
183
|
+
configurable: true,
|
|
184
|
+
enumerable: !!desc.enumerable,
|
|
185
|
+
});
|
|
186
|
+
return desc.value;
|
|
187
|
+
} catch (e) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/** 改写 prototype 上的 accessor:仅替换 getter/setter,保留 configurable/enumerable 形态。 */
|
|
193
|
+
var replaceProtoAccessor = function(proto, key, options) {
|
|
194
|
+
try {
|
|
195
|
+
var desc = _getOwnPropertyDescriptor(proto, key);
|
|
196
|
+
if (!desc || !desc.configurable) return null;
|
|
197
|
+
var nextDesc = {
|
|
198
|
+
configurable: true,
|
|
199
|
+
enumerable: !!desc.enumerable,
|
|
200
|
+
};
|
|
201
|
+
if (options.get || desc.get) nextDesc.get = options.get || desc.get;
|
|
202
|
+
if (options.set || desc.set) nextDesc.set = options.set || desc.set;
|
|
203
|
+
_defineProperty(proto, key, nextDesc);
|
|
204
|
+
return desc;
|
|
205
|
+
} catch (e) {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
// ===== navigator.webdriver:在 Navigator.prototype 上覆盖 getter,保持 accessor 形态 =====
|
|
211
|
+
try {
|
|
212
|
+
var navProto = Object.getPrototypeOf(navigator);
|
|
213
|
+
if (navProto) {
|
|
214
|
+
replaceProtoAccessor(navProto, 'webdriver', {
|
|
215
|
+
get: asNative(function() { return false; }, 'get webdriver'),
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
} catch (e) {}
|
|
219
|
+
|
|
220
|
+
// ===== navigator.languages:仅在为空时回填,使用 prototype getter =====
|
|
221
|
+
try {
|
|
222
|
+
if (!navigator.languages || navigator.languages.length === 0) {
|
|
223
|
+
var navProto2 = Object.getPrototypeOf(navigator);
|
|
224
|
+
if (navProto2) {
|
|
225
|
+
var langs = ['zh-CN', 'zh', 'en'];
|
|
226
|
+
replaceProtoAccessor(navProto2, 'languages', {
|
|
227
|
+
get: asNative(function() { return langs; }, 'get languages'),
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
} catch (e) {}
|
|
232
|
+
|
|
233
|
+
// ===== window.close:改为空函数(保留 native 形态)=====
|
|
234
|
+
try {
|
|
235
|
+
var winProto = Object.getPrototypeOf(window);
|
|
236
|
+
if (winProto) {
|
|
237
|
+
replaceProtoMethod(winProto, 'close', asNative(function close() {}, 'close'));
|
|
238
|
+
}
|
|
239
|
+
} catch (e) {}
|
|
240
|
+
|
|
241
|
+
// ===== history.back / forward / go =====
|
|
242
|
+
try {
|
|
243
|
+
var historyProto = Object.getPrototypeOf(history);
|
|
244
|
+
if (historyProto) {
|
|
245
|
+
var origGo = historyProto.go;
|
|
246
|
+
replaceProtoMethod(historyProto, 'back', asNative(function back() {}, 'back'));
|
|
247
|
+
replaceProtoMethod(historyProto, 'forward', asNative(function forward() {}, 'forward'));
|
|
248
|
+
replaceProtoMethod(historyProto, 'go', asNative(function go(n) {
|
|
249
|
+
if (typeof n === 'number' && n < 0) return undefined;
|
|
250
|
+
return origGo.call(this, n);
|
|
251
|
+
}, 'go'));
|
|
252
|
+
}
|
|
253
|
+
} catch (e) {}
|
|
254
|
+
|
|
255
|
+
// ===== Location.assign / replace / href setter =====
|
|
256
|
+
var BLOCK_PATH = /\\/web\\/common\\/(?:403|nonsupport)\\.html|\\/web\\/user\\/safe\\/verify|\\/web\\/passport\\/(?:zp\\/(?:403|verify|security)\\.html|cm\\/(?:403|verify|security-check)\\.html)/i;
|
|
257
|
+
var isBlockedTarget = function(value) {
|
|
258
|
+
var s = _String(value);
|
|
259
|
+
if (s === 'about:blank') return true;
|
|
260
|
+
return BLOCK_PATH.test(s);
|
|
261
|
+
};
|
|
262
|
+
try {
|
|
263
|
+
var locProto = Location.prototype;
|
|
264
|
+
var origAssign = locProto.assign;
|
|
265
|
+
var origReplace = locProto.replace;
|
|
266
|
+
replaceProtoMethod(locProto, 'assign', asNative(function assign(url) {
|
|
267
|
+
if (isBlockedTarget(url)) return undefined;
|
|
268
|
+
return origAssign.call(this, url);
|
|
269
|
+
}, 'assign'));
|
|
270
|
+
replaceProtoMethod(locProto, 'replace', asNative(function replace(url) {
|
|
271
|
+
if (isBlockedTarget(url)) return undefined;
|
|
272
|
+
return origReplace.call(this, url);
|
|
273
|
+
}, 'replace'));
|
|
274
|
+
|
|
275
|
+
var hrefDesc = _getOwnPropertyDescriptor(locProto, 'href');
|
|
276
|
+
if (hrefDesc && hrefDesc.configurable && hrefDesc.set) {
|
|
277
|
+
var origHrefSet = hrefDesc.set;
|
|
278
|
+
_defineProperty(locProto, 'href', {
|
|
279
|
+
get: hrefDesc.get,
|
|
280
|
+
set: asNative(function(value) {
|
|
281
|
+
if (isBlockedTarget(value)) return undefined;
|
|
282
|
+
return origHrefSet.call(this, value);
|
|
283
|
+
}, 'set href'),
|
|
284
|
+
configurable: true,
|
|
285
|
+
enumerable: !!hrefDesc.enumerable,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
} catch (e) {}
|
|
289
|
+
|
|
290
|
+
// ===== console.clear:可选替身,原生形态空函数 =====
|
|
291
|
+
if (!__SHOULD_ALLOW_CONSOLE_CLEAR__) {
|
|
292
|
+
try {
|
|
293
|
+
var consoleProtoForClear = Object.getPrototypeOf(console);
|
|
294
|
+
var ownClearDesc = Object.getOwnPropertyDescriptor(console, 'clear');
|
|
295
|
+
var protoClearDesc = consoleProtoForClear
|
|
296
|
+
? _getOwnPropertyDescriptor(consoleProtoForClear, 'clear')
|
|
297
|
+
: null;
|
|
298
|
+
var clearSrcDesc = ownClearDesc || protoClearDesc;
|
|
299
|
+
if (clearSrcDesc && typeof clearSrcDesc.value === 'function') {
|
|
300
|
+
try {
|
|
301
|
+
_defineProperty(console, 'clear', {
|
|
302
|
+
value: asNative(function clear() {}, 'clear'),
|
|
303
|
+
writable: 'writable' in clearSrcDesc ? clearSrcDesc.writable !== false : true,
|
|
304
|
+
configurable: true,
|
|
305
|
+
enumerable: !!clearSrcDesc.enumerable,
|
|
306
|
+
});
|
|
307
|
+
} catch (_) {}
|
|
308
|
+
}
|
|
309
|
+
} catch (e) {}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// ===== console 时间差探测对抗 =====
|
|
313
|
+
// 主包用 \`console.log\` / \`console.table\` 重复打印大对象(典型:50 次 × 0..500 数组),
|
|
314
|
+
// 比较前后 \`performance.now()\`,DevTools 打开时 V8 inspector 会把对象逐一序列化送去,
|
|
315
|
+
// 耗时显著上升即判定 DevTools 打开。对抗手段:把所有对象参数在我们这层先归一化为
|
|
316
|
+
// \`[object Type]\` 这种 O(1) 字符串再交给原生方法,inspector 序列化路径只看到短字符串,
|
|
317
|
+
// 耗时不再随 DevTools 状态变化。代价:DevTools 控制台中对象会显示成 \`[object Type]\`,
|
|
318
|
+
// 失去对象树展开 UX;断点 / Watch / Sources / 调用栈不受影响。
|
|
319
|
+
if (!__SHOULD_ALLOW_VERBOSE_CONSOLE__) {
|
|
320
|
+
try {
|
|
321
|
+
var _objToString = Object.prototype.toString;
|
|
322
|
+
var sanitizeArgs = function(rawArgs) {
|
|
323
|
+
var len = rawArgs.length;
|
|
324
|
+
var out = new Array(len);
|
|
325
|
+
for (var i = 0; i < len; i++) {
|
|
326
|
+
var a = rawArgs[i];
|
|
327
|
+
if (a !== null && typeof a === 'object') {
|
|
328
|
+
try {
|
|
329
|
+
out[i] = _objToString.call(a);
|
|
330
|
+
} catch (_) {
|
|
331
|
+
out[i] = '[object Object]';
|
|
332
|
+
}
|
|
333
|
+
} else if (typeof a === 'function') {
|
|
334
|
+
// 函数也别交给 inspector,避免 toString 串走慢路径
|
|
335
|
+
out[i] = '[Function: ' + (a.name || 'anonymous') + ']';
|
|
336
|
+
} else {
|
|
337
|
+
out[i] = a;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return out;
|
|
341
|
+
};
|
|
342
|
+
var consoleProtoForLog = Object.getPrototypeOf(console);
|
|
343
|
+
var consoleMethodNames = [
|
|
344
|
+
'log', 'info', 'debug', 'warn', 'error',
|
|
345
|
+
'table', 'dir', 'dirxml', 'trace',
|
|
346
|
+
'group', 'groupCollapsed',
|
|
347
|
+
];
|
|
348
|
+
for (var ci = 0; ci < consoleMethodNames.length; ci++) {
|
|
349
|
+
(function(method) {
|
|
350
|
+
// Chrome 把这些方法挂在 console 实例的 own property 上;
|
|
351
|
+
// 部分浏览器(含历史 Firefox)会挂在 Console.prototype 上。
|
|
352
|
+
// 优先取 own,否则退回 prototype;patch 一律 define 到实例上,
|
|
353
|
+
// 这样既能覆盖 own 写法,又能在 prototype 形态下 shadow 掉原方法。
|
|
354
|
+
var ownDesc = Object.getOwnPropertyDescriptor(console, method);
|
|
355
|
+
var protoDesc = consoleProtoForLog
|
|
356
|
+
? _getOwnPropertyDescriptor(consoleProtoForLog, method)
|
|
357
|
+
: null;
|
|
358
|
+
var srcDesc = ownDesc || protoDesc;
|
|
359
|
+
if (!srcDesc || typeof srcDesc.value !== 'function') return;
|
|
360
|
+
var orig = srcDesc.value;
|
|
361
|
+
var wrapped = asNative(function() {
|
|
362
|
+
return orig.apply(this, sanitizeArgs(arguments));
|
|
363
|
+
}, method);
|
|
364
|
+
try {
|
|
365
|
+
_defineProperty(console, method, {
|
|
366
|
+
value: wrapped,
|
|
367
|
+
writable: 'writable' in srcDesc ? srcDesc.writable !== false : true,
|
|
368
|
+
configurable: true,
|
|
369
|
+
enumerable: !!srcDesc.enumerable,
|
|
370
|
+
});
|
|
371
|
+
} catch (_) {}
|
|
372
|
+
})(consoleMethodNames[ci]);
|
|
373
|
+
}
|
|
374
|
+
} catch (e) {}
|
|
375
|
+
}
|
|
376
376
|
})();`;
|
|
377
377
|
function buildPageGuardScript() {
|
|
378
378
|
return BOSS_PAGE_GUARD_SCRIPT_TEMPLATE
|