node/test/pummel/test-heapdump-zlib.js
Anna Henningsen db6a31d1a1
src: do not track weak BaseObjects as childrens of Realms
Heap dumps are used for analyzing the relationship between
objects that keep each other alive, so that retainers of
memory can be detected and memory leaks fixed.

6e60ab744e broke this for a wide range of `BaseObject`
instances. Marking all `BaseObject`s, including weak ones,
as children of `Realm` and `Environment` instances gives
the incorrect impression that they are held alive by those
objects, effectively hiding the "real" set of strong roots
that keep other objects alive through GC.

An upcoming change in V8 will allow us to represent this
relationship between `Realm` and `Environment` and its
`BaseObject` and `CppgcMixin` instances properly.

Refs: e37cadf114
Refs: https://github.com/nodejs/node/pull/57417
Signed-off-by: Anna Henningsen <anna@addaleax.net>
PR-URL: https://github.com/nodejs/node/pull/63842
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
2026-06-18 10:11:21 +02:00

47 lines
1.6 KiB
JavaScript

'use strict';
// This tests heap snapshot integration of zlib stream.
const common = require('../common');
const assert = require('assert');
const { validateByRetainingPath, validateByRetainingPathFromNodes, getRetainingNodes } = require('../common/heap');
const zlib = require('zlib');
// Before zlib stream is created, no ZlibStream should be created.
{
const nodes = validateByRetainingPath('Node / ZlibStream', []);
assert.strictEqual(nodes.length, 0);
}
const gzip = zlib.createGzip();
// After zlib stream is created, a ZlibStream should be created.
{
const streams = validateByRetainingPath('Node / ZlibStream', []);
validateByRetainingPathFromNodes(streams, 'Node / ZlibStream', [
{ node_name: 'Zlib', edge_name: 'native_to_javascript' },
]);
// No entry for memory because zlib memory is initialized lazily.
const withMemory = validateByRetainingPathFromNodes(streams, 'Node / ZlibStream', [
{ node_name: 'Node / zlib_memory', edge_name: 'zlib_memory' },
], true);
assert.strictEqual(withMemory.length, 0);
}
{
// Assert that the `ZlibStream` has no unexpected connections
// to other `Node / ...` nodes.
const contexts = validateByRetainingPath('Node / ZlibContext', []);
assert.deepStrictEqual(
getRetainingNodes(contexts[0], (node) => node.name?.startsWith('Node /'))
.map((node) => node.name).sort(), [
'Node / ZlibContext',
'Node / ZlibStream',
]);
}
// After zlib stream is written, zlib_memory should be created.
gzip.write('hello world', common.mustCall(() => {
validateByRetainingPath('Node / ZlibStream', [
{ node_name: 'Node / zlib_memory', edge_name: 'zlib_memory' },
]);
}));