@sentry/core
Version:
Base implementation for all Sentry JavaScript SDKs
176 lines (151 loc) • 4.07 kB
JavaScript
import { isThenable } from '@sentry/utils';
import { getDefaultCurrentScope, getDefaultIsolationScope } from '../defaultScopes.js';
import { Scope } from '../scope.js';
import { getMainCarrier, getSentryCarrier } from '../carrier.js';
/**
* This is an object that holds a stack of scopes.
*/
class AsyncContextStack {
constructor(scope, isolationScope) {
let assignedScope;
if (!scope) {
assignedScope = new Scope();
} else {
assignedScope = scope;
}
let assignedIsolationScope;
if (!isolationScope) {
assignedIsolationScope = new Scope();
} else {
assignedIsolationScope = isolationScope;
}
this._stack = [{ scope: assignedScope }];
this._isolationScope = assignedIsolationScope;
}
/**
* Fork a scope for the stack.
*/
withScope(callback) {
const scope = this._pushScope();
let maybePromiseResult;
try {
maybePromiseResult = callback(scope);
} catch (e) {
this._popScope();
throw e;
}
if (isThenable(maybePromiseResult)) {
// @ts-expect-error - isThenable returns the wrong type
return maybePromiseResult.then(
res => {
this._popScope();
return res;
},
e => {
this._popScope();
throw e;
},
);
}
this._popScope();
return maybePromiseResult;
}
/**
* Get the client of the stack.
*/
getClient() {
return this.getStackTop().client ;
}
/**
* Returns the scope of the top stack.
*/
getScope() {
return this.getStackTop().scope;
}
/**
* Get the isolation scope for the stack.
*/
getIsolationScope() {
return this._isolationScope;
}
/**
* Returns the scope stack for domains or the process.
*/
getStack() {
return this._stack;
}
/**
* Returns the topmost scope layer in the order domain > local > process.
*/
getStackTop() {
return this._stack[this._stack.length - 1];
}
/**
* Push a scope to the stack.
*/
_pushScope() {
// We want to clone the content of prev scope
const scope = this.getScope().clone();
this.getStack().push({
client: this.getClient(),
scope,
});
return scope;
}
/**
* Pop a scope from the stack.
*/
_popScope() {
if (this.getStack().length <= 1) return false;
return !!this.getStack().pop();
}
}
/**
* Get the global async context stack.
* This will be removed during the v8 cycle and is only here to make migration easier.
*/
function getAsyncContextStack() {
const registry = getMainCarrier();
// For now we continue to keep this as `hub` on the ACS,
// as e.g. the Loader Script relies on this.
// Eventually we may change this if/when we update the loader to not require this field anymore
// Related, we also write to `hub` in {@link ./../sdk.ts registerClientOnGlobalHub}
const sentry = getSentryCarrier(registry) ;
if (sentry.hub) {
return sentry.hub;
}
sentry.hub = new AsyncContextStack(getDefaultCurrentScope(), getDefaultIsolationScope());
return sentry.hub;
}
function withScope(callback) {
return getAsyncContextStack().withScope(callback);
}
function withSetScope(scope, callback) {
const hub = getAsyncContextStack() ;
return hub.withScope(() => {
hub.getStackTop().scope = scope;
return callback(scope);
});
}
function withIsolationScope(callback) {
return getAsyncContextStack().withScope(() => {
return callback(getAsyncContextStack().getIsolationScope());
});
}
/**
* Get the stack-based async context strategy.
*/
function getStackAsyncContextStrategy() {
return {
withIsolationScope,
withScope,
withSetScope,
withSetIsolationScope: (_isolationScope, callback) => {
return withIsolationScope(callback);
},
getCurrentScope: () => getAsyncContextStack().getScope(),
getIsolationScope: () => getAsyncContextStack().getIsolationScope(),
};
}
export { AsyncContextStack, getStackAsyncContextStrategy };
//# sourceMappingURL=stackStrategy.js.map