@agoric/internal 0.2.2-pismo-dev-50dc068.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/package.json +15 -7
  3. package/src/action-types.d.ts +16 -0
  4. package/src/action-types.d.ts.map +1 -0
  5. package/src/action-types.js +17 -0
  6. package/src/batched-deliver.d.ts +15 -0
  7. package/src/batched-deliver.d.ts.map +1 -0
  8. package/src/batched-deliver.js +50 -0
  9. package/src/callback.d.ts +23 -0
  10. package/src/callback.d.ts.map +1 -0
  11. package/src/callback.js +322 -0
  12. package/src/chain-storage-paths.d.ts +16 -0
  13. package/src/chain-storage-paths.d.ts.map +1 -0
  14. package/src/chain-storage-paths.js +17 -0
  15. package/src/config.d.ts +25 -0
  16. package/src/config.d.ts.map +1 -0
  17. package/src/config.js +20 -3
  18. package/src/debug.d.ts +2 -0
  19. package/src/debug.d.ts.map +1 -0
  20. package/src/debug.js +41 -0
  21. package/src/index.d.ts +6 -0
  22. package/src/index.d.ts.map +1 -0
  23. package/src/index.js +7 -2
  24. package/src/lib-chainStorage.d.ts +179 -0
  25. package/src/lib-chainStorage.d.ts.map +1 -0
  26. package/src/lib-chainStorage.js +304 -0
  27. package/src/magic-cookie-test-only.d.ts +2 -0
  28. package/src/magic-cookie-test-only.d.ts.map +1 -0
  29. package/src/magic-cookie-test-only.js +11 -0
  30. package/src/method-tools.d.ts +3 -0
  31. package/src/method-tools.d.ts.map +1 -0
  32. package/src/method-tools.js +110 -0
  33. package/src/node/buffer-line-transform.d.ts +41 -0
  34. package/src/node/buffer-line-transform.d.ts.map +1 -0
  35. package/src/node/buffer-line-transform.js +119 -0
  36. package/src/node/createBundles.d.ts +4 -0
  37. package/src/node/createBundles.d.ts.map +1 -0
  38. package/src/node/createBundles.js +80 -0
  39. package/src/node/fs-stream.d.ts +8 -0
  40. package/src/node/fs-stream.d.ts.map +1 -0
  41. package/src/node/fs-stream.js +105 -0
  42. package/src/node/shutdown.d.ts +6 -0
  43. package/src/node/shutdown.d.ts.map +1 -0
  44. package/src/node/shutdown.js +81 -0
  45. package/src/priority-senders.d.ts +31 -0
  46. package/src/priority-senders.d.ts.map +1 -0
  47. package/src/priority-senders.js +104 -0
  48. package/src/queue.d.ts +2 -0
  49. package/src/queue.d.ts.map +1 -0
  50. package/src/queue.js +58 -0
  51. package/src/scratch.d.ts +19 -0
  52. package/src/scratch.d.ts.map +1 -0
  53. package/src/scratch.js +52 -0
  54. package/src/storage-test-utils.d.ts +99 -0
  55. package/src/storage-test-utils.d.ts.map +1 -0
  56. package/src/storage-test-utils.js +228 -0
  57. package/src/testing-utils.d.ts +2 -0
  58. package/src/testing-utils.d.ts.map +1 -0
  59. package/src/testing-utils.js +14 -0
  60. package/src/typeGuards.d.ts +2 -0
  61. package/src/typeGuards.d.ts.map +1 -0
  62. package/src/typeGuards.js +5 -0
  63. package/src/types.d.ts +20 -0
  64. package/src/upgrade-api.d.ts +8 -0
  65. package/src/upgrade-api.d.ts.map +1 -0
  66. package/src/upgrade-api.js +41 -0
  67. package/src/utils.d.ts +67 -0
  68. package/src/utils.d.ts.map +1 -0
  69. package/src/utils.js +232 -124
@@ -0,0 +1,104 @@
1
+ import { E, Far } from '@endo/far';
2
+
3
+ const { Fail, quote: q } = assert;
4
+
5
+ const PRIORITY_SENDERS_NAMESPACE_RE = /^[a-zA-Z0-9_-]{1,50}$/;
6
+
7
+ /** @type {(namespace: string) => string} */
8
+ export const normalizeSenderNamespace = namespace => {
9
+ const candidate = namespace.replace(/[ ,()]/g, '_');
10
+ PRIORITY_SENDERS_NAMESPACE_RE.test(candidate) ||
11
+ Fail`invalid namespace ${q(namespace)}`;
12
+ return candidate;
13
+ };
14
+ harden(normalizeSenderNamespace);
15
+
16
+ /**
17
+ * XXX lets holder manage sender list for all namespaces
18
+ *
19
+ * @param {ERef<import('./lib-chainStorage.js').StorageNode>} sendersNode
20
+ */
21
+ export const makePrioritySendersManager = sendersNode => {
22
+ /**
23
+ * address to tuple with storage node and set of namespaces that requested priority
24
+ *
25
+ * @type {Map<string, readonly [node: StorageNode, namespaces: Set<string>]>}
26
+ */
27
+ const addressRecords = new Map();
28
+
29
+ /**
30
+ * Write a list of namespaces into a storage node.
31
+ *
32
+ * @param {import('./lib-chainStorage.js').StorageNode} node
33
+ * @param {Set<string>} namespaces
34
+ */
35
+ const refreshVstorage = (node, namespaces) => {
36
+ return E(node).setValue(
37
+ // if the list set is empty, the string will be '' and thus deleted from IAVL
38
+ [...namespaces.keys()].sort().join(','),
39
+ );
40
+ };
41
+
42
+ const provideRecordForAddress = async address => {
43
+ const extant = addressRecords.get(address);
44
+ if (extant) {
45
+ return extant;
46
+ }
47
+ const node = await E(sendersNode).makeChildNode(address, {
48
+ sequence: false,
49
+ });
50
+ /** @type {readonly [ node: StorageNode, namespaces: Set<string> ]} */
51
+ const r = [node, new Set()];
52
+ addressRecords.set(address, r);
53
+ return r;
54
+ };
55
+
56
+ return Far('prioritySenders manager', {
57
+ /**
58
+ * @param {string} rawNamespace
59
+ * @param {string} address
60
+ * @returns {Promise<void>}
61
+ */
62
+ add: async (rawNamespace, address) => {
63
+ const namespace = normalizeSenderNamespace(rawNamespace);
64
+
65
+ const record = await provideRecordForAddress(address);
66
+
67
+ const [node, namespaces] = record;
68
+ if (namespaces.has(namespace)) {
69
+ throw Fail`namespace ${q(namespace)} already has address ${q(address)}`;
70
+ }
71
+ namespaces.add(namespace);
72
+
73
+ return refreshVstorage(node, namespaces);
74
+ },
75
+ /**
76
+ * @param {string} rawNamespace
77
+ * @param {string} address
78
+ * @returns {Promise<void>}
79
+ */
80
+ remove: (rawNamespace, address) => {
81
+ const namespace = normalizeSenderNamespace(rawNamespace);
82
+ const record = addressRecords.get(address);
83
+ if (!record) {
84
+ throw Fail`address not registered: ${q(address)}`;
85
+ }
86
+ const [node, namespaces] = record;
87
+ if (!namespaces.has(namespace)) {
88
+ throw Fail`namespace ${q(namespace)} does not have address ${q(
89
+ address,
90
+ )}`;
91
+ }
92
+
93
+ namespaces.delete(namespace);
94
+ if (namespaces.size === 0) {
95
+ addressRecords.delete(address);
96
+ }
97
+
98
+ return refreshVstorage(node, namespaces);
99
+ },
100
+ });
101
+ };
102
+ harden(makePrioritySendersManager);
103
+
104
+ /** @typedef {ReturnType<typeof makePrioritySendersManager>} PrioritySendersManager */
package/src/queue.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export function makeWithQueue(): <T extends any[], R>(inner: (...args: T) => Promise<R>) => (...args: T) => Promise<R>;
2
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["queue.js"],"names":[],"mappings":"AAQO,uHAiDN"}
package/src/queue.js ADDED
@@ -0,0 +1,58 @@
1
+ // @jessie-check
2
+
3
+ import { makePromiseKit } from '@endo/promise-kit';
4
+
5
+ /**
6
+ * Return a function that can wrap an async or sync method, but
7
+ * ensures only one of them (in order) is running at a time.
8
+ */
9
+ export const makeWithQueue = () => {
10
+ const queue = [];
11
+
12
+ // Execute the thunk at the front of the queue.
13
+ const dequeue = () => {
14
+ if (!queue.length) {
15
+ return;
16
+ }
17
+ const [thunk, resolve, reject] = queue[0];
18
+ // Run the thunk in a new turn.
19
+ Promise.resolve()
20
+ .then(thunk)
21
+ // Resolve or reject our caller with the thunk's value.
22
+ .then(resolve, reject)
23
+ // Rerun dequeue() after settling.
24
+ .finally(() => {
25
+ queue.shift();
26
+ if (queue.length) {
27
+ dequeue();
28
+ }
29
+ });
30
+ };
31
+
32
+ /**
33
+ * @template {any[]} T
34
+ * @template R
35
+ * @param {(...args: T) => Promise<R>} inner
36
+ */
37
+ return function withQueue(inner) {
38
+ /**
39
+ * @param {T} args
40
+ * @returns {Promise<R>}
41
+ */
42
+ return function queueCall(...args) {
43
+ // Curry the arguments into the inner function, and
44
+ // resolve/reject with whatever the inner function does.
45
+ const thunk = _ => inner(...args);
46
+ const pr = makePromiseKit();
47
+ queue.push([thunk, pr.resolve, pr.reject]);
48
+
49
+ if (queue.length === 1) {
50
+ // Start running immediately.
51
+ dequeue();
52
+ }
53
+
54
+ // Allow the caller to retrieve our thunk's results.
55
+ return pr.promise;
56
+ };
57
+ };
58
+ };
@@ -0,0 +1,19 @@
1
+ export default function makeScratchPad(): {
2
+ delete: (keyP: any) => Promise<void>;
3
+ get: (keyP: any) => Promise<any>;
4
+ lookup: (...path: any[]) => any;
5
+ init: (keyP: any, objP: any) => Promise<any>;
6
+ keys: () => Promise<any[]>;
7
+ list: () => Promise<any[]>;
8
+ set: (keyP: any, objP: any) => Promise<any>;
9
+ } & import("@endo/eventual-send").RemotableBrand<{}, {
10
+ delete: (keyP: any) => Promise<void>;
11
+ get: (keyP: any) => Promise<any>;
12
+ lookup: (...path: any[]) => any;
13
+ init: (keyP: any, objP: any) => Promise<any>;
14
+ keys: () => Promise<any[]>;
15
+ list: () => Promise<any[]>;
16
+ set: (keyP: any, objP: any) => Promise<any>;
17
+ }>;
18
+ export type ScratchPad = ReturnType<typeof makeScratchPad>;
19
+ //# sourceMappingURL=scratch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scratch.d.ts","sourceRoot":"","sources":["scratch.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgDC;yBACa,WAAW,qBAAqB,CAAC"}
package/src/scratch.js ADDED
@@ -0,0 +1,52 @@
1
+ import { E, Far } from '@endo/far';
2
+
3
+ export default function makeScratchPad() {
4
+ const map = new Map();
5
+
6
+ const keys = async () => {
7
+ const keyList = [...map.keys()];
8
+ return harden(keyList.sort());
9
+ };
10
+
11
+ const scratch = Far('scratchPad', {
12
+ delete: async keyP => {
13
+ const key = await keyP;
14
+ map.delete(key);
15
+ },
16
+ get: async keyP => {
17
+ const key = await keyP;
18
+ return map.get(key);
19
+ },
20
+ lookup: (...path) => {
21
+ if (path.length === 0) {
22
+ return scratch;
23
+ }
24
+ const [first, ...rest] = path;
25
+ const firstValue = E(scratch).get(first);
26
+ if (rest.length === 0) {
27
+ return firstValue;
28
+ }
29
+ return E(firstValue).lookup(...rest);
30
+ },
31
+ // Initialize a key only if it doesn't already exist. Needed for atomicity
32
+ // between multiple invocations.
33
+ init: async (keyP, objP) => {
34
+ const [key, obj] = await Promise.all([keyP, objP]);
35
+ if (map.has(key)) {
36
+ throw Error(`Scratchpad already has key ${key}`);
37
+ }
38
+ map.set(key, obj);
39
+ return key;
40
+ },
41
+ keys,
42
+ // Legacy alias for `keys`.
43
+ list: keys,
44
+ set: async (keyP, objP) => {
45
+ const [key, obj] = await Promise.all([keyP, objP]);
46
+ map.set(key, obj);
47
+ return key;
48
+ },
49
+ });
50
+ return scratch;
51
+ }
52
+ /** @typedef {ReturnType<typeof makeScratchPad>} ScratchPad */
@@ -0,0 +1,99 @@
1
+ export function slotToRemotable(_slotId: string, iface?: string): import("@endo/eventual-send").RemotableBrand<{}, {}>;
2
+ /**
3
+ * A basic marshaller whose unserializer produces Remotables. It can
4
+ * only serialize plain data, not Remotables.
5
+ */
6
+ export const defaultMarshaller: {
7
+ toCapData: import("@endo/marshal/src/marshal.js").ToCapData<string>;
8
+ fromCapData: import("@endo/marshal/src/marshal.js").FromCapData<string>;
9
+ serialize: import("@endo/marshal/src/marshal.js").ToCapData<string>;
10
+ unserialize: import("@endo/marshal/src/marshal.js").FromCapData<string>;
11
+ };
12
+ export function slotStringUnserialize(capData: any): any;
13
+ export function makeFakeStorageKit(rootPath: string, rootOptions?: [handleStorageMessage: (message: import("./lib-chainStorage.js").StorageMessage) => any, rootPath: string, rootOptions?: {
14
+ sequence?: boolean | undefined;
15
+ } | undefined][2]): {
16
+ rootNode: {
17
+ getPath(): string;
18
+ getStoreKey(): Promise<import("./lib-chainStorage.js").VStorageKey>;
19
+ makeChildNode(name: string, childNodeOptions?: {
20
+ sequence?: boolean | undefined;
21
+ } | undefined): import("./lib-chainStorage.js").StorageNode;
22
+ setValue(value: string): Promise<void>;
23
+ } & import("@endo/eventual-send").RemotableBrand<{}, {
24
+ getPath(): string;
25
+ getStoreKey(): Promise<import("./lib-chainStorage.js").VStorageKey>;
26
+ makeChildNode(name: string, childNodeOptions?: {
27
+ sequence?: boolean | undefined;
28
+ } | undefined): import("./lib-chainStorage.js").StorageNode;
29
+ setValue(value: string): Promise<void>;
30
+ }>;
31
+ data: Map<string, string>;
32
+ messages: import("./lib-chainStorage.js").StorageMessage[];
33
+ toStorage: (message: import('../src/lib-chainStorage.js').StorageMessage) => string | number | any[] | {
34
+ storeName: string;
35
+ storeSubkey: string;
36
+ } | null | undefined;
37
+ };
38
+ export function makeMockChainStorageRoot(): {
39
+ /**
40
+ * Defaults to deserializing slot references into plain Remotable
41
+ * objects having the specified interface name (as from `Far(iface)`),
42
+ * but can accept a different marshaller for producing Remotables
43
+ * that e.g. embed the slot string in their iface name.
44
+ *
45
+ * @param {string} path
46
+ * @param {import('./lib-chainStorage.js').Marshaller} marshaller
47
+ * @returns {unknown}
48
+ */
49
+ getBody: (path: string, marshaller?: import('./lib-chainStorage.js').Marshaller) => unknown;
50
+ keys: () => string[];
51
+ getPath(): string;
52
+ getStoreKey(): Promise<import("./lib-chainStorage.js").VStorageKey>;
53
+ makeChildNode(name: string, childNodeOptions?: {
54
+ sequence?: boolean | undefined;
55
+ } | undefined): import("./lib-chainStorage.js").StorageNode;
56
+ setValue(value: string): Promise<void>;
57
+ } & import("@endo/eventual-send").RemotableBrand<{}, {
58
+ /**
59
+ * Defaults to deserializing slot references into plain Remotable
60
+ * objects having the specified interface name (as from `Far(iface)`),
61
+ * but can accept a different marshaller for producing Remotables
62
+ * that e.g. embed the slot string in their iface name.
63
+ *
64
+ * @param {string} path
65
+ * @param {import('./lib-chainStorage.js').Marshaller} marshaller
66
+ * @returns {unknown}
67
+ */
68
+ getBody: (path: string, marshaller?: import('./lib-chainStorage.js').Marshaller) => unknown;
69
+ keys: () => string[];
70
+ getPath(): string;
71
+ getStoreKey(): Promise<import("./lib-chainStorage.js").VStorageKey>;
72
+ makeChildNode(name: string, childNodeOptions?: {
73
+ sequence?: boolean | undefined;
74
+ } | undefined): import("./lib-chainStorage.js").StorageNode;
75
+ setValue(value: string): Promise<void>;
76
+ }>;
77
+ /**
78
+ * A map corresponding with a total function such that `get(key)`
79
+ * is assumed to always succeed.
80
+ */
81
+ export type TotalMap<K, V> = {
82
+ [Symbol.iterator]: () => IterableIterator<[K, V]>;
83
+ [Symbol.toStringTag]: string;
84
+ entries: () => IterableIterator<[K, V]>;
85
+ keys: () => IterableIterator<K>;
86
+ values: () => IterableIterator<V>;
87
+ has: (key: K) => boolean;
88
+ size: number;
89
+ set: (key: K, value: V) => Map<K, V>;
90
+ clear: () => void;
91
+ delete: (key: K) => boolean;
92
+ forEach: (callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any) => void;
93
+ } & {
94
+ get: (key: K) => V;
95
+ };
96
+ export type TotalMapFrom<T> = T extends Map<infer K, infer V> ? TotalMap<K, V> : never;
97
+ export type FakeStorageKit = ReturnType<typeof makeFakeStorageKit>;
98
+ export type MockChainStorageRoot = ReturnType<typeof makeMockChainStorageRoot>;
99
+ //# sourceMappingURL=storage-test-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-test-utils.d.ts","sourceRoot":"","sources":["storage-test-utils.js"],"names":[],"mappings":"AA+BO,yCAHI,MAAM,UACN,MAAM,wDAGC;AAElB;;;GAGG;AACH;;;;;EAEG;AAsBW,+CAAU,GAAG,GAAK,GAAG,CAAA;AAgC5B,6CAHI,MAAM,gBACN;;eAAwC,CAAC,CAAC;;;;;;;;;;;;;;;;;;yBAyBvC,OAAO,4BAA4B,EAAE,cAAc;;;;EAkFhE;AAIM;IAIH;;;;;;;;;OASG;oBAHQ,MAAM,eACN,OAAO,uBAAuB,EAAE,UAAU,KACxC,OAAO;;;;;;;;;IARpB;;;;;;;;;OASG;oBAHQ,MAAM,eACN,OAAO,uBAAuB,EAAE,UAAU,KACxC,OAAO;;;;;;;;GAWvB;;;;;;;;;;;;;;;;;;eAjNiF,CAAC,KAAK,CAAC;;;6BAwL3E,WAAY,yBAAyB,CAAC;mCA0BtC,WAAW,+BAA+B,CAAC"}
@@ -0,0 +1,228 @@
1
+ // @ts-check
2
+ import { Far } from '@endo/far';
3
+ import { makeMarshal, Remotable } from '@endo/marshal';
4
+ import {
5
+ isStreamCell,
6
+ makeChainStorageRoot,
7
+ unmarshalFromVstorage,
8
+ } from './lib-chainStorage.js';
9
+ import { bindAllMethods } from './method-tools.js';
10
+
11
+ const { Fail } = assert;
12
+
13
+ /**
14
+ * A map corresponding with a total function such that `get(key)`
15
+ * is assumed to always succeed.
16
+ *
17
+ * @template K, V
18
+ * @typedef {{[k in Exclude<keyof Map<K, V>, 'get'>]: Map<K, V>[k]} & {get: (key: K) => V}} TotalMap
19
+ */
20
+ /**
21
+ * @template T
22
+ * @typedef {T extends Map<infer K, infer V> ? TotalMap<K, V> : never} TotalMapFrom
23
+ */
24
+
25
+ /**
26
+ * A convertSlotToVal function that produces basic Remotables. Assumes
27
+ * that all slots are Remotables (i.e. none are Promises).
28
+ *
29
+ * @param {string} _slotId
30
+ * @param {string} iface
31
+ */
32
+ export const slotToRemotable = (_slotId, iface = 'Remotable') =>
33
+ Remotable(iface);
34
+
35
+ /**
36
+ * A basic marshaller whose unserializer produces Remotables. It can
37
+ * only serialize plain data, not Remotables.
38
+ */
39
+ export const defaultMarshaller = makeMarshal(undefined, slotToRemotable, {
40
+ serializeBodyFormat: 'smallcaps',
41
+ });
42
+
43
+ /**
44
+ * A deserializer which produces slot strings instead of Remotables,
45
+ * so if `a = Far('iface')`, and serializing `{ a }` into `capData`
46
+ * assigned it slot `board123`, then `slotStringUnserialize(capData)`
47
+ * would produce `{ a: 'board123' }`.
48
+ *
49
+ * This may be useful for display purposes.
50
+ *
51
+ * Limitations:
52
+ * * it cannot handle Symbols (registered or well-known)
53
+ * * it can handle BigInts, but serialized data that contains a
54
+ * particular unusual string will be unserialized into a BigInt by
55
+ * mistake
56
+ * * it cannot handle Promises, NaN, +/- Infinity, undefined, or
57
+ * other non-JSONable JavaScript values
58
+ */
59
+ const makeSlotStringUnserialize = () => {
60
+ /** @type { (slot: string, iface: string) => any } */
61
+ const identitySlotToValFn = (slot, _) => Far('unk', { toJSON: () => slot });
62
+ const { fromCapData } = makeMarshal(undefined, identitySlotToValFn);
63
+ /** @type { (capData: any) => any } */
64
+ const unserialize = capData =>
65
+ JSON.parse(
66
+ JSON.stringify(fromCapData(capData), (_, val) => {
67
+ if (typeof val === 'bigint') {
68
+ // JSON cannot accept BigInts. This unusual string is a
69
+ // cheap alternative to a proper Hilbert Hotel.
70
+ return `@encromulate:${val}`;
71
+ } else {
72
+ return val;
73
+ }
74
+ }),
75
+ (_key, val) => {
76
+ if (typeof val === 'string' && val.startsWith('@encromulate')) {
77
+ return BigInt(val.split(':')[1]);
78
+ } else {
79
+ return val;
80
+ }
81
+ },
82
+ );
83
+ return harden(unserialize);
84
+ };
85
+ export const slotStringUnserialize = makeSlotStringUnserialize();
86
+
87
+ /**
88
+ * For testing, creates a chainStorage root node over an in-memory map
89
+ * and exposes both the map and the sequence of received messages.
90
+ * The `sequence` option defaults to true.
91
+ *
92
+ * @param {string} rootPath
93
+ * @param {Parameters<typeof makeChainStorageRoot>[2]} [rootOptions]
94
+ */
95
+ export const makeFakeStorageKit = (rootPath, rootOptions) => {
96
+ const resolvedOptions = { sequence: true, ...rootOptions };
97
+ /** @type {TotalMap<string, string>} */
98
+ const data = new Map();
99
+ /** @param {string} prefix */
100
+ const getChildEntries = prefix => {
101
+ assert(prefix.endsWith('.'));
102
+ const childEntries = new Map();
103
+ for (const [path, value] of data.entries()) {
104
+ if (!path.startsWith(prefix)) {
105
+ continue;
106
+ }
107
+ const [segment, ...suffix] = path.slice(prefix.length).split('.');
108
+ if (suffix.length === 0) {
109
+ childEntries.set(segment, value);
110
+ } else if (!childEntries.has(segment)) {
111
+ childEntries.set(segment, null);
112
+ }
113
+ }
114
+ return childEntries;
115
+ };
116
+ /** @type {import('../src/lib-chainStorage.js').StorageMessage[]} */
117
+ const messages = [];
118
+ /** @param {import('../src/lib-chainStorage.js').StorageMessage} message */
119
+ // eslint-disable-next-line consistent-return
120
+ const toStorage = message => {
121
+ messages.push(message);
122
+ switch (message.method) {
123
+ case 'getStoreKey': {
124
+ const [key] = message.args;
125
+ return { storeName: 'swingset', storeSubkey: `fake:${key}` };
126
+ }
127
+ case 'get': {
128
+ const [key] = message.args;
129
+ return data.has(key) ? data.get(key) : null;
130
+ }
131
+ case 'children': {
132
+ const [key] = message.args;
133
+ const childEntries = getChildEntries(`${key}.`);
134
+ return [...childEntries.keys()];
135
+ }
136
+ case 'entries': {
137
+ const [key] = message.args;
138
+ const childEntries = getChildEntries(`${key}.`);
139
+ return [...childEntries.entries()].map(entry =>
140
+ entry[1] != null ? entry : [entry[0]],
141
+ );
142
+ }
143
+ case 'set':
144
+ case 'setWithoutNotify': {
145
+ /** @type {import('../src/lib-chainStorage.js').StorageEntry[]} */
146
+ const newEntries = message.args;
147
+ for (const [key, value] of newEntries) {
148
+ if (value != null) {
149
+ data.set(key, value);
150
+ } else {
151
+ data.delete(key);
152
+ }
153
+ }
154
+ break;
155
+ }
156
+ case 'append': {
157
+ /** @type {import('../src/lib-chainStorage.js').StorageEntry[]} */
158
+ const newEntries = message.args;
159
+ for (const [key, value] of newEntries) {
160
+ value != null || Fail`attempt to append with no value`;
161
+ // In the absence of block boundaries, everything goes in a single StreamCell.
162
+ const oldVal = data.get(key);
163
+ let streamCell;
164
+ if (oldVal != null) {
165
+ try {
166
+ streamCell = JSON.parse(oldVal);
167
+ assert(isStreamCell(streamCell));
168
+ } catch (_err) {
169
+ streamCell = undefined;
170
+ }
171
+ }
172
+ if (streamCell === undefined) {
173
+ streamCell = {
174
+ blockHeight: '0',
175
+ values: oldVal != null ? [oldVal] : [],
176
+ };
177
+ }
178
+ streamCell.values.push(value);
179
+ data.set(key, JSON.stringify(streamCell));
180
+ }
181
+ break;
182
+ }
183
+ case 'size':
184
+ // Intentionally incorrect because it counts non-child descendants,
185
+ // but nevertheless supports a "has children" test.
186
+ return [...data.keys()].filter(k => k.startsWith(`${message.args[0]}.`))
187
+ .length;
188
+ default:
189
+ throw Error(`unsupported method: ${message.method}`);
190
+ }
191
+ };
192
+ const rootNode = makeChainStorageRoot(toStorage, rootPath, resolvedOptions);
193
+ return {
194
+ rootNode,
195
+ // eslint-disable-next-line object-shorthand
196
+ data: /** @type {Map<string, string>} */ (data),
197
+ messages,
198
+ toStorage,
199
+ };
200
+ };
201
+ harden(makeFakeStorageKit);
202
+ /** @typedef {ReturnType< typeof makeFakeStorageKit>} FakeStorageKit */
203
+
204
+ export const makeMockChainStorageRoot = () => {
205
+ const { rootNode, data } = makeFakeStorageKit('mockChainStorageRoot');
206
+ return Far('mockChainStorage', {
207
+ ...bindAllMethods(rootNode),
208
+ /**
209
+ * Defaults to deserializing slot references into plain Remotable
210
+ * objects having the specified interface name (as from `Far(iface)`),
211
+ * but can accept a different marshaller for producing Remotables
212
+ * that e.g. embed the slot string in their iface name.
213
+ *
214
+ * @param {string} path
215
+ * @param {import('./lib-chainStorage.js').Marshaller} marshaller
216
+ * @returns {unknown}
217
+ */
218
+ getBody: (path, marshaller = defaultMarshaller) => {
219
+ data.size || Fail`no data in storage`;
220
+ /** @type {ReturnType<typeof import('@endo/marshal').makeMarshal>['fromCapData']} */
221
+ const fromCapData = (...args) =>
222
+ Reflect.apply(marshaller.fromCapData, marshaller, args);
223
+ return unmarshalFromVstorage(data, path, fromCapData);
224
+ },
225
+ keys: () => [...data.keys()],
226
+ });
227
+ };
228
+ /** @typedef {ReturnType<typeof makeMockChainStorageRoot>} MockChainStorageRoot */
@@ -0,0 +1,2 @@
1
+ export function eventLoopIteration(): Promise<any>;
2
+ //# sourceMappingURL=testing-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing-utils.d.ts","sourceRoot":"","sources":["testing-utils.js"],"names":[],"mappings":"AAWO,mDACwC"}
@@ -0,0 +1,14 @@
1
+ /** @file note this cannot be called test-utils.js due to https://github.com/Agoric/agoric-sdk/issues/7503 */
2
+ /* global setImmediate */
3
+
4
+ /**
5
+ * A workaround for some issues with fake time in tests.
6
+ *
7
+ * Lines of test code can depend on async promises outside the test
8
+ * resolving before they run. Awaiting this function result ensures
9
+ * that all promises that can do resolve.
10
+ * Note that this doesn't mean all outstanding promises.
11
+ */
12
+ export const eventLoopIteration = async () =>
13
+ new Promise(resolve => setImmediate(resolve));
14
+ harden(eventLoopIteration);
@@ -0,0 +1,2 @@
1
+ export const StorageNodeShape: import("@endo/patterns").Matcher;
2
+ //# sourceMappingURL=typeGuards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeGuards.d.ts","sourceRoot":"","sources":["typeGuards.js"],"names":[],"mappings":"AAIA,gEAA2D"}
@@ -0,0 +1,5 @@
1
+ // @jessie-check
2
+
3
+ import { M } from '@endo/patterns';
4
+
5
+ export const StorageNodeShape = M.remotable('StorageNode');
package/src/types.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ /* eslint-disable max-classes-per-file */
2
+ export declare class Callback<I extends (...args: unknown[]) => any> {
3
+ private iface: I;
4
+
5
+ public target: any;
6
+
7
+ public methodName?: PropertyKey;
8
+
9
+ public bound: unknown[];
10
+
11
+ public isSync: boolean;
12
+ }
13
+
14
+ export declare class SyncCallback<
15
+ I extends (...args: unknown[]) => any,
16
+ > extends Callback<I> {
17
+ private syncIface: I;
18
+
19
+ public isSync: true;
20
+ }
@@ -0,0 +1,8 @@
1
+ export function makeUpgradeDisconnection(upgradeMessage: string, toIncarnationNumber: number): DisconnectionObject;
2
+ export function isUpgradeDisconnection(err: any): err is DisconnectionObject;
3
+ export type DisconnectionObject = {
4
+ name: string;
5
+ upgradeMessage: string;
6
+ incarnationNumber: number;
7
+ };
8
+ //# sourceMappingURL=upgrade-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade-api.d.ts","sourceRoot":"","sources":["upgrade-api.js"],"names":[],"mappings":"AAgBO,yDAJI,MAAM,uBACN,MAAM,GACJ,mBAAmB,CAO5B;AAcG,4CAHI,GAAG,8BAO6B;kCAlC9B;IAAE,MAAM,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE"}