Skip to content

Commit 364c0e1

Browse files
committed
perf_hooks: fix webperf idlharness
1. Enforce receiver checks on IDL interfaces. 2. Avoid prototype manipulation on constructing IDL interfaces with `ReflectConstruct`. 3. `defineReplaceableAttribute` should create IDL getter/setter. 4. Corrected `PerformanceResourceTiming` to inherit the public interface `PerformanceEntry` instead of the internal interface `InternalPerformanceResourceTiming`. 5. `detail` is not a specified attribute on `PerfomanceEntry`. Node.js specific extensions are moved to a subclass of `PerformanceEntry` as `PerformanceNodeEntry`. PR-URL: #44483 Reviewed-By: Antoine du Hamel <[email protected]> Reviewed-By: Minwoo Jung <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent f529f73 commit 364c0e1

File tree

218 files changed

+8089
-529
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

218 files changed

+8089
-529
lines changed

doc/api/perf_hooks.md

+271-45
Large diffs are not rendered by default.

lib/internal/bootstrap/browser.js

+25-6
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ exposeInterface(globalThis, 'Blob', buffer.Blob);
7575
// https://www.w3.org/TR/hr-time-2/#the-performance-attribute
7676
const perf_hooks = require('perf_hooks');
7777
exposeInterface(globalThis, 'Performance', perf_hooks.Performance);
78-
defineReplacableAttribute(globalThis, 'performance',
79-
perf_hooks.performance);
78+
defineReplaceableAttribute(globalThis, 'performance',
79+
perf_hooks.performance);
8080

8181
function createGlobalConsole() {
8282
const consoleFromNode =
@@ -114,14 +114,33 @@ function exposeGetterAndSetter(target, name, getter, setter = undefined) {
114114
});
115115
}
116116

117-
// https://heycam.github.io/webidl/#Replaceable
118-
function defineReplacableAttribute(target, name, value) {
117+
// https://webidl.spec.whatwg.org/#Replaceable
118+
function defineReplaceableAttribute(target, name, value) {
119+
let slot = value;
120+
121+
// https://webidl.spec.whatwg.org/#dfn-attribute-getter
122+
function get() {
123+
return slot;
124+
}
125+
ObjectDefineProperty(get, 'name', {
126+
__proto__: null,
127+
value: `get ${name}`,
128+
});
129+
130+
function set(value) {
131+
slot = value;
132+
}
133+
ObjectDefineProperty(set, 'name', {
134+
__proto__: null,
135+
value: `set ${name}`,
136+
});
137+
119138
ObjectDefineProperty(target, name, {
120139
__proto__: null,
121-
writable: true,
122140
enumerable: true,
123141
configurable: true,
124-
value,
142+
get,
143+
set,
125144
});
126145
}
127146

lib/internal/perf/observe.js

+59-16
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ const {
1616
ObjectDefineProperties,
1717
ObjectFreeze,
1818
ObjectKeys,
19+
ReflectConstruct,
1920
SafeMap,
2021
SafeSet,
2122
Symbol,
23+
SymbolToStringTag,
2224
} = primordials;
2325

2426
const {
@@ -36,12 +38,13 @@ const {
3638
} = internalBinding('performance');
3739

3840
const {
39-
InternalPerformanceEntry,
4041
isPerformanceEntry,
42+
createPerformanceNodeEntry,
4143
} = require('internal/perf/performance_entry');
4244

4345
const {
4446
codes: {
47+
ERR_ILLEGAL_CONSTRUCTOR,
4548
ERR_INVALID_ARG_VALUE,
4649
ERR_INVALID_ARG_TYPE,
4750
ERR_MISSING_ARGS,
@@ -51,13 +54,15 @@ const {
5154
const {
5255
validateFunction,
5356
validateObject,
57+
validateInternalField,
5458
} = require('internal/validators');
5559

5660
const {
5761
customInspectSymbol: kInspect,
5862
deprecate,
5963
lazyDOMException,
6064
kEmptyObject,
65+
kEnumerableProperty,
6166
} = require('internal/util');
6267

6368
const {
@@ -68,6 +73,7 @@ const { inspect } = require('util');
6873

6974
const { now } = require('internal/perf/utils');
7075

76+
const kBuffer = Symbol('kBuffer');
7177
const kDispatch = Symbol('kDispatch');
7278
const kMaybeBuffer = Symbol('kMaybeBuffer');
7379
const kDeprecatedFields = Symbol('kDeprecatedFields');
@@ -167,34 +173,39 @@ function maybeIncrementObserverCount(type) {
167173
}
168174

169175
class PerformanceObserverEntryList {
170-
#buffer = [];
171-
172-
constructor(entries) {
173-
this.#buffer = ArrayPrototypeSort(entries, (first, second) => {
174-
return first.startTime - second.startTime;
175-
});
176+
constructor() {
177+
throw new ERR_ILLEGAL_CONSTRUCTOR();
176178
}
177179

178180
getEntries() {
179-
return ArrayPrototypeSlice(this.#buffer);
181+
validateInternalField(this, kBuffer, 'PerformanceObserverEntryList');
182+
return ArrayPrototypeSlice(this[kBuffer]);
180183
}
181184

182185
getEntriesByType(type) {
186+
validateInternalField(this, kBuffer, 'PerformanceObserverEntryList');
187+
if (arguments.length === 0) {
188+
throw new ERR_MISSING_ARGS('type');
189+
}
183190
type = `${type}`;
184191
return ArrayPrototypeFilter(
185-
this.#buffer,
192+
this[kBuffer],
186193
(entry) => entry.entryType === type);
187194
}
188195

189-
getEntriesByName(name, type) {
196+
getEntriesByName(name, type = undefined) {
197+
validateInternalField(this, kBuffer, 'PerformanceObserverEntryList');
198+
if (arguments.length === 0) {
199+
throw new ERR_MISSING_ARGS('name');
200+
}
190201
name = `${name}`;
191202
if (type != null /** not nullish */) {
192203
return ArrayPrototypeFilter(
193-
this.#buffer,
204+
this[kBuffer],
194205
(entry) => entry.name === name && entry.entryType === type);
195206
}
196207
return ArrayPrototypeFilter(
197-
this.#buffer,
208+
this[kBuffer],
198209
(entry) => entry.name === name);
199210
}
200211

@@ -206,9 +217,29 @@ class PerformanceObserverEntryList {
206217
depth: options.depth == null ? null : options.depth - 1
207218
};
208219

209-
return `PerformanceObserverEntryList ${inspect(this.#buffer, opts)}`;
220+
return `PerformanceObserverEntryList ${inspect(this[kBuffer], opts)}`;
210221
}
211222
}
223+
ObjectDefineProperties(PerformanceObserverEntryList.prototype, {
224+
getEntries: kEnumerableProperty,
225+
getEntriesByType: kEnumerableProperty,
226+
getEntriesByName: kEnumerableProperty,
227+
[SymbolToStringTag]: {
228+
__proto__: null,
229+
writable: false,
230+
enumerable: false,
231+
configurable: true,
232+
value: 'PerformanceObserverEntryList',
233+
},
234+
});
235+
236+
function createPerformanceObserverEntryList(entries) {
237+
return ReflectConstruct(function PerformanceObserverEntryList() {
238+
this[kBuffer] = ArrayPrototypeSort(entries, (first, second) => {
239+
return first.startTime - second.startTime;
240+
});
241+
}, [], PerformanceObserverEntryList);
242+
}
212243

213244
class PerformanceObserver {
214245
#buffer = [];
@@ -319,7 +350,7 @@ class PerformanceObserver {
319350
}
320351

321352
[kDispatch]() {
322-
this.#callback(new PerformanceObserverEntryList(this.takeRecords()),
353+
this.#callback(createPerformanceObserverEntryList(this.takeRecords()),
323354
this);
324355
}
325356

@@ -339,6 +370,18 @@ class PerformanceObserver {
339370
}, opts)}`;
340371
}
341372
}
373+
ObjectDefineProperties(PerformanceObserver.prototype, {
374+
observe: kEnumerableProperty,
375+
disconnect: kEnumerableProperty,
376+
takeRecords: kEnumerableProperty,
377+
[SymbolToStringTag]: {
378+
__proto__: null,
379+
writable: false,
380+
enumerable: false,
381+
configurable: true,
382+
value: 'PerformanceObserver',
383+
},
384+
});
342385

343386
/**
344387
* https://www.w3.org/TR/performance-timeline/#dfn-queue-a-performanceentry
@@ -485,7 +528,7 @@ function filterBufferMapByNameAndType(name, type) {
485528

486529
function observerCallback(name, type, startTime, duration, details) {
487530
const entry =
488-
new InternalPerformanceEntry(
531+
createPerformanceNodeEntry(
489532
name,
490533
type,
491534
startTime,
@@ -542,7 +585,7 @@ function stopPerf(target, key, context = {}) {
542585
return;
543586
}
544587
const startTime = ctx.startTime;
545-
const entry = new InternalPerformanceEntry(
588+
const entry = createPerformanceNodeEntry(
546589
ctx.name,
547590
ctx.type,
548591
startTime,

0 commit comments

Comments
 (0)