@agoric/captp
Advanced tools
Comparing version 1.3.3 to 1.4.0
@@ -6,2 +6,25 @@ # Change Log | ||
# [1.4.0](https://github.com/Agoric/agoric-sdk/compare/@agoric/captp@1.3.3...@agoric/captp@1.4.0) (2020-08-31) | ||
### Bug Fixes | ||
* don't delete the questionID too soon ([1e51cef](https://github.com/Agoric/agoric-sdk/commit/1e51cef98cdf9e4267b92378c6bf6d0e3fdecf85)) | ||
* properly abort all communication when CapTP is disconnected ([c2c0196](https://github.com/Agoric/agoric-sdk/commit/c2c0196001c2bc94d14645272b931e39ee38c197)) | ||
* reduce inconsistency among our linting rules ([#1492](https://github.com/Agoric/agoric-sdk/issues/1492)) ([b6b675e](https://github.com/Agoric/agoric-sdk/commit/b6b675e2de110e2af19cad784a66220cab21dacf)) | ||
* rename producePromise to makePromiseKit ([#1329](https://github.com/Agoric/agoric-sdk/issues/1329)) ([1d2925a](https://github.com/Agoric/agoric-sdk/commit/1d2925ad640cce7b419751027b44737bd46a6d59)) | ||
* send and receive Remotable tags ([#1628](https://github.com/Agoric/agoric-sdk/issues/1628)) ([1bae122](https://github.com/Agoric/agoric-sdk/commit/1bae1220c2c35f48f279cb3aeab6012bce8ddb5a)) | ||
* shuffle around exports ([c95282e](https://github.com/Agoric/agoric-sdk/commit/c95282ec5b72260353441ec8dd2ad0eaba9cdfa8)) | ||
* supply default disconnected abort exception ([274ed53](https://github.com/Agoric/agoric-sdk/commit/274ed53fb99c0fb135b8beae984e3f0b731dbb81)) | ||
* **captp:** make more code paths fail on disconnect ([5c0c509](https://github.com/Agoric/agoric-sdk/commit/5c0c5097acd4dacf2b594d84606d0494d71f0216)) | ||
### Features | ||
* **captp:** allow onReject handler to avoid unhandled promise ([f76c804](https://github.com/Agoric/agoric-sdk/commit/f76c804bb47ad8be71a9c512800c8b864edd7e6a)) | ||
## [1.3.3](https://github.com/Agoric/agoric-sdk/compare/@agoric/captp@1.3.2...@agoric/captp@1.3.3) (2020-06-30) | ||
@@ -8,0 +31,0 @@ |
138
lib/captp.js
@@ -0,14 +1,40 @@ | ||
/* global harden HandledPromise */ | ||
// Your app may need to `import '@agoric/eventual-send/shim'` to get HandledPromise | ||
// This logic was mostly lifted from @agoric/swingset-vat liveSlots.js | ||
// Defects in it are mfig's fault. | ||
import { Remotable, makeMarshal, QCLASS } from '@agoric/marshal'; | ||
import harden from '@agoric/harden'; | ||
import Nat from '@agoric/nat'; | ||
import { HandledPromise, E } from '@agoric/eventual-send'; | ||
import { isPromise } from '@agoric/produce-promise'; | ||
import { E } from '@agoric/eventual-send'; | ||
import { isPromise } from '@agoric/promise-kit'; | ||
export { E, HandledPromise, Nat, harden }; | ||
export { E }; | ||
export function makeCapTP(ourId, send, bootstrapObj = undefined) { | ||
export function makeCapTP(ourId, rawSend, bootstrapObj = undefined, opts = {}) { | ||
const { | ||
onReject = err => console.error('CapTP', ourId, 'exception:', err), | ||
} = opts; | ||
let unplug = false; | ||
async function quietReject(reason = undefined, returnIt = true) { | ||
if (onReject && (unplug === false || reason !== unplug)) { | ||
onReject(reason); | ||
} | ||
if (!returnIt) { | ||
return Promise.resolve(); | ||
} | ||
// Silence the unhandled rejection warning, but don't affect | ||
// the user's handlers. | ||
const p = Promise.reject(reason); | ||
p.catch(_ => {}); | ||
return p; | ||
} | ||
function send(...args) { | ||
// Don't throw here if unplugged, just don't send. | ||
if (unplug === false) { | ||
rawSend(...args); | ||
} | ||
} | ||
// convertValToSlot and convertSlotToVal both perform side effects, | ||
@@ -98,3 +124,3 @@ // populating the c-lists (imports/exports/questions/answers) upon | ||
// eslint-disable-next-line no-use-before-define | ||
const pr = makeRemote(questionID); | ||
const pr = makeRemoteKit(questionID); | ||
questions.set(questionID, pr); | ||
@@ -105,3 +131,3 @@ return [questionID, pr]; | ||
// Make a remote promise for `target` (an id in the questions table) | ||
function makeRemote(target) { | ||
function makeRemoteKit(target) { | ||
// This handler is set up such that it will transform both | ||
@@ -112,2 +138,5 @@ // attribute access and method invocation of this remote promise | ||
get(_o, prop) { | ||
if (unplug !== false) { | ||
return quietReject(unplug); | ||
} | ||
const [questionID, pr] = makeQuestion(); | ||
@@ -123,2 +152,5 @@ send({ | ||
applyMethod(_o, prop, args) { | ||
if (unplug !== false) { | ||
return quietReject(unplug); | ||
} | ||
// Support: o~.[prop](...args) remote method invocation | ||
@@ -142,2 +174,7 @@ const [questionID, pr] = makeQuestion(); | ||
}, handler); | ||
// Silence the unhandled rejection warning, but don't affect | ||
// the user's handlers. | ||
pr.p.catch(e => quietReject(e, false)); | ||
return harden(pr); | ||
@@ -147,3 +184,3 @@ } | ||
// Set up import | ||
function convertSlotToVal(theirSlot) { | ||
function convertSlotToVal(theirSlot, iface = undefined) { | ||
let val; | ||
@@ -161,7 +198,10 @@ // Invert slot direction from other side. | ||
// Make a new handled promise for the slot. | ||
const pr = makeRemote(slot); | ||
const pr = makeRemoteKit(slot); | ||
if (slot[0] === 'o') { | ||
// A new remote presence | ||
const pres = pr.resPres(); | ||
val = Remotable(`Presence ${ourId} ${slot}`, undefined, pres); | ||
if (iface === undefined) { | ||
iface = `Alleged: Presence ${ourId} ${slot}`; | ||
} | ||
val = Remotable(iface, undefined, pres); | ||
} else { | ||
@@ -181,3 +221,3 @@ // A new promise | ||
// Remote is asking for bootstrap object | ||
CTP_BOOTSTRAP(obj) { | ||
async CTP_BOOTSTRAP(obj) { | ||
const { questionID } = obj; | ||
@@ -188,3 +228,3 @@ const bootstrap = | ||
answers.set(questionID, bootstrap); | ||
send({ | ||
return send({ | ||
type: 'CTP_RETURN', | ||
@@ -196,3 +236,3 @@ answerID: questionID, | ||
// Remote is invoking a method or retrieving a property. | ||
CTP_CALL(obj) { | ||
async CTP_CALL(obj) { | ||
// questionId: Remote promise (for promise pipelining) this call is | ||
@@ -225,18 +265,20 @@ // to fulfill | ||
// message to other vat when fulfilled/broken. | ||
hp.then(res => | ||
send({ | ||
type: 'CTP_RETURN', | ||
answerID: questionID, | ||
result: serialize(harden(res)), | ||
}), | ||
).catch(rej => | ||
send({ | ||
type: 'CTP_RETURN', | ||
answerID: questionID, | ||
exception: serialize(harden(rej)), | ||
}), | ||
); | ||
return hp | ||
.then(res => | ||
send({ | ||
type: 'CTP_RETURN', | ||
answerID: questionID, | ||
result: serialize(harden(res)), | ||
}), | ||
) | ||
.catch(rej => | ||
send({ | ||
type: 'CTP_RETURN', | ||
answerID: questionID, | ||
exception: serialize(harden(rej)), | ||
}), | ||
); | ||
}, | ||
// Answer to one of our questions. | ||
CTP_RETURN(obj) { | ||
async CTP_RETURN(obj) { | ||
const { result, exception, answerID } = obj; | ||
@@ -249,6 +291,5 @@ const pr = questions.get(answerID); | ||
} | ||
questions.delete(answerID); | ||
}, | ||
// Resolution to an imported promise | ||
CTP_RESOLVE(obj) { | ||
async CTP_RESOLVE(obj) { | ||
const { promiseID, res, rej } = obj; | ||
@@ -265,5 +306,9 @@ const pr = imports.get(promiseID); | ||
// Pull the plug! | ||
CTP_ABORT(obj) { | ||
async CTP_ABORT(obj) { | ||
const { exception } = obj; | ||
unplug = true; | ||
send(obj); | ||
if (unplug === false) { | ||
quietReject(exception, false); | ||
unplug = exception; | ||
} | ||
for (const pr of questions.values()) { | ||
@@ -275,3 +320,2 @@ pr.rej(exception); | ||
} | ||
send(obj); | ||
}, | ||
@@ -281,3 +325,6 @@ }; | ||
// Get a reference to the other side's bootstrap object. | ||
const getBootstrap = () => { | ||
const getBootstrap = async () => { | ||
if (unplug !== false) { | ||
return quietReject(unplug); | ||
} | ||
const [questionID, pr] = makeQuestion(); | ||
@@ -294,17 +341,24 @@ send({ | ||
const dispatch = obj => { | ||
if (unplug) { | ||
try { | ||
if (unplug !== false) { | ||
return false; | ||
} | ||
const fn = handler[obj.type]; | ||
if (fn) { | ||
fn(obj).catch(e => quietReject(e, false)); | ||
return true; | ||
} | ||
return false; | ||
} catch (e) { | ||
quietReject(e, false); | ||
return false; | ||
} | ||
const fn = handler[obj.type]; | ||
if (fn) { | ||
fn(obj); | ||
return true; | ||
} | ||
return false; | ||
}; | ||
// Abort a connection. | ||
const abort = exception => dispatch({ type: 'CTP_ABORT', exception }); | ||
const abort = ( | ||
exception = Error(`disconnected from ${JSON.stringify(ourId)}`), | ||
) => dispatch({ type: 'CTP_ABORT', exception }); | ||
return harden({ abort, dispatch, getBootstrap }); | ||
} |
{ | ||
"name": "@agoric/captp", | ||
"version": "1.3.3", | ||
"version": "1.4.0", | ||
"description": "Capability Transfer Protocol for distributed objects", | ||
@@ -28,5 +28,5 @@ "keywords": [ | ||
"build": "exit 0", | ||
"test": "tape -r esm 'test/**/*.js'", | ||
"test": "ava", | ||
"lint-fix": "eslint --fix '**/*.js'", | ||
"lint-check": "eslint '**/*.js'", | ||
"lint-check": "eslint 'lib/*.js'", | ||
"lint-fix-jessie": "eslint -c '.eslintrc-jessie.js' --fix '**/*.js'", | ||
@@ -36,12 +36,10 @@ "lint-check-jessie": "eslint -c '.eslintrc-jessie.js' '**/*.js'" | ||
"devDependencies": { | ||
"tap-spec": "^5.0.0", | ||
"tape": "^4.11.0", | ||
"tape-promise": "^4.0.0" | ||
"@agoric/install-ses": "^0.3.0", | ||
"ava": "^3.11.1" | ||
}, | ||
"dependencies": { | ||
"@agoric/eventual-send": "^0.9.3", | ||
"@agoric/harden": "^0.0.8", | ||
"@agoric/marshal": "^0.2.3", | ||
"@agoric/eventual-send": "^0.10.0", | ||
"@agoric/marshal": "^0.2.4", | ||
"@agoric/nat": "^2.0.1", | ||
"@agoric/produce-promise": "^0.1.3", | ||
"@agoric/promise-kit": "^0.1.4", | ||
"esm": "^3.2.5" | ||
@@ -55,3 +53,11 @@ }, | ||
}, | ||
"gitHead": "d74ea289800c2fc52c005674a55b2412385f57d9" | ||
"ava": { | ||
"files": [ | ||
"test/**/test-*.js" | ||
], | ||
"require": [ | ||
"esm" | ||
], | ||
"timeout": "2m" | ||
} | ||
} |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
29398
5
2
7
330
0
+ Added@agoric/promise-kit@^0.1.4
+ Added@agoric/eventual-send@0.10.0(transitive)
- Removed@agoric/harden@^0.0.8
- Removed@agoric/produce-promise@^0.1.3
- Removed@agoric/eventual-send@0.9.3(transitive)
- Removed@agoric/harden@0.0.8(transitive)
- Removed@agoric/make-hardener@0.0.8(transitive)
- Removed@agoric/produce-promise@0.1.3(transitive)
Updated@agoric/marshal@^0.2.4