1'use strict'; 2 3const common = require('../common'); 4const assert = require('assert'); 5const tick = require('../common/tick'); 6const async_hooks = require('async_hooks'); 7const { AsyncResource } = async_hooks; 8 9const initHooks = require('./init-hooks'); 10const { checkInvocations } = require('./hook-checks'); 11 12const hooks = initHooks(); 13hooks.enable(); 14 15assert.throws( 16 () => new AsyncResource(), { 17 code: 'ERR_INVALID_ARG_TYPE', 18 name: 'TypeError', 19 }); 20assert.throws(() => { 21 new AsyncResource('invalid_trigger_id', { triggerAsyncId: null }); 22}, { 23 code: 'ERR_INVALID_ASYNC_ID', 24 name: 'RangeError', 25}); 26 27assert.strictEqual( 28 new AsyncResource('default_trigger_id').triggerAsyncId(), 29 async_hooks.executionAsyncId() 30); 31 32// Create first custom event 'alcazares' with triggerAsyncId derived 33// from async_hooks executionAsyncId 34const alcaTriggerId = async_hooks.executionAsyncId(); 35const alcaEvent = new AsyncResource('alcazares', alcaTriggerId); 36const alcazaresActivities = hooks.activitiesOfTypes([ 'alcazares' ]); 37 38// Alcazares event was constructed and thus only has an `init` call 39assert.strictEqual(alcazaresActivities.length, 1); 40const alcazares = alcazaresActivities[0]; 41assert.strictEqual(alcazares.type, 'alcazares'); 42assert.strictEqual(typeof alcazares.uid, 'number'); 43assert.strictEqual(alcazares.triggerAsyncId, alcaTriggerId); 44checkInvocations(alcazares, { init: 1 }, 'alcazares constructed'); 45 46assert.strictEqual(typeof alcaEvent.asyncId(), 'number'); 47assert.notStrictEqual(alcaEvent.asyncId(), alcaTriggerId); 48assert.strictEqual(alcaEvent.triggerAsyncId(), alcaTriggerId); 49 50alcaEvent.runInAsyncScope(() => { 51 checkInvocations(alcazares, { init: 1, before: 1 }, 52 'alcazares emitted before'); 53}); 54checkInvocations(alcazares, { init: 1, before: 1, after: 1 }, 55 'alcazares emitted after'); 56alcaEvent.runInAsyncScope(() => { 57 checkInvocations(alcazares, { init: 1, before: 2, after: 1 }, 58 'alcazares emitted before again'); 59}); 60checkInvocations(alcazares, { init: 1, before: 2, after: 2 }, 61 'alcazares emitted after again'); 62alcaEvent.emitDestroy(); 63tick(1, common.mustCall(tick1)); 64 65function tick1() { 66 checkInvocations(alcazares, { init: 1, before: 2, after: 2, destroy: 1 }, 67 'alcazares emitted destroy'); 68 69 // The below shows that we can pass any number as a trigger id 70 const pobTriggerId = 111; 71 const pobEvent = new AsyncResource('poblado', pobTriggerId); 72 const pobladoActivities = hooks.activitiesOfTypes([ 'poblado' ]); 73 const poblado = pobladoActivities[0]; 74 assert.strictEqual(poblado.type, 'poblado'); 75 assert.strictEqual(typeof poblado.uid, 'number'); 76 assert.strictEqual(poblado.triggerAsyncId, pobTriggerId); 77 checkInvocations(poblado, { init: 1 }, 'poblado constructed'); 78 pobEvent.runInAsyncScope(() => { 79 checkInvocations(poblado, { init: 1, before: 1 }, 80 'poblado emitted before'); 81 }); 82 83 checkInvocations(poblado, { init: 1, before: 1, after: 1 }, 84 'poblado emitted after'); 85 86 // After we disable the hooks we shouldn't receive any events anymore 87 hooks.disable(); 88 alcaEvent.emitDestroy(); 89 tick(1, common.mustCall(tick2)); 90 91 function tick2() { 92 checkInvocations( 93 alcazares, { init: 1, before: 2, after: 2, destroy: 1 }, 94 'alcazares emitted destroy a second time after hooks disabled'); 95 pobEvent.emitDestroy(); 96 tick(1, common.mustCall(tick3)); 97 } 98 99 function tick3() { 100 checkInvocations(poblado, { init: 1, before: 1, after: 1 }, 101 'poblado emitted destroy after hooks disabled'); 102 } 103} 104