@ccheever/exact-ibex-runtime 0.1.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/package.json +63 -0
- package/src/abort/AbortController.ts +23 -0
- package/src/abort/AbortSignal.ts +152 -0
- package/src/abort/index.ts +2 -0
- package/src/accessibility.ts +12 -0
- package/src/arraybuffer-detach.ts +109 -0
- package/src/base64/base64.ts +168 -0
- package/src/base64/index.ts +1 -0
- package/src/blob/Blob.ts +259 -0
- package/src/blob/File.ts +59 -0
- package/src/blob/FormData.ts +323 -0
- package/src/blob/index.ts +3 -0
- package/src/bootstrap.ts +1946 -0
- package/src/broadcast/BroadcastChannel.ts +280 -0
- package/src/broadcast/index.ts +5 -0
- package/src/cache/Cache.ts +349 -0
- package/src/cache/CacheStorage.ts +89 -0
- package/src/cache/index.ts +27 -0
- package/src/camera/index.ts +6202 -0
- package/src/camera/processor.worker.ts +194 -0
- package/src/camera/scene.ts +195 -0
- package/src/clipboard/Clipboard.ts +129 -0
- package/src/clipboard/ClipboardItem.ts +97 -0
- package/src/clipboard/index.ts +6 -0
- package/src/clone/index.ts +1 -0
- package/src/clone/structuredClone.ts +389 -0
- package/src/clone/transferableSymbols.ts +2 -0
- package/src/compression/CompressionStream.ts +146 -0
- package/src/compression/DecompressionStream.ts +342 -0
- package/src/compression/index.ts +4 -0
- package/src/console/Console.ts +341 -0
- package/src/console/index.ts +2 -0
- package/src/core/accessibility-state.ts +263 -0
- package/src/core/accessibility.ts +184 -0
- package/src/core/agent-state.ts +37 -0
- package/src/core/diagnostics-logs.ts +144 -0
- package/src/core/host-call-bridge.ts +16 -0
- package/src/core/i18n-helpers.ts +189 -0
- package/src/core/locale-state.ts +253 -0
- package/src/core/locale.ts +95 -0
- package/src/crypto/Crypto.ts +2743 -0
- package/src/crypto/index.ts +1 -0
- package/src/diagnostics/logs.ts +7 -0
- package/src/encoding/TextDecoder.ts +1181 -0
- package/src/encoding/TextDecoderStream.ts +58 -0
- package/src/encoding/TextEncoder.ts +180 -0
- package/src/encoding/TextEncoderStream.ts +39 -0
- package/src/encoding/index.ts +8 -0
- package/src/events/CloseEvent.ts +91 -0
- package/src/events/DOMException.ts +409 -0
- package/src/events/ErrorEvent.ts +39 -0
- package/src/events/Event.ts +151 -0
- package/src/events/EventTarget.ts +280 -0
- package/src/events/FocusEvent.ts +27 -0
- package/src/events/KeyboardEvent.ts +46 -0
- package/src/events/MessageEvent.ts +61 -0
- package/src/events/ProgressEvent.ts +33 -0
- package/src/events/PromiseRejectionEvent.ts +31 -0
- package/src/events/index.ts +52 -0
- package/src/eventsource/EventSource.ts +371 -0
- package/src/eventsource/index.ts +2 -0
- package/src/fetch/Headers.ts +642 -0
- package/src/fetch/Request.ts +760 -0
- package/src/fetch/Response.ts +543 -0
- package/src/fetch/body.ts +1256 -0
- package/src/fetch/cookie-jar.ts +566 -0
- package/src/fetch/demo.ts +207 -0
- package/src/fetch/errors.ts +101 -0
- package/src/fetch/fetch.ts +2610 -0
- package/src/fetch/index.ts +101 -0
- package/src/fetch/native-bridge.ts +65 -0
- package/src/fetch/types.ts +258 -0
- package/src/filereader/FileReader.ts +236 -0
- package/src/filereader/index.ts +1 -0
- package/src/fs/Dirent.ts +39 -0
- package/src/fs/ExactFile.ts +450 -0
- package/src/fs/Stats.ts +80 -0
- package/src/fs/index.ts +944 -0
- package/src/fs/promises.ts +386 -0
- package/src/fs/shared.ts +328 -0
- package/src/http-server/index.js +697 -0
- package/src/http-server/index.ts +27 -0
- package/src/identity.generated.ts +14 -0
- package/src/index.ts +283 -0
- package/src/indexeddb/IDBCursor.ts +188 -0
- package/src/indexeddb/IDBDatabase.ts +343 -0
- package/src/indexeddb/IDBFactory.ts +269 -0
- package/src/indexeddb/IDBIndex.ts +194 -0
- package/src/indexeddb/IDBKeyRange.ts +109 -0
- package/src/indexeddb/IDBObjectStore.ts +468 -0
- package/src/indexeddb/IDBRequest.ts +163 -0
- package/src/indexeddb/IDBTransaction.ts +207 -0
- package/src/indexeddb/index.ts +34 -0
- package/src/indexeddb/utils.ts +52 -0
- package/src/inspect/index.ts +1 -0
- package/src/inspect/inspect.ts +465 -0
- package/src/internal/detect.ts +104 -0
- package/src/locale.ts +10 -0
- package/src/location/index.ts +1059 -0
- package/src/locks/LockManager.ts +460 -0
- package/src/locks/index.ts +12 -0
- package/src/media/VideoFrame.ts +58 -0
- package/src/messaging/MessageChannel.ts +31 -0
- package/src/messaging/MessagePort.ts +180 -0
- package/src/messaging/index.ts +2 -0
- package/src/messaging.ts +247 -0
- package/src/native/NativeModules.ts +354 -0
- package/src/native/index.ts +1 -0
- package/src/navigator/Navigator.ts +351 -0
- package/src/navigator/index.ts +1 -0
- package/src/node/Buffer.ts +1786 -0
- package/src/node/index.ts +4 -0
- package/src/node/path.ts +495 -0
- package/src/node/process.ts +2528 -0
- package/src/performance/Performance.ts +532 -0
- package/src/performance/index.ts +21 -0
- package/src/polyfills/array.ts +236 -0
- package/src/polyfills/arraybuffer.ts +172 -0
- package/src/polyfills/groupby.ts +85 -0
- package/src/polyfills/index.ts +85 -0
- package/src/polyfills/intl.ts +1956 -0
- package/src/polyfills/iterator.ts +479 -0
- package/src/polyfills/promise.ts +37 -0
- package/src/polyfills/set.ts +245 -0
- package/src/polyfills/string.ts +85 -0
- package/src/polyfills/typedarray.ts +110 -0
- package/src/promise-rejection-tracking.ts +464 -0
- package/src/react-native/index.ts +388 -0
- package/src/runtime-entry.ts +55 -0
- package/src/scheduling/AnimationFrame.ts +105 -0
- package/src/scheduling/IdleCallback.ts +167 -0
- package/src/scheduling/index.ts +13 -0
- package/src/security/Capabilities.ts +1146 -0
- package/src/security/Permissions.ts +392 -0
- package/src/security/capability-bits.generated.ts +63 -0
- package/src/security/index.ts +16 -0
- package/src/sqlite/Database.ts +456 -0
- package/src/sqlite/Statement.ts +206 -0
- package/src/sqlite/constants.ts +79 -0
- package/src/sqlite/errors.ts +25 -0
- package/src/sqlite/index.ts +34 -0
- package/src/sqlite/module.js +438 -0
- package/src/storage/Storage.ts +291 -0
- package/src/storage/StorageManager.ts +91 -0
- package/src/storage/index.ts +3 -0
- package/src/stream-compat.ts +47 -0
- package/src/streams/ReadableStream.ts +4131 -0
- package/src/streams/TransformStream.ts +375 -0
- package/src/streams/WritableStream.ts +866 -0
- package/src/streams/index.ts +41 -0
- package/src/timers/Timers.ts +296 -0
- package/src/timers/index.ts +11 -0
- package/src/url/URL.ts +656 -0
- package/src/url/URLPattern.ts +850 -0
- package/src/url/URLSearchParams.ts +244 -0
- package/src/url/index.ts +9 -0
- package/src/websocket/WebSocket.ts +770 -0
- package/src/websocket/WebSocketError.ts +52 -0
- package/src/websocket/WebSocketStream.ts +628 -0
- package/src/websocket/index.ts +7 -0
- package/src/window/index.ts +872 -0
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Performance - Web Standard Performance API Implementation
|
|
4
|
+
*
|
|
5
|
+
* @see https://www.w3.org/TR/hr-time/
|
|
6
|
+
* @see https://www.w3.org/TR/user-timing/
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { EventTarget } from "../events/EventTarget";
|
|
10
|
+
|
|
11
|
+
export interface PerformanceMarkOptions {
|
|
12
|
+
detail?: any;
|
|
13
|
+
startTime?: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface PerformanceMeasureOptions {
|
|
17
|
+
detail?: any;
|
|
18
|
+
start?: string | number;
|
|
19
|
+
duration?: number;
|
|
20
|
+
end?: string | number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface PerformanceEntryInit {
|
|
24
|
+
name: string;
|
|
25
|
+
entryType: string;
|
|
26
|
+
startTime: number;
|
|
27
|
+
duration: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class PerformanceEntry {
|
|
31
|
+
readonly name: string;
|
|
32
|
+
readonly entryType: string;
|
|
33
|
+
readonly startTime: number;
|
|
34
|
+
readonly duration: number;
|
|
35
|
+
|
|
36
|
+
constructor(init: PerformanceEntryInit) {
|
|
37
|
+
this.name = init.name;
|
|
38
|
+
this.entryType = init.entryType;
|
|
39
|
+
this.startTime = init.startTime;
|
|
40
|
+
this.duration = init.duration;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
toJSON(): object {
|
|
44
|
+
return {
|
|
45
|
+
name: this.name,
|
|
46
|
+
entryType: this.entryType,
|
|
47
|
+
startTime: this.startTime,
|
|
48
|
+
duration: this.duration,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export class PerformanceMark extends PerformanceEntry {
|
|
54
|
+
readonly detail: any;
|
|
55
|
+
|
|
56
|
+
constructor(name: string, options?: PerformanceMarkOptions) {
|
|
57
|
+
super({
|
|
58
|
+
name,
|
|
59
|
+
entryType: "mark",
|
|
60
|
+
startTime: options?.startTime ?? performance?.now?.() ?? Date.now(),
|
|
61
|
+
duration: 0,
|
|
62
|
+
});
|
|
63
|
+
this.detail = options?.detail;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export class PerformanceMeasure extends PerformanceEntry {
|
|
68
|
+
readonly detail: any;
|
|
69
|
+
|
|
70
|
+
constructor(
|
|
71
|
+
name: string,
|
|
72
|
+
startTime: number,
|
|
73
|
+
duration: number,
|
|
74
|
+
detail?: any
|
|
75
|
+
) {
|
|
76
|
+
super({
|
|
77
|
+
name,
|
|
78
|
+
entryType: "measure",
|
|
79
|
+
startTime,
|
|
80
|
+
duration,
|
|
81
|
+
});
|
|
82
|
+
this.detail = detail;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Native module for high-resolution timing
|
|
87
|
+
export interface PerformanceModule {
|
|
88
|
+
now(): number;
|
|
89
|
+
timeOrigin: number;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
let nativeModule: PerformanceModule | null = null;
|
|
93
|
+
|
|
94
|
+
export function setNativePerformanceModule(module: PerformanceModule): void {
|
|
95
|
+
nativeModule = module;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Fallback using Date.now() with offset
|
|
99
|
+
const fallbackTimeOrigin = Date.now();
|
|
100
|
+
const fallbackModule: PerformanceModule = {
|
|
101
|
+
now: () => Date.now() - fallbackTimeOrigin,
|
|
102
|
+
timeOrigin: fallbackTimeOrigin,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
function getModule(): PerformanceModule {
|
|
106
|
+
return nativeModule ?? fallbackModule;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export class Performance {
|
|
110
|
+
private _marks: Map<string, PerformanceMark[]> = new Map();
|
|
111
|
+
private _measures: Map<string, PerformanceMeasure[]> = new Map();
|
|
112
|
+
private _entries: PerformanceEntry[] = [];
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Time origin (when the runtime started)
|
|
116
|
+
*/
|
|
117
|
+
get timeOrigin(): number {
|
|
118
|
+
return getModule().timeOrigin;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Current high-resolution timestamp in milliseconds
|
|
123
|
+
*/
|
|
124
|
+
now(): number {
|
|
125
|
+
return getModule().now();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Create a performance mark
|
|
130
|
+
*/
|
|
131
|
+
mark(markName: string, markOptions?: PerformanceMarkOptions): PerformanceMark {
|
|
132
|
+
const mark = new PerformanceMark(markName, {
|
|
133
|
+
...markOptions,
|
|
134
|
+
startTime: markOptions?.startTime ?? this.now(),
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
let marks = this._marks.get(markName);
|
|
138
|
+
if (!marks) {
|
|
139
|
+
marks = [];
|
|
140
|
+
this._marks.set(markName, marks);
|
|
141
|
+
}
|
|
142
|
+
marks.push(mark);
|
|
143
|
+
this._entries.push(mark);
|
|
144
|
+
|
|
145
|
+
return mark;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Create a performance measure between two marks or times
|
|
150
|
+
*/
|
|
151
|
+
measure(
|
|
152
|
+
measureName: string,
|
|
153
|
+
startOrMeasureOptions?: string | PerformanceMeasureOptions,
|
|
154
|
+
endMark?: string
|
|
155
|
+
): PerformanceMeasure {
|
|
156
|
+
let startTime: number;
|
|
157
|
+
let endTime: number;
|
|
158
|
+
let detail: any;
|
|
159
|
+
|
|
160
|
+
if (typeof startOrMeasureOptions === "string" || startOrMeasureOptions === undefined) {
|
|
161
|
+
// Legacy signature: measure(name, startMark?, endMark?)
|
|
162
|
+
const startMarkName = startOrMeasureOptions;
|
|
163
|
+
|
|
164
|
+
if (startMarkName) {
|
|
165
|
+
const startMarks = this._marks.get(startMarkName);
|
|
166
|
+
if (!startMarks || startMarks.length === 0) {
|
|
167
|
+
throw new DOMException(
|
|
168
|
+
`Failed to execute 'measure': The mark '${startMarkName}' does not exist.`,
|
|
169
|
+
"SyntaxError"
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
startTime = startMarks[startMarks.length - 1].startTime;
|
|
173
|
+
} else {
|
|
174
|
+
startTime = 0;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (endMark) {
|
|
178
|
+
const endMarks = this._marks.get(endMark);
|
|
179
|
+
if (!endMarks || endMarks.length === 0) {
|
|
180
|
+
throw new DOMException(
|
|
181
|
+
`Failed to execute 'measure': The mark '${endMark}' does not exist.`,
|
|
182
|
+
"SyntaxError"
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
endTime = endMarks[endMarks.length - 1].startTime;
|
|
186
|
+
} else {
|
|
187
|
+
endTime = this.now();
|
|
188
|
+
}
|
|
189
|
+
} else {
|
|
190
|
+
// Modern signature: measure(name, options)
|
|
191
|
+
const options = startOrMeasureOptions;
|
|
192
|
+
detail = options.detail;
|
|
193
|
+
|
|
194
|
+
if (options.start !== undefined) {
|
|
195
|
+
if (typeof options.start === "string") {
|
|
196
|
+
const startMarks = this._marks.get(options.start);
|
|
197
|
+
if (!startMarks || startMarks.length === 0) {
|
|
198
|
+
throw new DOMException(
|
|
199
|
+
`Failed to execute 'measure': The mark '${options.start}' does not exist.`,
|
|
200
|
+
"SyntaxError"
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
startTime = startMarks[startMarks.length - 1].startTime;
|
|
204
|
+
} else {
|
|
205
|
+
startTime = options.start;
|
|
206
|
+
}
|
|
207
|
+
} else {
|
|
208
|
+
startTime = 0;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (options.end !== undefined) {
|
|
212
|
+
if (typeof options.end === "string") {
|
|
213
|
+
const endMarks = this._marks.get(options.end);
|
|
214
|
+
if (!endMarks || endMarks.length === 0) {
|
|
215
|
+
throw new DOMException(
|
|
216
|
+
`Failed to execute 'measure': The mark '${options.end}' does not exist.`,
|
|
217
|
+
"SyntaxError"
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
endTime = endMarks[endMarks.length - 1].startTime;
|
|
221
|
+
} else {
|
|
222
|
+
endTime = options.end;
|
|
223
|
+
}
|
|
224
|
+
} else if (options.duration !== undefined) {
|
|
225
|
+
endTime = startTime + options.duration;
|
|
226
|
+
} else {
|
|
227
|
+
endTime = this.now();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const duration = endTime - startTime;
|
|
232
|
+
const measure = new PerformanceMeasure(measureName, startTime, duration, detail);
|
|
233
|
+
|
|
234
|
+
let measures = this._measures.get(measureName);
|
|
235
|
+
if (!measures) {
|
|
236
|
+
measures = [];
|
|
237
|
+
this._measures.set(measureName, measures);
|
|
238
|
+
}
|
|
239
|
+
measures.push(measure);
|
|
240
|
+
this._entries.push(measure);
|
|
241
|
+
|
|
242
|
+
return measure;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Clear marks by name (or all marks if no name given)
|
|
247
|
+
*/
|
|
248
|
+
clearMarks(markName?: string): void {
|
|
249
|
+
if (markName) {
|
|
250
|
+
this._marks.delete(markName);
|
|
251
|
+
this._entries = this._entries.filter(
|
|
252
|
+
(e) => !(e.entryType === "mark" && e.name === markName)
|
|
253
|
+
);
|
|
254
|
+
} else {
|
|
255
|
+
this._marks.clear();
|
|
256
|
+
this._entries = this._entries.filter((e) => e.entryType !== "mark");
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Clear measures by name (or all measures if no name given)
|
|
262
|
+
*/
|
|
263
|
+
clearMeasures(measureName?: string): void {
|
|
264
|
+
if (measureName) {
|
|
265
|
+
this._measures.delete(measureName);
|
|
266
|
+
this._entries = this._entries.filter(
|
|
267
|
+
(e) => !(e.entryType === "measure" && e.name === measureName)
|
|
268
|
+
);
|
|
269
|
+
} else {
|
|
270
|
+
this._measures.clear();
|
|
271
|
+
this._entries = this._entries.filter((e) => e.entryType !== "measure");
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Get all entries
|
|
277
|
+
*/
|
|
278
|
+
getEntries(): PerformanceEntry[] {
|
|
279
|
+
return [...this._entries].sort((a, b) => a.startTime - b.startTime);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Get entries by name
|
|
284
|
+
*/
|
|
285
|
+
getEntriesByName(name: string, type?: string): PerformanceEntry[] {
|
|
286
|
+
return this._entries
|
|
287
|
+
.filter((e) => e.name === name && (!type || e.entryType === type))
|
|
288
|
+
.sort((a, b) => a.startTime - b.startTime);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Get entries by type
|
|
293
|
+
*/
|
|
294
|
+
getEntriesByType(type: string): PerformanceEntry[] {
|
|
295
|
+
return this._entries
|
|
296
|
+
.filter((e) => e.entryType === type)
|
|
297
|
+
.sort((a, b) => a.startTime - b.startTime);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Resource timing (stubs for compatibility)
|
|
301
|
+
clearResourceTimings(): void {
|
|
302
|
+
// No-op in Exact (no resource timing)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
setResourceTimingBufferSize(_maxSize: number): void {
|
|
306
|
+
// No-op in Exact
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
toJSON(): object {
|
|
310
|
+
return {
|
|
311
|
+
timeOrigin: this.timeOrigin,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Mix in EventTarget methods on Performance.prototype so that
|
|
317
|
+
// `performance instanceof EventTarget` is true and addEventListener/
|
|
318
|
+
// dispatchEvent work correctly (per spec, Performance extends EventTarget).
|
|
319
|
+
// We do this as a mixin instead of class inheritance because Babel's
|
|
320
|
+
// ES5 transpilation of `class Performance extends EventTarget` doesn't
|
|
321
|
+
// properly set up the prototype chain when compiled to an IIFE for Hermes.
|
|
322
|
+
Object.setPrototypeOf(Performance.prototype, EventTarget.prototype);
|
|
323
|
+
|
|
324
|
+
// Create singleton
|
|
325
|
+
export const performance = new Performance();
|
|
326
|
+
// Initialize the EventTarget internal state on the singleton.
|
|
327
|
+
// We can't use EventTarget.call(performance) because Babel's _classCallCheck
|
|
328
|
+
// prevents calling a class constructor without `new`. Instead, directly
|
|
329
|
+
// initialize the internal _listeners Map that EventTarget expects.
|
|
330
|
+
(performance as any)._listeners = new Map();
|
|
331
|
+
|
|
332
|
+
// =============================================================================
|
|
333
|
+
// PerformanceObserver
|
|
334
|
+
// =============================================================================
|
|
335
|
+
|
|
336
|
+
export interface PerformanceObserverInit {
|
|
337
|
+
entryTypes?: string[];
|
|
338
|
+
type?: string;
|
|
339
|
+
buffered?: boolean;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export interface PerformanceObserverCallbackOptions {
|
|
343
|
+
droppedEntriesCount?: number;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export type PerformanceObserverCallback = (
|
|
347
|
+
entries: PerformanceObserverEntryList,
|
|
348
|
+
observer: PerformanceObserver,
|
|
349
|
+
options?: PerformanceObserverCallbackOptions
|
|
350
|
+
) => void;
|
|
351
|
+
|
|
352
|
+
export class PerformanceObserverEntryList {
|
|
353
|
+
private _entries: PerformanceEntry[];
|
|
354
|
+
|
|
355
|
+
constructor(entries: PerformanceEntry[]) {
|
|
356
|
+
this._entries = entries;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
getEntries(): PerformanceEntry[] {
|
|
360
|
+
return [...this._entries].sort((a, b) => a.startTime - b.startTime);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
getEntriesByName(name: string, type?: string): PerformanceEntry[] {
|
|
364
|
+
return this._entries
|
|
365
|
+
.filter((e) => e.name === name && (!type || e.entryType === type))
|
|
366
|
+
.sort((a, b) => a.startTime - b.startTime);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
getEntriesByType(type: string): PerformanceEntry[] {
|
|
370
|
+
return this._entries
|
|
371
|
+
.filter((e) => e.entryType === type)
|
|
372
|
+
.sort((a, b) => a.startTime - b.startTime);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Store active observers
|
|
377
|
+
const observers = new Set<PerformanceObserver>();
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* PerformanceObserver enables observing performance timeline entries.
|
|
381
|
+
*/
|
|
382
|
+
export class PerformanceObserver {
|
|
383
|
+
private _callback: PerformanceObserverCallback;
|
|
384
|
+
private _entryTypes: Set<string> = new Set();
|
|
385
|
+
private _buffer: PerformanceEntry[] = [];
|
|
386
|
+
private _isObserving = false;
|
|
387
|
+
private _scheduled = false;
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Supported entry types.
|
|
391
|
+
*/
|
|
392
|
+
static get supportedEntryTypes(): readonly string[] {
|
|
393
|
+
return Object.freeze(['mark', 'measure']);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
constructor(callback: PerformanceObserverCallback) {
|
|
397
|
+
if (typeof callback !== 'function') {
|
|
398
|
+
throw new TypeError('Callback must be a function');
|
|
399
|
+
}
|
|
400
|
+
this._callback = callback;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Start observing performance entries.
|
|
405
|
+
*/
|
|
406
|
+
observe(options: PerformanceObserverInit): void {
|
|
407
|
+
if (!options.entryTypes && !options.type) {
|
|
408
|
+
throw new TypeError('Either entryTypes or type must be specified');
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (options.entryTypes && options.type) {
|
|
412
|
+
throw new TypeError('Cannot specify both entryTypes and type');
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
this._entryTypes.clear();
|
|
416
|
+
|
|
417
|
+
if (options.entryTypes) {
|
|
418
|
+
for (let i = 0; i < options.entryTypes.length; i++) {
|
|
419
|
+
const type = options.entryTypes[i];
|
|
420
|
+
if (PerformanceObserver.supportedEntryTypes.includes(type)) {
|
|
421
|
+
this._entryTypes.add(type);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
} else if (options.type) {
|
|
425
|
+
if (PerformanceObserver.supportedEntryTypes.includes(options.type)) {
|
|
426
|
+
this._entryTypes.add(options.type);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (this._entryTypes.size === 0) {
|
|
431
|
+
// Per spec: if no supported entry types remain, silently return
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// If buffered, only works with single `type` API (not `entryTypes`)
|
|
436
|
+
if (options.buffered && options.type) {
|
|
437
|
+
const existingEntries: PerformanceEntry[] = [];
|
|
438
|
+
const timelineEntries = performance.getEntries();
|
|
439
|
+
for (let i = 0; i < timelineEntries.length; i++) {
|
|
440
|
+
const entry = timelineEntries[i];
|
|
441
|
+
if (this._entryTypes.has(entry.entryType)) {
|
|
442
|
+
existingEntries.push(entry);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
if (existingEntries.length > 0) {
|
|
446
|
+
this._buffer.push(...existingEntries);
|
|
447
|
+
this._scheduleCallback();
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
this._isObserving = true;
|
|
452
|
+
observers.add(this);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Stop observing.
|
|
457
|
+
*/
|
|
458
|
+
disconnect(): void {
|
|
459
|
+
this._isObserving = false;
|
|
460
|
+
this._buffer = [];
|
|
461
|
+
observers.delete(this);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Get buffered entries and clear the buffer.
|
|
466
|
+
*/
|
|
467
|
+
takeRecords(): PerformanceEntry[] {
|
|
468
|
+
const entries = [...this._buffer];
|
|
469
|
+
this._buffer = [];
|
|
470
|
+
return entries;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Internal: Called when a new entry is added.
|
|
475
|
+
*/
|
|
476
|
+
_notify(entry: PerformanceEntry): void {
|
|
477
|
+
if (!this._isObserving) return;
|
|
478
|
+
if (!this._entryTypes.has(entry.entryType)) return;
|
|
479
|
+
|
|
480
|
+
this._buffer.push(entry);
|
|
481
|
+
this._scheduleCallback();
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
private _scheduleCallback(): void {
|
|
485
|
+
if (this._scheduled) return;
|
|
486
|
+
this._scheduled = true;
|
|
487
|
+
const observer = this;
|
|
488
|
+
|
|
489
|
+
queueMicrotask(function() {
|
|
490
|
+
observer._scheduled = false;
|
|
491
|
+
if (observer._buffer.length === 0) return;
|
|
492
|
+
|
|
493
|
+
const entries = observer.takeRecords();
|
|
494
|
+
const list = new PerformanceObserverEntryList(entries);
|
|
495
|
+
|
|
496
|
+
try {
|
|
497
|
+
observer._callback(list, observer);
|
|
498
|
+
} catch (e) {
|
|
499
|
+
console.error('PerformanceObserver callback error:', e);
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Notify all observers of a new entry.
|
|
507
|
+
* Called internally when marks/measures are created.
|
|
508
|
+
*/
|
|
509
|
+
export function notifyObservers(entry: PerformanceEntry): void {
|
|
510
|
+
for (const observer of observers) {
|
|
511
|
+
observer._notify(entry);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// Patch Performance to notify observers
|
|
516
|
+
const originalMark = Performance.prototype.mark;
|
|
517
|
+
Performance.prototype.mark = function(markName: string, markOptions?: PerformanceMarkOptions): PerformanceMark {
|
|
518
|
+
const mark = originalMark.call(this, markName, markOptions);
|
|
519
|
+
notifyObservers(mark);
|
|
520
|
+
return mark;
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
const originalMeasure = Performance.prototype.measure;
|
|
524
|
+
Performance.prototype.measure = function(
|
|
525
|
+
measureName: string,
|
|
526
|
+
startOrMeasureOptions?: string | PerformanceMeasureOptions,
|
|
527
|
+
endMark?: string
|
|
528
|
+
): PerformanceMeasure {
|
|
529
|
+
const measure = originalMeasure.call(this, measureName, startOrMeasureOptions, endMark);
|
|
530
|
+
notifyObservers(measure);
|
|
531
|
+
return measure;
|
|
532
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export {
|
|
2
|
+
Performance,
|
|
3
|
+
PerformanceEntry,
|
|
4
|
+
PerformanceMark,
|
|
5
|
+
PerformanceMeasure,
|
|
6
|
+
PerformanceObserver,
|
|
7
|
+
PerformanceObserverEntryList,
|
|
8
|
+
performance,
|
|
9
|
+
setNativePerformanceModule,
|
|
10
|
+
notifyObservers,
|
|
11
|
+
} from "./Performance";
|
|
12
|
+
|
|
13
|
+
export type {
|
|
14
|
+
PerformanceModule,
|
|
15
|
+
PerformanceMarkOptions,
|
|
16
|
+
PerformanceMeasureOptions,
|
|
17
|
+
PerformanceEntryInit,
|
|
18
|
+
PerformanceObserverInit,
|
|
19
|
+
PerformanceObserverCallback,
|
|
20
|
+
PerformanceObserverCallbackOptions,
|
|
21
|
+
} from "./Performance";
|