Skip to content

Instantly share code, notes, and snippets.

@bmeck
Created September 23, 2021 21:49
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save bmeck/58abdfe1e722c1f260cb11a6a86237b6 to your computer and use it in GitHub Desktop.
import util from 'util';
const promiseDebugging = util.debuglog('promises').enabled;
const danglingPromise = new FinalizationRegistry((stack) => {
danglingStacks.delete(stack);
console.log(stack);
});
const danglingStacks = new Set();
const stackCache = new WeakMap();
/**
* @template T
* @param {TemplateStringsArray} uniqLocation
* @param {Promise<T>} promise
* @returns {Promise<T>}
*/
function mustAwait(uniqLocation, promise) {
if (!promiseDebugging) return promise;
let stack = stackCache.get(uniqLocation);
if (!stack) {
stack = new Error('dangling promise').stack;
stackCache.set(uniqLocation, stack);
}
try {
danglingPromise.register(promise, stack);
danglingStacks.add(stack);
} catch {
return promise;
}
const proxy = new Proxy(promise, {
get(target, prop, receiver) {
if (prop === 'then' || prop === 'catch' || prop === 'finally') {
const real = Reflect.get(target, prop, receiver);
return function () {
let recv = this;
if (this === proxy) {
danglingPromise.unregister(promise);
danglingStacks.delete(stack);
recv = promise;
}
return Reflect.apply(real, recv, arguments);
};
} else {
console.log(new Error('attempted to do something prior to awaiting Promise').stack);
}
return Reflect.get(target, prop, receiver);
}
});
return proxy;
}
process.on('exit', () => {
for (const stack of danglingStacks) {
console.log(stack);
}
})
let one = Promise.resolve(1);
let tracker = mustAwait`${one}`;
let { x } = tracker;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment