diff --git a/doc/api/v8.md b/doc/api/v8.md index 399cb1e82adf12..e5c32c96937790 100644 --- a/doc/api/v8.md +++ b/doc/api/v8.md @@ -242,6 +242,89 @@ buffers and external strings. } ``` +## `v8.queryObjects(ctor[, options])` + + + +> Stability: 1.1 - Active development + +* `ctor` {Function} The constructor that can be used to search on the + prototype chain in order to filter target objects in the heap. +* `options` {undefined|Object} + * `format` {string} If it's `'count'`, the count of matched objects + is returned. If it's `'summary'`, an array with summary strings + of the matched objects is returned. +* Returns: {number|Array} + +This is similar to the [`queryObjects()` console API][] provided by the +Chromium DevTools console. It can be used to search for objects that +have the matching constructor on its prototype chain in the heap after +a full garbage collection, which can be useful for memory leak +regression tests. To avoid surprising results, users should avoid using +this API on constructors whose implementation they don't control, or on +constructors that can be invoked by other parties in the application. + +To avoid accidental leaks, this API does not return raw references to +the objects found. By default, it returns the count of the objects +found. If `options.format` is `'summary'`, it returns an array +containing brief string representations for each object. The visibility +provided in this API is similar to what the heap snapshot provides, +while users can save the cost of serialization and parsing and directly +filter the target objects during the search. + +Only objects created in the current execution context are included in the +results. + +```cjs +const { queryObjects } = require('node:v8'); +class A { foo = 'bar'; } +console.log(queryObjects(A)); // 0 +const a = new A(); +console.log(queryObjects(A)); // 1 +// [ "A { foo: 'bar' }" ] +console.log(queryObjects(A, { format: 'summary' })); + +class B extends A { bar = 'qux'; } +const b = new B(); +console.log(queryObjects(B)); // 1 +// [ "B { foo: 'bar', bar: 'qux' }" ] +console.log(queryObjects(B, { format: 'summary' })); + +// Note that, when there are child classes inheriting from a constructor, +// the constructor also shows up in the prototype chain of the child +// classes's prototoype, so the child classes's prototoype would also be +// included in the result. +console.log(queryObjects(A)); // 3 +// [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ] +console.log(queryObjects(A, { format: 'summary' })); +``` + +```mjs +import { queryObjects } from 'node:v8'; +class A { foo = 'bar'; } +console.log(queryObjects(A)); // 0 +const a = new A(); +console.log(queryObjects(A)); // 1 +// [ "A { foo: 'bar' }" ] +console.log(queryObjects(A, { format: 'summary' })); + +class B extends A { bar = 'qux'; } +const b = new B(); +console.log(queryObjects(B)); // 1 +// [ "B { foo: 'bar', bar: 'qux' }" ] +console.log(queryObjects(B, { format: 'summary' })); + +// Note that, when there are child classes inheriting from a constructor, +// the constructor also shows up in the prototype chain of the child +// classes's prototoype, so the child classes's prototoype would also be +// included in the result. +console.log(queryObjects(A)); // 3 +// [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ] +console.log(queryObjects(A, { format: 'summary' })); +``` + ## `v8.setFlagsFromString(flags)`