| '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/); |
| } |