Skip to content

Commit

Permalink
fix: restore context when a function run with a given context throws (#…
Browse files Browse the repository at this point in the history
…727)

PR-URL: #727
  • Loading branch information
kjin authored Apr 19, 2018
1 parent 132db9b commit edb8135
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 8 deletions.
18 changes: 10 additions & 8 deletions src/cls/async-hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,11 @@ export class AsyncHooksCLS<Context extends {}> implements CLS<Context> {
runWithNewContext<T>(fn: Func<T>): T {
const oldContext = this.currentContext.value;
this.currentContext.value = this.defaultContext;
// TODO(kjin) Handle the case where fn throws. Context: PR #708
const res = fn();
this.currentContext.value = oldContext;
return res;
try {
return fn();
} finally {
this.currentContext.value = oldContext;
}
}

bindWithCurrentContext<T>(fn: Func<T>): Func<T> {
Expand All @@ -101,10 +102,11 @@ export class AsyncHooksCLS<Context extends {}> implements CLS<Context> {
const contextWrapper: ContextWrapped<Func<T>> = function(this: {}) {
const oldContext = current.value;
current.value = boundContext;
// TODO(kjin) Handle the case where fn throws. Context: PR #708
const res = fn.apply(this, arguments) as T;
current.value = oldContext;
return res;
try {
return fn.apply(this, arguments) as T;
} finally {
current.value = oldContext;
}
};
contextWrapper[WRAPPED] = true;
Object.defineProperty(contextWrapper, 'length', {
Expand Down
26 changes: 26 additions & 0 deletions test/test-cls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,32 @@ describe('Continuation-Local Storage', () => {
});
});

it('Corrects context when function run with new context throws', () => {
try {
c.runWithNewContext(() => {
c.setContext('modified');
throw new Error();
});
} catch (e) {
assert.strictEqual(c.getContext(), 'default');
}
});

it('Corrects context when function bound to a context throws', () => {
let runLater = () => {
c.setContext('modified');
throw new Error();
};
c.runWithNewContext(() => {
runLater = c.bindWithCurrentContext(runLater);
});
try {
runLater();
} catch (e) {
assert.strictEqual(c.getContext(), 'default');
}
});

it('Can be used to patch event emitters to propagate context', () => {
const ee = new EventEmitter();
assert.strictEqual(c.getContext(), 'default');
Expand Down

0 comments on commit edb8135

Please sign in to comment.