@agoric/eventual-send
Advanced tools
Comparing version 0.3.3 to 0.4.0
@@ -115,4 +115,4 @@ 'use strict'; | ||
}, | ||
// TODO: Change HandledPromise.apply(target, args) to be | ||
// HandledPromise.applyMethod(target, undefined, args) | ||
// TODO: Change HandledPromise.apply to be | ||
// HandledPromise.applyFunction | ||
// to avoid conflict with constructor .apply behaviour. | ||
@@ -175,9 +175,9 @@ apply(target, args) { | ||
function handle(p, operation, ...args) { | ||
ensureMaps(); | ||
const unfulfilledHandler = promiseToHandler.get(p); | ||
let executor; | ||
if (unfulfilledHandler) { | ||
if (typeof unfulfilledHandler[operation] !== 'function') { | ||
throw TypeError(`unfulfilledHandler.${operation} is not a function`); | ||
} | ||
if ( | ||
unfulfilledHandler && | ||
typeof unfulfilledHandler[operation] === 'function' | ||
) { | ||
executor = (resolve, reject) => { | ||
@@ -269,2 +269,3 @@ // We run in a future turn to prevent synchronous attacks, | ||
let handledReject; | ||
let fulfilled = false; | ||
let continueForwarding = () => {}; | ||
@@ -283,4 +284,8 @@ const handledP = new Promise((resolve, reject) => { | ||
// local handled Promise. | ||
const interlockP = new Promise(resolve => { | ||
continueForwarding = (targetP = undefined) => { | ||
const interlockP = new Promise((resolve, reject) => { | ||
continueForwarding = (err = null, targetP = undefined) => { | ||
if (err !== null) { | ||
reject(err); | ||
return; | ||
} | ||
// Box the target promise so that it isn't further resolved. | ||
@@ -295,3 +300,3 @@ resolve([targetP]); | ||
return function postpone(x, ...args) { | ||
// console.log(`forwarding ${postponedOperation}`); | ||
// console.log(`forwarding ${postponedOperation} ${args[0]}`); | ||
return Promise.makeHandled((resolve, reject) => { | ||
@@ -328,66 +333,76 @@ interlockP | ||
function rejectHandled(reason) { | ||
continueForwarding(); | ||
if (fulfilled) { | ||
return; | ||
} | ||
fulfilled = true; | ||
handledReject(reason); | ||
continueForwarding(reason); | ||
} | ||
async function resolveHandled(target, fulfilledHandler) { | ||
let presence = null; | ||
function resolveWithPresence(presenceHandler) { | ||
if (fulfilled) { | ||
return presence; | ||
} | ||
fulfilled = true; | ||
try { | ||
// Sanity checks. | ||
if (fulfilledHandler) { | ||
validateHandler(fulfilledHandler); | ||
} | ||
validateHandler(presenceHandler); | ||
if (!fulfilledHandler) { | ||
// Resolve with the target when it's ready. | ||
handledResolve(target); | ||
// Validate and install our mapped target (i.e. presence). | ||
presence = Object.create(null); | ||
const existingUnfulfilledHandler = promiseToHandler.get(target); | ||
if (existingUnfulfilledHandler) { | ||
// Reuse the unfulfilled handler. | ||
promiseToHandler.set(handledP, existingUnfulfilledHandler); | ||
return continueForwarding(target); | ||
} | ||
// Create table entries for the presence mapped to the | ||
// fulfilledHandler. | ||
presenceToPromise.set(presence, handledP); | ||
presenceToHandler.set(presence, presenceHandler); | ||
// See if the target is a presence we already know of. | ||
const presence = await target; | ||
const existingFulfilledHandler = presenceToHandler.get(presence); | ||
if (existingFulfilledHandler) { | ||
promiseToHandler.set(handledP, existingFulfilledHandler); | ||
return continueForwarding(); | ||
} | ||
// Remove the mapping, as our presenceHandler should be | ||
// used instead. | ||
promiseToHandler.delete(handledP); | ||
// Remove the mapping, as we don't need a handler. | ||
promiseToHandler.delete(handledP); | ||
return continueForwarding(); | ||
} | ||
// We committed to this presence, so resolve. | ||
handledResolve(presence); | ||
continueForwarding(); | ||
return presence; | ||
} catch (e) { | ||
handledReject(e); | ||
continueForwarding(); | ||
throw e; | ||
} | ||
} | ||
// Validate and install our mapped target (i.e. presence). | ||
const presence = target; | ||
if (Object(presence) !== presence) { | ||
throw TypeError(`Presence ${presence} cannot be a primitive`); | ||
} | ||
if (presence === null) { | ||
throw TypeError(`Presence ${presence} cannot be null`); | ||
} | ||
if (presence && typeof presence.then === 'function') { | ||
async function resolveHandled(target, deprecatedPresenceHandler) { | ||
if (fulfilled) { | ||
return undefined; | ||
} | ||
fulfilled = true; | ||
try { | ||
if (deprecatedPresenceHandler) { | ||
throw TypeError( | ||
`Presence ${presence} cannot be a Promise or other thenable`, | ||
`resolveHandled no longer accepts a handler; use resolveWithPresence`, | ||
); | ||
} | ||
// Just like platform Promises, multiple calls to resolve | ||
// don't fail. | ||
if (!presenceToHandler.has(presence)) { | ||
// Create table entries for the presence mapped to the | ||
// fulfilledHandler. | ||
presenceToPromise.set(presence, handledP); | ||
presenceToHandler.set(presence, fulfilledHandler); | ||
// Resolve with the target when it's ready. | ||
handledResolve(target); | ||
const existingUnfulfilledHandler = promiseToHandler.get(target); | ||
if (existingUnfulfilledHandler) { | ||
// Reuse the unfulfilled handler. | ||
promiseToHandler.set(handledP, existingUnfulfilledHandler); | ||
return continueForwarding(null, target); | ||
} | ||
// Remove the mapping, as our fulfilledHandler should be | ||
// used instead. | ||
// See if the target is a presence we already know of. | ||
const presence = await target; | ||
const existingPresenceHandler = presenceToHandler.get(presence); | ||
if (existingPresenceHandler) { | ||
promiseToHandler.set(handledP, existingPresenceHandler); | ||
return continueForwarding(null, handledP); | ||
} | ||
// Remove the mapping, as we don't need a handler. | ||
promiseToHandler.delete(handledP); | ||
// We committed to this presence, so resolve. | ||
handledResolve(presence); | ||
return continueForwarding(); | ||
} catch (e) { | ||
@@ -400,5 +415,9 @@ handledReject(e); | ||
// Invoke the callback to let the user resolve/reject. | ||
executor((...args) => { | ||
resolveHandled(...args); | ||
}, rejectHandled); | ||
executor( | ||
(...args) => { | ||
resolveHandled(...args); | ||
}, | ||
rejectHandled, | ||
resolveWithPresence, | ||
); | ||
@@ -416,7 +435,7 @@ // Return a handled Promise, which wil be resolved/rejected | ||
const fulfilledHandler = presenceToHandler.get(o); | ||
if (fulfilledHandler) { | ||
if ( | ||
fulfilledHandler && | ||
typeof fulfilledHandler[operation] === 'function' | ||
) { | ||
// The handler was resolved, so use it. | ||
if (typeof fulfilledHandler[operation] !== 'function') { | ||
throw TypeError(`fulfilledHandler.${operation} is not a function`); | ||
} | ||
return fulfilledHandler[operation](o, ...args); | ||
@@ -438,2 +457,3 @@ } | ||
} | ||
// console.log(`sending`, optKey, o[optKey], o); | ||
return o[optKey](...args); | ||
@@ -440,0 +460,0 @@ }), |
@@ -111,4 +111,4 @@ /* global globalThis window */ | ||
}, | ||
// TODO: Change HandledPromise.apply(target, args) to be | ||
// HandledPromise.applyMethod(target, undefined, args) | ||
// TODO: Change HandledPromise.apply to be | ||
// HandledPromise.applyFunction | ||
// to avoid conflict with constructor .apply behaviour. | ||
@@ -171,9 +171,9 @@ apply(target, args) { | ||
function handle(p, operation, ...args) { | ||
ensureMaps(); | ||
const unfulfilledHandler = promiseToHandler.get(p); | ||
let executor; | ||
if (unfulfilledHandler) { | ||
if (typeof unfulfilledHandler[operation] !== 'function') { | ||
throw TypeError(`unfulfilledHandler.${operation} is not a function`); | ||
} | ||
if ( | ||
unfulfilledHandler && | ||
typeof unfulfilledHandler[operation] === 'function' | ||
) { | ||
executor = (resolve, reject) => { | ||
@@ -265,2 +265,3 @@ // We run in a future turn to prevent synchronous attacks, | ||
let handledReject; | ||
let fulfilled = false; | ||
let continueForwarding = () => {}; | ||
@@ -279,4 +280,8 @@ const handledP = new Promise((resolve, reject) => { | ||
// local handled Promise. | ||
const interlockP = new Promise(resolve => { | ||
continueForwarding = (targetP = undefined) => { | ||
const interlockP = new Promise((resolve, reject) => { | ||
continueForwarding = (err = null, targetP = undefined) => { | ||
if (err !== null) { | ||
reject(err); | ||
return; | ||
} | ||
// Box the target promise so that it isn't further resolved. | ||
@@ -291,3 +296,3 @@ resolve([targetP]); | ||
return function postpone(x, ...args) { | ||
// console.log(`forwarding ${postponedOperation}`); | ||
// console.log(`forwarding ${postponedOperation} ${args[0]}`); | ||
return Promise.makeHandled((resolve, reject) => { | ||
@@ -324,66 +329,76 @@ interlockP | ||
function rejectHandled(reason) { | ||
continueForwarding(); | ||
if (fulfilled) { | ||
return; | ||
} | ||
fulfilled = true; | ||
handledReject(reason); | ||
continueForwarding(reason); | ||
} | ||
async function resolveHandled(target, fulfilledHandler) { | ||
let presence = null; | ||
function resolveWithPresence(presenceHandler) { | ||
if (fulfilled) { | ||
return presence; | ||
} | ||
fulfilled = true; | ||
try { | ||
// Sanity checks. | ||
if (fulfilledHandler) { | ||
validateHandler(fulfilledHandler); | ||
} | ||
validateHandler(presenceHandler); | ||
if (!fulfilledHandler) { | ||
// Resolve with the target when it's ready. | ||
handledResolve(target); | ||
// Validate and install our mapped target (i.e. presence). | ||
presence = Object.create(null); | ||
const existingUnfulfilledHandler = promiseToHandler.get(target); | ||
if (existingUnfulfilledHandler) { | ||
// Reuse the unfulfilled handler. | ||
promiseToHandler.set(handledP, existingUnfulfilledHandler); | ||
return continueForwarding(target); | ||
} | ||
// Create table entries for the presence mapped to the | ||
// fulfilledHandler. | ||
presenceToPromise.set(presence, handledP); | ||
presenceToHandler.set(presence, presenceHandler); | ||
// See if the target is a presence we already know of. | ||
const presence = await target; | ||
const existingFulfilledHandler = presenceToHandler.get(presence); | ||
if (existingFulfilledHandler) { | ||
promiseToHandler.set(handledP, existingFulfilledHandler); | ||
return continueForwarding(); | ||
} | ||
// Remove the mapping, as our presenceHandler should be | ||
// used instead. | ||
promiseToHandler.delete(handledP); | ||
// Remove the mapping, as we don't need a handler. | ||
promiseToHandler.delete(handledP); | ||
return continueForwarding(); | ||
} | ||
// We committed to this presence, so resolve. | ||
handledResolve(presence); | ||
continueForwarding(); | ||
return presence; | ||
} catch (e) { | ||
handledReject(e); | ||
continueForwarding(); | ||
throw e; | ||
} | ||
} | ||
// Validate and install our mapped target (i.e. presence). | ||
const presence = target; | ||
if (Object(presence) !== presence) { | ||
throw TypeError(`Presence ${presence} cannot be a primitive`); | ||
} | ||
if (presence === null) { | ||
throw TypeError(`Presence ${presence} cannot be null`); | ||
} | ||
if (presence && typeof presence.then === 'function') { | ||
async function resolveHandled(target, deprecatedPresenceHandler) { | ||
if (fulfilled) { | ||
return undefined; | ||
} | ||
fulfilled = true; | ||
try { | ||
if (deprecatedPresenceHandler) { | ||
throw TypeError( | ||
`Presence ${presence} cannot be a Promise or other thenable`, | ||
`resolveHandled no longer accepts a handler; use resolveWithPresence`, | ||
); | ||
} | ||
// Just like platform Promises, multiple calls to resolve | ||
// don't fail. | ||
if (!presenceToHandler.has(presence)) { | ||
// Create table entries for the presence mapped to the | ||
// fulfilledHandler. | ||
presenceToPromise.set(presence, handledP); | ||
presenceToHandler.set(presence, fulfilledHandler); | ||
// Resolve with the target when it's ready. | ||
handledResolve(target); | ||
const existingUnfulfilledHandler = promiseToHandler.get(target); | ||
if (existingUnfulfilledHandler) { | ||
// Reuse the unfulfilled handler. | ||
promiseToHandler.set(handledP, existingUnfulfilledHandler); | ||
return continueForwarding(null, target); | ||
} | ||
// Remove the mapping, as our fulfilledHandler should be | ||
// used instead. | ||
// See if the target is a presence we already know of. | ||
const presence = await target; | ||
const existingPresenceHandler = presenceToHandler.get(presence); | ||
if (existingPresenceHandler) { | ||
promiseToHandler.set(handledP, existingPresenceHandler); | ||
return continueForwarding(null, handledP); | ||
} | ||
// Remove the mapping, as we don't need a handler. | ||
promiseToHandler.delete(handledP); | ||
// We committed to this presence, so resolve. | ||
handledResolve(presence); | ||
return continueForwarding(); | ||
} catch (e) { | ||
@@ -396,5 +411,9 @@ handledReject(e); | ||
// Invoke the callback to let the user resolve/reject. | ||
executor((...args) => { | ||
resolveHandled(...args); | ||
}, rejectHandled); | ||
executor( | ||
(...args) => { | ||
resolveHandled(...args); | ||
}, | ||
rejectHandled, | ||
resolveWithPresence, | ||
); | ||
@@ -412,7 +431,7 @@ // Return a handled Promise, which wil be resolved/rejected | ||
const fulfilledHandler = presenceToHandler.get(o); | ||
if (fulfilledHandler) { | ||
if ( | ||
fulfilledHandler && | ||
typeof fulfilledHandler[operation] === 'function' | ||
) { | ||
// The handler was resolved, so use it. | ||
if (typeof fulfilledHandler[operation] !== 'function') { | ||
throw TypeError(`fulfilledHandler.${operation} is not a function`); | ||
} | ||
return fulfilledHandler[operation](o, ...args); | ||
@@ -434,2 +453,3 @@ } | ||
} | ||
// console.log(`sending`, optKey, o[optKey], o); | ||
return o[optKey](...args); | ||
@@ -436,0 +456,0 @@ }), |
@@ -117,4 +117,4 @@ (function (global, factory) { | ||
}, | ||
// TODO: Change HandledPromise.apply(target, args) to be | ||
// HandledPromise.applyMethod(target, undefined, args) | ||
// TODO: Change HandledPromise.apply to be | ||
// HandledPromise.applyFunction | ||
// to avoid conflict with constructor .apply behaviour. | ||
@@ -177,9 +177,9 @@ apply(target, args) { | ||
function handle(p, operation, ...args) { | ||
ensureMaps(); | ||
const unfulfilledHandler = promiseToHandler.get(p); | ||
let executor; | ||
if (unfulfilledHandler) { | ||
if (typeof unfulfilledHandler[operation] !== 'function') { | ||
throw TypeError(`unfulfilledHandler.${operation} is not a function`); | ||
} | ||
if ( | ||
unfulfilledHandler && | ||
typeof unfulfilledHandler[operation] === 'function' | ||
) { | ||
executor = (resolve, reject) => { | ||
@@ -271,2 +271,3 @@ // We run in a future turn to prevent synchronous attacks, | ||
let handledReject; | ||
let fulfilled = false; | ||
let continueForwarding = () => {}; | ||
@@ -285,4 +286,8 @@ const handledP = new Promise((resolve, reject) => { | ||
// local handled Promise. | ||
const interlockP = new Promise(resolve => { | ||
continueForwarding = (targetP = undefined) => { | ||
const interlockP = new Promise((resolve, reject) => { | ||
continueForwarding = (err = null, targetP = undefined) => { | ||
if (err !== null) { | ||
reject(err); | ||
return; | ||
} | ||
// Box the target promise so that it isn't further resolved. | ||
@@ -297,3 +302,3 @@ resolve([targetP]); | ||
return function postpone(x, ...args) { | ||
// console.log(`forwarding ${postponedOperation}`); | ||
// console.log(`forwarding ${postponedOperation} ${args[0]}`); | ||
return Promise.makeHandled((resolve, reject) => { | ||
@@ -330,66 +335,76 @@ interlockP | ||
function rejectHandled(reason) { | ||
continueForwarding(); | ||
if (fulfilled) { | ||
return; | ||
} | ||
fulfilled = true; | ||
handledReject(reason); | ||
continueForwarding(reason); | ||
} | ||
async function resolveHandled(target, fulfilledHandler) { | ||
let presence = null; | ||
function resolveWithPresence(presenceHandler) { | ||
if (fulfilled) { | ||
return presence; | ||
} | ||
fulfilled = true; | ||
try { | ||
// Sanity checks. | ||
if (fulfilledHandler) { | ||
validateHandler(fulfilledHandler); | ||
} | ||
validateHandler(presenceHandler); | ||
if (!fulfilledHandler) { | ||
// Resolve with the target when it's ready. | ||
handledResolve(target); | ||
// Validate and install our mapped target (i.e. presence). | ||
presence = Object.create(null); | ||
const existingUnfulfilledHandler = promiseToHandler.get(target); | ||
if (existingUnfulfilledHandler) { | ||
// Reuse the unfulfilled handler. | ||
promiseToHandler.set(handledP, existingUnfulfilledHandler); | ||
return continueForwarding(target); | ||
} | ||
// Create table entries for the presence mapped to the | ||
// fulfilledHandler. | ||
presenceToPromise.set(presence, handledP); | ||
presenceToHandler.set(presence, presenceHandler); | ||
// See if the target is a presence we already know of. | ||
const presence = await target; | ||
const existingFulfilledHandler = presenceToHandler.get(presence); | ||
if (existingFulfilledHandler) { | ||
promiseToHandler.set(handledP, existingFulfilledHandler); | ||
return continueForwarding(); | ||
} | ||
// Remove the mapping, as our presenceHandler should be | ||
// used instead. | ||
promiseToHandler.delete(handledP); | ||
// Remove the mapping, as we don't need a handler. | ||
promiseToHandler.delete(handledP); | ||
return continueForwarding(); | ||
} | ||
// We committed to this presence, so resolve. | ||
handledResolve(presence); | ||
continueForwarding(); | ||
return presence; | ||
} catch (e) { | ||
handledReject(e); | ||
continueForwarding(); | ||
throw e; | ||
} | ||
} | ||
// Validate and install our mapped target (i.e. presence). | ||
const presence = target; | ||
if (Object(presence) !== presence) { | ||
throw TypeError(`Presence ${presence} cannot be a primitive`); | ||
} | ||
if (presence === null) { | ||
throw TypeError(`Presence ${presence} cannot be null`); | ||
} | ||
if (presence && typeof presence.then === 'function') { | ||
async function resolveHandled(target, deprecatedPresenceHandler) { | ||
if (fulfilled) { | ||
return undefined; | ||
} | ||
fulfilled = true; | ||
try { | ||
if (deprecatedPresenceHandler) { | ||
throw TypeError( | ||
`Presence ${presence} cannot be a Promise or other thenable`, | ||
`resolveHandled no longer accepts a handler; use resolveWithPresence`, | ||
); | ||
} | ||
// Just like platform Promises, multiple calls to resolve | ||
// don't fail. | ||
if (!presenceToHandler.has(presence)) { | ||
// Create table entries for the presence mapped to the | ||
// fulfilledHandler. | ||
presenceToPromise.set(presence, handledP); | ||
presenceToHandler.set(presence, fulfilledHandler); | ||
// Resolve with the target when it's ready. | ||
handledResolve(target); | ||
const existingUnfulfilledHandler = promiseToHandler.get(target); | ||
if (existingUnfulfilledHandler) { | ||
// Reuse the unfulfilled handler. | ||
promiseToHandler.set(handledP, existingUnfulfilledHandler); | ||
return continueForwarding(null, target); | ||
} | ||
// Remove the mapping, as our fulfilledHandler should be | ||
// used instead. | ||
// See if the target is a presence we already know of. | ||
const presence = await target; | ||
const existingPresenceHandler = presenceToHandler.get(presence); | ||
if (existingPresenceHandler) { | ||
promiseToHandler.set(handledP, existingPresenceHandler); | ||
return continueForwarding(null, handledP); | ||
} | ||
// Remove the mapping, as we don't need a handler. | ||
promiseToHandler.delete(handledP); | ||
// We committed to this presence, so resolve. | ||
handledResolve(presence); | ||
return continueForwarding(); | ||
} catch (e) { | ||
@@ -402,5 +417,9 @@ handledReject(e); | ||
// Invoke the callback to let the user resolve/reject. | ||
executor((...args) => { | ||
resolveHandled(...args); | ||
}, rejectHandled); | ||
executor( | ||
(...args) => { | ||
resolveHandled(...args); | ||
}, | ||
rejectHandled, | ||
resolveWithPresence, | ||
); | ||
@@ -418,7 +437,7 @@ // Return a handled Promise, which wil be resolved/rejected | ||
const fulfilledHandler = presenceToHandler.get(o); | ||
if (fulfilledHandler) { | ||
if ( | ||
fulfilledHandler && | ||
typeof fulfilledHandler[operation] === 'function' | ||
) { | ||
// The handler was resolved, so use it. | ||
if (typeof fulfilledHandler[operation] !== 'function') { | ||
throw TypeError(`fulfilledHandler.${operation} is not a function`); | ||
} | ||
return fulfilledHandler[operation](o, ...args); | ||
@@ -440,2 +459,3 @@ } | ||
} | ||
// console.log(`sending`, optKey, o[optKey], o); | ||
return o[optKey](...args); | ||
@@ -442,0 +462,0 @@ }), |
{ | ||
"name": "@agoric/eventual-send", | ||
"version": "0.3.3", | ||
"version": "0.4.0", | ||
"description": "Extend a Promise class to implement the eventual-send API", | ||
@@ -5,0 +5,0 @@ "main": "dist/eventual-send.cjs.js", |
@@ -42,4 +42,5 @@ // Type definitions for eventual-send | ||
type HandledExecutor<R> = ( | ||
resolveHandled: (value?: R, resolvedHandler?: EHandler) => void, | ||
resolveHandled: (value?: R) => void, | ||
rejectHandled: (reason?: unknown) => void, | ||
resolveWithPresence: (presenceHandler: EHandler) => object, | ||
) => void; | ||
@@ -49,3 +50,3 @@ | ||
prototype: EPromise<unknown>; | ||
makeHandled<R>(executor: HandledExecutor<R>, unresolvedHandler?: EHandler): EPromise<R>; | ||
makeHandled<R>(executor: HandledExecutor<R>, unfulfilledHandler?: EHandler): EPromise<R>; | ||
resolve<R>(value: R): EPromise<R>; | ||
@@ -52,0 +53,0 @@ reject(reason: unknown): EPromise<never>; |
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
60940
1270