Skip to content

Commit

Permalink
Do not register async hook symbols as well-known
Browse files Browse the repository at this point in the history
  • Loading branch information
mhofman committed Mar 17, 2022
1 parent 96c6676 commit 65c52e3
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 46 deletions.
11 changes: 0 additions & 11 deletions packages/init/node-async_hooks-symbols.d.ts

This file was deleted.

58 changes: 33 additions & 25 deletions packages/init/node-async_hooks.js
@@ -1,27 +1,30 @@
import { createHook, AsyncResource } from 'async_hooks';

/// <reference path="./node-async_hooks-symbols.d.ts" />

const asyncHooksWellKnownNameFromDescription = {
async_id_symbol: 'nodeAsyncHooksAsyncId',
trigger_async_id_symbol: 'nodeAsyncHooksTriggerAsyncId',
destroyed: 'nodeAsyncHooksDestroyed',
const asyncHooksSymbols = {
async_id_symbol: undefined,
trigger_async_id_symbol: undefined,
destroyed: undefined,
};

const promiseAsyncHookFallbackStates = new WeakMap();

const setAsyncSymbol = (description, symbol) => {
const wellKnownName = asyncHooksWellKnownNameFromDescription[description];
if (!wellKnownName) {
if (!(description in asyncHooksSymbols)) {
throw new Error('Unknown symbol');
} else if (!Symbol[wellKnownName]) {
Symbol[wellKnownName] = symbol;
} else if (!asyncHooksSymbols[description]) {
if (symbol.description !== description) {
// Throw an error since the whitelist mechanism relies on the description
throw new Error(
`Mismatched symbol found for ${description}: ${String(symbol)}`,
);
}
asyncHooksSymbols[description] = symbol;
return true;
} else if (Symbol[wellKnownName] !== symbol) {
} else if (asyncHooksSymbols[description] !== symbol) {
// process._rawDebug(
// `Found duplicate ${description}:`,
// symbol,
// Symbol[wellKnownName],
// asyncHooksSymbols[description],
// );
return false;
} else {
Expand All @@ -37,7 +40,7 @@ const findAsyncSymbolsFromAsyncResource = () => {
let found = 0;
Object.getOwnPropertySymbols(new AsyncResource('Bootstrap')).forEach(sym => {
const { description } = sym;
if (description in asyncHooksWellKnownNameFromDescription) {
if (description in asyncHooksSymbols) {
if (setAsyncSymbol(description, sym)) {
found += 1;
}
Expand Down Expand Up @@ -136,11 +139,11 @@ const getAsyncHookFallbackState = (promise, { create = false } = {}) => {
let state = promiseAsyncHookFallbackStates.get(promise);
if (!state && create) {
state = {
[Symbol.nodeAsyncHooksAsyncId]: undefined,
[Symbol.nodeAsyncHooksTriggerAsyncId]: undefined,
[asyncHooksSymbols.async_id_symbol]: undefined,
[asyncHooksSymbols.trigger_async_id_symbol]: undefined,
};
if (Symbol.nodeAsyncHooksDestroyed) {
state[Symbol.nodeAsyncHooksDestroyed] = undefined;
if (asyncHooksSymbols.destroyed) {
state[asyncHooksSymbols.destroyed] = undefined;
}
promiseAsyncHookFallbackStates.set(promise, state);
}
Expand Down Expand Up @@ -196,28 +199,33 @@ export const setup = ({ withDestroy = true } = {}) => {
findAsyncSymbolsFromAsyncResource();
}

if (!Symbol.nodeAsyncHooksAsyncId || !Symbol.nodeAsyncHooksTriggerAsyncId) {
if (
!asyncHooksSymbols.async_id_symbol ||
!asyncHooksSymbols.trigger_async_id_symbol
) {
// process._rawDebug(`Async symbols not found, moving on`);
return;
}

const PromiseProto = Promise.prototype;
Object.defineProperty(
PromiseProto,
Symbol.nodeAsyncHooksAsyncId,
getAsyncHookSymbolPromiseProtoDesc(Symbol.nodeAsyncHooksAsyncId),
asyncHooksSymbols.async_id_symbol,
getAsyncHookSymbolPromiseProtoDesc(asyncHooksSymbols.async_id_symbol),
);
Object.defineProperty(
PromiseProto,
Symbol.nodeAsyncHooksTriggerAsyncId,
getAsyncHookSymbolPromiseProtoDesc(Symbol.nodeAsyncHooksTriggerAsyncId),
asyncHooksSymbols.trigger_async_id_symbol,
getAsyncHookSymbolPromiseProtoDesc(
asyncHooksSymbols.trigger_async_id_symbol,
),
);

if (Symbol.nodeAsyncHooksDestroyed) {
if (asyncHooksSymbols.destroyed) {
Object.defineProperty(
PromiseProto,
Symbol.nodeAsyncHooksDestroyed,
getAsyncHookSymbolPromiseProtoDesc(Symbol.nodeAsyncHooksDestroyed, {
asyncHooksSymbols.destroyed,
getAsyncHookSymbolPromiseProtoDesc(asyncHooksSymbols.destroyed, {
disallowGet: true,
}),
);
Expand Down
8 changes: 4 additions & 4 deletions packages/init/test/test-async_hooks.js
Expand Up @@ -16,8 +16,8 @@ const gcP = (async () => {
})();

test('async_hooks Promise patch', async t => {
const hasSymbols =
Symbol.nodeAsyncHooksAsyncId && Symbol.nodeAsyncHooksTriggerAsyncId;
const hasAsyncSymbols =
Object.getOwnPropertySymbols(Promise.prototype).length > 1;
let resolve;
const q = (() => {
const p1 = new Promise(r => (resolve = r));
Expand Down Expand Up @@ -48,7 +48,7 @@ test('async_hooks Promise patch', async t => {

// Create a promise with symbols attached
const p3 = Promise.resolve();
t.is(Reflect.ownKeys(p3).length > 0, hasSymbols);
t.is(Reflect.ownKeys(p3).length > 0, hasAsyncSymbols);

return Promise.resolve().then(() => {
resolve(8);
Expand All @@ -60,7 +60,7 @@ test('async_hooks Promise patch', async t => {
// node versions will fail and generate a new one because of an own check
p1.then(() => {});

t.is(Reflect.ownKeys(ret).length > 0, hasSymbols);
t.is(Reflect.ownKeys(ret).length > 0, hasAsyncSymbols);

// testHooks.disable();

Expand Down
9 changes: 3 additions & 6 deletions packages/ses/src/whitelist.js
Expand Up @@ -504,9 +504,6 @@ export const whitelist = {
keyFor: fn,
match: 'symbol',
matchAll: 'symbol',
nodeAsyncHooksAsyncId: 'symbol',
nodeAsyncHooksTriggerAsyncId: 'symbol',
nodeAsyncHooksDestroyed: 'symbol',
prototype: '%SymbolPrototype%',
replace: 'symbol',
search: 'symbol',
Expand Down Expand Up @@ -1296,9 +1293,9 @@ export const whitelist = {
then: fn,
'@@toStringTag': 'string',
// Non-standard, used in node to prevent async_hooks from breaking
'@@nodeAsyncHooksAsyncId': accessor,
'@@nodeAsyncHooksTriggerAsyncId': accessor,
'@@nodeAsyncHooksDestroyed': accessor,
'UniqueSymbol(async_id_symbol)': accessor,
'UniqueSymbol(trigger_async_id_symbol)': accessor,
'UniqueSymbol(destroyed)': accessor,
},

'%InertAsyncFunction%': {
Expand Down

0 comments on commit 65c52e3

Please sign in to comment.