mirror of
https://github.com/nodejs/node.git
synced 2024-12-01 16:10:02 +01:00
f59ec2abee
This allows us to track the essentially-global objects in Environment in the heap snapshot. Note that this patch only tracks the fields that can be tracked correctly. There are still several types of fields that cannot be tracked: - v8::Data including v8::Private, v8::ObjectTemplate etc. - Internal types that do not implement MemoryRetainer yet - STL containers with MemoryRetainer* inside - STL containers with numeric types inside that should not have their nodes elided e.g. numeric keys in maps. The `BaseObject`s are now no longer globals. They are tracked as arguments in CleanupHookCallbacks referenced by the Environment node. This model is closer to how their lifetime is managed internally. To track the per-environment strong persistent properties, this patch divides them into those that are also `v8::Value` and those that are just `v8::Data`. The values can be tracked by the current memory tracker while the data cannot. This patch also implements the `MemoryRetainer` interface in several internal classes so that they can be tracked in the heap snapshot. PR-URL: https://github.com/nodejs/node/pull/27018 Refs: https://github.com/nodejs/node/issues/26776 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
67 lines
2.0 KiB
JavaScript
67 lines
2.0 KiB
JavaScript
// Flags: --expose-internals
|
|
'use strict';
|
|
|
|
// This tests that Environment is tracked in heap snapshots.
|
|
|
|
require('../common');
|
|
const { validateSnapshotNodes } = require('../common/heap');
|
|
const assert = require('assert');
|
|
|
|
// This is just using ContextifyScript as an example here, it can be replaced
|
|
// with any BaseObject that we can easily instantiate here and register in
|
|
// cleanup hooks.
|
|
// These can all be changed to reflect the status of how these objects
|
|
// are captured in the snapshot.
|
|
const context = require('vm').createScript('const foo = 123');
|
|
|
|
validateSnapshotNodes('Node / Environment', [{
|
|
children: [
|
|
cleanupHooksFilter,
|
|
{ node_name: 'Node / cleanup_hooks', edge_name: 'cleanup_hooks' },
|
|
{ node_name: 'process', edge_name: 'process_object' },
|
|
{ node_name: 'Node / IsolateData', edge_name: 'isolate_data' },
|
|
]
|
|
}]);
|
|
|
|
function cleanupHooksFilter(edge) {
|
|
if (edge.name !== 'cleanup_hooks') {
|
|
return false;
|
|
}
|
|
if (edge.to.type === 'native') {
|
|
verifyCleanupHooksInSnapshot(edge.to);
|
|
} else {
|
|
verifyCleanupHooksInGraph(edge.to);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function verifyCleanupHooksInSnapshot(node) {
|
|
assert.strictEqual(node.name, 'Node / cleanup_hooks');
|
|
const baseObjects = [];
|
|
for (const hook of node.outgoingEdges) {
|
|
for (const hookEdge of hook.to.outgoingEdges) {
|
|
if (hookEdge.name === 'arg') {
|
|
baseObjects.push(hookEdge.to);
|
|
}
|
|
}
|
|
}
|
|
// Make sure our ContextifyScript show up.
|
|
assert(baseObjects.some((node) => node.name === 'Node / ContextifyScript'));
|
|
}
|
|
|
|
function verifyCleanupHooksInGraph(node) {
|
|
assert.strictEqual(node.name, 'Node / cleanup_hooks');
|
|
const baseObjects = [];
|
|
for (const hook of node.edges) {
|
|
for (const hookEdge of hook.to.edges) {
|
|
if (hookEdge.name === 'arg') {
|
|
baseObjects.push(hookEdge.to);
|
|
}
|
|
}
|
|
}
|
|
// Make sure our ContextifyScript show up.
|
|
assert(baseObjects.some((node) => node.name === 'Node / ContextifyScript'));
|
|
}
|
|
|
|
console.log(context); // Make sure it's not GC'ed
|