profile
viewpoint
Stephen Belanger Qard Vancouver, BC, Canada http://stephenbelanger.com @nodejs core contributor, founded tracing (now diagnostics) working group. I hack on compilers and VMs.

othiym23/node-continuation-local-storage 948

implementation of https://github.com/joyent/node/issues/5243

othiym23/async-listener 163

polyfill version of the 0.11 version of the asyncListener API

ddfreyne/glove 67

Crystal framework for making games

Qard/async-iterator-pipe 3

Pipe between async iterators and streams

Qard/async-iterator-talk 3

VanJS talk about async iterators and streams

garnet-engine/ecs 1

entity component system framework, with actions

garnet-engine/math 1

vector and matrix math constructs

garnet-engine/tween 1

tweening algorithms

Qard/axemule 1

Javascript DSL for writing XML or HTML structures

pull request commentnodejs/node

v8: patch for thenables in PromiseHook API

I haven't run it through the benchmarks, but just structurally, it's a branch within another branch so it should have zero cost in any non-thenable case, and only a single load and branch in the thenable case, so basically zero. 🤷

Qard

comment created time in 15 hours

pull request commentnodejs/node

v8: patch for thenables in PromiseHook API

Thanks, @devsnek!

Qard

comment created time in a day

Pull request review commentnodejs/node

v8: patch for thenables in PromiseHook API

 void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask(     const TNode<Object> thenable = LoadObjectField(         microtask, PromiseResolveThenableJobTask::kThenableOffset); +    // Run the promise before/debug hook if enabled.+    RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context,

Agreed. They have it for the other branches in there, but not thenables. Makes me think there could be a specific reason for that. As far as I can tell though it's just been overlooked. In testing it locally though, it fixes the problem perfectly for our needs.

Qard

comment created time in a day

pull request commentnodejs/node

v8: patch for thenables in PromiseHook API

@devsnek That'd be much appreciated! I'll get to work on figuring out a V8 test for it too. :)

Qard

comment created time in a day

PR opened nodejs/node

v8: patch for thenables in PromiseHook API async_hooks discuss

Thenables produce an additional promise which is not currently emitting before/after hooks from the PromiseHook API in V8. This change makes that additional promise also emit the proper events.

I spent some time digging into V8 trying to figure out a fix for the thenables issue which I previously attempted a higher-level fix for in #33189 and got some resistance. With this change, async_hooks and therefore AsyncLocalStorage will now be able to correctly propagate context into the then(...) method call of a thenable.

I'm submitting this as a PR here to seek help in getting this change into V8 and for us to have the option to land it as a patch, if we want. I haven't written tests for it, though I've tested it manually, as I'm not yet sure how we want to approach landing this.

cc @nodejs/v8 @nodejs/diagnostics @nodejs/async_hooks

+9 -0

0 comment

1 changed file

pr created time in a day

push eventQard/node

Stephen Belanger

commit sha 8f519507901a2dc54a83fb806634f27b0c9de6f9

v8: patch for thenables in PromiseHook API Thenables produce an additional promise which is not currently emitting before/after hooks from the PromiseHook API in V8. This change makes that additional promise also emit the proper events.

view details

push time in a day

create barnchQard/node

branch : thenables-fix-2-the-refixening

created branch time in a day

issue commenttheduke/quickjs-rs

module init macro

I might get around to contributing it myself, if I can find the time at some point and no one else gets to it first. My thinking is something like:

use quick_js::Context;

#[quickjs_init_module(my_module)]
fn init_module(context: Context, name: String) -> Module {
  Module::new(context, name, |module| {
    module.add_callback("add", |a: i32, b: i32| a + b).unwrap();
  })
}

For reference, here's what it looks like in C: https://github.com/Qard/quickjs-glfw/blob/master/glfw.c#L178-L188

Qard

comment created time in 2 days

issue commenttheduke/quickjs-rs

module init macro

Yes, which requires an entrypoint function with that signature. It'd be nice to have a macro that lets you write a function with the rust-wrapped types and the macro will wrap it appropriately to expose the C types.

Qard

comment created time in 2 days

issue commentnodejs/diagnostics

Async hooks and cancellation

Shouldn't need to change anything. Cancellation of some form is already expected with clearTimeout, so it should be assumed that any resource might just never reach before/after events. 🤷

benjamingr

comment created time in 3 days

issue commentnodejs/diagnostics

Reviving "Zones" like proposals to TC39

Oh, actually, I think you're right about that not mattering in JS. The stack trace output remains the same. I must've been mis-remembering. 😅

legendecas

comment created time in 4 days

issue commentnodejs/diagnostics

Reviving "Zones" like proposals to TC39

The throw does some extra stuff to imprint the given error with the location that throw occurred. That means throwing something that has already been thrown will mess with the stack information such that the error then points to the new throw point not the original. This is an observable difference so it would be nice to be able to bail out after some quick checks to see the error can not be handled at that level after all. 🤔

legendecas

comment created time in 4 days

push eventQard/node

Denys Otrishko

commit sha bc55b57e64a374e5b677644c857c3d26247c72ef

lib: fix few comment typos in fs/watchers.js PR-URL: https://github.com/nodejs/node/pull/31705 Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>

view details

Robert Nagy

commit sha b9a7625fdf0a8217195300f5a8844b6da1a5a35a

stream: removed outdated TODO Was resolved in https://github.com/nodejs/node/commit/e559842188f541b884abff2ffad4d2d3e1b841a6. PR-URL: https://github.com/nodejs/node/pull/31701 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Denys Otrishko <shishugi@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>

view details

Andrey Pechkurov

commit sha 26cb448b0d74fa6440ca77ca83b1adba6cc50a87

doc: fix default server timeout description for https PR-URL: https://github.com/nodejs/node/pull/31692 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>

view details

Ujjwal Sharma

commit sha 917914112341da2de7215d304dcc1bf33184e53b

doc: update contact email for @ryzokuken Update my personal email address from usharma1998@gmail.com (tired) to ryzokuken@disroot.org (wired). PR-URL: https://github.com/nodejs/node/pull/31670 Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com>

view details

Juan José Arboleda

commit sha 94eb0f907bd4023c4ed4647b38d049be8c1c8826

doc: fix typo on fs docs PR-URL: https://github.com/nodejs/node/pull/31620 Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: James M Snell <jasnell@gmail.com>

view details

Antoine du HAMEL

commit sha 611a158f1ad53720b0ca2bf30f42abb3c2fe0c47

worker: add support for .cjs extension PR-URL: https://github.com/nodejs/node/pull/31662 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: Yuta Hiroto <hello@hiroppy.me> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Denys Otrishko <shishugi@gmail.com>

view details

Ujjwal Sharma

commit sha 9e805b1fbf3ae7658dfbf2aca22d6d2f1e099474

doc: add prerequisites information for Arch Add prerequisites for Arch Linux and derivatives in BUILDING.md. PR-URL: https://github.com/nodejs/node/pull/31669 Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>

view details

Alex Ramirez

commit sha d0ed4310412e0848a8b071cb04b49e22e9a633a5

benchmark: swap var for let in benchmarks In benchmark directory this changes for loops using var to let when it applies for consistency PR-URL: https://github.com/nodejs/node/pull/28958 Reviewed-By: Anna Henningsen <anna@addaleax.net>

view details

Daniele Belardi

commit sha 4bf888d3d2500351e72fbe4403143a25a9402409

benchmark: use let instead of var Use `let` in module, napi, net, os, path, process, querystring, streams and string_decoder. PR-URL: https://github.com/nodejs/node/pull/31592 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>

view details

Robert Nagy

commit sha 9cbf6af5b5ace0cc53c1a1da3234aeca02522ec6

crypto: fix performance regression https://github.com/nodejs/node/commit/e559842188f541b884abff2ffad4d2d3e1b841a6 made writable/readable computed with a legacy mode if the properties are written to. LazyTransform still unecessarily wrote to these properties causing a performance regression. Fixes: https://github.com/nodejs/node/issues/31739 PR-URL: https://github.com/nodejs/node/pull/31742 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>

view details

gengjiawen

commit sha 13c05cd10c07a0e0ed5833eef102938dc782ce60

doc: add glossary.md PR-URL: https://github.com/nodejs/node/pull/27517 Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Denys Otrishko <shishugi@gmail.com>

view details

Rich Trott

commit sha 9a1c19bb28c7aca25a6554f3c28f06ca5017873f

test: mark test-fs-stat-bigint flaky on FreeBSD Refs: https://github.com/nodejs/node/issues/31727 PR-URL: https://github.com/nodejs/node/pull/31728 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Denys Otrishko <shishugi@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>

view details

Robert Nagy

commit sha 087583741716969edf12874d4f1f1774de581f50

stream: fix async iterator destroyed error order There was an edge case where if _destroy calls the error callback later than one tick the iterator would complete early and not propgate the error. PR-URL: https://github.com/nodejs/node/pull/31314 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> PR-URL: https://github.com/nodejs/node/pull/31700 Reviewed-By: Anna Henningsen <anna@addaleax.net>

view details

Robert Nagy

commit sha 0c7ff7fcfb221310f5b560202ff0f256c5a9781f

stream: simplify Writable.write Slightly refactors Writable.write for minor perf and readability improvements. PR-URL: https://github.com/nodejs/node/pull/31146 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: David Carlier <devnexen@gmail.com>

view details

Robert Nagy

commit sha df1592d2e9935305539c909fecabcb96e3dd8aee

test: async iterate destroyed stream PR-URL: https://github.com/nodejs/node/pull/28995 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>

view details

legendecas

commit sha 75311dbc2f5fbd1c81dbab94e1372b55e0dbb1ac

async_hooks: ensure event after been emitted on runInAsyncScope The exception handler user-defined will not automatically emit after for the async resource. Also removes a duplicated case `test-emit-after-uncaught-exception-runInAsyncScope.js` which is identical to test-emit-after-uncaught-exception.js. Refs: https://github.com/nodejs/node/pull/30965 PR-URL: https://github.com/nodejs/node/pull/31784 Fixes: https://github.com/nodejs/node/issues/31783 Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>

view details

Anna Henningsen

commit sha e460f8cf43863a5a8d73273ce311135ad3245699

src: keep main-thread Isolate attached to platform during Dispose This works around a situation in which the V8 WASM code calls into the platform while the Isolate is being disposed. This goes against the V8 API constract for `v8::Platform`. In lieu of a proper fix, it should be okay to keep the Isolate registered; the race condition fixed by 25447d82d cannot occur for the `NodeMainInstance`’s Isolate, as it is the last one to exit in any given Node.js process. This partially reverts 25447d82d. Refs: https://github.com/nodejs/node/pull/30909 Refs: https://github.com/nodejs/node/issues/31752 PR-URL: https://github.com/nodejs/node/pull/31795 Reviewed-By: Denys Otrishko <shishugi@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>

view details

Shelley Vohr

commit sha 3a2254959b9e8c5177289ab1c1259f18ceaf9449

src: use hex not decimal in IsArrayIndex PR-URL: https://github.com/nodejs/node/pull/31758 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: Denys Otrishko <shishugi@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>

view details

Michael Dawson

commit sha 79296dc2d02c0b9872bbfcbb89148ea036a546d0

doc: guide - using valgrind to debug memory leaks Add doc for using valgrind to debug native memory leaks. Started writing this up as part of an effort in the Diagnostic WG but think it's better to have it in the core guides and then be referenced by the docs in the Diagnostic WG repo. For more details on the Diagnostic WG effort see https://github.com/nodejs/diagnostics/issues/254#issuecomment-538853390 This guide is related to `/step3 - using_native_tools.md` PR-URL: https://github.com/nodejs/node/pull/31501 Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com> Reviewed-By: Denys Otrishko <shishugi@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>

view details

Anna Henningsen

commit sha a7c523e26df468782691c7e16b2e033c6256beb3

src: prefer 3-argument Array::New() This is nicer, because: 1. It reduces overall code size, 2. It’s faster, because `Object::Set()` calls are relatively slow, and 3. It helps avoid invalid `.Check()`/`.FromJust()` calls. PR-URL: https://github.com/nodejs/node/pull/31775 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: David Carlier <devnexen@gmail.com>

view details

push time in 5 days

startedjhen0409/react-native-debugger

started time in 5 days

issue commentnodejs/diagnostics

Reviving "Zones" like proposals to TC39

👍 for AsyncLocalStorage copied mostly as-is. It wouldn't be too hard to layer error-handling concepts on later, but I do think they are separate enough that they should not block the context propagation capability.

My main concern with attaching error-handling to it is that multi-tenancy gets very complicated. It'd need the ability to rethrow an error, or let it flow through somehow, without tainting the original information as an outer container might be expecting it to look a certain way.

On a related note: I have been thinking it'd be nice to have a "clean" rethrow feature of sorts like try { ... } catch (e) { rethrow } that'd return to unwinding the stack for the currently intercepted error without modifying the trace information on it. Could actually help a bunch with making the need for conditional error handling here more reasonable. 🤔

legendecas

comment created time in 6 days

issue openedtheduke/quickjs-rs

module init macro

It'd be cool to have a fancy macro to build the extern function required to create a native module that can be imported by the qjs CLI. With qjs you can build and import native modules from *.so files by simply having a function something like:

JSModuleDef* js_init_module_qjsc_my_module(JSContext* ctx, const char* module_name);

Then in JS you just do:

import * from 'my_module.so'

created time in 6 days

starteddoctorn/micro-mitten

started time in 6 days

startedartichoke/artichoke

started time in 6 days

startedstarship/starship

started time in 6 days

startedsharkdp/hyperfine

started time in 7 days

issue commentnodejs/diagnostics

Proposal for reworking promise integration into async_hooks

I tried the MicrotaskQueue subclass idea. Doesn't work out quite how I hoped. The specific EnqueueMicrotask variant we need to capture thenables is not virtual and the default constructor is private. It's also an opaque type which lacks the sizing information to be subclassed without some major changes to V8. Because the class exposed in v8.h is actually just a super-class of the internal MicrotaskQueue, there's not much we can work with for the custom MicrotaskQueue idea.

I'm refocusing my effort on seeing if I can just produce a new API which roughly parallels the PromiseHook API in functionality, but focuses specifically on microtask creation and lifecycle rather than promises.

AndreasMadsen

comment created time in 7 days

issue commentothiym23/node-continuation-local-storage

await breaks context

Try cls-hooked, or if you're willing to upgrade your Node.js version, you could give AsyncLocalStorage a try. This module is not really well supported anymore as other modules have filled the gap for more modern versions of Node.js This was mostly targetted at pre-10.x versions of Node.js.

mikhailrojo

comment created time in 7 days

Pull request review commentnodejs/node

src: use symbol to store `AsyncWrap` resource

 MaybeLocal<Value> AsyncWrap::MakeCallback(const Local<Function> cb,   ProviderType provider = provider_type();   async_context context { get_async_id(), get_trigger_async_id() };   MaybeLocal<Value> ret = InternalMakeCallback(-      env(), GetResource(), object(), cb, argc, argv, context);+      env(), object(), object(), cb, argc, argv, context);

Nope, no strong feelings about it. Just wanted to know what your feelings are about it. Seemed to me a bit like the move toward resource_symbol and owner_symbol was going in a somewhat different direction from the changes in #32930 so it wasn't fully clear to me if it was still fully relevant or if you maybe had a plan on how to proceed without it.

addaleax

comment created time in 8 days

Pull request review commentnodejs/node

src: use symbol to store `AsyncWrap` resource

 MaybeLocal<Value> AsyncWrap::MakeCallback(const Local<Function> cb,   ProviderType provider = provider_type();   async_context context { get_async_id(), get_trigger_async_id() };   MaybeLocal<Value> ret = InternalMakeCallback(-      env(), GetResource(), object(), cb, argc, argv, context);+      env(), object(), object(), cb, argc, argv, context);

So with this change, having the extra "resource" field on InternalMakeCallback(...) becomes unnecessary here. Just wondering if you have thoughts on if/how to expose the resource_symbol/owner_symbol stuff to userland for native modules to be able to handle resource re-use appropriately. It'd be nice if we could make #32930 irrelevant.

addaleax

comment created time in 8 days

push eventQard/quickjs-qlfw

Stephen Belanger

commit sha 3f2024e3cb3cb43c5c3e4619c50f09d9095eee85

Add monitor, video mode, work area, scale and gamma ramp classes

view details

push time in 8 days

delete branch Qard/dd-trace-js

delete branch : benchmark-async-local-storage

delete time in 12 days

push eventQard/dd-trace-js

Stephen Belanger

commit sha 6dd0f422884ba6339e8e7eb81d1fbfb76696c8a5

Add promise benchmark to compare against async/await

view details

push time in 13 days

push eventQard/dd-trace-js

Stephen Belanger

commit sha d4a22eb18372762b4cb73deff9570aba7d01fdec

Add queueMicrotask async test for comparison

view details

push time in 13 days

PR opened DataDog/dd-trace-js

Benchmark AsyncLocalStorage

This adds a new benchmark for AsyncLocalStorage and updates async_hooks benchmarks to use AsyncResource similarily.

+113 -46

0 comment

3 changed files

pr created time in 13 days

create barnchQard/dd-trace-js

branch : benchmark-async-local-storage

created branch time in 13 days

delete branch Qard/dd-trace-js

delete branch : async-local-storage-scope

delete time in 14 days

startedgfx-rs/wgpu

started time in 14 days

Pull request review commentDataDog/dd-trace-js

Add option for AsyncLocalStorage for scope management

+'use strict'++const {+  AsyncLocalStorage,+  AsyncResource,+  executionAsyncId+} = require('async_hooks')+const Scope = require('../../src/scope/async_local_storage')+const Span = require('opentracing').Span+const testScope = require('./test')++wrapIt()++if (AsyncLocalStorage) {+  describe('Scope (AsyncLocalStorage)', test)+} else {+  describe.skip('Scope (AsyncLocalStorage)', test)+}++function test () {+  let scope+  let span++  beforeEach(() => {+    scope = new Scope()+    span = new Span()+  })++  it('should not break propagation for nested resources', done => {+    scope.activate(span, () => {+      const asyncResource = new AsyncResource(+        'TEST', { triggerAsyncId: executionAsyncId(), requireManualDestroy: false }+      )++      asyncResource.runInAsyncScope(() => {})++      expect(scope.active()).to.equal(span)++      // AsyncLocalStorage context persists through `done()` unless we tell it+      // not to. Without this, the following tests will run inside this scope.+      scope._storage.exit(done)

Just tested a simulated fail there with a throw and no done call. Seems to work fine.

Qard

comment created time in 14 days

push eventQard/dd-trace-js

Stephen Belanger

commit sha 506ca0e2258d167418472b1d946d9cb627f8a39b

Add option for AsyncLocalStorage for scope management

view details

push time in 14 days

Pull request review commentDataDog/dd-trace-js

Add option for AsyncLocalStorage for scope management

+'use strict'++const {+  AsyncLocalStorage,+  AsyncResource,+  executionAsyncId+} = require('async_hooks')+const Scope = require('../../src/scope/async_local_storage')+const Span = require('opentracing').Span+const testScope = require('./test')++wrapIt()++if (AsyncLocalStorage) {+  describe('Scope (AsyncLocalStorage)', test)+} else {+  describe.skip('Scope (AsyncLocalStorage)', test)+}++function test () {+  let scope+  let span++  beforeEach(() => {+    scope = new Scope()+    span = new Span()+  })++  it('should not break propagation for nested resources', done => {+    scope.activate(span, () => {+      const asyncResource = new AsyncResource(+        'TEST', { triggerAsyncId: executionAsyncId(), requireManualDestroy: false }+      )++      asyncResource.runInAsyncScope(() => {})++      expect(scope.active()).to.equal(span)++      // AsyncLocalStorage context persists through `done()` unless we tell it+      // not to. Without this, the following tests will run inside this scope.+      scope._storage.exit(done)

It just wouldn't reach the done call. 🤷

I assume the test suite has a timeout system built-in, which would have been initialized outside the context and therefore not be impacted.

Qard

comment created time in 14 days

pull request commentDataDog/dd-trace-js

Add option for AsyncLocalStorage for scope management

No, storage.exit(...) will prevent any context propagation within its callback, so anything triggered within it would return undefined when trying to get the store.

Qard

comment created time in 14 days

issue commentnodejs/diagnostics

Proposal for reworking promise integration into async_hooks

I don't think there's really a "correct" path. As Microsoft folks brought up in the previous async context formalization discussions, there's really two relevant paths: user-intent and technical causality. The user intent is generally what is reflected by capturing executionAsyncId in the init event, while technical causality is reflected by triggerAsyncId. These two branches will later converge in a callback of some form. However, the causality branch will have additional data between the call and callback in the graph while the user intent branch will connect directly, therefore complete context coverage can be attained at all points by always following the causal path.

AndreasMadsen

comment created time in 14 days

Pull request review commentDataDog/dd-trace-js

Add option for AsyncLocalStorage for scope management

 const platform = {   on: emitter.on.bind(emitter),   off: emitter.removeListener.bind(emitter),   Loader,-  Scope,+  getScope (scope) {

Fixed. 👍

Qard

comment created time in 14 days

push eventQard/dd-trace-js

Stephen Belanger

commit sha 8242930d36f518d67d059237c49dd8d5034deec5

Add option for AsyncLocalStorage for scope management

view details

push time in 14 days

pull request commentDataDog/dd-trace-js

Add option for AsyncLocalStorage for scope management

By binding to null you mean scope._activate(null, callback)? The AsyncLocalStorage way of escaping the context is with storage.exit(callback), so would it make sense to detect if the span is null and call storage.exit(callback) rather than storage.run(span, callback) in that case?

Qard

comment created time in 14 days

push eventQard/dd-trace-js

Stephen Belanger

commit sha b3fb01ddd5c223e796a1f00310b99622a93417d2

Add option for AsyncLocalStorage for scope management

view details

push time in 14 days

push eventQard/dd-trace-js

Stephen Belanger

commit sha 5c2bece12cd36e415e7a2ff26c4a99477abb5c6b

Add option for AsyncLocalStorage for scope management

view details

push time in 14 days

push eventQard/dd-trace-js

Stephen Belanger

commit sha 7a014e286cd94c188fabe7cf8d39bcdad1efa8c6

Add option for AsyncLocalStorage for scope management

view details

push time in 14 days

push eventQard/dd-trace-js

Stephen Belanger

commit sha b0303461501837bb009b781fae9e092b95a3b243

Add option for AsyncLocalStorage for scope management

view details

push time in 14 days

PR opened DataDog/dd-trace-js

Add option for AsyncLocalStorage for scope management

I've added support for using the new AsyncLocalStorage class in Node.js 14+ as a simpler and faster scope manager.

Note the comment in the test: this is a bit more aggressive at maintaining the context than the existing scope manager so it may be necessary to expose the storage.exit(...) method for some cases where you don't want the context propagated.

+73 -0

0 comment

6 changed files

pr created time in 14 days

create barnchQard/dd-trace-js

branch : async-local-storage-scope

created branch time in 14 days

issue commentnodejs/diagnostics

Proposal for reworking promise integration into async_hooks

@targos Yep. That's the plan!

AndreasMadsen

comment created time in 15 days

issue commentnodejs/diagnostics

Proposal for reworking promise integration into async_hooks

The [[then]] method of a thenable will be called within a microtask. That microtask would need an async context so the init for the [[then]] would have a executionAsyncId and triggerAsyncId to connect to which it currently does not have. It may be possible to use a subclassed MicrotaskQueue, wrapping the EnqueueMicrotask(...) method to inject additional microtasks before and after the given one to set and clear the context, but that might be expensive.

Also, I think this is actually slightly overthinking and/or looking past where the real issue is. We don't actually need promise hooks at all. What we need is microtask hooks.

When it comes down to it, promises are actually conceptually similar to event emitters in that they are only async because of external forces making them so. In this case, the microtask queue. The [[then]] is the same as emitter.on(...) and the resolve(...) and reject(...) are the same as emitter.emit(...) with the only difference being that the resolve and reject internally have a microtask queue call. It conceptually looks something like this:

function resolve(value) {
  for (const realResolve of resolversForChainedPromises) {
    queueMicrotask(() => {
      realResolve(value)
    })
  }
}

If instead of wrapping promises we wrapped microtasks at the point they are created and the points before and after they are executed, it would solve the same problem and would actually be a much simpler solution.

AndreasMadsen

comment created time in 16 days

push eventQard/quickjs-qlfw

Stephen Belanger

commit sha fe56cf85b15fd2cc528530ab1a7aab18eaef7eb9

got the basics all working

view details

push time in 16 days

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

I'm a bit on the fence about if it should be documented at all. It'd be a step beyond just "experimental" more toward "you probably shouldn't use this unless you really know what you are doing and why" 🤔

Also, my hope is that even if this does manage to land that we can figure out a lower-level fix and therefore not even need it later. This PR is basically an experiment and demonstration that the issue can be fixed without needing to hack up V8, and also a possible temporary fix, if we decide we want it enough.

Qard

comment created time in 16 days

delete branch Qard/node

delete branch : promise-hooks-in-js

delete time in 16 days

push eventQard/quickjs-qlfw

Stephen Belanger

commit sha 016ca47d8c07acb0d596d665f8f2c5bad4e1fac7

got the basics all working

view details

push time in 16 days

create barnchQard/quickjs-qlfw

branch : master

created branch time in 16 days

created repositoryQard/quickjs-qlfw

GLFW bindings for QuickJS

created time in 16 days

startedmaierfelix/nvk

started time in 18 days

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

Good suggestion @mhdawson. I've expanded that a bit, rearranged the doc some and elaborated in some other areas too. I'm also going to add something later elaborating on the technical details of exactly where in the Node.js core code this issue is happening and the technical reasons why it's difficult to solve.

Qard

comment created time in 18 days

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

Here's the gist explaining the problem in more detail: https://gist.github.com/Qard/faad53ba2368db54c95828365751d7bc

If you have any more questions, I'll try to expand the examples further.

Qard

comment created time in 20 days

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

I'm working on a gist explaining exactly how to reproduce the problem, what the implications are, and abstractly what needs to be solved to "correctly" handle it. I'll post it here when I'm done.

Qard

comment created time in 20 days

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

@mcollina The before and after hooks only exist when someone has explicitly asked for them now though, so that shouldn't be so much of an issue. If there are no AsyncLocalStorage objects with the trackAsyncAwait option then it will use to original init-only version.

For the option name, I'm open to whatever name people think is clearest. :)

As for the manual wrap idea, that's already basically what AsyncResource does. It's meant to just be the backup plan though. It leaks concerns for context propagation into userland, and most places its needed are places that the developer of the code had no reason to think about async_hooks. Due to the potential for thenables to exist anywhere, any place that anyone awaits anything would potentially need to be patched or the context would be lost. This makes module interop in an async/await-based world extremely fragile.

One of the main reasons the "thenables" concept exists is to support ecosystem promise implementations like bluebird. Without support for it in async_hooks to correctly assign ids to thenables, all these libraries are needing to patch themselves to not break the world. This is problematic, especially given that this means that anyone writing and publishing a Node.js module to do anything async needs to be aware of this or they might publish something that breaks the world. That adds an extra cognitive burden to the focus of every single developer that wants to write stuff with Node.js.

In its current state, async_hooks is fundamentally broken because within any awaited thenable it will have zero as a trigger id and an empty resource stack, which should be impossible. Thenables are not kicked off within a context we control so it starts off with no async_hooks context whatsoever and then could potentially create an entire orphaned chain of async behaviour beneath it.

Because of how ubiquitous thenables are in userland--almost every single database or cache module uses them--async_hooks very often gets broken in user apps. And it's not just a small context loss here or there. In most cases, they lose 90% of the async graph that APM products attempt to capture. I've worked with four different APM vendors and all have had by far the largest user complaint was context loss resulting in little to know data in the APM dashboard. I've seen literally hundreds, if not thousands, of users complaining about it on the various APM products I've worked on. And those are just the ones vocal enough to bother contacting support about it or opening an issue. I'd bet many more just give up and uninstall without reporting.

I get that AsyncResource can fix a lot of cases, but there's also hundreds of thousands of modules on npm. There's no possible way APM vendors could review even a fraction of those for context loss issues and open pull requests. At past APM companies I spent 90% of my time tracking down context loss issues for whatever user was having issues that day, and the majority of times it was some obscure module with only a couple thousand downloads that they just happened to be using for one thing in their system, but the presence broke the context everywhere because it just happened to be in the path between two other more common modules deep in the internals of some dependency somewhere. 😬

Qard

comment created time in 21 days

issue commentnodejs/TSC

Node.js Technical Steering Committee (TSC) Meeting 2020-05-07

I'm happy to join any discussion about nodejs/node#33189, or to start a separate discussion, to explain why the current state of thenables is such an issue and to work out how to deal with the problem. It's a fairly complex issue that is not adequately solved by any of the existing "fixes" we have and the nuance and complexity makes it difficult to explain adequately in text.

mhdawson

comment created time in 22 days

issue commentnodejs/diagnostics

Discuss usage and support of eBPF

Yeah, I read a bit about it. The ability to define tracepoints at runtime made me curious about the possible use for APM products. It'd be super neat if an APM vendor could toggle low-level tracepoints on and off as-needed. It'd be super valuable to be able to provide deeper insights when something seriously anomalous is detected. 🤔

No9

comment created time in 22 days

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

I put it behind an option. I'll continue trying to figure out a lower-level fix.

Qard

comment created time in 22 days

push eventQard/node

Stephen Belanger

commit sha cb867d7d6a258c13923642e904c3c1e39e2c9f0d

async_hooks: add trackAsyncAwait option to AsyncLocalStorage

view details

push time in 22 days

issue commentnodejs/diagnostics

async_hooks performance/stability improvement plans

I agree that the then(...) call is the most "correct" representation of the async barrier and we should therefore be creating a resource at that level. However, because await runs that in an unwrapped microtask that would break everything, the way things are currently. We would need a way to be able to capture and wrap the context for each microtask for it to run as within the queue. Perhaps we could supply our own custom MicrotaskQueue?

Qard

comment created time in 23 days

issue commentnodejs/diagnostics

Discuss usage and support of eBPF

I'm also very interested. I have been meaning to dig into eBPF stuff to learn what we could do with it, but haven't got to it yet. The concept sounds very promising to me though so I'd love to learn more. :)

No9

comment created time in 23 days

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

And again, let me reiterate: I am not advocating for this exact fix as it is right now. I'm presenting a rough idea for how it could be fixed and seeking feedback on how the approach could be made better, not that it should be discarded entirely in favor of the approach we're already taking and have long seen to be deficient.

Qard

comment created time in 23 days

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

You're framing this as broken thenable implementations, but that's not the case at all. This is completely valid code according to the spec for thenables which we are handling incorrectly in Node.js core. AsyncResource is only supposed to be the backup plan for when async_hooks can't retain the context on its own.

This sort of push back is exactly why it took over half a decade to get a CLS implementation in Node.js core. People saw that it was possible (albeit terrible) to achieve the same thing in userland and therefore pushed back hard against the much faster and better way of doing it in core.

This is a well-known issue that impacts all APM vendors, which are the heaviest users of async_hooks. If a feature is broken for everyone, we should probably consider trying to fix it in core.

Qard

comment created time in 23 days

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

Lots of potential timing issues. What if you do two queries at the same time with Promise.all(...)? How would you pass two separate resources into the two separate microtasks without a way to pass data alongside an await? You can't store the reference on the object because both microtasks will run in the same tick and there won't be anywhere in-between that the reference can be updated to match the microtask. There's also not really clear "terminal" operations, as you put it, so you'd still have to make a bunch of AsyncResource instances that never reach the before/after events.

Also, using native promises would require a breaking change which wouldn't help all the people stuck on the older versions. APM vendors need to support whatever module set the customer has in their app. We can't just tell them they can't use our product unless they update all their modules. Many dependencies they will not have control of, and actually quite often APM gets used by companies that built something once, years ago, and do not intend to update the code until absolutely necessary. I know of at least one very major company still using Node.js 0.8 in production because it just works, and they will probably never update it until either the server catches fire or they go out of business. 🙄

Qard

comment created time in 23 days

delete branch Qard/node

delete branch : async-storage-eliminate-exit-transition

delete time in 23 days

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

That's the comment I'm referring to. The issue you mention is separate and easily patchable if the context is available somewhere else in the chain. Without a fix for the thenables issue however, there might not be a context accessible at the appropriate place to patch that.

Qard

comment created time in 23 days

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

As I already explained: some libraries, especially knex, have no clear place to put a fix. I have patched a few libraries with AsyncResource before where it was clear how to do so. However there is a clear pattern of module authors trying to use thenables in more advanced ways like this which is making it harder and harder for APMs to keep a stable context. This problem will only get bigger with time and trying to just tell users to code a certain way is not going to help much when most aren't listening, and the few that are would often miss the point of supporting a feature they don't use directly. I've had AsyncResource PRs rejected before because the module owner didn't feel they needed the feature themself and they didn't trust an API that is marked experimental.

As for your comment about it being a "partial" fix--I don't see how that is the case. It certainly doesn't 100% eliminate all cases where AsyncResource is needed--queuing patterns will always be a thing--but it does ensure that specific boundary is always linked correctly, allowing the subsequent chain of internal code to be patch appropriately in the context it needs rather than needing to pile on some very sketchy and non-performant hacks in userland to try and re-establish that context before doing anything.

Qard

comment created time in 23 days

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

@targos The problem is not continuing context, it is internal context. If you need to get the store from somewhere within the execution of the queryBuilder thenable execution, which is the standard case for every APM product, there will be no context. This is also specific to async/await, because the calling of the then method occurs within a microtask tick with no async_hooks context. Your code calls the then method directly in user code, so it would have a context to connect to there.

As shown in https://github.com/nodejs/node/pull/33189#issuecomment-622510386, the context is available before and after a thenable, but not within it.

@puzpuzpuz We don't see reports here because the issue only surfaces in APM products, the actual users of this API. As someone that has worked in APM for half a decade building three different APM products, I am reporting this. I have seen this issue reported on my agents literally hundreds of times and have had to do horrible and fragile hacks to attempt to get around this.

Qard

comment created time in 23 days

pull request commentnodejs/node

async_hooks: fast-path for PromiseHooks in JS

I think so, yes.

Qard

comment created time in 24 days

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

The problem though is that the before/after will link back to where the new AsyncResource occurs though, and there's not a clear "correct" place to do that in many cases.

With knex, the knex object will be shared across all queries so it probably shouldn't be in the construction of that.

You can do knex('table') to start operating on a certain table, so you might think to put it there but you could also do knex.select().from('table').

You can also reuse intermediate results:

const baseQuery = knex('accounts as a1')
  .leftJoin('accounts as a2', function() {
    this.on('a1.email', '<>', 'a2.email');
  })
  .select(['a1.email', 'a2.email'])

const data = await baseQuery.where(knex.raw('a1.id = 1'))
const data = await baseQuery.where(knex.raw('a1.id = 2'))

The baseQuery could be create anywhere, including outside of the request, which would mean creating the resource somewhere in the would link to entirely the wrong place.

So where would the AsyncResource get constructed for those queries? If you create a fresh AsyncResource for every single call most would never be used and you'd be polluting the async_hooks event stream with tons of inits that never actually have a before/after.

The cognitive burden of expecting the ecosystem to fix our context loss problems for us instead of fixing it properly ourselves can get very high. We need to fix this properly or we will continue to have modules like this which break context, forcing us to do even worse hacks to attempt to restore it.

I'm not arguing for this fix specifically but that we absolutely need some fix for this.

Qard

comment created time in 25 days

Pull request review commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

 class AsyncResource { }  const storageList = [];+const seenLayer = [];+let depth = 0;++function patchPromiseBarrier(currentResource) {+  PromiseResolve({+    then(resolve) {+      const resource = executionAsyncResource();+      propagateToStorageLists(resource, currentResource);+      resolve();+    }+  });+}++function propagateToStorageLists(resource, currentResource) {+  for (let i = 0; i < storageList.length; ++i) {+    storageList[i]._propagate(resource, currentResource);+  }+}+ const storageHook = createHook({   init(asyncId, type, triggerAsyncId, resource) {     const currentResource = executionAsyncResource();     // Value of currentResource is always a non null object-    for (let i = 0; i < storageList.length; ++i) {-      storageList[i]._propagate(resource, currentResource);+    propagateToStorageLists(resource, currentResource);++    if (type === 'PROMISE' && !seenLayer[depth]) {+      seenLayer[depth] = true;+      patchPromiseBarrier(currentResource);     }+  },++  before(asyncId) {+    depth++;+    seenLayer[depth] = false;+  },++  after(asyncId) {+    depth--;   }

Yep, that's fine. Just putting something up that I can iterate on. If the possible lower-level fix is what it needs to be to land, so be it. :)

Qard

comment created time in 25 days

Pull request review commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

 class AsyncResource { }  const storageList = [];+const seenLayer = [];+let depth = 0;++function patchPromiseBarrier(currentResource) {+  PromiseResolve({+    then(resolve) {+      const resource = executionAsyncResource();+      propagateToStorageLists(resource, currentResource);+      resolve();+    }+  });+}++function propagateToStorageLists(resource, currentResource) {+  for (let i = 0; i < storageList.length; ++i) {+    storageList[i]._propagate(resource, currentResource);+  }+}+ const storageHook = createHook({   init(asyncId, type, triggerAsyncId, resource) {     const currentResource = executionAsyncResource();     // Value of currentResource is always a non null object-    for (let i = 0; i < storageList.length; ++i) {-      storageList[i]._propagate(resource, currentResource);+    propagateToStorageLists(resource, currentResource);++    if (type === 'PROMISE' && !seenLayer[depth]) {+      seenLayer[depth] = true;+      patchPromiseBarrier(currentResource);     }+  },++  before(asyncId) {+    depth++;+    seenLayer[depth] = false;+  },++  after(asyncId) {+    depth--;   }

Yep, I'm trying to figure out a lower-level fix. I just made this as a possible higher-level solution for now, until we can come up with something better. Agreed it's not great though, needing the extra before/after hooks.

Qard

comment created time in 25 days

Pull request review commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

 class AsyncResource { }  const storageList = [];+const seenLayer = [];+let depth = 0;++function patchPromiseBarrier(currentResource) {+  PromiseResolve({+    then(resolve) {+      const resource = executionAsyncResource();+      propagateToStorageLists(resource, currentResource);+      resolve();+    }+  });+}++function propagateToStorageLists(resource, currentResource) {+  for (let i = 0; i < storageList.length; ++i) {+    storageList[i]._propagate(resource, currentResource);+  }+}+ const storageHook = createHook({   init(asyncId, type, triggerAsyncId, resource) {     const currentResource = executionAsyncResource();     // Value of currentResource is always a non null object-    for (let i = 0; i < storageList.length; ++i) {-      storageList[i]._propagate(resource, currentResource);+    propagateToStorageLists(resource, currentResource);++    if (type === 'PROMISE' && !seenLayer[depth]) {+      seenLayer[depth] = true;+      patchPromiseBarrier(currentResource);     }+  },++  before(asyncId) {+    depth++;+    seenLayer[depth] = false;+  },++  after(asyncId) {+    depth--;   }

I'm thinking a config option like trackAsyncAwait which would switch between two hook sets so it only does the before/after if a user of AsyncLocalStorage has explicitly requested it. What do you think?

Qard

comment created time in 25 days

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

Another side note: a fix of some sort for this needs to exist in core for domains to be stable. Domains need to be able to track through internals to be able to adequately contain the execution and internal errors.

Qard

comment created time in a month

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

For context, here's the then method implementation in knex: https://github.com/knex/knex/blob/e37aeaa31c8ef9c1b07d2e4d3ec6607e557d800d/lib/interface.js#L18-L33

That is merged into a bunch of other classes, none of which have sufficient awareness of the point at which the runner would be invoked to be able to know when to create an AsyncResource instance or how to store it to retrieve later, when the then method actually gets called.

Qard

comment created time in a month

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

That works in the case where you have a factory function which you can put the construction of the AsyncResource in, but the reality is that the vast majority of thenable issues derive from fluid or reusable objects. The most common case being database query builder libraries like knex, which use the call to then to join the current state of the built query and kick off the connection to the database. There is no point in the chain at which it knows itself to be "done" building until the then is called, and that is too late to create the AsyncResource. This means that almost all existing cases of AsyncResource used in the wild today do not work with async/await.

Qard

comment created time in a month

pull request commentnodejs/node

Move AsyncLocalStorage into its own core module

I don't think it should. The link to async_hooks is really just an implementation detail.

vdeturckheim

comment created time in a month

pull request commentnodejs/node

Move AsyncLocalStorage into its own core module

By the way, a smooth transition could be:

  • move out of experimental in a minor as a class in async_hooks module
  • add a re-exporting top-level module as a major
  • eventually shift code to other module and have async_hooks module re-export that
  • eventually deprecate the re-export in async_hooks
vdeturckheim

comment created time in a month

issue commentnodejs/diagnostics

async_hooks performance/stability improvement plans

I should point out that is exactly the timing issue that this PR is solving. In async/await, the [[then]] is called from within an unwrapped microtask, so there is currently no async_hooks stack to link to. Moving all promises to this model would definitely break everything.

Qard

comment created time in a month

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

What do you think about a configuration passed to the AsyncLocalStorage constructor to turn this on manually? Would that deal with your concerns?

Qard

comment created time in a month

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

Yes, the problem exists in bluebird too. Every userland implementation of promises will have the same problem because it doesn't matter how the userland implementation itself works, it matters how the native promise facilities to upgrade a thenable to a native promise for the await works.

The problem is outlined here:

const cls = new AsyncLocalStorage()
const data = { foo: 'bar' }

function thenable() {
  return {
    then(cb) {
      assert.strictEqual(data, cls.getStore()) // fail
      cb()
    }
  }
}

cls.run(data, async () => {
  assert.strictEqual(data, cls.getStore()) // pass
  await thenable()
  assert.strictEqual(data, cls.getStore()) // pass
})

So basically, there is a deadzone within the thenable itself between when the then method is called and when the promise actually resolves, yielding the value back out through the await. The linear context within the async function remains intact, but the causality of the internals behind the thenable is lost.

Ideally this should be fixed at a lower level, and I'm working on that. This is just a possible fix which I know works at this level.

Qard

comment created time in a month

pull request commentnodejs/node

async_hooks: fix async/await context loss in AsyncLocalStorage

cc @nodejs/async_hooks @nodejs/diagnostics

Qard

comment created time in a month

push eventQard/node

Stephen Belanger

commit sha ec6b04867b73fe839c76fbbace204d7bfd37ec9e

async_hooks: fix async/await context loss in AsyncLocalStorage

view details

push time in a month

issue commentnodejs/diagnostics

async_hooks performance/stability improvement plans

I wouldn't say await is quite the same. You can eager-init.

async function main() {
  const first = asyncThing()
  const second = asyncThing()

  await first
  await second
}

The point at which the Promise instance is created for second is different from when the await and therefore the then happens.

Qard

comment created time in a month

pull request commentnodejs/node

Move AsyncLocalStorage into its own core module

Agreed with @jasnell, but also we could consider adding another module that just re-exports async_hooks.AsyncLocalStorage.

vdeturckheim

comment created time in a month

issue commentnodejs/diagnostics

async_hooks performance/stability improvement plans

The real problem, in my opinion, is that we are conflating promise gc with handle closes in the destroy hook. Those should really be two different events that can be handled separately, and that's one of the things I hope to work on.

Qard

comment created time in a month

pull request commentnodejs/node

async_hooks: fast-path for PromiseHooks in JS

Okay, looks like I finally got the CI to cooperate. 😅

Qard

comment created time in a month

push eventQard/remark-lint-code-eslint

snyk-bot

commit sha 8ce0b0242914482e93268c113c18d866eb8e621a

fix: package.json & .snyk to reduce vulnerabilities The following vulnerabilities are fixed with a Snyk patch: - https://snyk.io/vuln/SNYK-JS-LODASH-567746

view details

push time in a month

push eventQard/remark-lint-code-eslint

snyk-bot

commit sha 673e1e5c88a852108e3d6cc4b259485854581fe2

fix: package.json & .snyk to reduce vulnerabilities The following vulnerabilities are fixed with a Snyk patch: - https://snyk.io/vuln/SNYK-JS-LODASH-567746

view details

push time in a month

push eventQard/elastic-modeller

snyk-bot

commit sha 3d8cc9c3110284fadaa4126c0905a1d3a2157ebb

fix: package.json & .snyk to reduce vulnerabilities The following vulnerabilities are fixed with a Snyk patch: - https://snyk.io/vuln/SNYK-JS-LODASH-567746

view details

push time in a month

push eventQard/elastic-modeller

snyk-bot

commit sha 6b6ee2ab9c76e3aa44d11680acb08aa3d74d252f

fix: package.json & .snyk to reduce vulnerabilities The following vulnerabilities are fixed with a Snyk patch: - https://snyk.io/vuln/SNYK-JS-LODASH-567746

view details

push time in a month

push eventQard/node

Stephen Belanger

commit sha fe17123b60b061ab790483abac8c65aeb12c6616

async_hooks: fix async/await context loss in AsyncLocalStorage

view details

push time in a month

push eventQard/node

Stephen Belanger

commit sha c70528b5a06c9b10567ce168d908fb5329739aef

async_hooks: remove unused isolate reference

view details

push time in a month

more