diff --git a/package-lock.json b/package-lock.json index a398995c3f3..3dec607c0a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,22 +25,15 @@ "integrity": "sha512-lWAVssRdJBK1Rr7lndOdJ24qaG/r8dIY43oUFumQr0FW9f4oID2WZoBlX7pDBdwZXHIHIvYa+p09q5obYBoROw==" }, "@agoric/default-evaluate-options": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@agoric/default-evaluate-options/-/default-evaluate-options-0.1.2.tgz", - "integrity": "sha512-pnquALs836Z6F1he2Nqg6NN4sLAetuPGhpoVIC90t9p40p2M0jOKukk2jS+QzHhIDtJyfEM8MBzVdy7uylss5A==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@agoric/default-evaluate-options/-/default-evaluate-options-0.1.3.tgz", + "integrity": "sha512-oEV1HOV+vqDgwLKLoyTH8+YO+zrjbp9zj8U2GiEtIYHeQUhXG3nCWFxvpamvaabDOaAJNjX/FRgiCY2dIDo8sQ==", "requires": { "@agoric/babel-parser": "^7.5.0", - "@agoric/eventual-send": "^0.2.3", + "@agoric/eventual-send": "^0.2.4", "@agoric/transform-bang": "^0.3.1", "@babel/generator": "^7.5.5", "esm": "^3.2.5" - }, - "dependencies": { - "@agoric/eventual-send": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@agoric/eventual-send/-/eventual-send-0.2.3.tgz", - "integrity": "sha512-ThrncI+G2sIexJBAxK+M6LWLQvUe6+JuNC/SC/s1OTjWrD+U3UWKdGPg8mbF0YkxDeoCj07VQlSAfSIiam4FJw==" - } } }, "@agoric/evaluate": { @@ -52,6 +45,11 @@ "esm": "^3.2.5" } }, + "@agoric/eventual-send": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@agoric/eventual-send/-/eventual-send-0.2.4.tgz", + "integrity": "sha512-QYlLK+OY78Eor3wwYfU2SUeNnFm12w6nhdKZDfqJ1wOp9HiXlX5etub1JjYy8ViWEITKBmKyx3WyUxaUhdveNQ==" + }, "@agoric/harden": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/@agoric/harden/-/harden-0.0.4.tgz", @@ -115,11 +113,11 @@ } }, "@babel/generator": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", - "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.0.tgz", + "integrity": "sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA==", "requires": { - "@babel/types": "^7.5.5", + "@babel/types": "^7.6.0", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0", @@ -147,9 +145,9 @@ } }, "@babel/types": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", - "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.0.tgz", + "integrity": "sha512-+wLIp3XW60cvkZP/pvKMM85qoJbx7Hn3tNUpkGBLsGaSEYRz8Ut389/UsSa+wSBwSchtsLJm5IsqlA5sXawqew==", "requires": { "esutils": "^2.0.2", "lodash": "^4.17.13", diff --git a/package.json b/package.json index 13d825eb469..ae83037cfa4 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ }, "dependencies": { "@agoric/acorn-infix-bang": "0.0.4", - "@agoric/default-evaluate-options": "^0.1.2", + "@agoric/default-evaluate-options": "^0.1.3", "@agoric/evaluate": "^1.3.2", "@agoric/harden": "^0.0.4", "@agoric/marshal": "0.0.1", diff --git a/src/kernel/liveSlots.js b/src/kernel/liveSlots.js index 6c612f9643c..6f352d02b56 100644 --- a/src/kernel/liveSlots.js +++ b/src/kernel/liveSlots.js @@ -1,7 +1,6 @@ import harden from '@agoric/harden'; import Nat from '@agoric/nat'; import { QCLASS, mustPassByPresence, makeMarshal } from '@agoric/marshal'; -import makePromise from './makePromise'; // 'makeLiveSlots' is a dispatcher which uses javascript Maps to keep track // of local objects which have been exported. These cannot be persisted @@ -199,11 +198,12 @@ function build(syscall, _state, makeRoot, forVatID) { const m = makeMarshal(serializeSlot, unserializeSlot); function queueMessage(targetSlot, prop, args) { - const done = makePromise(); const ser = m.serialize(harden({ args })); lsdebug(`ls.qm send(${JSON.stringify(targetSlot)}, ${prop}`); const promiseID = syscall.send(targetSlot, prop, ser.argsString, ser.slots); lsdebug(` ls.qm got promiseID ${promiseID}`); + const slot = { type: 'promise', id: promiseID }; + const done = makeQueued(slot); // prepare for notifyFulfillToData/etc importedPromisesByPromiseID.set(promiseID, done); @@ -215,7 +215,6 @@ function build(syscall, _state, makeRoot, forVatID) { // prepare the serializer to recognize it, if it's used as an argument or // return value - const slot = { type: 'promise', id: promiseID }; const key = slotToKey(slot); valToSlot.set(done.p, slot); slotKeyToVal.set(key, done.p); diff --git a/test/test-liveslots.js b/test/test-liveslots.js new file mode 100644 index 00000000000..9e274e4bddc --- /dev/null +++ b/test/test-liveslots.js @@ -0,0 +1,71 @@ +// eslint-disable-next-line no-redeclare +/* global setImmediate */ +import { test } from 'tape-promise/tape'; +import harden from '@agoric/harden'; +// eslint-disable-next-line no-unused-vars +import evaluateExpr from '@agoric/evaluate'; // to get Promise.makeHandled +import buildKernel from '../src/kernel/index'; +import { makeLiveSlots } from '../src/kernel/liveSlots'; + +test('liveslots pipelines to syscall.send', async t => { + const kernel = buildKernel({ setImmediate }); + const log = []; + + function setupA(syscallA, state, helpers) { + function build(E, _D) { + return harden({ + one(x) { + const p1 = E(x).pipe1(); + const p2 = E(p1).pipe2(); + E(p2).pipe3(); + log.push('sent p1p2p3'); + }, + }); + } + return makeLiveSlots(syscallA, state, build, helpers.vatID); + } + kernel.addGenesisVat('a', setupA); + + let syscall; + function setupB(syscallB, _state, _helpers) { + syscall = syscallB; + function deliver() {} + return { deliver }; + } + kernel.addGenesisVat('b', setupB); + + await kernel.start(); // no bootstrap + t.deepEqual(kernel.dump().runQueue, []); + + const root = kernel.addImport( + 'b', + harden({ type: 'export', vatID: 'a', id: 0 }), + ); + + // root!one(x) // sendOnly + const arg0 = JSON.stringify({ args: [{ '@qclass': 'slot', index: 0 }] }); + syscall.send(root, 'one', arg0, [harden({ type: 'export', id: 5 })]); + + // calling one() should cause three syscall.send() calls to be made: one + // for x!pipe1(), a second pipelined to the result promise of it, and a + // third pipelined to the result of the second. With the current design, + // the kernel ought to put the first onto the runQueue, and second onto the + // kernel promise queue for the result of the first, and likewise the + // third. + await kernel.step(); + const resolverID = kernel.dump().runQueue[0].msg.kernelResolverID; + const state = JSON.parse(kernel.getState()); + const kp = state.kernelPromises[resolverID]; + t.equal(kp.queue.length, 1); + t.equal(kp.queue[0].method, 'pipe2'); + const resolverID2 = kp.queue[0].kernelResolverID; + const kp2 = state.kernelPromises[resolverID2]; + t.equal(kp2.queue.length, 1); + t.equal(kp2.queue[0].method, 'pipe3'); + + // in the new design, three sends() mean three items on the runqueue, and + // they'll be appended to kernel promise queues after they get to the front + // t.deepEqual(kernel.dump().runQueue.length, 3); + + t.end(); +});