Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf_hooks: fix performance timeline wpt failures #39532

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 30 additions & 7 deletions lib/internal/perf/observe.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const {
const {
customInspectSymbol: kInspect,
deprecate,
lazyDOMException,
} = require('internal/util');

const {
Expand Down Expand Up @@ -106,9 +107,10 @@ function queuePending() {
isPending = true;
setImmediate(() => {
isPending = false;
for (const pending of kPending)
pending[kDispatch]();
const pendings = ArrayFrom(kPending.values());
kPending.clear();
for (const pending of pendings)
pending[kDispatch]();
});
}

Expand Down Expand Up @@ -168,8 +170,13 @@ class PerformanceObserverEntryList {
(entry) => entry.entryType === type);
}

getEntriesByName(name) {
getEntriesByName(name, type) {
name = `${name}`;
if (type != null /** not nullish */) {
return ArrayPrototypeFilter(
this[kBuffer],
(entry) => entry.name === name && entry.entryType === type);
}
return ArrayPrototypeFilter(
this[kBuffer],
(entry) => entry.name === name);
Expand Down Expand Up @@ -208,6 +215,11 @@ class PerformanceObserver {
} = { ...options };
if (entryTypes === undefined && type === undefined)
throw new ERR_MISSING_ARGS('options.entryTypes', 'options.type');
if (entryTypes != null && type != null)
throw new ERR_INVALID_ARG_VALUE('options.entryTypes',
entryTypes,
'options.entryTypes can not set with ' +
'options.type together');

switch (this[kType]) {
case undefined:
Expand All @@ -216,11 +228,15 @@ class PerformanceObserver {
break;
case kTypeSingle:
if (entryTypes !== undefined)
throw new ERR_INVALID_ARG_VALUE('options.entryTypes', entryTypes);
throw lazyDOMException(
'PerformanceObserver can not change to multiple observations',
'InvalidModificationError');
break;
case kTypeMultiple:
if (type !== undefined)
throw new ERR_INVALID_ARG_VALUE('options.type', type);
throw lazyDOMException(
'PerformanceObserver can not change to single observation',
'InvalidModificationError');
break;
}

Expand Down Expand Up @@ -271,7 +287,7 @@ class PerformanceObserver {
takeRecords() {
const list = this[kBuffer];
this[kBuffer] = [];
return new PerformanceObserverEntryList(list);
return list;
}

static get supportedEntryTypes() {
Expand All @@ -287,7 +303,10 @@ class PerformanceObserver {
queuePending();
}

[kDispatch]() { this[kCallback](this.takeRecords(), this); }
[kDispatch]() {
this[kCallback](new PerformanceObserverEntryList(this.takeRecords()),
this);
}

[kInspect](depth, options) {
if (depth < 0) return this;
Expand Down Expand Up @@ -367,6 +386,7 @@ function clearEntriesFromBuffer(type, name) {

let head = null;
let tail = null;
let count = 0;
for (let entry = buffer.head; entry !== null; entry = entry[kBufferNext]) {
if (entry.name !== name) {
head = head ?? entry;
Expand All @@ -377,9 +397,11 @@ function clearEntriesFromBuffer(type, name) {
continue;
}
tail[kBufferNext] = entry[kBufferNext];
count++;
}
buffer.head = head;
buffer.tail = tail;
buffer.count = count;
}

function filterBufferMapByNameAndType(name, type) {
Expand Down Expand Up @@ -469,6 +491,7 @@ function resetBuffer(buffer) {

module.exports = {
PerformanceObserver,
PerformanceObserverEntryList,
enqueue,
hasObserver,
clearEntriesFromBuffer,
Expand Down
6 changes: 5 additions & 1 deletion lib/perf_hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ const {
} = internalBinding('performance');

const { PerformanceEntry } = require('internal/perf/performance_entry');
const { PerformanceObserver } = require('internal/perf/observe');
const {
PerformanceObserver,
PerformanceObserverEntryList,
} = require('internal/perf/observe');
const {
PerformanceMark,
PerformanceMeasure,
Expand All @@ -27,6 +30,7 @@ module.exports = {
PerformanceMark,
PerformanceMeasure,
PerformanceObserver,
PerformanceObserverEntryList,
monitorEventLoopDelay,
createHistogram,
performance: new InternalPerformance(),
Expand Down
12 changes: 11 additions & 1 deletion test/wpt/status/performance-timeline.json
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
{}
{
"case-sensitivity.any.js": {
"fail": "resource entry type not supported"
},
"idlharness.any.js": {
"skip": "idlharness cannot recognize Node.js environment"
},
"webtiming-resolution.any.js": {
"skip": "flaky"
}
}
4 changes: 3 additions & 1 deletion test/wpt/test-performance-timeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
require('../common');
const { WPTRunner } = require('../common/wpt');

const runner = new WPTRunner('user-timing');
const runner = new WPTRunner('performance-timeline');

// Needed to access to DOMException.
runner.setFlags(['--expose-internals']);
Expand All @@ -12,11 +12,13 @@ runner.setInitScript(`
PerformanceMark,
PerformanceMeasure,
PerformanceObserver,
PerformanceObserverEntryList,
performance,
} = require('perf_hooks');
global.PerformanceMark = performance;
global.PerformanceMeasure = performance;
global.PerformanceObserver = PerformanceObserver;
global.PerformanceObserverEntryList = PerformanceObserverEntryList;
global.performance = performance;

const { internalBinding } = require('internal/test/binding');
Expand Down