Created
March 13, 2019 23:27
-
-
Save devsnek/4128215236f40dc7939b269a50db5646 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