-
-
Save wentout/9d8c42042fda9b2ed75ff4bb2c42ab5a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const { | |
AsyncResource, | |
executionAsyncId, | |
createHook, | |
} = require('async_hooks'); | |
const EventEmitter = require('events'); | |
const util = require('util'); | |
const HasOwnProperty = Function.call.bind(Object.prototype.hasOwnProperty); | |
const zones = new Map(); | |
class Zone extends EventEmitter { | |
#spec; | |
#resource; | |
#report; | |
constructor({ name = null, spec = {} } = {}) { | |
super(); | |
this.name = name; | |
this.#spec = spec; | |
this.#resource = new AsyncResource('ZONE', { | |
triggerAsyncId: executionAsyncId(), | |
requireManualDestroy: false, | |
}); | |
zones.set(this.#resource.asyncId(), this); | |
} | |
run(fn, thisArg, ...args) { | |
let r; | |
try { | |
r = this.#resource.runInAsyncScope(fn, thisArg, ...args); | |
if (r instanceof Promise) { | |
r.catch((err) => { | |
this.emit('error', err); | |
}); | |
} | |
} catch (err) { | |
this.emit('error', err); | |
} | |
return r; | |
} | |
get(name) { | |
return HasOwnProperty(this.#spec, name) ? this.#spec[name] : undefined; | |
} | |
fork({ name, spec } = {}) { | |
const z = new Zone({ | |
name, | |
spec: { | |
...spec, | |
...this.#spec, | |
}, | |
}); | |
return z; | |
} | |
get parent() { | |
return zones.get(this.#resource.triggerAsyncId()); | |
} | |
static get current() { | |
return zones.get(executionAsyncId()); | |
} | |
[util.inspect.custom](depth, options) { | |
const O = Object.assign({}, options, { | |
depth: options.depth === null ? null : options.depth - 1, | |
}); | |
return `Zone { | |
name => ${util.inspect(this.name, O)} | |
spec => ${util.inspect(this.#spec, O)} }`; | |
} | |
} | |
Zone.prototype[Symbol.toStringTag] = 'Zone'; | |
zones.set(executionAsyncId(), new Zone()); | |
createHook({ | |
init: (asyncId, type, triggerAsyncId) => { | |
zones.set(asyncId, zones.get(triggerAsyncId)); | |
}, | |
destroy: (asyncId) => { | |
zones.delete(asyncId); | |
}, | |
}).enable(); | |
global.Zone = Zone; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment