Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: integrate JSON.stringify/parse in board marshallers #6646

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions packages/internal/src/lib-chainStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const { Fail } = assert;
*/

const ChainStorageNodeI = M.interface('StorageNode', {
setValue: M.callWhen(M.string()).returns(),
setValue: M.callWhen(M.await(M.string())).returns(),
getPath: M.call().returns(M.string()),
getStoreKey: M.callWhen().returns(M.record()),
makeChildNode: M.call(M.string())
Expand Down Expand Up @@ -221,13 +221,14 @@ harden(makeStorageNodeChild);
// TODO find a better module for this
/**
* @param {import('@endo/far').ERef<StorageNode>} storageNode
* @param {import('@endo/far').ERef<Marshaller>} marshaller
* @param {import('@endo/far').ERef<Marshaller & {
* serializeAndStringify: (value: unknown) => string
* }>} marshaller
* @returns {(value: unknown) => Promise<void>}
*/
export const makeSerializeToStorage = (storageNode, marshaller) => {
return async value => {
const marshalled = await E(marshaller).toCapData(value);
const serialized = JSON.stringify(marshalled);
const serialized = await E(marshaller).serializeAndStringify(value);
return E(storageNode).setValue(serialized);
};
};
21 changes: 20 additions & 1 deletion packages/vats/src/lib-board.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ export const DEFAULT_CRC_DIGITS = 2;
export const DEFAULT_PREFIX = 'board0';

//#region Interface Guards
// TODO import from Endo
const CapDataShape = { body: M.string(), slots: M.array() };
const MarshalI = M.interface('Marshaller', {
toCapData: M.call(M.any()).returns(CapDataShape),
serialize: M.call(M.any()).returns(CapDataShape),
fromCapData: M.call(CapDataShape).returns(M.any()),
serializeAndStringify: M.callWhen(M.any()).returns(M.string()),
unserialize: M.call(CapDataShape).returns(M.any()),
parseAndDecode: M.callWhen(M.string()).returns(M.any()),
});

const IdShape = M.string();
Expand Down Expand Up @@ -344,6 +345,15 @@ export const prepareBoardKit = baggage => {
unserialize(data) {
return this.facets.readonlyMarshaller.fromCapData(data);
},
serializeAndStringify(val) {
const readonly = makeReadonlyMarshaller(this.state);
return JSON.stringify(readonly.serialize(val));
},
parseAndDecode(str) {
const data = JSON.parse(str);
const readonly = makeReadonlyMarshaller(this.state);
return readonly.unserialize(data);
Copy link
Member

@turadg turadg Apr 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be fromCapData. the Endo sync is imminent and will save some churn to wait for it: https://github.com/Agoric/agoric-sdk/pull/7273/files#diff-298ac87f534f4fb60e42f478a8a866d0eb2f4e4853f6c7cb12c7f99c92594b2eR22

though I suppose this could land first and that PR could update the call.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will save some churn to wait for it

ok

},
},
publishingMarshaller: {
toCapData(val) {
Expand All @@ -360,6 +370,15 @@ export const prepareBoardKit = baggage => {
unserialize(data) {
return this.facets.publishingMarshaller.fromCapData(data);
},
serializeAndStringify(val) {
const publishing = makePublishingMarshaller(this.state);
return JSON.stringify(publishing.serialize(val));
},
parseAndDecode(str) {
const data = JSON.parse(str);
const publishing = makePublishingMarshaller(this.state);
return publishing.unserialize(data);
},
},
},
);
Expand Down
17 changes: 17 additions & 0 deletions packages/vats/test/test-lib-board.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,20 @@ test(`getReadonlyMarshaller doesn't leak unpublished objects`, async t => {
const marshaller = board.getReadonlyMarshaller();
await testBoardMarshaller(t, board, marshaller, false);
});

test('serialize and stringify to save a round trip', async t => {
const board = makeBoard();
const marshaller = board.getPublishingMarshaller();
const obj2 = Far('obj2', {});
const s = await E(marshaller).serializeAndStringify(obj2);
t.is(s, '{"body":"#\\"$0.Alleged: obj2\\"","slots":["board0371"]}');
});

test('parse and decode', async t => {
const board = makeBoard();
const marshaller = board.getPublishingMarshaller();
const obj2 = Far('obj2', {});
const s = await E(marshaller).serializeAndStringify(obj2);
const actual = await E(marshaller).parseAndDecode(s);
t.is(actual, obj2);
});
10 changes: 4 additions & 6 deletions packages/zoe/src/contractSupport/recorder.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,8 @@ export const prepareRecorder = (baggage, marshaller) => {
const { closed, publisher, storageNode, valueShape } = this.state;
!closed || Fail`cannot write to closed recorder`;
mustMatch(value, valueShape);
const encoded = await E(marshaller).toCapData(value);
const serialized = JSON.stringify(encoded);
await E(storageNode).setValue(serialized);
const serializedP = await E(marshaller).serializeAndStringify(value);
await E(storageNode).setValue(serializedP);

// below here differs from writeFinal()
return publisher.publish(value);
Expand All @@ -118,9 +117,8 @@ export const prepareRecorder = (baggage, marshaller) => {
const { closed, publisher, storageNode, valueShape } = this.state;
!closed || Fail`cannot write to closed recorder`;
mustMatch(value, valueShape);
const encoded = await E(marshaller).toCapData(value);
const serialized = JSON.stringify(encoded);
await E(storageNode).setValue(serialized);
const serializedP = await E(marshaller).serializeAndStringify(value);
await E(storageNode).setValue(serializedP);

// below here differs from writeFinal()
this.state.closed = true;
Expand Down