11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci// Flags: --gc-interval=100 --gc-global 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ciconst common = require('../../common'); 51cb0ef41Sopenharmony_ciconst assert = require('assert'); 61cb0ef41Sopenharmony_ciconst async_hooks = require('async_hooks'); 71cb0ef41Sopenharmony_ciconst { 81cb0ef41Sopenharmony_ci createAsyncResource, 91cb0ef41Sopenharmony_ci destroyAsyncResource, 101cb0ef41Sopenharmony_ci makeCallback, 111cb0ef41Sopenharmony_ci} = require(`./build/${common.buildType}/binding`); 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ci// Test for https://github.com/nodejs/node/issues/27218: 141cb0ef41Sopenharmony_ci// napi_async_destroy() can be called during a regular garbage collection run. 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ciconst hook_result = { 171cb0ef41Sopenharmony_ci id: null, 181cb0ef41Sopenharmony_ci init_called: false, 191cb0ef41Sopenharmony_ci destroy_called: false, 201cb0ef41Sopenharmony_ci}; 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ciconst test_hook = async_hooks.createHook({ 231cb0ef41Sopenharmony_ci init: (id, type) => { 241cb0ef41Sopenharmony_ci if (type === 'test_async') { 251cb0ef41Sopenharmony_ci hook_result.id = id; 261cb0ef41Sopenharmony_ci hook_result.init_called = true; 271cb0ef41Sopenharmony_ci } 281cb0ef41Sopenharmony_ci }, 291cb0ef41Sopenharmony_ci destroy: (id) => { 301cb0ef41Sopenharmony_ci if (id === hook_result.id) hook_result.destroy_called = true; 311cb0ef41Sopenharmony_ci }, 321cb0ef41Sopenharmony_ci}); 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_citest_hook.enable(); 351cb0ef41Sopenharmony_ciconst asyncResource = createAsyncResource( 361cb0ef41Sopenharmony_ci { foo: 'bar' }, 371cb0ef41Sopenharmony_ci /* destroy_on_finalizer */false, 381cb0ef41Sopenharmony_ci); 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci// Trigger GC. This does *not* use global.gc(), because what we want to verify 411cb0ef41Sopenharmony_ci// is that `napi_async_destroy()` can be called when there is no JS context 421cb0ef41Sopenharmony_ci// on the stack at the time of GC. 431cb0ef41Sopenharmony_ci// Currently, using --gc-interval=100 + 1M elements seems to work fine for this. 441cb0ef41Sopenharmony_ciconst arr = new Array(1024 * 1024); 451cb0ef41Sopenharmony_cifor (let i = 0; i < arr.length; i++) 461cb0ef41Sopenharmony_ci arr[i] = {}; 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ciassert.strictEqual(hook_result.destroy_called, false); 491cb0ef41Sopenharmony_cisetImmediate(() => { 501cb0ef41Sopenharmony_ci assert.strictEqual(hook_result.destroy_called, false); 511cb0ef41Sopenharmony_ci makeCallback(asyncResource, process, () => { 521cb0ef41Sopenharmony_ci const executionAsyncResource = async_hooks.executionAsyncResource(); 531cb0ef41Sopenharmony_ci // Assuming the executionAsyncResource was created for the absence of the 541cb0ef41Sopenharmony_ci // initial `{ foo: 'bar' }`. 551cb0ef41Sopenharmony_ci // This is the worst path of `napi_async_context` related API of 561cb0ef41Sopenharmony_ci // recovering from the condition and not break the executionAsyncResource 571cb0ef41Sopenharmony_ci // shape, although the executionAsyncResource might not be correct. 581cb0ef41Sopenharmony_ci assert.strictEqual(typeof executionAsyncResource, 'object'); 591cb0ef41Sopenharmony_ci assert.strictEqual(executionAsyncResource.foo, undefined); 601cb0ef41Sopenharmony_ci destroyAsyncResource(asyncResource); 611cb0ef41Sopenharmony_ci setImmediate(() => { 621cb0ef41Sopenharmony_ci assert.strictEqual(hook_result.destroy_called, true); 631cb0ef41Sopenharmony_ci }); 641cb0ef41Sopenharmony_ci }); 651cb0ef41Sopenharmony_ci}); 66