@endo/eventual-send
Advanced tools
Comparing version 0.16.0 to 0.16.1
@@ -6,2 +6,16 @@ # Change Log | ||
### [0.16.1](https://github.com/endojs/endo/compare/@endo/eventual-send@0.16.0...@endo/eventual-send@0.16.1) (2022-08-25) | ||
### Features | ||
* **eventual-send:** Feature-flag track-turns ([e07019e](https://github.com/endojs/endo/commit/e07019e3c312391da26fbe6cce6a875484302288)) | ||
### Bug Fixes | ||
* **eventual-send:** hoist closures to discourage argument retention ([7786d4c](https://github.com/endojs/endo/commit/7786d4c201cfc5e5fbd27cd456d45597c25284a2)), closes [#1245](https://github.com/endojs/endo/issues/1245) | ||
## [0.16.0](https://github.com/endojs/endo/compare/@endo/eventual-send@0.15.5...@endo/eventual-send@0.16.0) (2022-08-23) | ||
@@ -8,0 +22,0 @@ |
{ | ||
"name": "@endo/eventual-send", | ||
"version": "0.16.0", | ||
"version": "0.16.1", | ||
"description": "Extend a Promise class to implement the eventual-send API", | ||
@@ -30,4 +30,4 @@ "type": "module", | ||
"devDependencies": { | ||
"@endo/lockdown": "^0.1.16", | ||
"@endo/ses-ava": "^0.2.28", | ||
"@endo/lockdown": "^0.1.17", | ||
"@endo/ses-ava": "^0.2.29", | ||
"ava": "^3.12.1", | ||
@@ -66,3 +66,3 @@ "c8": "^7.7.3", | ||
}, | ||
"gitHead": "7dc29059b201826295cbf2deb28bb2ed70f5ec1f" | ||
"gitHead": "3f129c5d6e1bde4fd5fe399c24a6205e660a4aad" | ||
} |
@@ -18,5 +18,57 @@ /* global globalThis */ | ||
// TODO Use environment-options.js currently in ses/src after factoring it out | ||
// to a new package. | ||
const env = globalThis?.process?.env; | ||
// Turn on if you seem to be losing error logging at the top of the event loop | ||
const VERBOSE = false; | ||
const VERBOSE = (env?.DEBUG ?? '').split(':').includes('track-turns'); | ||
// Track-turns is disabled by default and can be enabled by an environment | ||
// option. We intend to change the default after verifying that having | ||
// the feature enabled in production does not cause memory to leak. | ||
const ENABLED = env?.TRACK_TURNS === 'enabled'; | ||
// We hoist these functions out of trackTurns() to discourage the | ||
// closures from holding onto 'args' or 'func' longer than necessary, | ||
// which we've seen cause HandledPromise arguments to be retained for | ||
// a surprisingly long time. | ||
const addRejectionNote = detailsNote => reason => { | ||
if (reason instanceof Error) { | ||
assert.note(reason, detailsNote); | ||
} | ||
if (VERBOSE) { | ||
console.log('REJECTED at top of event loop', reason); | ||
} | ||
}; | ||
const wrapFunction = (func, sendingError, X) => (...args) => { | ||
hiddenPriorError = sendingError; | ||
hiddenCurrentTurn += 1; | ||
hiddenCurrentEvent = 0; | ||
try { | ||
let result; | ||
try { | ||
result = func(...args); | ||
} catch (err) { | ||
if (err instanceof Error) { | ||
assert.note( | ||
err, | ||
X`Thrown from: ${hiddenPriorError}:${hiddenCurrentTurn}.${hiddenCurrentEvent}`, | ||
); | ||
} | ||
if (VERBOSE) { | ||
console.log('THROWN to top of event loop', err); | ||
} | ||
throw err; | ||
} | ||
// Must capture this now, not when the catch triggers. | ||
const detailsNote = X`Rejection from: ${hiddenPriorError}:${hiddenCurrentTurn}.${hiddenCurrentEvent}`; | ||
Promise.resolve(result).catch(addRejectionNote(detailsNote)); | ||
return harden(result); | ||
} finally { | ||
hiddenPriorError = undefined; | ||
} | ||
}; | ||
/** | ||
@@ -44,3 +96,3 @@ * @typedef {((...args: any[]) => any) | undefined} TurnStarterFn | ||
export const trackTurns = funcs => { | ||
if (typeof globalThis === 'undefined' || !globalThis.assert) { | ||
if (!ENABLED || typeof globalThis === 'undefined' || !globalThis.assert) { | ||
return funcs; | ||
@@ -58,41 +110,3 @@ } | ||
return funcs.map( | ||
func => | ||
func && | ||
((...args) => { | ||
hiddenPriorError = sendingError; | ||
hiddenCurrentTurn += 1; | ||
hiddenCurrentEvent = 0; | ||
try { | ||
let result; | ||
try { | ||
result = func(...args); | ||
} catch (err) { | ||
if (err instanceof Error) { | ||
assert.note( | ||
err, | ||
X`Thrown from: ${hiddenPriorError}:${hiddenCurrentTurn}.${hiddenCurrentEvent}`, | ||
); | ||
} | ||
if (VERBOSE) { | ||
console.log('THROWN to top of event loop', err); | ||
} | ||
throw err; | ||
} | ||
// Must capture this now, not when the catch triggers. | ||
const detailsNote = X`Rejection from: ${hiddenPriorError}:${hiddenCurrentTurn}.${hiddenCurrentEvent}`; | ||
Promise.resolve(result).catch(reason => { | ||
if (reason instanceof Error) { | ||
assert.note(reason, detailsNote); | ||
} | ||
if (VERBOSE) { | ||
console.log('REJECTED at top of event loop', reason); | ||
} | ||
}); | ||
return harden(result); | ||
} finally { | ||
hiddenPriorError = undefined; | ||
} | ||
}), | ||
); | ||
return funcs.map(func => func && wrapFunction(func, sendingError, X)); | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
86085
1221