Skip to content

Commit

Permalink
async_hooks: add thisArg to AsyncResource.bind
Browse files Browse the repository at this point in the history
Semver-major

Support setting the `thisArg` for AsyncResource.bind and
AsyncResource.prototype.bind. If `thisArg` is not set,
then `this` will be set to the `AsyncResource` instance.

Fixes: #36051
Signed-off-by: James M Snell <jasnell@gmail.com>
  • Loading branch information
jasnell committed Jan 6, 2021
1 parent ceb0dc9 commit 25d1319
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 6 deletions.
14 changes: 12 additions & 2 deletions doc/api/async_hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -730,30 +730,40 @@ class DBQuery extends AsyncResource {
}
```

#### Static method: `AsyncResource.bind(fn[, type])`
#### Static method: `AsyncResource.bind(fn[, type, [thisArg]])`
<!-- YAML
added:
- v14.8.0
- v12.19.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/36782
description: Added optional thisArg.
-->

* `fn` {Function} The function to bind to the current execution context.
* `type` {string} An optional name to associate with the underlying
`AsyncResource`.
* `thisArg` {any}

Binds the given function to the current execution context.

The returned function will have an `asyncResource` property referencing
the `AsyncResource` to which the function is bound.

#### `asyncResource.bind(fn)`
#### `asyncResource.bind(fn[, thisArg])`
<!-- YAML
added:
- v14.8.0
- v12.19.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/36782
description: Added optional thisArg.
-->

* `fn` {Function} The function to bind to the current `AsyncResource`.
* `thisArg` {any}

Binds the given function to execute to this `AsyncResource`'s scope.

Expand Down
13 changes: 9 additions & 4 deletions lib/async_hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,15 @@ class AsyncResource {
return this[trigger_async_id_symbol];
}

bind(fn) {
bind(fn, thisArg = this) {
if (typeof fn !== 'function')
throw new ERR_INVALID_ARG_TYPE('fn', 'Function', fn);
const ret = FunctionPrototypeBind(this.runInAsyncScope, this, fn);
const ret =
FunctionPrototypeBind(
this.runInAsyncScope,
this,
fn,
thisArg);
ObjectDefineProperties(ret, {
'length': {
configurable: true,
Expand All @@ -241,9 +246,9 @@ class AsyncResource {
return ret;
}

static bind(fn, type) {
static bind(fn, type, thisArg) {
type = type || fn.name;
return (new AsyncResource(type || 'bound-anonymous-fn')).bind(fn);
return (new AsyncResource(type || 'bound-anonymous-fn')).bind(fn, thisArg);
}
}

Expand Down
16 changes: 16 additions & 0 deletions test/parallel/test-asyncresource-bind.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,19 @@ setImmediate(() => {
assert.strictEqual(asyncResource.asyncId(), fn2());
assert.notStrictEqual(asyncId, fn2());
});

const foo = {};
const fn3 = asyncResource.bind(common.mustCall(function() {
assert.strictEqual(this, foo);
}), foo);
fn3();

const fn4 = asyncResource.bind(common.mustCall(function() {
assert.strictEqual(this, asyncResource);
}));
fn4();

const fn5 = asyncResource.bind(common.mustCall(function() {
assert.strictEqual(this, false);
}), false);
fn5();

0 comments on commit 25d1319

Please sign in to comment.