done all
This commit is contained in:
@@ -2,9 +2,18 @@
|
||||
/**
|
||||
* P0: Performance mock
|
||||
* hsw 检测:timing / timeOrigin / getEntriesByType('resource') / getEntriesByType('navigation')
|
||||
* Now with: 5µs quantization, proper prototype chain (Performance -> EventTarget -> Object),
|
||||
* PerformanceEntry / PerformanceResourceTiming / PerformanceNavigationTiming classes,
|
||||
* getEntries() method
|
||||
*/
|
||||
|
||||
const { createNative } = require('./native');
|
||||
const { nativeMethod: M } = require('./native');
|
||||
const {
|
||||
Performance,
|
||||
PerformanceEntry,
|
||||
PerformanceResourceTiming,
|
||||
PerformanceNavigationTiming,
|
||||
} = require('./class_registry');
|
||||
|
||||
const NAV_START = Date.now() - 1200;
|
||||
|
||||
@@ -32,9 +41,23 @@ const timingData = {
|
||||
unloadEventEnd: 0,
|
||||
};
|
||||
|
||||
// ── Helper: create PerformanceResourceTiming instance ────────────
|
||||
const makeResourceEntry = (data) => {
|
||||
const entry = Object.create(PerformanceResourceTiming.prototype);
|
||||
Object.assign(entry, data);
|
||||
return entry;
|
||||
};
|
||||
|
||||
// ── Helper: create PerformanceNavigationTiming instance ──────────
|
||||
const makeNavEntry = (data) => {
|
||||
const entry = Object.create(PerformanceNavigationTiming.prototype);
|
||||
Object.assign(entry, data);
|
||||
return entry;
|
||||
};
|
||||
|
||||
// 模拟 resource 条目(hsw 会查 checksiteconfig 请求痕迹)
|
||||
const resourceEntries = [
|
||||
{
|
||||
makeResourceEntry({
|
||||
name: 'https://api.hcaptcha.com/checksiteconfig?v=xxx&host=b.stripecdn.com&sitekey=xxx&sc=1&swa=1&spst=1',
|
||||
entryType: 'resource',
|
||||
initiatorType: 'xmlhttprequest',
|
||||
@@ -60,11 +83,11 @@ const resourceEntries = [
|
||||
requestStart: 0,
|
||||
responseStart: 0,
|
||||
firstInterimResponseStart: 0,
|
||||
finalResponseHeadersStart: 0, // P2 要求的字段
|
||||
finalResponseHeadersStart: 0,
|
||||
serverTiming: [],
|
||||
renderBlockingStatus: 'non-blocking',
|
||||
},
|
||||
{
|
||||
}),
|
||||
makeResourceEntry({
|
||||
name: 'https://newassets.hcaptcha.com/c/xxx/hsw.js',
|
||||
entryType: 'resource',
|
||||
initiatorType: 'script',
|
||||
@@ -93,11 +116,11 @@ const resourceEntries = [
|
||||
redirectEnd: 0,
|
||||
serverTiming: [],
|
||||
renderBlockingStatus: 'non-blocking',
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
// 模拟 navigation 条目
|
||||
const navigationEntry = {
|
||||
const navigationEntry = makeNavEntry({
|
||||
name: 'https://newassets.hcaptcha.com/captcha/v1/xxx/static/hcaptcha.html',
|
||||
entryType: 'navigation',
|
||||
initiatorType: 'navigation',
|
||||
@@ -140,31 +163,47 @@ const navigationEntry = {
|
||||
workerStart: 0,
|
||||
contentEncoding: 'br',
|
||||
renderBlockingStatus: 'non-blocking',
|
||||
};
|
||||
});
|
||||
|
||||
const performanceMock = {
|
||||
// ── Build performance object with proper prototype ──────────────
|
||||
const performanceMock = Object.create(Performance.prototype);
|
||||
|
||||
Object.assign(performanceMock, {
|
||||
timeOrigin: NAV_START,
|
||||
timing: timingData,
|
||||
navigation: { type: 0, redirectCount: 0 },
|
||||
|
||||
getEntriesByType: createNative('getEntriesByType', function (type) {
|
||||
// 5µs quantization (Chromium feature)
|
||||
now: M('now', 0, () => {
|
||||
const raw = Date.now() - NAV_START;
|
||||
return Math.round(raw * 200) / 200; // 0.005ms = 5µs steps
|
||||
}),
|
||||
|
||||
getEntries: M('getEntries', 0, () => {
|
||||
return [navigationEntry, ...resourceEntries];
|
||||
}),
|
||||
|
||||
getEntriesByType: M('getEntriesByType', 1, (type) => {
|
||||
if (type === 'resource') return resourceEntries;
|
||||
if (type === 'navigation') return [navigationEntry];
|
||||
if (type === 'paint') return [];
|
||||
if (type === 'mark') return [];
|
||||
if (type === 'measure') return [];
|
||||
return [];
|
||||
}),
|
||||
|
||||
getEntriesByName: createNative('getEntriesByName', function (name) {
|
||||
return resourceEntries.filter(e => e.name === name);
|
||||
getEntriesByName: M('getEntriesByName', 1, (name) => {
|
||||
return [...resourceEntries, navigationEntry].filter(e => e.name === name);
|
||||
}),
|
||||
|
||||
now: createNative('now', function () {
|
||||
return Date.now() - NAV_START;
|
||||
}),
|
||||
|
||||
mark: createNative('mark', function () {}),
|
||||
measure: createNative('measure', function () {}),
|
||||
clearMarks: createNative('clearMarks', function () {}),
|
||||
clearMeasures: createNative('clearMeasures', function () {}),
|
||||
};
|
||||
mark: M('mark', 1, () => {}),
|
||||
measure: M('measure', 1, () => {}),
|
||||
clearMarks: M('clearMarks', 0, () => {}),
|
||||
clearMeasures: M('clearMeasures', 0, () => {}),
|
||||
clearResourceTimings: M('clearResourceTimings', 0, () => {}),
|
||||
setResourceTimingBufferSize: M('setResourceTimingBufferSize', 1, () => {}),
|
||||
addEventListener: M('addEventListener', 2, () => {}),
|
||||
removeEventListener: M('removeEventListener', 2, () => {}),
|
||||
});
|
||||
|
||||
module.exports = performanceMock;
|
||||
|
||||
Reference in New Issue
Block a user