http_mimic 0.5.3 → 0.5.5

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.
@@ -0,0 +1,1297 @@
1
+ // Virtual Browser Environment Polyfill for QuickJS
2
+ (function(global) {
3
+ "use strict";
4
+
5
+ // 1. Establish window hierarchy
6
+ global.window = global;
7
+ global.self = global;
8
+ global.top = global;
9
+ global.parent = global;
10
+ global.name = "";
11
+ global.innerWidth = 1920;
12
+ global.innerHeight = 960;
13
+ global.outerWidth = 1920;
14
+ global.outerHeight = 1080;
15
+ global.screenX = 0;
16
+ global.screenY = 25;
17
+ global.screenLeft = 0;
18
+ global.screenTop = 25;
19
+ global.crossOriginIsolated = false;
20
+ global.isSecureContext = true;
21
+ global.devicePixelRatio = 2;
22
+ global.chrome = {
23
+ app: { isInstalled: false, InstallState: { DISABLED: "disabled", INSTALLED: "installed", NOT_INSTALLED: "not_installed" }, RunningState: { CANNOT_RUN: "cannot_run", READY_TO_RUN: "ready_to_run", RUNNING: "running" } },
24
+ runtime: { id: undefined }
25
+ };
26
+
27
+ // Helper to make functions look like native functions & shield from prototype inspection
28
+ const nativeFnMap = new WeakMap();
29
+ const oldFunctionToString = Function.prototype.toString;
30
+
31
+ function patchNative(fn, name) {
32
+ if (!fn) return fn;
33
+ try {
34
+ Object.defineProperty(fn, "name", { value: name, configurable: true });
35
+ } catch(e) {}
36
+ const nativeStr = "function " + name + "() { [native code] }";
37
+ nativeFnMap.set(fn, nativeStr);
38
+ try {
39
+ fn.toString = function() { return nativeStr; };
40
+ nativeFnMap.set(fn.toString, "function toString() { [native code] }");
41
+ } catch(e) {}
42
+ return fn;
43
+ }
44
+
45
+ Function.prototype.toString = function() {
46
+ if (nativeFnMap.has(this)) {
47
+ return nativeFnMap.get(this);
48
+ }
49
+ return oldFunctionToString.call(this);
50
+ };
51
+ patchNative(Function.prototype.toString, "toString");
52
+
53
+ // V8 Error Stack Trace Helpers
54
+ if (!Error.captureStackTrace) {
55
+ Error.captureStackTrace = patchNative(function(targetObj, constructorOpt) {
56
+ const err = new Error();
57
+ targetObj.stack = err.stack;
58
+ }, "captureStackTrace");
59
+ }
60
+
61
+ // Modern browser global APIs
62
+ function fetch(input, init) {
63
+ return Promise.resolve({
64
+ ok: true,
65
+ status: 200,
66
+ statusText: "OK",
67
+ headers: { get: function() { return null; } },
68
+ text: patchNative(function() { return Promise.resolve(""); }, "text"),
69
+ json: patchNative(function() { return Promise.resolve({}); }, "json"),
70
+ blob: patchNative(function() { return Promise.resolve({}); }, "blob")
71
+ });
72
+ }
73
+ patchNative(fetch, "fetch");
74
+ global.fetch = fetch;
75
+
76
+ function Notification(title, options) {
77
+ this.title = String(title || "");
78
+ }
79
+ Notification.permission = "default";
80
+ Notification.requestPermission = patchNative(function() {
81
+ return Promise.resolve("default");
82
+ }, "requestPermission");
83
+ patchNative(Notification, "Notification");
84
+ global.Notification = Notification;
85
+
86
+ const speechSynthesis = {
87
+ pending: false,
88
+ speaking: false,
89
+ paused: false,
90
+ onvoiceschanged: null,
91
+ getVoices: patchNative(function() { return []; }, "getVoices"),
92
+ speak: patchNative(function() {}, "speak"),
93
+ cancel: patchNative(function() {}, "cancel"),
94
+ pause: patchNative(function() {}, "pause"),
95
+ resume: patchNative(function() {}, "resume"),
96
+ addEventListener: patchNative(function() {}, "addEventListener"),
97
+ removeEventListener: patchNative(function() {}, "removeEventListener"),
98
+ dispatchEvent: patchNative(function() { return true; }, "dispatchEvent")
99
+ };
100
+ Object.defineProperty(global, "speechSynthesis", { value: speechSynthesis, writable: true, configurable: true });
101
+
102
+ // 2. Base Prototypes & WebIDL hierarchy
103
+ function EventTarget() {}
104
+ function Node() {}
105
+ function Element() {}
106
+ function HTMLElement() {}
107
+ function HTMLDocument() {}
108
+ function Document() {}
109
+ function Window() {}
110
+
111
+ Object.setPrototypeOf(Node.prototype, EventTarget.prototype);
112
+ Object.setPrototypeOf(Element.prototype, Node.prototype);
113
+ Object.setPrototypeOf(HTMLElement.prototype, Element.prototype);
114
+ Object.setPrototypeOf(Document.prototype, Node.prototype);
115
+ Object.setPrototypeOf(HTMLDocument.prototype, Document.prototype);
116
+
117
+ patchNative(EventTarget, "EventTarget");
118
+ patchNative(Node, "Node");
119
+ patchNative(Element, "Element");
120
+ patchNative(HTMLElement, "HTMLElement");
121
+ patchNative(Document, "Document");
122
+ patchNative(HTMLDocument, "HTMLDocument");
123
+ patchNative(Window, "Window");
124
+
125
+ global.EventTarget = EventTarget;
126
+ global.Node = Node;
127
+ global.Element = Element;
128
+ global.HTMLElement = HTMLElement;
129
+ global.Document = Document;
130
+ global.HTMLDocument = HTMLDocument;
131
+ global.Window = Window;
132
+
133
+ // Generic constructor generator
134
+ const genericConstructors = [
135
+ "HTMLDivElement", "HTMLSpanElement", "HTMLImageElement", "HTMLAnchorElement",
136
+ "HTMLHeadElement", "HTMLBodyElement", "HTMLScriptElement", "HTMLStyleElement",
137
+ "HTMLLinkElement", "HTMLMetaElement", "HTMLTitleElement", "HTMLParagraphElement",
138
+ "HTMLHeadingElement", "HTMLInputElement", "HTMLButtonElement", "HTMLFormElement",
139
+ "HTMLSelectElement", "HTMLOptionElement", "HTMLTextAreaElement", "HTMLTableElement",
140
+ "HTMLTableRowElement", "HTMLTableCellElement", "HTMLAudioElement", "HTMLVideoElement",
141
+ "HTMLIFrameElement", "HTMLCanvasElement", "CanvasRenderingContext2D", "WebGLRenderingContext",
142
+ "WebGL2RenderingContext", "AudioContext", "webkitAudioContext", "OfflineAudioContext",
143
+ "AudioBuffer", "AudioNode", "GainNode", "OscillatorNode", "DynamicsCompressorNode",
144
+ "AnalyserNode", "Event", "CustomEvent", "UIEvent", "MouseEvent", "KeyboardEvent",
145
+ "TouchEvent", "PointerEvent", "FocusEvent", "InputEvent", "WheelEvent",
146
+ "DeviceOrientationEvent", "DeviceMotionEvent", "Performance", "PerformanceEntry",
147
+ "PerformanceNavigationTiming", "PerformanceResourceTiming", "Storage", "File",
148
+ "FileList", "FileReader", "Blob", "FormData", "Headers", "Request", "Response",
149
+ "AbortController", "AbortSignal", "WebSocket", "Worker", "SharedWorker", "ServiceWorker",
150
+ "MutationObserver", "IntersectionObserver", "ResizeObserver", "PerformanceObserver",
151
+ "URLSearchParams", "DOMParser", "XMLSerializer", "XPathEvaluator", "XPathResult",
152
+ "MediaStream", "RTCPeerConnection", "IDBFactory", "IDBDatabase", "Cache", "CacheStorage",
153
+ "Credential", "CredentialsContainer", "Navigator", "Screen", "History", "Location",
154
+ "BarProp", "VisualViewport", "SpeechSynthesis", "SpeechSynthesisUtterance",
155
+ "PaymentRequest", "Bluetooth", "USB", "HID", "Serial", "XRSystem", "WakeLock",
156
+ "Geolocation", "BatteryManager", "NetworkInformation", "Permissions", "PermissionStatus"
157
+ ];
158
+
159
+ genericConstructors.forEach(name => {
160
+ if (typeof global[name] === "undefined") {
161
+ function Ctor() {}
162
+ Ctor.prototype = Object.create(HTMLElement.prototype);
163
+ Ctor.prototype.constructor = Ctor;
164
+ patchNative(Ctor, name);
165
+ global[name] = Ctor;
166
+ }
167
+ });
168
+
169
+ function parseUrlComponents(urlString, baseUrl) {
170
+ let str = String(urlString || "");
171
+ if (!str.startsWith("http://") && !str.startsWith("https://")) {
172
+ const base = baseUrl || (typeof location !== "undefined" ? location.href : (global.__TARGET_URL__ || "http://localhost/"));
173
+ if (str.startsWith("//")) {
174
+ const proto = (typeof location !== "undefined" ? location.protocol : "https:");
175
+ str = proto + str;
176
+ } else if (str.startsWith("/")) {
177
+ const orig = (typeof location !== "undefined" ? location.origin : "http://localhost");
178
+ str = orig + str;
179
+ } else {
180
+ const orig = (typeof location !== "undefined" ? location.origin : "http://localhost");
181
+ str = orig + "/" + str;
182
+ }
183
+ }
184
+ const match = str.match(/^(https?:)\/\/([^/:?#]+)(?::(\d+))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?$/);
185
+ if (!match) return { href: str, protocol: "https:", host: "", hostname: "", port: "", pathname: "/", search: "", hash: "", origin: "" };
186
+ const proto = match[1];
187
+ const hostName = match[2];
188
+ const portNum = match[3] || "";
189
+ const fullHost = portNum ? `${hostName}:${portNum}` : hostName;
190
+ return {
191
+ href: str,
192
+ protocol: proto,
193
+ hostname: hostName,
194
+ port: portNum,
195
+ host: fullHost,
196
+ origin: `${proto}//${fullHost}`,
197
+ pathname: match[4] || "/",
198
+ search: match[5] ? `?${match[5]}` : "",
199
+ hash: match[6] ? `#${match[6]}` : ""
200
+ };
201
+ }
202
+
203
+ function MockURL(url, base) {
204
+ const p = parseUrlComponents(url, base);
205
+ Object.assign(this, p);
206
+ this.toString = function() { return this.href; };
207
+ }
208
+ patchNative(MockURL, "URL");
209
+ global.URL = MockURL;
210
+
211
+ // 3. Location object
212
+ const currentUrl = global.__TARGET_URL__ || "http://localhost/";
213
+ const parsedUrl = parseUrlComponents(currentUrl);
214
+
215
+ const location = {
216
+ ...parsedUrl,
217
+ assign: patchNative(function(url) {}, "assign"),
218
+ replace: patchNative(function(url) {}, "replace"),
219
+ reload: patchNative(function() {}, "reload"),
220
+ toString: patchNative(function() { return this.href; }, "toString")
221
+ };
222
+ Object.defineProperty(global, "location", { value: location, writable: true, configurable: true });
223
+
224
+ const history = {
225
+ length: 1,
226
+ scrollRestoration: "auto",
227
+ state: null,
228
+ back: patchNative(function() {}, "back"),
229
+ forward: patchNative(function() {}, "forward"),
230
+ go: patchNative(function(delta) {}, "go"),
231
+ pushState: patchNative(function(state, title, url) { this.state = state; }, "pushState"),
232
+ replaceState: patchNative(function(state, title, url) { this.state = state; }, "replaceState")
233
+ };
234
+ Object.defineProperty(global, "history", { value: history, writable: true, configurable: true });
235
+
236
+ // 4. Navigator object
237
+ const defaultUA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
238
+ const userAgent = global.__USER_AGENT__ || defaultUA;
239
+ const isAndroid = userAgent.includes("Android");
240
+ const isIOS = userAgent.includes("iPhone") || userAgent.includes("iPad");
241
+ const isMobile = isAndroid || isIOS || userAgent.includes("Mobile");
242
+
243
+ const platform = global.__PLATFORM__ || (userAgent.includes("Win") ? "Win32" : (isAndroid ? "Linux armv8l" : (isIOS ? "iPhone" : "MacIntel")));
244
+ const language = global.__LANGUAGE__ || "en-US";
245
+
246
+ if (isMobile) {
247
+ global.innerWidth = 412;
248
+ global.innerHeight = 823;
249
+ global.outerWidth = 412;
250
+ global.outerHeight = 915;
251
+ global.screenX = 0;
252
+ global.screenY = 0;
253
+ global.screenLeft = 0;
254
+ global.screenTop = 0;
255
+ global.devicePixelRatio = 2.625;
256
+ global.ontouchstart = null;
257
+ global.ontouchend = null;
258
+ global.ontouchmove = null;
259
+ global.ontouchcancel = null;
260
+ }
261
+
262
+ const navigator = {
263
+ userAgent: userAgent,
264
+ appVersion: userAgent.replace(/^Mozilla\//, ""),
265
+ appName: "Netscape",
266
+ appCodeName: "Mozilla",
267
+ platform: platform,
268
+ product: "Gecko",
269
+ productSub: "20030107",
270
+ vendor: userAgent.includes("Chrome") || userAgent.includes("Chromium") ? "Google Inc." : (userAgent.includes("Apple") ? "Apple Computer, Inc." : ""),
271
+ vendorSub: "",
272
+ language: language,
273
+ languages: Object.freeze([language, language.split("-")[0]].filter(Boolean)),
274
+ cookieEnabled: true,
275
+ hardwareConcurrency: 8,
276
+ deviceMemory: 8,
277
+ webdriver: false,
278
+ maxTouchPoints: isMobile ? 5 : 0,
279
+ onLine: true,
280
+ doNotTrack: null,
281
+ plugins: (function() {
282
+ const list = isMobile ? [] : [
283
+ { name: "PDF Viewer", filename: "internal-pdf-viewer", description: "Portable Document Format" },
284
+ { name: "Chrome PDF Viewer", filename: "internal-pdf-viewer", description: "Portable Document Format" },
285
+ { name: "Chromium PDF Viewer", filename: "internal-pdf-viewer", description: "Portable Document Format" },
286
+ { name: "Microsoft Edge PDF Viewer", filename: "internal-pdf-viewer", description: "Portable Document Format" },
287
+ { name: "WebKit built-in PDF", filename: "internal-pdf-viewer", description: "Portable Document Format" }
288
+ ];
289
+ list.item = patchNative(function(i) { return list[i] || null; }, "item");
290
+ list.namedItem = patchNative(function(name) { return list.find(p => p.name === name) || null; }, "namedItem");
291
+ list.refresh = patchNative(function() {}, "refresh");
292
+ return Object.freeze(list);
293
+ })(),
294
+ mimeTypes: (function() {
295
+ const list = isMobile ? [] : [
296
+ { type: "application/pdf", suffixes: "pdf", description: "Portable Document Format" },
297
+ { type: "text/pdf", suffixes: "pdf", description: "Portable Document Format" }
298
+ ];
299
+ list.item = patchNative(function(i) { return list[i] || null; }, "item");
300
+ list.namedItem = patchNative(function(type) { return list.find(m => m.type === type) || null; }, "namedItem");
301
+ return Object.freeze(list);
302
+ })(),
303
+ connection: {
304
+ effectiveType: "4g",
305
+ rtt: 50,
306
+ downlink: 10,
307
+ saveData: false,
308
+ addEventListener: patchNative(function() {}, "addEventListener")
309
+ },
310
+ mediaDevices: {
311
+ enumerateDevices: patchNative(function() {
312
+ return Promise.resolve([
313
+ { deviceId: "default", kind: "audioinput", label: "", groupId: "f7a39d8e" },
314
+ { deviceId: "default", kind: "videoinput", label: "", groupId: "f7a39d8e" },
315
+ { deviceId: "default", kind: "audiooutput", label: "", groupId: "f7a39d8e" }
316
+ ]);
317
+ }, "enumerateDevices"),
318
+ addEventListener: patchNative(function() {}, "addEventListener"),
319
+ removeEventListener: patchNative(function() {}, "removeEventListener"),
320
+ dispatchEvent: patchNative(function() { return true; }, "dispatchEvent")
321
+ },
322
+ permissions: {
323
+ query: patchNative(function(desc) {
324
+ const name = (desc && desc.name) || "";
325
+ let state = "granted";
326
+ if (name === "notifications" || name === "geolocation" || name === "camera" || name === "microphone") {
327
+ state = "prompt";
328
+ }
329
+ return Promise.resolve({
330
+ state: state,
331
+ name: name,
332
+ onchange: null,
333
+ addEventListener: patchNative(function() {}, "addEventListener"),
334
+ removeEventListener: patchNative(function() {}, "removeEventListener"),
335
+ dispatchEvent: patchNative(function() { return true; }, "dispatchEvent")
336
+ });
337
+ }, "query")
338
+ },
339
+ userAgentData: {
340
+ brands: Object.freeze([
341
+ { brand: "Chromium", version: (userAgent.match(/Chrome\/(\d+)/) || [null, "131"])[1] },
342
+ { brand: "Not?A_Brand", version: "24" },
343
+ { brand: "Google Chrome", version: (userAgent.match(/Chrome\/(\d+)/) || [null, "131"])[1] }
344
+ ]),
345
+ mobile: isMobile,
346
+ platform: isAndroid ? "Android" : (isIOS ? "iOS" : (platform.includes("Win") ? "Windows" : (platform.includes("Linux") ? "Linux" : "macOS"))),
347
+ getHighEntropyValues: patchNative(function(hints) {
348
+ const ver = (userAgent.match(/Chrome\/(\d+)/) || [null, "131"])[1];
349
+ const fullVer = ver + ".0.6778.86";
350
+ return Promise.resolve({
351
+ architecture: isMobile ? "arm" : "x86",
352
+ bitness: "64",
353
+ brands: this.brands,
354
+ fullVersionList: [
355
+ { brand: "Chromium", version: fullVer },
356
+ { brand: "Not?A_Brand", version: "24.0.0.0" },
357
+ { brand: "Google Chrome", version: fullVer }
358
+ ],
359
+ mobile: this.mobile,
360
+ model: isAndroid ? "K" : "",
361
+ platform: this.platform,
362
+ platformVersion: isAndroid ? "10.0.0" : "13.6.9",
363
+ uaFullVersion: fullVer
364
+ });
365
+ }, "getHighEntropyValues"),
366
+ toJSON: patchNative(function() {
367
+ return { brands: this.brands, mobile: this.mobile, platform: this.platform };
368
+ }, "toJSON")
369
+ },
370
+ getBattery: patchNative(function() {
371
+ return Promise.resolve({
372
+ charging: true,
373
+ chargingTime: 0,
374
+ dischargingTime: Infinity,
375
+ level: 1,
376
+ addEventListener: patchNative(function() {}, "addEventListener")
377
+ });
378
+ }, "getBattery"),
379
+ javaEnabled: patchNative(function() { return false; }, "javaEnabled"),
380
+ vibrate: patchNative(function() { return true; }, "vibrate")
381
+ };
382
+ Object.defineProperty(global, "navigator", { value: navigator, writable: true, configurable: true });
383
+
384
+ // 5. Screen object
385
+ const screen = isMobile ? {
386
+ width: 412,
387
+ height: 915,
388
+ availWidth: 412,
389
+ availHeight: 915,
390
+ colorDepth: 24,
391
+ pixelDepth: 24,
392
+ availLeft: 0,
393
+ availTop: 0,
394
+ orientation: { type: "portrait-primary", angle: 0, addEventListener: function() {} }
395
+ } : {
396
+ width: 1920,
397
+ height: 1080,
398
+ availWidth: 1920,
399
+ availHeight: 1055,
400
+ colorDepth: 24,
401
+ pixelDepth: 24,
402
+ availLeft: 0,
403
+ availTop: 25,
404
+ orientation: { type: "landscape-primary", angle: 0, addEventListener: function() {} }
405
+ };
406
+ Object.defineProperty(global, "screen", { value: screen, writable: true, configurable: true });
407
+
408
+ // 6. DOM Element Factory & Authentic Font Metrics
409
+ const REAL_FONT_METRICS = {
410
+ "monospace": { "12px": [94, 14], "14px": [110, 16], "16px": [125, 19], "20px": [157, 24], "24px": [188, 28], "32px": [250, 38], "72px": [564, 84] },
411
+ "sans-serif": { "12px": [111, 17], "14px": [130, 20], "16px": [148, 22], "20px": [186, 28], "24px": [223, 33], "32px": [297, 45], "72px": [668, 100] },
412
+ "serif": { "12px": [104, 17], "14px": [121, 20], "16px": [139, 22], "20px": [173, 28], "24px": [208, 33], "32px": [277, 45], "72px": [624, 100] },
413
+ "Arial": { "12px": [108, 14], "14px": [126, 16], "16px": [144, 19], "20px": [180, 24], "24px": [216, 28], "32px": [288, 38], "72px": [648, 84] },
414
+ "Times New Roman": { "12px": [104, 14], "14px": [121, 16], "16px": [139, 19], "20px": [173, 24], "24px": [208, 28], "32px": [277, 38], "72px": [624, 84] },
415
+ "Courier New": { "12px": [101, 14], "14px": [118, 16], "16px": [135, 19], "20px": [168, 24], "24px": [202, 28], "32px": [269, 38], "72px": [605, 84] },
416
+ "Helvetica": { "12px": [108, 14], "14px": [126, 16], "16px": [144, 19], "20px": [180, 24], "24px": [216, 28], "32px": [288, 38], "72px": [648, 84] },
417
+ "Verdana": { "12px": [116, 15], "14px": [135, 17], "16px": [154, 20], "20px": [193, 25], "24px": [232, 29], "32px": [309, 39], "72px": [695, 87] },
418
+ "Georgia": { "12px": [109, 14], "14px": [127, 16], "16px": [145, 19], "20px": [182, 24], "24px": [218, 28], "32px": [291, 38], "72px": [655, 84] },
419
+ "Impact": { "12px": [82, 15], "14px": [96, 17], "16px": [109, 20], "20px": [137, 25], "24px": [164, 29], "32px": [219, 39], "72px": [492, 87] },
420
+ "Trebuchet MS": { "12px": [106, 14], "14px": [124, 16], "16px": [141, 19], "20px": [177, 24], "24px": [212, 28], "32px": [283, 38], "72px": [637, 84] },
421
+ "Tahoma": { "12px": [109, 15], "14px": [127, 17], "16px": [145, 20], "20px": [182, 25], "24px": [218, 29], "32px": [291, 39], "72px": [655, 87] }
422
+ };
423
+
424
+ const eventListeners = {};
425
+ const trackedScripts = [];
426
+ function addEventListener(type, listener) {
427
+ if (!eventListeners[type]) eventListeners[type] = [];
428
+ eventListeners[type].push(listener);
429
+ }
430
+ function removeEventListener(type, listener) {
431
+ if (!eventListeners[type]) return;
432
+ eventListeners[type] = eventListeners[type].filter(l => l !== listener);
433
+ }
434
+ function dispatchEvent(evt) {
435
+ const list = eventListeners[evt.type] || [];
436
+ list.forEach(fn => { try { fn(evt); } catch(e) {} });
437
+ }
438
+
439
+ const elementsById = {};
440
+
441
+ function createMockElement(tagName) {
442
+ const tag = tagName.toLowerCase();
443
+ const children = [];
444
+ const attributes = {};
445
+ const style = { display: "block", visibility: "visible" };
446
+
447
+ const el = {
448
+ tagName: tagName.toUpperCase(),
449
+ nodeName: tagName.toUpperCase(),
450
+ nodeType: 1,
451
+ style: style,
452
+ children: children,
453
+ childNodes: children,
454
+ parentNode: null,
455
+ clientWidth: tag === "body" || tag === "html" ? 1920 : 300,
456
+ clientHeight: tag === "body" || tag === "html" ? 1080 : 150,
457
+ offsetWidth: tag === "body" || tag === "html" ? 1920 : 300,
458
+ offsetHeight: tag === "body" || tag === "html" ? 1080 : 150,
459
+ offsetLeft: 0,
460
+ offsetTop: 0,
461
+ id: "",
462
+ className: "",
463
+ innerHTML: "",
464
+ innerText: "",
465
+ textContent: "",
466
+ setAttribute: patchNative(function(k, v) {
467
+ attributes[k] = String(v);
468
+ if (k === "id") {
469
+ el.id = String(v);
470
+ elementsById[el.id] = el;
471
+ }
472
+ }, "setAttribute"),
473
+ getAttribute: patchNative(function(k) { return attributes[k] || null; }, "getAttribute"),
474
+ hasAttribute: patchNative(function(k) { return k in attributes; }, "hasAttribute"),
475
+ removeAttribute: patchNative(function(k) {
476
+ delete attributes[k];
477
+ if (k === "id") { delete elementsById[el.id]; el.id = ""; }
478
+ }, "removeAttribute"),
479
+ appendChild: patchNative(function(child) {
480
+ if (child) {
481
+ child.parentNode = el;
482
+ children.push(child);
483
+ }
484
+ return child;
485
+ }, "appendChild"),
486
+ removeChild: patchNative(function(child) {
487
+ const idx = children.indexOf(child);
488
+ if (idx !== -1) {
489
+ children.splice(idx, 1);
490
+ if (child) child.parentNode = null;
491
+ }
492
+ return child;
493
+ }, "removeChild"),
494
+ remove: patchNative(function() {
495
+ if (el.parentNode) {
496
+ el.parentNode.removeChild(el);
497
+ }
498
+ }, "remove"),
499
+ contains: patchNative(function(child) {
500
+ return children.includes(child);
501
+ }, "contains"),
502
+ insertBefore: patchNative(function(node) {
503
+ if (node) {
504
+ node.parentNode = el;
505
+ children.push(node);
506
+ }
507
+ return node;
508
+ }, "insertBefore"),
509
+ addEventListener: patchNative(addEventListener, "addEventListener"),
510
+ removeEventListener: patchNative(removeEventListener, "removeEventListener"),
511
+ dispatchEvent: patchNative(dispatchEvent, "dispatchEvent"),
512
+ getBoundingClientRect: patchNative(function() {
513
+ return { top: 0, left: 0, right: 300, bottom: 150, width: 300, height: 150, x: 0, y: 0 };
514
+ }, "getBoundingClientRect"),
515
+ getElementsByTagName: patchNative(function(t) {
516
+ const lower = (t || "").toLowerCase();
517
+ if (lower === "script") return trackedScripts.length > 0 ? trackedScripts : [createMockElement("script")];
518
+ return [];
519
+ }, "getElementsByTagName")
520
+ };
521
+
522
+ if (tag === "a") {
523
+ let _href = "";
524
+ Object.defineProperty(el, "href", {
525
+ get() { return _href; },
526
+ set(val) {
527
+ _href = String(val);
528
+ attributes["href"] = _href;
529
+ try {
530
+ const u = new URL(_href, location.href);
531
+ el.protocol = u.protocol;
532
+ el.host = u.host;
533
+ el.hostname = u.hostname;
534
+ el.port = u.port;
535
+ el.pathname = u.pathname;
536
+ el.search = u.search;
537
+ el.hash = u.hash;
538
+ el.origin = u.origin;
539
+ } catch(e) {}
540
+ }
541
+ });
542
+ el.protocol = location.protocol;
543
+ el.host = location.host;
544
+ el.hostname = location.hostname;
545
+ el.port = location.port;
546
+ el.pathname = "/";
547
+ el.search = "";
548
+ el.hash = "";
549
+ el.origin = location.origin;
550
+ }
551
+
552
+ if (tag === "script") {
553
+ let _src = "";
554
+ Object.defineProperty(el, "src", {
555
+ get: function() { return _src; },
556
+ set: function(val) {
557
+ _src = String(val);
558
+ attributes["src"] = _src;
559
+ },
560
+ configurable: true
561
+ });
562
+ trackedScripts.push(el);
563
+ }
564
+
565
+
566
+ Object.defineProperty(el, "offsetWidth", {
567
+ get: function() {
568
+ const family = el.style.fontFamily || "sans-serif";
569
+ const size = el.style.fontSize || "16px";
570
+ for (const font in REAL_FONT_METRICS) {
571
+ if (family.includes(font)) {
572
+ const match = REAL_FONT_METRICS[font][size] || REAL_FONT_METRICS[font]["16px"];
573
+ return match ? match[0] : 148;
574
+ }
575
+ }
576
+ return 148;
577
+ },
578
+ configurable: true
579
+ });
580
+
581
+ Object.defineProperty(el, "offsetHeight", {
582
+ get: function() {
583
+ const family = el.style.fontFamily || "sans-serif";
584
+ const size = el.style.fontSize || "16px";
585
+ for (const font in REAL_FONT_METRICS) {
586
+ if (family.includes(font)) {
587
+ const match = REAL_FONT_METRICS[font][size] || REAL_FONT_METRICS[font]["16px"];
588
+ return match ? match[1] : 22;
589
+ }
590
+ }
591
+ return 22;
592
+ },
593
+ configurable: true
594
+ });
595
+
596
+ if (tag === "canvas") {
597
+ el.getContext = patchNative(function(type) {
598
+ if (type === "2d") {
599
+ return {
600
+ canvas: el,
601
+ fillStyle: "#000",
602
+ strokeStyle: "#000",
603
+ font: "10px sans-serif",
604
+ textBaseline: "alphabetic",
605
+ textAlign: "start",
606
+ fillText: patchNative(function() {}, "fillText"),
607
+ strokeText: patchNative(function() {}, "strokeText"),
608
+ fillRect: patchNative(function() {}, "fillRect"),
609
+ clearRect: patchNative(function() {}, "clearRect"),
610
+ beginPath: patchNative(function() {}, "beginPath"),
611
+ arc: patchNative(function() {}, "arc"),
612
+ closePath: patchNative(function() {}, "closePath"),
613
+ fill: patchNative(function() {}, "fill"),
614
+ stroke: patchNative(function() {}, "stroke"),
615
+ measureText: patchNative(function(txt) {
616
+ return { width: (txt || "").length * 8, actualBoundingBoxAscent: 10, actualBoundingBoxDescent: 2 };
617
+ }, "measureText"),
618
+ getImageData: patchNative(function(x, y, w, h) {
619
+ const width = w || 16;
620
+ const height = h || 16;
621
+ const len = width * height * 4;
622
+ const data = new Uint8ClampedArray(len);
623
+ for (let i = 0; i < len; i += 4) {
624
+ const pixelIndex = i / 4;
625
+ const px = pixelIndex % width;
626
+ const py = Math.floor(pixelIndex / width);
627
+ data[i] = (px > 2 && px < 14 && py > 2 && py < 14) ? 255 : 10;
628
+ data[i + 1] = (px > 4 && py > 4) ? 102 : 20;
629
+ data[i + 2] = (px * 13 + py * 17) % 256;
630
+ data[i + 3] = 255;
631
+ }
632
+ return { data: data, width: width, height: height };
633
+ }, "getImageData"),
634
+ save: patchNative(function() {}, "save"),
635
+ restore: patchNative(function() {}, "restore")
636
+ };
637
+ }
638
+ if (type && type.includes("webgl")) {
639
+ const gl = {
640
+ canvas: el,
641
+ _clearR: 0.8,
642
+ _clearG: 0.4,
643
+ _clearB: 0.2,
644
+ _clearA: 1.0,
645
+ VERTEX_SHADER: 35633,
646
+ FRAGMENT_SHADER: 35632,
647
+ COMPILE_STATUS: 35713,
648
+ LINK_STATUS: 35714,
649
+ COLOR_BUFFER_BIT: 16384,
650
+ DEPTH_BUFFER_BIT: 256,
651
+ TRIANGLES: 4,
652
+ FLOAT: 5126,
653
+ RGBA: 6408,
654
+ UNSIGNED_BYTE: 5121,
655
+ HIGH_FLOAT: 36338,
656
+ MEDIUM_FLOAT: 36337,
657
+ LOW_FLOAT: 36336,
658
+ HIGH_INT: 36341,
659
+ MEDIUM_INT: 36340,
660
+ LOW_INT: 36339,
661
+ ARRAY_BUFFER: 34962,
662
+ STATIC_DRAW: 35044,
663
+ UNPACK_FLIP_Y_WEBGL: 37440,
664
+ TEXTURE_2D: 3553,
665
+ MAX_TEXTURE_SIZE: 16384,
666
+ MAX_VIEWPORT_DIMS: 3386,
667
+ VENDOR: 7936,
668
+ RENDERER: 7937,
669
+ VERSION: 7938,
670
+ SHADING_LANGUAGE_VERSION: 35724,
671
+
672
+ getParameter: patchNative(function(param) {
673
+ if (param === 0x9245 || param === 37445) return isAndroid ? "Qualcomm" : "Google Inc. (Intel)";
674
+ if (param === 0x9246 || param === 37446) return isAndroid ? "Adreno (TM) 640" : "ANGLE (Intel, ANGLE Metal Renderer: Intel(R) UHD Graphics 630, Unspecified Version)";
675
+ if (param === 7936) return "WebKit";
676
+ if (param === 7937) return "WebKit WebGL";
677
+ if (param === 7938) return "WebGL 1.0 (OpenGL ES 2.0 Chromium)";
678
+ if (param === 35724) return "WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.0 Chromium)";
679
+ if (param === 3379) return 16384; // MAX_TEXTURE_SIZE
680
+ if (param === 3386) return new Int32Array([16384, 16384]); // MAX_VIEWPORT_DIMS
681
+ if (param === 34076) return 16384; // MAX_CUBE_MAP_TEXTURE_SIZE
682
+ if (param === 34921) return 16; // MAX_VERTEX_ATTRIBS
683
+ if (param === 34930) return 16; // MAX_TEXTURE_IMAGE_UNITS
684
+ if (param === 35661) return 32; // MAX_COMBINED_TEXTURE_IMAGE_UNITS
685
+ if (param === 36347) return 1024; // MAX_FRAGMENT_UNIFORM_VECTORS
686
+ if (param === 36348) return 1024; // MAX_VERTEX_UNIFORM_VECTORS
687
+ if (param === 36349) return 30; // MAX_VARYING_VECTORS
688
+ if (param === 34024) return 16384; // MAX_RENDERBUFFER_SIZE
689
+ if (param === 35373) return 16; // MAX_VERTEX_TEXTURE_IMAGE_UNITS
690
+ if (param === 33901) return new Float32Array([1, 511]); // ALIASED_POINT_SIZE_RANGE
691
+ if (param === 33902) return new Float32Array([1, 1]); // ALIASED_LINE_WIDTH_RANGE
692
+ return 0;
693
+ }, "getParameter"),
694
+ getExtension: patchNative(function(ext) {
695
+ if (ext === "WEBGL_debug_renderer_info") {
696
+ return { UNMASKED_VENDOR_WEBGL: 37445, UNMASKED_RENDERER_WEBGL: 37446 };
697
+ }
698
+ if (ext === "EXT_texture_filter_anisotropic") {
699
+ return { MAX_TEXTURE_MAX_ANISOTROPY_EXT: 34047 };
700
+ }
701
+ return {};
702
+ }, "getExtension"),
703
+ getSupportedExtensions: patchNative(function() {
704
+ return [
705
+ "ANGLE_instanced_arrays",
706
+ "EXT_blend_minmax",
707
+ "EXT_clip_control",
708
+ "EXT_color_buffer_half_float",
709
+ "EXT_depth_clamp",
710
+ "EXT_disjoint_timer_query",
711
+ "EXT_float_blend",
712
+ "EXT_frag_depth",
713
+ "EXT_polygon_offset_clamp",
714
+ "EXT_shader_texture_lod",
715
+ "EXT_texture_compression_bptc",
716
+ "EXT_texture_compression_rgtc",
717
+ "EXT_texture_filter_anisotropic",
718
+ "EXT_texture_mirror_clamp_to_edge",
719
+ "EXT_sRGB",
720
+ "KHR_parallel_shader_compile",
721
+ "OES_element_index_uint",
722
+ "OES_fbo_render_mipmap",
723
+ "OES_standard_derivatives",
724
+ "OES_texture_float",
725
+ "OES_texture_float_linear",
726
+ "OES_texture_half_float",
727
+ "OES_texture_half_float_linear",
728
+ "OES_vertex_array_object",
729
+ "WEBGL_blend_func_extended",
730
+ "WEBGL_color_buffer_float",
731
+ "WEBGL_compressed_texture_s3tc",
732
+ "WEBGL_compressed_texture_s3tc_srgb",
733
+ "WEBGL_debug_renderer_info",
734
+ "WEBGL_debug_shaders",
735
+ "WEBGL_depth_texture",
736
+ "WEBGL_draw_buffers",
737
+ "WEBGL_lose_context",
738
+ "WEBGL_multi_draw",
739
+ "WEBGL_polygon_mode"
740
+ ];
741
+ }, "getSupportedExtensions"),
742
+ getShaderPrecisionFormat: patchNative(function(shaderType, precisionType) {
743
+ return { precision: 23, rangeMin: 127, rangeMax: 127 };
744
+ }, "getShaderPrecisionFormat"),
745
+ createShader: patchNative(function(type) {
746
+ return { type: type, source: "", compiled: true };
747
+ }, "createShader"),
748
+ shaderSource: patchNative(function(shader, src) {
749
+ if (shader) shader.source = src;
750
+ }, "shaderSource"),
751
+ compileShader: patchNative(function(shader) {
752
+ if (shader) shader.compiled = true;
753
+ }, "compileShader"),
754
+ getShaderParameter: patchNative(function(shader, param) {
755
+ return true;
756
+ }, "getShaderParameter"),
757
+ getShaderInfoLog: patchNative(function() { return ""; }, "getShaderInfoLog"),
758
+ createProgram: patchNative(function() {
759
+ return { shaders: [], linked: true };
760
+ }, "createProgram"),
761
+ attachShader: patchNative(function(prog, shader) {
762
+ if (prog && shader) prog.shaders.push(shader);
763
+ }, "attachShader"),
764
+ linkProgram: patchNative(function(prog) {
765
+ if (prog) prog.linked = true;
766
+ }, "linkProgram"),
767
+ getProgramParameter: patchNative(function(prog, param) {
768
+ return true;
769
+ }, "getProgramParameter"),
770
+ getProgramInfoLog: patchNative(function() { return ""; }, "getProgramInfoLog"),
771
+ useProgram: patchNative(function() {}, "useProgram"),
772
+ getAttribLocation: patchNative(function(prog, name) { return 0; }, "getAttribLocation"),
773
+ getUniformLocation: patchNative(function(prog, name) { return {}; }, "getUniformLocation"),
774
+ enableVertexAttribArray: patchNative(function(idx) {}, "enableVertexAttribArray"),
775
+ vertexAttribPointer: patchNative(function() {}, "vertexAttribPointer"),
776
+ createBuffer: patchNative(function() { return {}; }, "createBuffer"),
777
+ bindBuffer: patchNative(function() {}, "bindBuffer"),
778
+ bufferData: patchNative(function() {}, "bufferData"),
779
+ viewport: patchNative(function(x, y, w, h) {}, "viewport"),
780
+ clearColor: patchNative(function(r, g, b, a) {
781
+ gl._clearR = r;
782
+ gl._clearG = g;
783
+ gl._clearB = b;
784
+ gl._clearA = a;
785
+ }, "clearColor"),
786
+ clear: patchNative(function(mask) {}, "clear"),
787
+ drawArrays: patchNative(function(mode, first, count) {}, "drawArrays"),
788
+ drawElements: patchNative(function() {}, "drawElements"),
789
+ createTexture: patchNative(function() { return {}; }, "createTexture"),
790
+ bindTexture: patchNative(function() {}, "bindTexture"),
791
+ texParameteri: patchNative(function() {}, "texParameteri"),
792
+ texImage2D: patchNative(function() {}, "texImage2D"),
793
+ readPixels: patchNative(function(x, y, w, h, format, type, pixels) {
794
+ if (pixels && pixels.length) {
795
+ const r = gl._clearR !== undefined ? Math.round(gl._clearR * 255) : 204;
796
+ const g = gl._clearG !== undefined ? Math.round(gl._clearG * 255) : 102;
797
+ const b = gl._clearB !== undefined ? Math.round(gl._clearB * 255) : 51;
798
+ const a = gl._clearA !== undefined ? Math.round(gl._clearA * 255) : 255;
799
+ for (let i = 0; i < pixels.length; i += 4) {
800
+ pixels[i] = r;
801
+ pixels[i + 1] = g;
802
+ pixels[i + 2] = b;
803
+ pixels[i + 3] = a;
804
+ }
805
+ }
806
+ }, "readPixels")
807
+ };
808
+ return gl;
809
+ }
810
+ return null;
811
+ }, "getContext");
812
+
813
+ el.toDataURL = patchNative(function() {
814
+ return "data:image/png;base64,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";
815
+ }, "toDataURL");
816
+ }
817
+
818
+ return el;
819
+ }
820
+
821
+ // 7. Document object
822
+ const document = {
823
+ readyState: "complete",
824
+ compatMode: "CSS1Compat",
825
+ characterSet: "UTF-8",
826
+ contentType: "text/html",
827
+ doctype: { name: "html" },
828
+ location: location,
829
+ URL: location.href,
830
+ documentURI: location.href,
831
+ referrer: global.__REFERRER__ || "",
832
+ currentScript: null,
833
+ title: global.__DOCUMENT_TITLE__ || "",
834
+ hidden: false,
835
+ visibilityState: "visible",
836
+ hasFocus: patchNative(function() { return true; }, "hasFocus"),
837
+ documentElement: createMockElement("html"),
838
+ head: createMockElement("head"),
839
+ body: createMockElement("body"),
840
+ createElement: patchNative(function(tag) { return createMockElement(tag); }, "createElement"),
841
+ createElementNS: patchNative(function(ns, tag) { return createMockElement(tag); }, "createElementNS"),
842
+ createTextNode: patchNative(function(txt) { return { nodeType: 3, nodeValue: String(txt) }; }, "createTextNode"),
843
+ getElementById: patchNative(function(id) {
844
+ if (!id) return null;
845
+ if (!elementsById[id]) {
846
+ const isBtn = String(id).toLowerCase().includes("button") || String(id).toLowerCase().includes("btn");
847
+ const el = createMockElement(isBtn ? "button" : "div");
848
+ el.id = id;
849
+ elementsById[id] = el;
850
+ document.body.appendChild(el);
851
+ }
852
+ return elementsById[id];
853
+ }, "getElementById"),
854
+ getElementsByTagName: patchNative(function(tag) {
855
+ const t = (tag || "").toLowerCase();
856
+ if (t === "script") return trackedScripts.length > 0 ? trackedScripts : [createMockElement("script")];
857
+ if (t === "head") return [document.head];
858
+ if (t === "body") return [document.body];
859
+ if (t === "html") return [document.documentElement];
860
+ return [];
861
+ }, "getElementsByTagName"),
862
+ getElementsByClassName: patchNative(function(cls) {
863
+ const el = createMockElement("div");
864
+ el.className = cls;
865
+ document.body.appendChild(el);
866
+ return [el];
867
+ }, "getElementsByClassName"),
868
+ getElementsByName: patchNative(function() { return []; }, "getElementsByName"),
869
+ querySelector: patchNative(function(sel) {
870
+ if (!sel) return null;
871
+ if (sel.startsWith("#")) {
872
+ return document.getElementById(sel.slice(1));
873
+ }
874
+ const el = createMockElement("div");
875
+ document.body.appendChild(el);
876
+ return el;
877
+ }, "querySelector"),
878
+ querySelectorAll: patchNative(function(sel) {
879
+ const el = document.querySelector(sel);
880
+ return el ? [el] : [];
881
+ }, "querySelectorAll"),
882
+ addEventListener: patchNative(addEventListener, "addEventListener"),
883
+ removeEventListener: patchNative(removeEventListener, "removeEventListener"),
884
+ dispatchEvent: patchNative(dispatchEvent, "dispatchEvent")
885
+ };
886
+ document.documentElement.appendChild(document.head);
887
+ document.documentElement.appendChild(document.body);
888
+
889
+ const CPT_ELEMENT_IDS = [
890
+ "sec-if-cpt-container",
891
+ "sec-bc-text-container",
892
+ "sec-bc-tile-parent",
893
+ "sec-bc-tile-container",
894
+ "progress-button",
895
+ "sec-cpr-overlay"
896
+ ];
897
+ CPT_ELEMENT_IDS.forEach(id => {
898
+ document.getElementById(id);
899
+ });
900
+
901
+ const cookieJar = new Map();
902
+ function initCookieJar(str) {
903
+ if (!str) return;
904
+ String(str).split(";").forEach(pair => {
905
+ const idx = pair.indexOf("=");
906
+ if (idx > -1) {
907
+ const k = pair.slice(0, idx).trim();
908
+ const v = pair.slice(idx + 1).trim();
909
+ if (k) cookieJar.set(k, v);
910
+ }
911
+ });
912
+ }
913
+ initCookieJar(global.__INITIAL_COOKIES__ || "");
914
+
915
+ Object.defineProperty(document, "cookie", {
916
+ get: patchNative(function() {
917
+ const pairs = [];
918
+ for (const [k, v] of cookieJar.entries()) {
919
+ pairs.push(k + "=" + v);
920
+ }
921
+ return pairs.join("; ");
922
+ }, "get_cookie"),
923
+ set: patchNative(function(v) {
924
+ if (!v) return;
925
+ const parts = String(v).split(";");
926
+ const first = parts[0];
927
+ const idx = first.indexOf("=");
928
+ if (idx > -1) {
929
+ const k = first.slice(0, idx).trim();
930
+ const val = first.slice(idx + 1).trim();
931
+ const isExpired = parts.some(p => {
932
+ const lower = p.trim().toLowerCase();
933
+ return lower.startsWith("max-age=0") || lower.includes("expires=thu, 01 jan 1970");
934
+ });
935
+ if (isExpired) {
936
+ cookieJar.delete(k);
937
+ } else {
938
+ cookieJar.set(k, val);
939
+ }
940
+ }
941
+ }, "set_cookie"),
942
+ configurable: true
943
+ });
944
+
945
+ Object.defineProperty(global, "document", { value: document, writable: true, configurable: true });
946
+ global.window.document = document;
947
+
948
+
949
+ // 8. Crypto and Audio Mocks
950
+ const crypto = {
951
+ getRandomValues: patchNative(function(arr) {
952
+ for (let i = 0; i < arr.length; i++) arr[i] = Math.floor(Math.random() * 256);
953
+ return arr;
954
+ }, "getRandomValues"),
955
+ subtle: {
956
+ digest: patchNative(function(algo, data) {
957
+ const buf = new ArrayBuffer(32);
958
+ const view = new Uint8Array(buf);
959
+ for (let i = 0; i < 32; i++) view[i] = (i * 17 + 5) % 256;
960
+ return Promise.resolve(buf);
961
+ }, "digest")
962
+ }
963
+ };
964
+ Object.defineProperty(global, "crypto", { value: crypto, writable: true, configurable: true });
965
+
966
+ function MockAudioBuffer() {
967
+ this.length = 44100;
968
+ this.sampleRate = 44100;
969
+ this.numberOfChannels = 1;
970
+ this.duration = 1.0;
971
+ this.getChannelData = patchNative(function(c) {
972
+ const data = new Float32Array(44100);
973
+ const realSlice = [
974
+ -0.10808049887418747, -0.39091169834136963, -0.005692684557288885, 0.3892313241958618,
975
+ 0.1189708486199379, -0.3545846939086914, -0.22215832769870758, 0.28990939259529114,
976
+ 0.30651888251304626, -0.20068730413913727, -0.3649080991744995, 0.09447670727968216,
977
+ 0.39241594076156616, 0.01972721517086029, -0.38671594858169556, -0.13228479027748108,
978
+ 0.34825482964515686, 0.2336597442626953, -0.28028473258018494, -0.3152626156806946
979
+ ];
980
+ for (let i = 0; i < data.length; i++) {
981
+ data[i] = realSlice[i % realSlice.length];
982
+ }
983
+ return data;
984
+ }, "getChannelData");
985
+ }
986
+
987
+ function MockAudioNode() {
988
+ this.connect = patchNative(function(target) { return target; }, "connect");
989
+ this.disconnect = patchNative(function() {}, "disconnect");
990
+ }
991
+
992
+ function MockOscillatorNode() {
993
+ MockAudioNode.call(this);
994
+ this.type = "sine";
995
+ this.frequency = { value: 440, setValueAtTime: function() {} };
996
+ this.start = patchNative(function() {}, "start");
997
+ this.stop = patchNative(function() {}, "stop");
998
+ }
999
+
1000
+ function MockDynamicsCompressorNode() {
1001
+ MockAudioNode.call(this);
1002
+ this.threshold = { value: -24 };
1003
+ this.knee = { value: 30 };
1004
+ this.ratio = { value: 12 };
1005
+ this.reduction = { value: 0 };
1006
+ this.attack = { value: 0.003 };
1007
+ this.release = { value: 0.25 };
1008
+ }
1009
+
1010
+ function MockAudioContext() {
1011
+ this.destination = new MockAudioNode();
1012
+ this.createOscillator = patchNative(function() { return new MockOscillatorNode(); }, "createOscillator");
1013
+ this.createDynamicsCompressor = patchNative(function() { return new MockDynamicsCompressorNode(); }, "createDynamicsCompressor");
1014
+ this.createGain = patchNative(function() { return new MockAudioNode(); }, "createGain");
1015
+ this.createAnalyser = patchNative(function() {
1016
+ const node = new MockAudioNode();
1017
+ node.getFloatFrequencyData = patchNative(function(arr) {}, "getFloatFrequencyData");
1018
+ node.getByteFrequencyData = patchNative(function(arr) {}, "getByteFrequencyData");
1019
+ return node;
1020
+ }, "createAnalyser");
1021
+ this.createBufferSource = patchNative(function() {
1022
+ const node = new MockAudioNode();
1023
+ node.buffer = null;
1024
+ node.start = patchNative(function() {}, "start");
1025
+ return node;
1026
+ }, "createBufferSource");
1027
+ this.startRendering = patchNative(function() {
1028
+ return Promise.resolve(new MockAudioBuffer());
1029
+ }, "startRendering");
1030
+ this.resume = patchNative(function() { return Promise.resolve(); }, "resume");
1031
+ this.close = patchNative(function() { return Promise.resolve(); }, "close");
1032
+ }
1033
+
1034
+ patchNative(MockAudioContext, "AudioContext");
1035
+ patchNative(MockAudioContext, "webkitAudioContext");
1036
+ patchNative(MockAudioContext, "OfflineAudioContext");
1037
+
1038
+ global.AudioContext = MockAudioContext;
1039
+ global.webkitAudioContext = MockAudioContext;
1040
+ global.OfflineAudioContext = MockAudioContext;
1041
+
1042
+ // 9. Performance & V8 Virtual JIT Clock Algorithm
1043
+ const startTime = Date.now() - 1500;
1044
+ let virtualNow = 118.4;
1045
+ let callCount = 0;
1046
+ let lastRealTime = Date.now();
1047
+
1048
+ function virtualJITNow() {
1049
+ callCount++;
1050
+ const currentRealTime = Date.now();
1051
+ const realDelta = currentRealTime - lastRealTime;
1052
+
1053
+ // V8 TurboFan warmup & micro-timing model:
1054
+ let microIncrement = 0.05 + (callCount % 5) * 0.02;
1055
+ if (callCount <= 12) {
1056
+ microIncrement += (12 - callCount) * 0.06;
1057
+ }
1058
+
1059
+ if (realDelta > 0) {
1060
+ const scaledDelta = realDelta * 0.35;
1061
+ virtualNow += Math.max(microIncrement, scaledDelta);
1062
+ lastRealTime = currentRealTime;
1063
+ } else {
1064
+ virtualNow += microIncrement;
1065
+ }
1066
+
1067
+ // Chrome quantizes performance.now to 100 microseconds (0.1ms)
1068
+ return Math.round(virtualNow * 10) / 10;
1069
+ }
1070
+
1071
+ const performance = {
1072
+ timeOrigin: startTime,
1073
+ now: patchNative(virtualJITNow, "now"),
1074
+ timing: {
1075
+ navigationStart: startTime,
1076
+ unloadEventStart: 0,
1077
+ unloadEventEnd: 0,
1078
+ redirectStart: 0,
1079
+ redirectEnd: 0,
1080
+ fetchStart: startTime + 5,
1081
+ domainLookupStart: startTime + 10,
1082
+ domainLookupEnd: startTime + 20,
1083
+ connectStart: startTime + 20,
1084
+ connectEnd: startTime + 45,
1085
+ secureConnectionStart: startTime + 25,
1086
+ requestStart: startTime + 46,
1087
+ responseStart: startTime + 90,
1088
+ responseEnd: startTime + 110,
1089
+ domLoading: startTime + 115,
1090
+ domInteractive: startTime + 250,
1091
+ domContentLoadedEventStart: startTime + 260,
1092
+ domContentLoadedEventEnd: startTime + 270,
1093
+ domComplete: startTime + 400,
1094
+ loadEventStart: startTime + 410,
1095
+ loadEventEnd: startTime + 420
1096
+ },
1097
+ getEntriesByType: patchNative(function() { return []; }, "getEntriesByType"),
1098
+ getEntriesByName: patchNative(function() { return []; }, "getEntriesByName"),
1099
+ getEntries: patchNative(function() { return []; }, "getEntries"),
1100
+ mark: patchNative(function() {}, "mark"),
1101
+ measure: patchNative(function() {}, "measure"),
1102
+ clearMarks: patchNative(function() {}, "clearMarks"),
1103
+ clearMeasures: patchNative(function() {}, "clearMeasures")
1104
+ };
1105
+ Object.defineProperty(global, "performance", { value: performance, writable: true, configurable: true });
1106
+
1107
+ // 10. Storage
1108
+ const storageMap = {};
1109
+ const storage = {
1110
+ getItem: patchNative(function(k) { return storageMap[k] || null; }, "getItem"),
1111
+ setItem: patchNative(function(k, v) { storageMap[k] = String(v); }, "setItem"),
1112
+ removeItem: patchNative(function(k) { delete storageMap[k]; }, "removeItem"),
1113
+ clear: patchNative(function() { Object.keys(storageMap).forEach(k => delete storageMap[k]); }, "clear"),
1114
+ key: patchNative(function(i) { return Object.keys(storageMap)[i] || null; }, "key"),
1115
+ get length() { return Object.keys(storageMap).length; }
1116
+ };
1117
+ Object.defineProperty(global, "localStorage", { value: storage, writable: true, configurable: true });
1118
+ Object.defineProperty(global, "sessionStorage", { value: storage, writable: true, configurable: true });
1119
+
1120
+ // 11. Timer and Event Loop Helpers
1121
+ const timers = [];
1122
+ global.setTimeout = patchNative(function(fn, delay, ...args) {
1123
+ const id = timers.length + 1;
1124
+ timers.push({ id, fn, args, delay: delay || 0, type: "timeout" });
1125
+ return id;
1126
+ }, "setTimeout");
1127
+
1128
+ global.setInterval = patchNative(function(fn, delay, ...args) {
1129
+ const id = timers.length + 1;
1130
+ timers.push({ id, fn, args, delay: delay || 0, type: "interval" });
1131
+ return id;
1132
+ }, "setInterval");
1133
+
1134
+ global.clearTimeout = patchNative(function(id) {}, "clearTimeout");
1135
+ global.clearInterval = patchNative(function(id) {}, "clearInterval");
1136
+ global.requestAnimationFrame = patchNative(function(fn) { return global.setTimeout(fn, 16); }, "requestAnimationFrame");
1137
+ global.cancelAnimationFrame = patchNative(function(id) { global.clearTimeout(id); }, "cancelAnimationFrame");
1138
+
1139
+ global.addEventListener = patchNative(addEventListener, "addEventListener");
1140
+ global.removeEventListener = patchNative(removeEventListener, "removeEventListener");
1141
+ global.dispatchEvent = patchNative(dispatchEvent, "dispatchEvent");
1142
+
1143
+ // 12. Captured XHR & Fetch Interceptor
1144
+ global.__captured_sensor_data = null;
1145
+ global.__sensor_posts = [];
1146
+
1147
+ function XMLHttpRequest() {
1148
+ this.method = "GET";
1149
+ this.url = "";
1150
+ this.responseURL = "";
1151
+ this.headers = {};
1152
+ this.readyState = 0;
1153
+ this.status = 200;
1154
+ this.statusText = "OK";
1155
+ this.responseText = "{}";
1156
+ this.response = "{}";
1157
+ this.onreadystatechange = null;
1158
+ this.onload = null;
1159
+ this.onerror = null;
1160
+
1161
+ const self = this;
1162
+ this.open = patchNative(function(method, url, async) {
1163
+ self.method = String(method || "GET").toUpperCase();
1164
+ self.url = String(url || "");
1165
+ try {
1166
+ self.responseURL = new URL(self.url, location.href).href;
1167
+ } catch(e) {
1168
+ self.responseURL = self.url;
1169
+ }
1170
+ self.readyState = 1;
1171
+ }, "open");
1172
+
1173
+ this.setRequestHeader = patchNative(function(header, value) {
1174
+ self.headers[header] = value;
1175
+ }, "setRequestHeader");
1176
+
1177
+ this.send = patchNative(function(body) {
1178
+ self.readyState = 4;
1179
+ self.status = 200;
1180
+ self.statusText = "OK";
1181
+ self.responseText = "{}";
1182
+ self.response = "{}";
1183
+ global.__captured_sensor_data = body;
1184
+ global.__sensor_posts.push({ url: self.url, method: self.method, headers: self.headers, body: body });
1185
+ if (typeof self.onreadystatechange === "function") {
1186
+ try { self.onreadystatechange(); } catch(e) {}
1187
+ }
1188
+ if (typeof self.onload === "function") {
1189
+ try { self.onload(); } catch(e) {}
1190
+ }
1191
+ }, "send");
1192
+ }
1193
+
1194
+ XMLHttpRequest.prototype.open = patchNative(function(method, url, async) {
1195
+ if (this.open) return this.open.apply(this, arguments);
1196
+ }, "open");
1197
+ XMLHttpRequest.prototype.setRequestHeader = patchNative(function(header, value) {
1198
+ if (this.setRequestHeader) return this.setRequestHeader.apply(this, arguments);
1199
+ }, "setRequestHeader");
1200
+ XMLHttpRequest.prototype.send = patchNative(function(body) {
1201
+ if (this.send) return this.send.apply(this, arguments);
1202
+ }, "send");
1203
+
1204
+ patchNative(XMLHttpRequest, "XMLHttpRequest");
1205
+ global.XMLHttpRequest = XMLHttpRequest;
1206
+
1207
+
1208
+
1209
+ // 13. Synthetic Human Interaction Simulation (Bézier Spline Physics)
1210
+ global.__simulateHumanInteractions = function() {
1211
+ // Generate natural human cursor trajectory between (120, 80) and (840, 520)
1212
+ const p0 = { x: 120, y: 80 };
1213
+ const p1 = { x: 310, y: 190 };
1214
+ const p2 = { x: 580, y: 440 };
1215
+ const p3 = { x: 840, y: 520 };
1216
+
1217
+ const totalSteps = 24;
1218
+ let prevX = p0.x, prevY = p0.y;
1219
+
1220
+ for (let i = 0; i <= totalSteps; i++) {
1221
+ const t = i / totalSteps;
1222
+ const u = 1 - t;
1223
+ // Cubic Bézier formula with micro-jitter
1224
+ const rawX = u*u*u*p0.x + 3*u*u*t*p1.x + 3*u*t*t*p2.x + t*t*t*p3.x;
1225
+ const rawY = u*u*u*p0.y + 3*u*u*t*p1.y + 3*u*t*t*p2.y + t*t*t*p3.y;
1226
+ const jitter = (i % 3 === 0) ? (i % 2 === 0 ? 1 : -1) : 0;
1227
+
1228
+ const x = Math.round(rawX + jitter);
1229
+ const y = Math.round(rawY + jitter);
1230
+ const timeOffset = Math.round(50 + t * 480 + Math.sin(t * Math.PI) * 20);
1231
+
1232
+ const evt = {
1233
+ type: "mousemove",
1234
+ clientX: x,
1235
+ clientY: y,
1236
+ pageX: x,
1237
+ pageY: y,
1238
+ screenX: x + 20,
1239
+ screenY: y + 85,
1240
+ movementX: x - prevX,
1241
+ movementY: y - prevY,
1242
+ buttons: 0,
1243
+ button: 0,
1244
+ timeStamp: startTime + timeOffset,
1245
+ target: document.body,
1246
+ isTrusted: true
1247
+ };
1248
+ prevX = x;
1249
+ prevY = y;
1250
+ dispatchEvent(evt);
1251
+ }
1252
+
1253
+ // Natural click at target coordinate
1254
+ const clickTime = startTime + 560;
1255
+ dispatchEvent({ type: "mousedown", clientX: prevX, clientY: prevY, screenX: prevX + 20, screenY: prevY + 85, button: 0, buttons: 1, timeStamp: clickTime, target: document.body, isTrusted: true });
1256
+ dispatchEvent({ type: "mouseup", clientX: prevX, clientY: prevY, screenX: prevX + 20, screenY: prevY + 85, button: 0, buttons: 0, timeStamp: clickTime + 85, target: document.body, isTrusted: true });
1257
+ dispatchEvent({ type: "click", clientX: prevX, clientY: prevY, screenX: prevX + 20, screenY: prevY + 85, button: 0, buttons: 0, timeStamp: clickTime + 90, target: document.body, isTrusted: true });
1258
+
1259
+ dispatchEvent({ type: "focus", target: window, isTrusted: true });
1260
+ dispatchEvent({ type: "scroll", target: window, isTrusted: true });
1261
+ };
1262
+
1263
+ // 14. Step-by-step Event Loop Runner
1264
+ global.__drainEventLoop = function(maxSteps = 50) {
1265
+ let steps = 0;
1266
+ while (timers.length > 0 && steps < maxSteps) {
1267
+ steps++;
1268
+ const timer = timers.shift();
1269
+ try {
1270
+ if (typeof timer.fn === "function") {
1271
+ timer.fn.apply(global, timer.args || []);
1272
+ } else if (typeof timer.fn === "string") {
1273
+ eval(timer.fn);
1274
+ }
1275
+ } catch(e) {}
1276
+ }
1277
+ };
1278
+
1279
+ // 15. Trusted Types Polyfill
1280
+ const trustedTypes = {
1281
+ createPolicy: patchNative(function(name, rules) {
1282
+ return {
1283
+ name: name,
1284
+ createScript: patchNative(function(s) { return rules && rules.createScript ? rules.createScript(s) : s; }, "createScript"),
1285
+ createScriptURL: patchNative(function(u) { return rules && rules.createScriptURL ? rules.createScriptURL(u) : u; }, "createScriptURL"),
1286
+ createHTML: patchNative(function(h) { return rules && rules.createHTML ? rules.createHTML(h) : h; }, "createHTML")
1287
+ };
1288
+ }, "createPolicy"),
1289
+ isScript: patchNative(function() { return true; }, "isScript"),
1290
+ isScriptURL: patchNative(function() { return true; }, "isScriptURL"),
1291
+ isHTML: patchNative(function() { return true; }, "isHTML"),
1292
+ emptyScript: "",
1293
+ emptyHTML: ""
1294
+ };
1295
+ Object.defineProperty(global, "trustedTypes", { value: trustedTypes, writable: true, configurable: true });
1296
+
1297
+ })(globalThis);