mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
Signed-off-by: Antoine du Hamel <duhamelantoine1995@gmail.com> PR-URL: https://github.com/nodejs/node/pull/63790 Reviewed-By: Filip Skokan <panva.ip@gmail.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: Jake Yuesong Li <jake.yuesong@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
90 lines
1.9 KiB
JavaScript
90 lines
1.9 KiB
JavaScript
'use strict';
|
|
|
|
const {
|
|
ObjectIs,
|
|
ReflectApply,
|
|
} = primordials;
|
|
|
|
const {
|
|
validateObject,
|
|
} = require('internal/validators');
|
|
|
|
const AsyncContextFrame = require('internal/async_context_frame');
|
|
const { AsyncResource } = require('async_hooks');
|
|
|
|
const RunScope = require('internal/async_local_storage/run_scope');
|
|
const { kEmptyObject } = require('internal/util');
|
|
|
|
class AsyncLocalStorage {
|
|
#defaultValue = undefined;
|
|
#name = undefined;
|
|
|
|
/**
|
|
* @typedef {object} AsyncLocalStorageOptions
|
|
* @property {any} [defaultValue] - The default value to use when no value is set.
|
|
* @property {string} [name] - The name of the storage.
|
|
*/
|
|
/**
|
|
* @param {AsyncLocalStorageOptions} [options]
|
|
*/
|
|
constructor(options = kEmptyObject) {
|
|
validateObject(options, 'options');
|
|
this.#defaultValue = options.defaultValue;
|
|
|
|
if (options.name !== undefined) {
|
|
this.#name = `${options.name}`;
|
|
}
|
|
}
|
|
|
|
/** @type {string} */
|
|
get name() { return this.#name || ''; }
|
|
|
|
static bind(fn) {
|
|
return AsyncResource.bind(fn);
|
|
}
|
|
|
|
static snapshot() {
|
|
return AsyncLocalStorage.bind((cb, ...args) => cb(...args));
|
|
}
|
|
|
|
disable() {
|
|
AsyncContextFrame.disable(this);
|
|
}
|
|
|
|
enterWith(data) {
|
|
const frame = new AsyncContextFrame(this, data);
|
|
AsyncContextFrame.set(frame);
|
|
}
|
|
|
|
run(data, fn, ...args) {
|
|
const prior = this.getStore();
|
|
if (ObjectIs(prior, data)) {
|
|
return ReflectApply(fn, null, args);
|
|
}
|
|
this.enterWith(data);
|
|
try {
|
|
return ReflectApply(fn, null, args);
|
|
} finally {
|
|
this.enterWith(prior);
|
|
}
|
|
}
|
|
|
|
exit(fn, ...args) {
|
|
return this.run(undefined, fn, ...args);
|
|
}
|
|
|
|
getStore() {
|
|
const frame = AsyncContextFrame.current();
|
|
if (!frame?.has(this)) {
|
|
return this.#defaultValue;
|
|
}
|
|
return frame?.get(this);
|
|
}
|
|
|
|
withScope(store) {
|
|
return new RunScope(this, store);
|
|
}
|
|
}
|
|
|
|
module.exports = AsyncLocalStorage;
|