Skip to content

fix(node:perf_hooks): make PerformanceNodeTiming startTime/duration work#32481

Open
0xfandom wants to merge 1 commit into
oven-sh:mainfrom
0xfandom:claude/perf-hooks-node-timing
Open

fix(node:perf_hooks): make PerformanceNodeTiming startTime/duration work#32481
0xfandom wants to merge 1 commit into
oven-sh:mainfrom
0xfandom:claude/perf-hooks-node-timing

Conversation

@0xfandom

Copy link
Copy Markdown

What does this PR do?

Fixes #23041. performance.nodeTiming.startTime and .duration threw TypeError: The PerformanceEntry.startTime getter can only be used on instances of PerformanceEntry, and the milestone fields were absolute epoch timestamps instead of offsets from performance.timeOrigin.

PerformanceNodeTiming is faked with $toClass, which replaces the class prototype with a fresh object inheriting only from PerformanceEntry. That discarded the name/entryType/startTime/duration getters and toJSON defined in the class body, so reading startTime/duration fell through to PerformanceEntry's native getters — which throw for any object that isn't a real PerformanceEntry instance.

  • Define the accessors and toJSON on the prototype after $toClass (the same idiom every other $toClass user follows).
  • startTime returns 0 to match Node (a "node" entry is the timeOrigin reference).
  • Report the startup milestones (nodeStart, v8Start, environment, bootstrapComplete, loopStart, idleTime) as offsets in ms from timeOrigin (0) rather than absolute epoch timestamps; loopExit stays -1.

Before / after (bun -e 'const {performance}=require("node:perf_hooks"); const nt=performance.nodeTiming; nt.startTime'):

before: TypeError: The PerformanceEntry.startTime getter can only be used on instances of PerformanceEntry
after:  0

How did you verify your code works?

Added a node:perf_hooks test asserting startTime/duration no longer throw, the name/entryType/startTime values match Node, the milestones are offsets (< 1e12) while timeOrigin is epoch-scale, and the toJSON() shape. Verified the new test passes on the debug build and fails on the released bun (USE_SYSTEM_BUN=1).

$toClass replaces the class prototype with a fresh object inheriting only from
PerformanceEntry, so the name/entryType/startTime/duration getters and toJSON
defined in the class body were discarded. Reading startTime or duration then
fell through to PerformanceEntry's native getters, which throw for objects that
are not real PerformanceEntry instances.

Define the accessors and toJSON on the prototype after $toClass, return 0 for
startTime to match Node, and report the startup milestones as offsets from
performance.timeOrigin (0) instead of absolute epoch timestamps.

Fixes oven-sh#23041

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

PerformanceNodeTiming in perf_hooks.ts is refactored from an in-class getter approach to a prototype-based one using $toClass, with name, entryType, startTime, and duration defined via Object.defineProperties on the prototype. Milestone offsets are reset from epoch-like values to 0. A new test validates the corrected shape and toJSON output.

Changes

PerformanceNodeTiming prototype refactor and offset fix

Layer / File(s) Summary
PerformanceNodeTiming prototype accessors and milestone offset reset
src/js/node/perf_hooks.ts
PerformanceNodeTiming is converted to an empty class via $toClass with name, entryType, startTime, and duration accessors defined using Object.defineProperties on the prototype; toJSON is also moved to the prototype. createPerformanceNodeTiming() resets nodeStart, v8Start, environment, bootstrapComplete, loopStart, and idleTime to 0 instead of epoch-derived values.
nodeTiming shape and toJSON test
test/js/node/perf_hooks/perf_hooks.test.ts
Adds a test asserting non-throwing access to startTime/duration, that timeOrigin is epoch-scale, that all milestone offsets are below 1e12, that loopExit === -1, and that toJSON() returns a numeric duration with the expected remaining property shape.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main fix: making PerformanceNodeTiming startTime/duration properties work by resolving the TypeError and aligning with Node.js behavior.
Description check ✅ Passed The PR description comprehensively covers what the PR does, why it was needed (fixing #23041), the technical root cause, and how it was verified with test coverage. It follows the template with both required sections completed.
Linked Issues check ✅ Passed The PR fully addresses all three coding requirements from #23041: (1) makes startTime and duration accessible without throwing TypeError by redefining them on the prototype after $toClass; (2) converts milestone offsets from absolute epoch timestamps to offsets from timeOrigin; (3) ensures properties are properly exposed and enumerable.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing #23041: the perf_hooks.ts refactoring implements the required fixes, and the new test validates the corrected behavior. No unrelated modifications are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/js/node/perf_hooks.ts`:
- Around line 64-78: The PerformanceNodeTiming.prototype.toJSON assignment
creates an enumerable property which differs from Node.js behavior where toJSON
is non-enumerable. Replace the direct assignment of
PerformanceNodeTiming.prototype.toJSON with Object.defineProperty, passing the
prototype object, the property name "toJSON", and a property descriptor object
that defines the value as the toJSON function while setting enumerable to false
to match Node.js implementation.
- Around line 55-62: The properties `name`, `entryType`, `startTime`, and
`duration` are currently defined only on the PerformanceNodeTiming.prototype,
but they must also be defined as own properties on the instance to match Node.js
v22+ behavior and ensure Object.getOwnPropertyNames returns them. In the
createPerformanceNodeTiming function, after creating the instance, apply
Object.defineProperties to the instance itself using the same property
descriptors (with the same getter functions for name, entryType, startTime, and
duration) that are defined on the prototype.

In `@test/js/node/perf_hooks/perf_hooks.test.ts`:
- Around line 25-30: The milestone offset validation loop iterates over
nodeStart, v8Start, environment, bootstrapComplete, and idleTime but is missing
loopStart, which was also converted from epoch timestamps to offsets. Add
loopStart to the array of keys being checked in the for loop that validates each
milestone is less than 1e12, ensuring that loopStart is properly validated
alongside the other milestone offsets.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 25088c16-7ff1-4e8f-9c5c-ee16f79530a6

📥 Commits

Reviewing files that changed from the base of the PR and between f9530ae and 79827ec.

📒 Files selected for processing (2)
  • src/js/node/perf_hooks.ts
  • test/js/node/perf_hooks/perf_hooks.test.ts

Comment thread src/js/node/perf_hooks.ts
Comment on lines +55 to +62
Object.defineProperties(PerformanceNodeTiming.prototype, {
name: { get: () => "node", configurable: true, enumerable: true },
entryType: { get: () => "node", configurable: true, enumerable: true },
// A "node" entry is the timeOrigin reference, so its startTime is always 0,
// matching Node.
startTime: { get: () => 0, configurable: true, enumerable: true },
duration: { get: () => performance.now(), configurable: true, enumerable: true },
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

bun bd -e '
const perf = require("node:perf_hooks");
const names = Object.getOwnPropertyNames(perf.performance.nodeTiming);
console.log(names);
if (!names.includes("startTime") || !names.includes("duration")) process.exit(1);
'

Repository: oven-sh/bun

Length of output: 99


🏁 Script executed:

cd /tmp && find . -name "perf_hooks.ts" -type f 2>/dev/null | head -5

Repository: oven-sh/bun

Length of output: 37


🏁 Script executed:

git -C /tmp ls-files "**perf_hooks.ts" 2>/dev/null | head -5

Repository: oven-sh/bun

Length of output: 37


🏁 Script executed:

fd -i perf_hooks.ts

Repository: oven-sh/bun

Length of output: 130


🏁 Script executed:

cat -n src/js/node/perf_hooks.ts | head -100

Repository: oven-sh/bun

Length of output: 4431


🏁 Script executed:

cat -n src/js/node/perf_hooks.ts | sed -n '46,92p'

Repository: oven-sh/bun

Length of output: 2384


🏁 Script executed:

python3 << 'PY'
import json

# Node.js behavior:
# In Node.js, performance.nodeTiming is a PerformanceNodeTiming instance
# that inherits from PerformanceEntry. Let me check how Node.js defines these properties.

# The key question: are name, entryType, startTime, duration own properties 
# or prototype properties?

# Let's verify by understanding what Object.getOwnPropertyNames returns
# for a typical PerformanceEntry instance

test_code = """
const perf = require('perf_hooks').performance;

// What does getOwnPropertyNames return?
const ownProps = Object.getOwnPropertyNames(perf.nodeTiming);
console.log('Own properties:', ownProps);

// Check if startTime is an own property
console.log('startTime is own property:', ownProps.includes('startTime'));
console.log('startTime descriptor:', Object.getOwnPropertyDescriptor(perf.nodeTiming, 'startTime'));

// Check prototype
console.log('startTime on prototype:', Object.getOwnPropertyDescriptor(Object.getPrototypeOf(perf.nodeTiming), 'startTime'));

// Check what Node.js reports
console.log('nodeTiming.startTime:', perf.nodeTiming.startTime);
console.log('nodeTiming.name:', perf.nodeTiming.name);
"""

print("Expected Node.js test code:")
print(test_code)
PY

Repository: oven-sh/bun

Length of output: 794


🏁 Script executed:

cat test/integration/bun-types/fixture/perf_hooks.ts

Repository: oven-sh/bun

Length of output: 208


🏁 Script executed:

rg -i "nodeTiming" test/ --type ts --type js -A 3 -B 3

Repository: oven-sh/bun

Length of output: 3457


🏁 Script executed:

rg -i "getOwnPropertyNames.*performance\|performance.*getOwnPropertyNames" test/ --type ts --type js

Repository: oven-sh/bun

Length of output: 37


🏁 Script executed:

rg "startTime.*duration\|duration.*startTime" src/js/node/ --type ts

Repository: oven-sh/bun

Length of output: 37


🏁 Script executed:

rg -A 5 "nodeTiming" src/js/node/perf_hooks.ts

Repository: oven-sh/bun

Length of output: 251


🏁 Script executed:

python3 << 'PY'
# The core issue: 
# Object.getOwnPropertyNames() returns ONLY own properties, not inherited ones
# 
# Current code:
# - Lines 55-62: defineProperties on PerformanceNodeTiming.prototype
# - Lines 80-89: createPerformanceNodeTiming() creates object with create(prototype)
#   and assigns milestone fields as own properties
#
# Result: name, entryType, startTime, duration are on prototype, not on the instance
# So Object.getOwnPropertyNames(instance) won't include them
#
# Proposed fix:
# - Also defineProperties on the instance itself in createPerformanceNodeTiming()
#
# This would make them show up in getOwnPropertyNames()

# Let's verify this is correct by understanding standard PerformanceEntry behavior

print("Understanding the issue:")
print("1. Current: properties only on prototype")
print("2. Problem: Object.getOwnPropertyNames() doesn't include prototype properties")
print("3. Solution: Define properties on both prototype AND instance")
print("")
print("The question: Does Node.js expose name/entryType/startTime/duration")
print("as own properties or prototype properties on performance.nodeTiming?")
print("")
print("In Node.js, PerformanceEntry instances typically have these as own properties")
print("when they're created, or they're accessible but not enumerable via getOwnPropertyNames")
print("depending on the implementation.")
PY

Repository: oven-sh/bun

Length of output: 598


🏁 Script executed:

rg "PerformanceEntry\|nodeTiming" src/ --type rs -i -A 2 -B 2 | head -50

Repository: oven-sh/bun

Length of output: 82


🏁 Script executed:

cat -n test/js/node/perf_hooks/perf_hooks.test.ts | head -60

Repository: oven-sh/bun

Length of output: 2679


🏁 Script executed:

rg "getOwnPropertyNames.*nodeTiming\|nodeTiming.*getOwnPropertyNames" test/

Repository: oven-sh/bun

Length of output: 37


🏁 Script executed:

cat -n test/js/node/perf_hooks/perf_hooks.test.ts | tail -20

Repository: oven-sh/bun

Length of output: 1001


🏁 Script executed:

rg "`#23041`" src/ test/ --type ts --type js

Repository: oven-sh/bun

Length of output: 37


🏁 Script executed:

web_search
What does Object.getOwnPropertyNames return for performance.nodeTiming in Node.js

Repository: oven-sh/bun

Length of output: 149


🌐 Web query:

Node.js performance.nodeTiming Object.getOwnPropertyNames behavior

💡 Result:

In Node.js, the performance.nodeTiming object is an instance of the PerformanceNodeTiming class, which provides performance metrics for specific Node.js operational milestones [1][2]. When you call Object.getOwnPropertyNames(performance.nodeTiming), it returns an array of all properties defined directly on that instance, including both enumerable and non-enumerable properties [3]. As of recent Node.js versions (e.g., v22+), this list typically includes the following [4]: - name - entryType - startTime - duration - nodeStart - v8Start - environment - loopStart - loopExit - bootstrapComplete - idleTime - uvMetricsInfo Because Object.getOwnPropertyNames() is designed to retrieve all own property names regardless of enumerability [3], it successfully returns these internal performance properties. This behavior is consistent with the standard JavaScript behavior for objects [3] and is used in Node.js test suites to inspect and verify the performance.nodeTiming object's structure [5]. Note that while these properties exist on the object, some may have specific behaviors or return values like -1 if a milestone has not yet been reached [6][7].

Citations:


🏁 Script executed:

rg "getOwnPropertyNames.*performance\|getOwnPropertyNames.*nodeTiming" test/js/node/perf_hooks/

Repository: oven-sh/bun

Length of output: 37


🏁 Script executed:

git log --oneline src/js/node/perf_hooks.ts | head -10

Repository: oven-sh/bun

Length of output: 128


🏁 Script executed:

rg "23041" src/ test/ --type ts --type js -B 2 -A 2

Repository: oven-sh/bun

Length of output: 503


Define entry accessors as own properties on the instance too.

Defining name, entryType, startTime, and duration on PerformanceNodeTiming.prototype prevents access from throwing (fixing #23041), but Object.getOwnPropertyNames(performance.nodeTiming) still omits them because the instance owns only the milestone fields assigned in createPerformanceNodeTiming(). In Node.js v22+, these entry properties are own properties on the instance, not just prototype properties. Without own property definitions, the behavior diverges from Node.js.

Apply the same property descriptors to the instance in createPerformanceNodeTiming():

+const performanceNodeTimingEntryDescriptors = {
+  name: { get: () => "node", configurable: true, enumerable: true },
+  entryType: { get: () => "node", configurable: true, enumerable: true },
+  startTime: { get: () => 0, configurable: true, enumerable: true },
+  duration: { get: () => performance.now(), configurable: true, enumerable: true },
+};
+
-Object.defineProperties(PerformanceNodeTiming.prototype, {
-  name: { get: () => "node", configurable: true, enumerable: true },
-  entryType: { get: () => "node", configurable: true, enumerable: true },
-  startTime: { get: () => 0, configurable: true, enumerable: true },
-  duration: { get: () => performance.now(), configurable: true, enumerable: true },
-});
+Object.defineProperties(PerformanceNodeTiming.prototype, performanceNodeTimingEntryDescriptors);

 function createPerformanceNodeTiming() {
   const object = Object.create(PerformanceNodeTiming.prototype);
+  Object.defineProperties(object, performanceNodeTimingEntryDescriptors);

This ensures both prototype and instance define these properties, matching Node.js behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/js/node/perf_hooks.ts` around lines 55 - 62, The properties `name`,
`entryType`, `startTime`, and `duration` are currently defined only on the
PerformanceNodeTiming.prototype, but they must also be defined as own properties
on the instance to match Node.js v22+ behavior and ensure
Object.getOwnPropertyNames returns them. In the createPerformanceNodeTiming
function, after creating the instance, apply Object.defineProperties to the
instance itself using the same property descriptors (with the same getter
functions for name, entryType, startTime, and duration) that are defined on the
prototype.

Comment thread src/js/node/perf_hooks.ts
Comment on lines +64 to +78
PerformanceNodeTiming.prototype.toJSON = function toJSON() {
return {
name: this.name,
entryType: this.entryType,
startTime: this.startTime,
duration: this.duration,
nodeStart: this.nodeStart,
v8Start: this.v8Start,
bootstrapComplete: this.bootstrapComplete,
environment: this.environment,
loopStart: this.loopStart,
loopExit: this.loopExit,
idleTime: this.idleTime,
};
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

bun bd -e '
const perf = require("node:perf_hooks");
const keys = [];
for (const key in perf.performance.nodeTiming) keys.push(key);
console.log(keys);
if (keys.includes("toJSON")) process.exit(1);
'

Repository: oven-sh/bun

Length of output: 99


🏁 Script executed:

cat -n src/js/node/perf_hooks.ts | head -100

Repository: oven-sh/bun

Length of output: 4431


🏁 Script executed:

# Test property enumeration behavior in JavaScript
# First test direct assignment vs Object.defineProperty

node -e "
const obj = {};
// Test 1: Direct assignment to prototype
function TestClass1() {}
TestClass1.prototype.toJSON = function() { return 'direct'; };

const keys1 = [];
for (const key in new TestClass1()) keys1.push(key);
console.log('Direct assignment enumerable:', keys1.includes('toJSON'));

// Test 2: Object.defineProperty with no descriptor
function TestClass2() {}
Object.defineProperty(TestClass2.prototype, 'toJSON', {
  value: function() { return 'defined'; },
  configurable: true,
  writable: true
});

const keys2 = [];
for (const key in new TestClass2()) keys2.push(key);
console.log('Object.defineProperty (no enumerable) enumerable:', keys2.includes('toJSON'));

// Test 3: Object.defineProperty with enumerable: false
function TestClass3() {}
Object.defineProperty(TestClass3.prototype, 'toJSON', {
  value: function() { return 'defined'; },
  configurable: true,
  writable: true,
  enumerable: false
});

const keys3 = [];
for (const key in new TestClass3()) keys3.push(key);
console.log('Object.defineProperty (enumerable: false) enumerable:', keys3.includes('toJSON'));
"

Repository: oven-sh/bun

Length of output: 206


🌐 Web query:

Node.js perf_hooks PerformanceNodeTiming.prototype.toJSON enumerable specification

💡 Result:

In Node.js, the toJSON() method on PerformanceNodeTiming.prototype is designed to be enumerable, consistent with the general convention for toJSON methods in the perf_hooks module [1][2]. Historical development in the Node.js codebase shows that PerformanceNodeTiming underwent changes to make it a first-class object, ensuring that its properties are properly exposed and enumerable to support serialization [3][4]. Similarly, the toJSON method has been explicitly added and defined on the prototypes of various performance-related classes within perf_hooks to allow for standard JSON representation, typically as an enumerable property to facilitate operations like JSON.stringify() [1]. While the official documentation for PerformanceNodeTiming details its properties, the specific enumeration behavior of toJSON follows the broader implementation pattern where these helper methods are enumerable to ensure they are discovered and included during serialization processes [1][5][6].

Citations:


🏁 Script executed:

# Verify Node.js actual behavior for PerformanceNodeTiming
node -e "
const perf = require('perf_hooks');
const nodeTiming = perf.performance.nodeTiming;

// Check if toJSON is enumerable
const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(nodeTiming), 'toJSON');
console.log('toJSON descriptor:', descriptor);

// Check enumeration
const keys = [];
for (const key in nodeTiming) keys.push(key);
console.log('for...in keys:', keys);
console.log('toJSON in keys:', keys.includes('toJSON'));

// Check Object.keys
console.log('Object.keys:', Object.keys(nodeTiming));
"

Repository: oven-sh/bun

Length of output: 591


🌐 Web query:

Node.js PerformanceNodeTiming toJSON method enumerable property specification

💡 Result:

In Node.js, the PerformanceNodeTiming.toJSON method is designed to provide a JSON-serializable representation of the performance timing object [1][2]. As part of a core architectural change to make nodeTiming a "first-class object" in Node.js, all properties of the PerformanceNodeTiming instance were made enumerable [3][4][5]. This ensures that when the toJSON method is invoked—or when the object is processed by methods like JSON.stringify—the relevant timing properties (such as startTime, duration, nodeStart, v8Start, etc.) are accessible and included in the output [3][4][5]. While the W3C Performance Timeline specification defines a generic [Default] toJSON behavior for PerformanceEntry objects [6], the Node.js implementation of PerformanceNodeTiming explicitly ensures its timing properties are enumerable [3][5]. This behavior allows developers to reliably serialize these performance metrics into JSON format for logging, debugging, or monitoring purposes [3][4].

Citations:


Keep toJSON non-enumerable on the prototype.

Assigning PerformanceNodeTiming.prototype.toJSON = ... creates an enumerable property, but Node.js implements toJSON as non-enumerable. This causes for...in over nodeTiming to include toJSON in Bun but not in Node.js. Define it with Object.defineProperty to match Node.js behavior.

Proposed fix
-PerformanceNodeTiming.prototype.toJSON = function toJSON() {
-  return {
-    name: this.name,
-    entryType: this.entryType,
-    startTime: this.startTime,
-    duration: this.duration,
-    nodeStart: this.nodeStart,
-    v8Start: this.v8Start,
-    bootstrapComplete: this.bootstrapComplete,
-    environment: this.environment,
-    loopStart: this.loopStart,
-    loopExit: this.loopExit,
-    idleTime: this.idleTime,
-  };
-};
+Object.defineProperty(PerformanceNodeTiming.prototype, "toJSON", {
+  value: function toJSON() {
+    return {
+      name: this.name,
+      entryType: this.entryType,
+      startTime: this.startTime,
+      duration: this.duration,
+      nodeStart: this.nodeStart,
+      v8Start: this.v8Start,
+      bootstrapComplete: this.bootstrapComplete,
+      environment: this.environment,
+      loopStart: this.loopStart,
+      loopExit: this.loopExit,
+      idleTime: this.idleTime,
+    };
+  },
+  configurable: true,
+  writable: true,
+});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/js/node/perf_hooks.ts` around lines 64 - 78, The
PerformanceNodeTiming.prototype.toJSON assignment creates an enumerable property
which differs from Node.js behavior where toJSON is non-enumerable. Replace the
direct assignment of PerformanceNodeTiming.prototype.toJSON with
Object.defineProperty, passing the prototype object, the property name "toJSON",
and a property descriptor object that defines the value as the toJSON function
while setting enumerable to false to match Node.js implementation.

Comment on lines +25 to +30
// Milestones are offsets in ms from timeOrigin, not absolute epoch timestamps.
expect(perf.performance.timeOrigin).toBeGreaterThan(1e12);
for (const key of ["nodeStart", "v8Start", "environment", "bootstrapComplete", "idleTime"] as const) {
expect(nt[key]).toBeNumber();
expect(nt[key]).toBeLessThan(1e12);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Include loopStart in the milestone offset check.

loopStart is one of the fields being fixed from epoch timestamps to offsets, but this loop skips it. The later toJSON() assertion only compares against nt.loopStart, so an epoch-valued loopStart would still pass.

Proposed fix
-  for (const key of ["nodeStart", "v8Start", "environment", "bootstrapComplete", "idleTime"] as const) {
+  for (const key of ["nodeStart", "v8Start", "environment", "bootstrapComplete", "loopStart", "idleTime"] as const) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/js/node/perf_hooks/perf_hooks.test.ts` around lines 25 - 30, The
milestone offset validation loop iterates over nodeStart, v8Start, environment,
bootstrapComplete, and idleTime but is missing loopStart, which was also
converted from epoch timestamps to offsets. Add loopStart to the array of keys
being checked in the for loop that validates each milestone is less than 1e12,
ensuring that loopStart is properly validated alongside the other milestone
offsets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

perf_hooks: PerformanceNodeTiming startTime/duration throw; nodeTiming shape differs from Node

1 participant