endo
endo copied to clipboard
Investigation for Node v24 AsyncLocalStorage compatibility issue
I've managed to at least turn a couple of banal type programming bugs into a perhaps more diagnostic semantic failure of the test:
- looks like
_enableis no longer a thing, but the new class code does have adisablemethod - not sure how the
kResourceStoreproperty setter used to get called, but looks like it doesn't anymore... - ...so all those
getStoreMap(this).get // or set or whateversites that were pledged a non-undefined blew up
This gets us to "at least now it's just our own expectation that's failing, rather than the test crashing" like:
✘ [fail]: async_hooks › AsyncLocalStorage patch
✔ async_hooks › async_hooks Promise patch (616ms)
✔ bundle › Can be bundled (594ms)
─
async_hooks › AsyncLocalStorage patch
Difference (- actual, + expected):
- undefined
+ 1
[object Object]
at packages/init/test/async_hooks.test.js:103:7
at async packages/init/test/async_hooks.test.js:88:3
─
1 test failed
For reference that debug print currently spits:
WAT AsyncLocalStorage {} { _propagate: [Function: _propagate] } [class AsyncLocalStorage] 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 = {}) {
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);
}
}
I recently heard that async_hooks no longer gets triggered by starting the debugger, so we may be able to simply nuke the async_hooks patch out of existence.
Opened https://github.com/endojs/endo/issues/3012