mirror of
https://github.com/nodejs/node.git
synced 2026-10-14 10:26:26 -04:00
src: add helpers for creating cppgc-managed wrappers
This patch adds helpers for wrapper classes based on cppgc (Oilpan) in `src/cppgc_helpers.h`, including `node::CppgcMixin` and `ASSIGN_OR_RETURN_UNWRAP_CPPGC`, which are designed to have similar interface to BaseObject helpers to help migration. They are documented in the `CppgcMixin` section in `src/README.md` To disambiguate, the global `node::Unwrap<>` has now been moved as `node::BaseObject::Unwrap<>`, and `node::Cppgc::Unwrap<>` implements a similar unwrapping mechanism for cppgc-managed wrappers. PR-URL: https://github.com/nodejs/node/pull/52295 Refs: https://github.com/nodejs/node/issues/40786 Refs: https://docs.google.com/document/d/1ny2Qz_EsUnXGKJRGxoA-FXIE2xpLgaMAN6jD7eAkqFQ/edit Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
This commit is contained in:
1 parent
4568df4c6d
commit
849db10fb3
11 files changed
+466
-21
No files matched your search
+87
-7
@@ -2,15 +2,21 @@
|
||||
const assert = require('assert');
|
||||
const util = require('util');
|
||||
|
||||
let internalBinding;
|
||||
try {
|
||||
internalBinding = require('internal/test/binding').internalBinding;
|
||||
} catch (e) {
|
||||
console.log('using `test/common/heap.js` requires `--expose-internals`');
|
||||
throw e;
|
||||
let _buildEmbedderGraph;
|
||||
function buildEmbedderGraph() {
|
||||
if (_buildEmbedderGraph) { return _buildEmbedderGraph(); }
|
||||
let internalBinding;
|
||||
try {
|
||||
internalBinding = require('internal/test/binding').internalBinding;
|
||||
} catch (e) {
|
||||
console.error('The test must be run with `--expose-internals`');
|
||||
throw e;
|
||||
}
|
||||
|
||||
({ buildEmbedderGraph: _buildEmbedderGraph } = internalBinding('heap_utils'));
|
||||
return _buildEmbedderGraph();
|
||||
}
|
||||
|
||||
const { buildEmbedderGraph } = internalBinding('heap_utils');
|
||||
const { getHeapSnapshot } = require('v8');
|
||||
|
||||
function createJSHeapSnapshot(stream = getHeapSnapshot()) {
|
||||
@@ -211,6 +217,79 @@ function validateSnapshotNodes(...args) {
|
||||
return recordState().validateSnapshotNodes(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* A alternative heap snapshot validator that can be used to verify cppgc-managed nodes.
|
||||
* Modified from
|
||||
* https://chromium.googlesource.com/v8/v8/+/b00e995fb212737802810384ba2b868d0d92f7e5/test/unittests/heap/cppgc-js/unified-heap-snapshot-unittest.cc#134
|
||||
* @param {string} rootName Name of the root node. Typically a class name used to filter all native nodes with
|
||||
* this name. For cppgc-managed objects, this is typically the name configured by
|
||||
* SET_CPPGC_NAME() prefixed with an additional "Node /" prefix e.g.
|
||||
* "Node / ContextifyScript"
|
||||
* @param {[{
|
||||
* node_name?: string,
|
||||
* edge_name?: string,
|
||||
* node_type?: string,
|
||||
* edge_type?: string,
|
||||
* }]} retainingPath The retaining path specification to search from the root nodes.
|
||||
* @returns {[object]} All the leaf nodes matching the retaining path specification. If none can be found,
|
||||
* logs the nodes found in the last matching step of the path (if any), and throws an
|
||||
* assertion error.
|
||||
*/
|
||||
function findByRetainingPath(rootName, retainingPath) {
|
||||
const nodes = createJSHeapSnapshot();
|
||||
let haystack = nodes.filter((n) => n.name === rootName && n.type !== 'string');
|
||||
|
||||
for (let i = 0; i < retainingPath.length; ++i) {
|
||||
const expected = retainingPath[i];
|
||||
const newHaystack = [];
|
||||
|
||||
for (const parent of haystack) {
|
||||
for (let j = 0; j < parent.outgoingEdges.length; j++) {
|
||||
const edge = parent.outgoingEdges[j];
|
||||
// The strings are represented as { type: 'string', name: '<string content>' } in the snapshot.
|
||||
// Ignore them or we'll poke into strings that are just referenced as names of real nodes,
|
||||
// unless the caller is specifically looking for string nodes via `node_type`.
|
||||
let match = (edge.to.type !== 'string');
|
||||
if (expected.node_type) {
|
||||
match = (edge.to.type === expected.node_type);
|
||||
}
|
||||
if (expected.node_name && edge.to.name !== expected.node_name) {
|
||||
match = false;
|
||||
}
|
||||
if (expected.edge_name && edge.name !== expected.edge_name) {
|
||||
match = false;
|
||||
}
|
||||
if (expected.edge_type && edge.type !== expected.type) {
|
||||
match = false;
|
||||
}
|
||||
if (match) {
|
||||
newHaystack.push(edge.to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newHaystack.length === 0) {
|
||||
const format = (val) => util.inspect(val, { breakLength: 128, depth: 3 });
|
||||
console.error('#');
|
||||
console.error('# Retaining path to search for:');
|
||||
for (let j = 0; j < retainingPath.length; ++j) {
|
||||
console.error(`# - '${format(retainingPath[j])}'${i === j ? '\t<--- not found' : ''}`);
|
||||
}
|
||||
console.error('#\n');
|
||||
console.error('# Nodes found in the last step include:');
|
||||
for (let j = 0; j < haystack.length; ++j) {
|
||||
console.error(`# - '${format(haystack[j])}`);
|
||||
}
|
||||
|
||||
assert.fail(`Could not find target edge ${format(expected)} in the heap snapshot.`);
|
||||
}
|
||||
|
||||
haystack = newHaystack;
|
||||
}
|
||||
|
||||
return haystack;
|
||||
}
|
||||
|
||||
function getHeapSnapshotOptionTests() {
|
||||
const fixtures = require('../common/fixtures');
|
||||
const cases = [
|
||||
@@ -245,5 +324,6 @@ function getHeapSnapshotOptionTests() {
|
||||
module.exports = {
|
||||
recordState,
|
||||
validateSnapshotNodes,
|
||||
findByRetainingPath,
|
||||
getHeapSnapshotOptionTests,
|
||||
};
|
||||
Reference in new issue
Block a user