@agoric/async-flow 0.1.1-dev-2ca7ea6.0 → 0.1.1-dev-7b2cca2.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.
- package/package.json +8 -8
- package/src/async-flow.js +2 -2
- package/src/log-store.d.ts +39 -2
- package/src/log-store.d.ts.map +1 -1
- package/src/log-store.js +121 -22
- package/src/replay-membrane.d.ts.map +1 -1
- package/src/replay-membrane.js +14 -5
- package/src/type-guards.d.ts.map +1 -1
- package/src/type-guards.js +1 -0
- package/src/types.d.ts +3 -15
- package/src/types.d.ts.map +1 -1
- package/src/types.ts +9 -19
- package/test/log-store.test.js +46 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/async-flow",
|
|
3
|
-
"version": "0.1.1-dev-
|
|
3
|
+
"version": "0.1.1-dev-7b2cca2.0+7b2cca2",
|
|
4
4
|
"description": "Upgrade async functions at await points by replay",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": "https://github.com/Agoric/agoric-sdk",
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
"author": "Agoric",
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@agoric/base-zone": "0.1.1-dev-
|
|
28
|
-
"@agoric/internal": "0.3.3-dev-
|
|
29
|
-
"@agoric/store": "0.9.3-dev-
|
|
30
|
-
"@agoric/vow": "0.1.1-dev-
|
|
27
|
+
"@agoric/base-zone": "0.1.1-dev-7b2cca2.0+7b2cca2",
|
|
28
|
+
"@agoric/internal": "0.3.3-dev-7b2cca2.0+7b2cca2",
|
|
29
|
+
"@agoric/store": "0.9.3-dev-7b2cca2.0+7b2cca2",
|
|
30
|
+
"@agoric/vow": "0.1.1-dev-7b2cca2.0+7b2cca2",
|
|
31
31
|
"@endo/common": "^1.2.6",
|
|
32
32
|
"@endo/errors": "^1.2.6",
|
|
33
33
|
"@endo/eventual-send": "^1.2.6",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"@endo/promise-kit": "^1.1.6"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@agoric/swingset-vat": "0.32.3-dev-
|
|
41
|
-
"@agoric/zone": "0.2.3-dev-
|
|
40
|
+
"@agoric/swingset-vat": "0.32.3-dev-7b2cca2.0+7b2cca2",
|
|
41
|
+
"@agoric/zone": "0.2.3-dev-7b2cca2.0+7b2cca2",
|
|
42
42
|
"@endo/env-options": "^1.1.7",
|
|
43
43
|
"ava": "^5.3.0",
|
|
44
44
|
"tsd": "^0.31.1"
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"typeCoverage": {
|
|
63
63
|
"atLeast": 76.93
|
|
64
64
|
},
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "7b2cca28af123fd20507378cbd0a540352a38553"
|
|
66
66
|
}
|
package/src/async-flow.js
CHANGED
|
@@ -11,7 +11,7 @@ import { prepareEndowmentTools } from './endowments.js';
|
|
|
11
11
|
import { LogEntryShape, FlowStateShape } from './type-guards.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* @import {WeakMapStore} from '@agoric/store'
|
|
14
|
+
* @import {WeakMapStore, MapStore} from '@agoric/store'
|
|
15
15
|
* @import {Zone} from '@agoric/base-zone'
|
|
16
16
|
* @import {FlowState, GuestAsyncFunc, HostAsyncFuncWrapper, HostOf, PreparationOptions} from '../src/types.js'
|
|
17
17
|
* @import {ReplayMembrane} from '../src/replay-membrane.js'
|
|
@@ -70,7 +70,7 @@ export const prepareAsyncFlowTools = (outerZone, outerOptions = {}) => {
|
|
|
70
70
|
keyShape: M.remotable('flow'), // flowState !== 'Done'
|
|
71
71
|
});
|
|
72
72
|
|
|
73
|
-
/** @type WeakMapStore<AsyncFlow, ReplayMembrane> */
|
|
73
|
+
/** @type {WeakMapStore<AsyncFlow, ReplayMembrane>} */
|
|
74
74
|
const membraneMap = makeScalarWeakMapStore('membraneFor', {
|
|
75
75
|
keyShape: M.remotable('flow'),
|
|
76
76
|
valueShape: M.remotable('membrane'),
|
package/src/log-store.d.ts
CHANGED
|
@@ -1,24 +1,61 @@
|
|
|
1
|
+
export function nextGeneration(zone: Zone): number;
|
|
1
2
|
export function prepareLogStore(zone: Zone): () => import("@endo/exo").Guarded<{
|
|
2
3
|
reset(): void;
|
|
3
4
|
dispose(): void;
|
|
5
|
+
getUnfilteredIndex(): number;
|
|
4
6
|
getIndex(): number;
|
|
5
7
|
getLength(): number;
|
|
6
8
|
isReplaying(): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* @returns {LogEntry}
|
|
11
|
+
*/
|
|
7
12
|
peekEntry(): LogEntry;
|
|
13
|
+
/**
|
|
14
|
+
* @returns {LogEntry}
|
|
15
|
+
*/
|
|
16
|
+
nextUnfilteredEntry(): LogEntry;
|
|
17
|
+
/**
|
|
18
|
+
* @returns {LogEntry}
|
|
19
|
+
*/
|
|
8
20
|
nextEntry(): LogEntry;
|
|
9
|
-
|
|
21
|
+
/**
|
|
22
|
+
* @param {LogEntry} latestEntry
|
|
23
|
+
*/
|
|
24
|
+
pushEntry(latestEntry: LogEntry): number;
|
|
25
|
+
/**
|
|
26
|
+
* @returns {LogEntry[]}
|
|
27
|
+
*/
|
|
28
|
+
dumpUnfiltered(): LogEntry[];
|
|
10
29
|
dump(): ([op: "doFulfill", vow: import("@agoric/vow").Vow<import("@endo/pass-style").Passable>, fulfillment: import("@endo/pass-style").Passable] | [op: "doReject", vow: import("@agoric/vow").Vow<import("@endo/pass-style").Passable>, reason: import("@endo/pass-style").Passable] | [op: "doReturn", callIndex: number, result: import("@endo/pass-style").Passable] | [op: "doThrow", callIndex: number, problem: import("@endo/pass-style").Passable] | [op: "checkCall", target: import("@endo/pass-style").Passable, optVerb: PropertyKey | undefined, args: import("@endo/pass-style").Passable[], callIndex: number] | [op: "checkSendOnly", target: import("@endo/pass-style").Passable, optVerb: PropertyKey | undefined, args: import("@endo/pass-style").Passable[], callIndex: number] | [op: "checkSend", target: import("@endo/pass-style").Passable, optVerb: PropertyKey | undefined, args: import("@endo/pass-style").Passable[], callIndex: number])[];
|
|
11
30
|
promiseReplayDone(): Promise<undefined>;
|
|
12
31
|
}>;
|
|
13
32
|
export type LogStore = ReturnType<ReturnType<(zone: Zone) => () => import("@endo/exo").Guarded<{
|
|
14
33
|
reset(): void;
|
|
15
34
|
dispose(): void;
|
|
35
|
+
getUnfilteredIndex(): number;
|
|
16
36
|
getIndex(): number;
|
|
17
37
|
getLength(): number;
|
|
18
38
|
isReplaying(): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* @returns {LogEntry}
|
|
41
|
+
*/
|
|
19
42
|
peekEntry(): LogEntry;
|
|
43
|
+
/**
|
|
44
|
+
* @returns {LogEntry}
|
|
45
|
+
*/
|
|
46
|
+
nextUnfilteredEntry(): LogEntry;
|
|
47
|
+
/**
|
|
48
|
+
* @returns {LogEntry}
|
|
49
|
+
*/
|
|
20
50
|
nextEntry(): LogEntry;
|
|
21
|
-
|
|
51
|
+
/**
|
|
52
|
+
* @param {LogEntry} latestEntry
|
|
53
|
+
*/
|
|
54
|
+
pushEntry(latestEntry: LogEntry): number;
|
|
55
|
+
/**
|
|
56
|
+
* @returns {LogEntry[]}
|
|
57
|
+
*/
|
|
58
|
+
dumpUnfiltered(): LogEntry[];
|
|
22
59
|
dump(): ([op: "doFulfill", vow: import("@agoric/vow").Vow<import("@endo/pass-style").Passable>, fulfillment: import("@endo/pass-style").Passable] | [op: "doReject", vow: import("@agoric/vow").Vow<import("@endo/pass-style").Passable>, reason: import("@endo/pass-style").Passable] | [op: "doReturn", callIndex: number, result: import("@endo/pass-style").Passable] | [op: "doThrow", callIndex: number, problem: import("@endo/pass-style").Passable] | [op: "checkCall", target: import("@endo/pass-style").Passable, optVerb: PropertyKey | undefined, args: import("@endo/pass-style").Passable[], callIndex: number] | [op: "checkSendOnly", target: import("@endo/pass-style").Passable, optVerb: PropertyKey | undefined, args: import("@endo/pass-style").Passable[], callIndex: number] | [op: "checkSend", target: import("@endo/pass-style").Passable, optVerb: PropertyKey | undefined, args: import("@endo/pass-style").Passable[], callIndex: number])[];
|
|
23
60
|
promiseReplayDone(): Promise<undefined>;
|
|
24
61
|
}>>>;
|
package/src/log-store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-store.d.ts","sourceRoot":"","sources":["log-store.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"log-store.d.ts","sourceRoot":"","sources":["log-store.js"],"names":[],"mappings":"AAmCO,qCAHI,IAAI,GACF,MAAM,CAgBlB;AAOM,sCAFI,IAAI;;;;;;;IAoGT;;OAEG;iBADU,QAAQ;IAcrB;;OAEG;2BADU,QAAQ;IAgBrB;;OAEG;iBADU,QAAQ;IAWrB;;OAEG;2BADQ,QAAQ;IAuCnB;;OAEG;sBADU,QAAQ,EAAE;;;GAwB5B;uBAGY,UAAU,CAAC,UAAU,QApNvB,IAAI;;;;;;;IAoGT;;OAEG;iBADU,QAAQ;IAcrB;;OAEG;2BADU,QAAQ;IAgBrB;;OAEG;iBADU,QAAQ;IAWrB;;OAEG;2BADQ,QAAQ;IAuCnB;;OAEG;sBADU,QAAQ,EAAE;;;GA2BsB,CAAC;0BAlQ7B,mBAAmB;8BAEL,YAAY"}
|
package/src/log-store.js
CHANGED
|
@@ -14,31 +14,76 @@ import { makeEphemera } from './ephemera.js';
|
|
|
14
14
|
const LogStoreI = M.interface('LogStore', {
|
|
15
15
|
reset: M.call().returns(),
|
|
16
16
|
dispose: M.call().returns(),
|
|
17
|
+
getUnfilteredIndex: M.call().returns(M.number()),
|
|
17
18
|
getIndex: M.call().returns(M.number()),
|
|
18
19
|
getLength: M.call().returns(M.number()),
|
|
19
20
|
isReplaying: M.call().returns(M.boolean()),
|
|
20
21
|
peekEntry: M.call().returns(LogEntryShape),
|
|
21
22
|
nextEntry: M.call().returns(LogEntryShape),
|
|
23
|
+
nextUnfilteredEntry: M.call().returns(LogEntryShape),
|
|
22
24
|
pushEntry: M.call(LogEntryShape).returns(M.number()),
|
|
25
|
+
dumpUnfiltered: M.call().returns(M.arrayOf(LogEntryShape)),
|
|
23
26
|
dump: M.call().returns(M.arrayOf(LogEntryShape)),
|
|
24
27
|
promiseReplayDone: M.call().returns(M.promise()),
|
|
25
28
|
});
|
|
26
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Get a generation number to use in `startGeneration` log entries.
|
|
32
|
+
*
|
|
33
|
+
* @param {Zone} zone
|
|
34
|
+
* @returns {number}
|
|
35
|
+
*/
|
|
36
|
+
export const nextGeneration = zone => {
|
|
37
|
+
/** @type {MapStore<'generation', number>} */
|
|
38
|
+
const logStoreMetadata = zone.mapStore('LogStoreMetadata');
|
|
39
|
+
const generationKey = 'generation';
|
|
40
|
+
|
|
41
|
+
if (!logStoreMetadata.has(generationKey)) {
|
|
42
|
+
const firstGen = 0;
|
|
43
|
+
logStoreMetadata.init(generationKey, firstGen);
|
|
44
|
+
return firstGen;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const nextGen = logStoreMetadata.get(generationKey) + 1;
|
|
48
|
+
logStoreMetadata.set(generationKey, nextGen);
|
|
49
|
+
return nextGen;
|
|
50
|
+
};
|
|
51
|
+
|
|
27
52
|
/**
|
|
28
53
|
* A growable, replayable, sequence of `LogEntry`s.
|
|
29
54
|
*
|
|
30
55
|
* @param {Zone} zone
|
|
31
56
|
*/
|
|
32
57
|
export const prepareLogStore = zone => {
|
|
58
|
+
/**
|
|
59
|
+
* Ensure that any new or reset LogStore instance that (for a given
|
|
60
|
+
* incarnation) pushes at least one entry will insert these entries first,
|
|
61
|
+
* even if the log is reset, replayed, and pushed to in the same incarnation.
|
|
62
|
+
* @type {LogEntry[]}
|
|
63
|
+
*/
|
|
64
|
+
const initialPush = harden([['startGeneration', nextGeneration(zone)]]);
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A predicate to indicate whether the entry is normally visible to the
|
|
68
|
+
* LogStore user, or is a more internal entry that only is visible via the
|
|
69
|
+
* Unfiltered methods.
|
|
70
|
+
* @param {LogEntry} entry
|
|
71
|
+
*/
|
|
72
|
+
const entryIsVisible = entry => entry[0] !== 'startGeneration';
|
|
73
|
+
|
|
33
74
|
/**
|
|
34
75
|
* @type {Ephemera<LogStore, {
|
|
35
|
-
* index: number
|
|
36
|
-
*
|
|
76
|
+
* index: number;
|
|
77
|
+
* unfilteredIndex: number;
|
|
78
|
+
* initialPush: LogEntry[] | undefined;
|
|
79
|
+
* replayDoneKit: PromiseKit<undefined>;
|
|
37
80
|
* }>}
|
|
38
81
|
*/
|
|
39
82
|
const tmp = makeEphemera(log => {
|
|
40
83
|
const result = {
|
|
41
84
|
index: 0,
|
|
85
|
+
unfilteredIndex: 0,
|
|
86
|
+
initialPush,
|
|
42
87
|
replayDoneKit: makePromiseKit(),
|
|
43
88
|
};
|
|
44
89
|
if (log.getLength() === 0) {
|
|
@@ -82,6 +127,12 @@ export const prepareLogStore = zone => {
|
|
|
82
127
|
tmp.resetFor(self);
|
|
83
128
|
mapStore.clear();
|
|
84
129
|
},
|
|
130
|
+
getUnfilteredIndex() {
|
|
131
|
+
const { self } = this;
|
|
132
|
+
const eph = tmp.for(self);
|
|
133
|
+
|
|
134
|
+
return eph.unfilteredIndex;
|
|
135
|
+
},
|
|
85
136
|
getIndex() {
|
|
86
137
|
const { self } = this;
|
|
87
138
|
const eph = tmp.for(self);
|
|
@@ -99,52 +150,96 @@ export const prepareLogStore = zone => {
|
|
|
99
150
|
const { mapStore } = state;
|
|
100
151
|
const eph = tmp.for(self);
|
|
101
152
|
|
|
102
|
-
return eph.
|
|
153
|
+
return eph.unfilteredIndex < mapStore.getSize();
|
|
103
154
|
},
|
|
155
|
+
/**
|
|
156
|
+
* @returns {LogEntry}
|
|
157
|
+
*/
|
|
104
158
|
peekEntry() {
|
|
105
159
|
const { state, self } = this;
|
|
106
160
|
const { mapStore } = state;
|
|
107
161
|
const eph = tmp.for(self);
|
|
108
162
|
|
|
109
163
|
self.isReplaying() ||
|
|
110
|
-
Fail`No longer replaying: ${q(eph.
|
|
164
|
+
Fail`No longer replaying: ${q(eph.unfilteredIndex)} vs ${q(
|
|
111
165
|
mapStore.getSize(),
|
|
112
166
|
)}`;
|
|
113
|
-
const result = mapStore.get(eph.
|
|
167
|
+
const result = mapStore.get(eph.unfilteredIndex);
|
|
114
168
|
return result;
|
|
115
169
|
},
|
|
116
|
-
|
|
170
|
+
/**
|
|
171
|
+
* @returns {LogEntry}
|
|
172
|
+
*/
|
|
173
|
+
nextUnfilteredEntry() {
|
|
117
174
|
const { self } = this;
|
|
118
175
|
const eph = tmp.for(self);
|
|
119
176
|
|
|
120
177
|
const result = self.peekEntry();
|
|
121
|
-
eph.
|
|
178
|
+
eph.unfilteredIndex += 1;
|
|
179
|
+
if (entryIsVisible(result)) {
|
|
180
|
+
eph.index += 1;
|
|
181
|
+
}
|
|
122
182
|
if (!self.isReplaying()) {
|
|
123
183
|
eph.replayDoneKit.resolve(undefined);
|
|
124
184
|
}
|
|
125
185
|
return result;
|
|
126
186
|
},
|
|
127
|
-
|
|
187
|
+
/**
|
|
188
|
+
* @returns {LogEntry}
|
|
189
|
+
*/
|
|
190
|
+
nextEntry() {
|
|
191
|
+
const { self } = this;
|
|
192
|
+
let result = self.nextUnfilteredEntry();
|
|
193
|
+
while (!entryIsVisible(result)) {
|
|
194
|
+
self.isReplaying() || Fail`Unexpected entry at log tail: ${result}`;
|
|
195
|
+
result = self.nextUnfilteredEntry();
|
|
196
|
+
}
|
|
197
|
+
return result;
|
|
198
|
+
},
|
|
199
|
+
/**
|
|
200
|
+
* @param {LogEntry} latestEntry
|
|
201
|
+
*/
|
|
202
|
+
pushEntry(latestEntry) {
|
|
128
203
|
const { state, self } = this;
|
|
204
|
+
|
|
129
205
|
const { mapStore } = state;
|
|
130
206
|
const eph = tmp.for(self);
|
|
131
207
|
|
|
132
208
|
!self.isReplaying() ||
|
|
133
|
-
Fail`still replaying: ${q(eph.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
209
|
+
Fail`still replaying: ${q(eph.unfilteredIndex)} vs ${q(mapStore.getSize())}`;
|
|
210
|
+
|
|
211
|
+
const pushOne = entry => {
|
|
212
|
+
eph.unfilteredIndex === mapStore.getSize() ||
|
|
213
|
+
Fail`internal: unfilteredIndex confusion ${q(eph.unfilteredIndex)} vs ${q(
|
|
214
|
+
mapStore.getSize(),
|
|
215
|
+
)}`;
|
|
216
|
+
mapStore.init(eph.unfilteredIndex, entry);
|
|
217
|
+
eph.unfilteredIndex += 1;
|
|
218
|
+
if (entryIsVisible(entry)) {
|
|
219
|
+
eph.index += 1;
|
|
220
|
+
}
|
|
221
|
+
eph.unfilteredIndex === mapStore.getSize() ||
|
|
222
|
+
Fail`internal: unfilteredIndex confusion ${q(eph.unfilteredIndex)} vs ${q(
|
|
223
|
+
mapStore.getSize(),
|
|
224
|
+
)}`;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
if (eph.initialPush) {
|
|
228
|
+
const initialEntries = eph.initialPush;
|
|
229
|
+
eph.initialPush = undefined;
|
|
230
|
+
for (const initialEntry of initialEntries) {
|
|
231
|
+
pushOne(initialEntry);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
pushOne(latestEntry);
|
|
235
|
+
|
|
236
|
+
// console.log('LOG ENTRY ', eph.unfilteredIndex - 1, entry);
|
|
237
|
+
return eph.unfilteredIndex;
|
|
146
238
|
},
|
|
147
|
-
|
|
239
|
+
/**
|
|
240
|
+
* @returns {LogEntry[]}
|
|
241
|
+
*/
|
|
242
|
+
dumpUnfiltered() {
|
|
148
243
|
const { state } = this;
|
|
149
244
|
const { mapStore } = state;
|
|
150
245
|
const len = mapStore.getSize();
|
|
@@ -154,6 +249,10 @@ export const prepareLogStore = zone => {
|
|
|
154
249
|
}
|
|
155
250
|
return harden(result);
|
|
156
251
|
},
|
|
252
|
+
dump() {
|
|
253
|
+
const { self } = this;
|
|
254
|
+
return harden(self.dumpUnfiltered().filter(entryIsVisible));
|
|
255
|
+
},
|
|
157
256
|
promiseReplayDone() {
|
|
158
257
|
const { self } = this;
|
|
159
258
|
const eph = tmp.for(self);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-membrane.d.ts","sourceRoot":"","sources":["replay-membrane.js"],"names":[],"mappings":"AA+BO,wCANJ;IAAsB,GAAG,EAAjB,QAAQ;IACO,SAAS,EAAxB,SAAS;IACK,QAAQ,EAAtB,QAAQ;IAC6B,SAAS,EAA9C,CAAC,MAAM,EAAE,eAAU,GAAG,KAAK,IAAI;IACA,KAAK,EAApC,CAAC,OAAO,EAAE,KAAK,KAAK,KAAK;CACnC;;;;;;;;;;GAMA;AAWM,wHAPJ;IAAsB,GAAG,EAAjB,QAAQ;IACO,SAAS,EAAxB,SAAS;IACK,QAAQ,EAAtB,QAAQ;IAC6B,SAAS,EAA9C,CAAC,MAAM,EAAE,eAAU,GAAG,KAAK,IAAI;IACA,KAAK,EAApC,CAAC,OAAO,EAAE,KAAK,KAAK,KAAK;IACX,wBAAwB;CAChD;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"replay-membrane.d.ts","sourceRoot":"","sources":["replay-membrane.js"],"names":[],"mappings":"AA+BO,wCANJ;IAAsB,GAAG,EAAjB,QAAQ;IACO,SAAS,EAAxB,SAAS;IACK,QAAQ,EAAtB,QAAQ;IAC6B,SAAS,EAA9C,CAAC,MAAM,EAAE,eAAU,GAAG,KAAK,IAAI;IACA,KAAK,EAApC,CAAC,OAAO,EAAE,KAAK,KAAK,KAAK;CACnC;;;;;;;;;;GAMA;AAWM,wHAPJ;IAAsB,GAAG,EAAjB,QAAQ;IACO,SAAS,EAAxB,SAAS;IACK,QAAQ,EAAtB,QAAQ;IAC6B,SAAS,EAA9C,CAAC,MAAM,EAAE,eAAU,GAAG,KAAK,IAAI;IACA,KAAK,EAApC,CAAC,OAAO,EAAE,KAAK,KAAK,KAAK;IACX,wBAAwB;CAChD;;;;;;;;;;GA4pBA;6BAGa,UAAU,OAprBrB;IAAsB,GAAG,EAAjB,QAAQ;IACO,SAAS,EAAxB,SAAS;IACK,QAAQ,EAAtB,QAAQ;IAC6B,SAAS,EAA9C,CAAC,MAAM,EAAE,eAAU,GAAG,KAAK,IAAI;IACA,KAAK,EAApC,CAAC,OAAO,EAAE,KAAK,KAAK,KAAK;CACnC;;;;;;;;;;GA+qB2C;8BA7rBjB,qBAAqB;+BACpB,qBAAqB;8BAFT,aAAa;yBAAb,aAAa;8BADH,kBAAkB;oCADnC,qBAAqB"}
|
package/src/replay-membrane.js
CHANGED
|
@@ -63,6 +63,13 @@ export const makeReplayMembraneForTesting = ({
|
|
|
63
63
|
|
|
64
64
|
const Panic = (template, ...args) => panic(makeError(X(template, ...args)));
|
|
65
65
|
|
|
66
|
+
const startGeneration = generation => {
|
|
67
|
+
Number.isSafeInteger(generation) ||
|
|
68
|
+
Fail`generation expected integer; got ${generation}`;
|
|
69
|
+
generation >= 0 ||
|
|
70
|
+
Fail`generation expected non-negative; got ${generation}`;
|
|
71
|
+
};
|
|
72
|
+
|
|
66
73
|
// ////////////// Host or Interpreter to Guest ///////////////////////////////
|
|
67
74
|
|
|
68
75
|
/**
|
|
@@ -278,6 +285,7 @@ export const makeReplayMembraneForTesting = ({
|
|
|
278
285
|
throw Panic`internal: eventual send synchronously failed ${hostProblem}`;
|
|
279
286
|
}
|
|
280
287
|
try {
|
|
288
|
+
/** @type {LogEntry} */
|
|
281
289
|
const entry = harden(['doReturn', callIndex, vow]);
|
|
282
290
|
log.pushEntry(entry);
|
|
283
291
|
const guestPromise = makeGuestForHostVow(vow, guestReturnedP);
|
|
@@ -602,21 +610,22 @@ export const makeReplayMembraneForTesting = ({
|
|
|
602
610
|
// /////////////////////////////// Interpreter ///////////////////////////////
|
|
603
611
|
|
|
604
612
|
/**
|
|
605
|
-
* These are the only ones that are driven from the interpreter loop
|
|
613
|
+
* These are the only ones that are driven from the top level interpreter loop
|
|
606
614
|
*/
|
|
607
615
|
const topDispatch = harden({
|
|
616
|
+
startGeneration,
|
|
608
617
|
doFulfill,
|
|
609
618
|
doReject,
|
|
610
619
|
// doCall, // unimplemented in the current plan
|
|
611
620
|
});
|
|
612
621
|
|
|
613
622
|
/**
|
|
614
|
-
* These are the only ones that are driven from the interpreter loop
|
|
623
|
+
* These are the only ones that are driven from the nested interpreter loop
|
|
615
624
|
*/
|
|
616
625
|
const nestDispatch = harden({
|
|
617
|
-
// doCall, // unimplemented in the current plan
|
|
618
626
|
doReturn,
|
|
619
627
|
doThrow,
|
|
628
|
+
// doCall, // unimplemented in the current plan
|
|
620
629
|
});
|
|
621
630
|
|
|
622
631
|
const interpretOne = (dispatch, [op, ...args]) => {
|
|
@@ -646,7 +655,7 @@ export const makeReplayMembraneForTesting = ({
|
|
|
646
655
|
const nestInterpreter = callIndex => {
|
|
647
656
|
callStack.push(callIndex);
|
|
648
657
|
while (log.isReplaying() && !stopped) {
|
|
649
|
-
const entry = log.
|
|
658
|
+
const entry = log.nextUnfilteredEntry();
|
|
650
659
|
const optOutcome = interpretOne(nestDispatch, entry);
|
|
651
660
|
if (unnestFlag) {
|
|
652
661
|
optOutcome ||
|
|
@@ -687,7 +696,7 @@ export const makeReplayMembraneForTesting = ({
|
|
|
687
696
|
if (!(op in topDispatch)) {
|
|
688
697
|
return;
|
|
689
698
|
}
|
|
690
|
-
void log.
|
|
699
|
+
void log.nextUnfilteredEntry();
|
|
691
700
|
interpretOne(topDispatch, entry);
|
|
692
701
|
}
|
|
693
702
|
};
|
package/src/type-guards.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type-guards.d.ts","sourceRoot":"","sources":["type-guards.js"],"names":[],"mappings":"AAGA,8DAME;AAEF,gEAA6D;AAE7D,
|
|
1
|
+
{"version":3,"file":"type-guards.d.ts","sourceRoot":"","sources":["type-guards.js"],"names":[],"mappings":"AAGA,8DAME;AAEF,gEAA6D;AAE7D,6DAuDE"}
|
package/src/type-guards.js
CHANGED
|
@@ -12,6 +12,7 @@ export const FlowStateShape = M.or(
|
|
|
12
12
|
export const PropertyKeyShape = M.or(M.string(), M.symbol());
|
|
13
13
|
|
|
14
14
|
export const LogEntryShape = M.or(
|
|
15
|
+
['startGeneration', M.number()],
|
|
15
16
|
// ////////////////////////////// From Host to Guest /////////////////////////
|
|
16
17
|
['doFulfill', VowShape, M.any()],
|
|
17
18
|
['doReject', VowShape, M.any()],
|
package/src/types.d.ts
CHANGED
|
@@ -75,11 +75,7 @@ export type Ephemera<S extends WeakKey = WeakKey, V extends unknown = any> = {
|
|
|
75
75
|
* @see {FutureLogEntry} below for the full membrane log entry, which we do not
|
|
76
76
|
* yet support.
|
|
77
77
|
*/
|
|
78
|
-
export type LogEntry = [
|
|
79
|
-
op: 'doFulfill',
|
|
80
|
-
vow: HostVow,
|
|
81
|
-
fulfillment: Host
|
|
82
|
-
] | [op: 'doReject', vow: HostVow, reason: Host] | [op: 'doReturn', callIndex: number, result: Host] | [op: 'doThrow', callIndex: number, problem: Host] | [
|
|
78
|
+
export type LogEntry = [op: 'startGeneration', generation: number] | [op: 'doFulfill', vow: HostVow, fulfillment: Host] | [op: 'doReject', vow: HostVow, reason: Host] | [op: 'doReturn', callIndex: number, result: Host] | [op: 'doThrow', callIndex: number, problem: Host] | [
|
|
83
79
|
op: 'checkCall',
|
|
84
80
|
target: Host,
|
|
85
81
|
optVerb: PropertyKey | undefined,
|
|
@@ -104,11 +100,7 @@ export type LogEntry = [
|
|
|
104
100
|
* - the guest using `E` to eventual-send to guest wrappers of the host
|
|
105
101
|
* vows and remotables.
|
|
106
102
|
*/
|
|
107
|
-
export type FutureLogEntry = [
|
|
108
|
-
op: 'doFulfill',
|
|
109
|
-
vow: HostVow,
|
|
110
|
-
fulfillment: Host
|
|
111
|
-
] | [op: 'doReject', vow: HostVow, reason: Host] | [
|
|
103
|
+
export type FutureLogEntry = [op: 'startGeneration', generation: number] | [op: 'doFulfill', vow: HostVow, fulfillment: Host] | [op: 'doReject', vow: HostVow, reason: Host] | [
|
|
112
104
|
op: 'doCall',
|
|
113
105
|
target: Host,
|
|
114
106
|
optVerb: PropertyKey | undefined,
|
|
@@ -126,11 +118,7 @@ export type FutureLogEntry = [
|
|
|
126
118
|
optVerb: PropertyKey | undefined,
|
|
127
119
|
args: Host[],
|
|
128
120
|
callIndex: number
|
|
129
|
-
] | [op: 'doReturn', callIndex: number, result: Host] | [op: 'doThrow', callIndex: number, problem: Host] | [
|
|
130
|
-
op: 'checkFulfill',
|
|
131
|
-
vow: HostVow,
|
|
132
|
-
fulfillment: Host
|
|
133
|
-
] | [op: 'checkReject', vow: HostVow, reason: Host] | [
|
|
121
|
+
] | [op: 'doReturn', callIndex: number, result: Host] | [op: 'doThrow', callIndex: number, problem: Host] | [op: 'checkFulfill', vow: HostVow, fulfillment: Host] | [op: 'checkReject', vow: HostVow, reason: Host] | [
|
|
134
122
|
op: 'checkCall',
|
|
135
123
|
target: Host,
|
|
136
124
|
optVerb: PropertyKey | undefined,
|
package/src/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"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"}
|
package/src/types.ts
CHANGED
|
@@ -122,17 +122,14 @@ export type Ephemera<S extends WeakKey = WeakKey, V extends unknown = any> = {
|
|
|
122
122
|
* yet support.
|
|
123
123
|
*/
|
|
124
124
|
export type LogEntry =
|
|
125
|
-
| [
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
vow: HostVow,
|
|
129
|
-
fulfillment: Host,
|
|
130
|
-
]
|
|
125
|
+
| [op: 'startGeneration', generation: number]
|
|
126
|
+
// ///////////////// From Host to Guest /////////////////////////
|
|
127
|
+
| [op: 'doFulfill', vow: HostVow, fulfillment: Host]
|
|
131
128
|
| [op: 'doReject', vow: HostVow, reason: Host]
|
|
132
129
|
| [op: 'doReturn', callIndex: number, result: Host]
|
|
133
130
|
| [op: 'doThrow', callIndex: number, problem: Host]
|
|
131
|
+
// ///////////////////// From Guest to Host /////////////////////////
|
|
134
132
|
| [
|
|
135
|
-
// ///////////////////// From Guest to Host /////////////////////////
|
|
136
133
|
op: 'checkCall',
|
|
137
134
|
target: Host,
|
|
138
135
|
optVerb: PropertyKey | undefined,
|
|
@@ -161,12 +158,9 @@ export type LogEntry =
|
|
|
161
158
|
* vows and remotables.
|
|
162
159
|
*/
|
|
163
160
|
export type FutureLogEntry =
|
|
164
|
-
| [
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
vow: HostVow,
|
|
168
|
-
fulfillment: Host,
|
|
169
|
-
]
|
|
161
|
+
| [op: 'startGeneration', generation: number]
|
|
162
|
+
// ///////////////// From Host to Guest ///////////////////////
|
|
163
|
+
| [op: 'doFulfill', vow: HostVow, fulfillment: Host]
|
|
170
164
|
| [op: 'doReject', vow: HostVow, reason: Host]
|
|
171
165
|
| [
|
|
172
166
|
op: 'doCall',
|
|
@@ -191,12 +185,8 @@ export type FutureLogEntry =
|
|
|
191
185
|
]
|
|
192
186
|
| [op: 'doReturn', callIndex: number, result: Host]
|
|
193
187
|
| [op: 'doThrow', callIndex: number, problem: Host]
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
op: 'checkFulfill',
|
|
197
|
-
vow: HostVow,
|
|
198
|
-
fulfillment: Host,
|
|
199
|
-
]
|
|
188
|
+
// ///////////////////// From Guest to Host /////////////////////////
|
|
189
|
+
| [op: 'checkFulfill', vow: HostVow, fulfillment: Host]
|
|
200
190
|
| [op: 'checkReject', vow: HostVow, reason: Host]
|
|
201
191
|
| [
|
|
202
192
|
op: 'checkCall',
|
package/test/log-store.test.js
CHANGED
|
@@ -15,11 +15,9 @@ import { makeDurableZone } from '@agoric/zone/durable.js';
|
|
|
15
15
|
import { prepareLogStore } from '../src/log-store.js';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* @import {PromiseKit} from '@endo/promise-kit'
|
|
19
18
|
* @import {Zone} from '@agoric/base-zone'
|
|
20
|
-
* @import {Vow
|
|
19
|
+
* @import {Vow} from '@agoric/vow'
|
|
21
20
|
* @import {LogStore} from '../src/log-store.js';
|
|
22
|
-
* @import {Bijection} from '../src/bijection.js';
|
|
23
21
|
*/
|
|
24
22
|
|
|
25
23
|
/**
|
|
@@ -36,15 +34,23 @@ const testLogStorePlay = async (t, zone) => {
|
|
|
36
34
|
|
|
37
35
|
t.is(log.getIndex(), 0);
|
|
38
36
|
t.is(log.getLength(), 0);
|
|
39
|
-
t.throws(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
t.throws(
|
|
38
|
+
() =>
|
|
39
|
+
// @ts-expect-error testing invalid input
|
|
40
|
+
log.pushEntry(['bogus']),
|
|
41
|
+
{
|
|
42
|
+
message:
|
|
43
|
+
/^In "pushEntry" method of \(LogStore\): arg 0: \["bogus"\] - Must match one of/,
|
|
44
|
+
},
|
|
45
|
+
);
|
|
43
46
|
t.false(log.isReplaying());
|
|
44
47
|
t.is(await log.promiseReplayDone(), undefined);
|
|
45
48
|
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
const gen0Entries = [['startGeneration', 0]];
|
|
50
|
+
const gen0 = i => gen0Entries.length + i;
|
|
51
|
+
|
|
52
|
+
t.is(log.pushEntry(harden(['doFulfill', v1, 'x'])), gen0(1));
|
|
53
|
+
t.is(log.pushEntry(harden(['doReject', v2, 'y'])), gen0(2));
|
|
48
54
|
t.deepEqual(log.dump(), [
|
|
49
55
|
['doFulfill', v1, 'x'],
|
|
50
56
|
['doReject', v2, 'y'],
|
|
@@ -56,7 +62,8 @@ const testLogStorePlay = async (t, zone) => {
|
|
|
56
62
|
t.is(toPassableCap(log.dump()[1][1]), toPassableCap(v2));
|
|
57
63
|
|
|
58
64
|
t.is(log.getIndex(), 2);
|
|
59
|
-
t.is(log.
|
|
65
|
+
t.is(log.getUnfilteredIndex(), gen0(2));
|
|
66
|
+
t.is(log.getLength(), gen0(2));
|
|
60
67
|
t.false(log.isReplaying());
|
|
61
68
|
t.is(await log.promiseReplayDone(), undefined);
|
|
62
69
|
};
|
|
@@ -75,14 +82,26 @@ const testLogStoreReplay = async (t, zone) => {
|
|
|
75
82
|
const v1 = /** @type {Vow} */ (zone.makeOnce('v1', () => Fail`need v1`));
|
|
76
83
|
const v2 = /** @type {Vow} */ (zone.makeOnce('v2', () => Fail`need v2`));
|
|
77
84
|
|
|
85
|
+
const gen0Entries = [['startGeneration', 0]];
|
|
86
|
+
const gen0 = i => gen0Entries.length + i;
|
|
87
|
+
const gen1Entries = [['startGeneration', 1]];
|
|
88
|
+
const gen1 = i => gen1Entries.length + i;
|
|
89
|
+
|
|
78
90
|
t.is(log.getIndex(), 0);
|
|
79
|
-
t.is(log.
|
|
91
|
+
t.is(log.getUnfilteredIndex(), 0);
|
|
92
|
+
t.is(log.getLength(), gen0(2));
|
|
80
93
|
t.true(log.isReplaying());
|
|
81
94
|
|
|
82
95
|
t.deepEqual(log.dump(), [
|
|
83
96
|
['doFulfill', v1, 'x'],
|
|
84
97
|
['doReject', v2, 'y'],
|
|
85
98
|
]);
|
|
99
|
+
|
|
100
|
+
t.deepEqual(log.dumpUnfiltered(), [
|
|
101
|
+
...gen0Entries,
|
|
102
|
+
['doFulfill', v1, 'x'],
|
|
103
|
+
['doReject', v2, 'y'],
|
|
104
|
+
]);
|
|
86
105
|
// Because t.deepEqual is too tolerant
|
|
87
106
|
// @ts-expect-error data dependent typing
|
|
88
107
|
t.is(toPassableCap(log.dump()[0][1]), toPassableCap(v1));
|
|
@@ -92,8 +111,24 @@ const testLogStoreReplay = async (t, zone) => {
|
|
|
92
111
|
t.deepEqual(log.nextEntry(), ['doFulfill', v1, 'x']);
|
|
93
112
|
t.deepEqual(log.nextEntry(), ['doReject', v2, 'y']);
|
|
94
113
|
t.is(log.getIndex(), 2);
|
|
114
|
+
t.is(log.getUnfilteredIndex(), gen0(2));
|
|
95
115
|
t.false(log.isReplaying());
|
|
96
116
|
t.is(await log.promiseReplayDone(), undefined);
|
|
117
|
+
|
|
118
|
+
t.is(log.pushEntry(harden(['doFulfill', v1, 'x2'])), gen1(gen0(3)));
|
|
119
|
+
t.deepEqual(log.dumpUnfiltered(), [
|
|
120
|
+
...gen0Entries,
|
|
121
|
+
['doFulfill', v1, 'x'],
|
|
122
|
+
['doReject', v2, 'y'],
|
|
123
|
+
...gen1Entries,
|
|
124
|
+
['doFulfill', v1, 'x2'],
|
|
125
|
+
]);
|
|
126
|
+
|
|
127
|
+
// Check that a disposed log starts from scratch, but the same generation.
|
|
128
|
+
log.dispose();
|
|
129
|
+
t.deepEqual(log.dumpUnfiltered(), []);
|
|
130
|
+
t.is(log.pushEntry(harden(['doFulfill', v1, 'x3'])), gen1(1));
|
|
131
|
+
t.deepEqual(log.dumpUnfiltered(), [...gen1Entries, ['doFulfill', v1, 'x3']]);
|
|
97
132
|
};
|
|
98
133
|
|
|
99
134
|
await test.serial('test heap log-store', async t => {
|