blob: 779f8d75ae208f9785b4cc90ae8ba8375b8e33c0 [file] [edit]
'use strict';
// This test verifies that stack overflow during deeply nested async operations
// with async_hooks enabled can be caught by try-catch. This simulates real-world
// scenarios like processing deeply nested JSON structures where each level
// creates async operations (e.g., database calls, API requests).
require('../common');
const assert = require('assert');
const { spawnSync } = require('child_process');
if (process.argv[2] === 'child') {
const { createHook } = require('async_hooks');
// Enable async_hooks with all callbacks (simulates APM tools)
createHook({
init() {},
before() {},
after() {},
destroy() {},
promiseResolve() {},
}).enable();
// Simulate an async operation (like a database call or API request)
async function fetchThing(id) {
return { id, data: `data-${id}` };
}
// Recursively process deeply nested data structure
// This will cause stack overflow when the nesting is deep enough
function processData(data, depth = 0) {
if (Array.isArray(data)) {
for (const item of data) {
// Create a promise to trigger async_hooks init callback
fetchThing(depth);
processData(item, depth + 1);
}
}
}
// Create deeply nested array structure iteratively (to avoid stack overflow
// during creation)
function createNestedArray(depth) {
let result = 'leaf';
for (let i = 0; i < depth; i++) {
result = [result];
}
return result;
}
// Create a very deep nesting that will cause stack overflow during processing
const deeplyNested = createNestedArray(50000);
try {
processData(deeplyNested);
// Should not complete successfully - the nesting is too deep
console.log('UNEXPECTED: Processing completed without error');
process.exit(1);
} catch (err) {
assert.strictEqual(err.name, 'RangeError');
assert.match(err.message, /Maximum call stack size exceeded/);
console.log('SUCCESS: try-catch caught the stack overflow in nested async');
process.exit(0);
}
} else {
// Parent process - spawn the child and check exit code
const result = spawnSync(
process.execPath,
[__filename, 'child'],
{ encoding: 'utf8', timeout: 30000 }
);
// Should exit successfully (try-catch worked)
assert.strictEqual(result.status, 0,
`Expected exit code 0, got ${result.status}.\n` +
`stdout: ${result.stdout}\n` +
`stderr: ${result.stderr}`);
// Verify the error was handled by try-catch
assert.match(result.stdout, /SUCCESS: try-catch caught the stack overflow/);
}