@agoric/internal 0.3.3-other-dev-fbe72e7.0.fbe72e7 → 0.3.3-other-dev-d15096d.0.d15096d
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/README.md +1 -4
- package/package.json +7 -5
- package/src/batched-deliver.d.ts +6 -2
- package/src/batched-deliver.d.ts.map +1 -1
- package/src/batched-deliver.js +7 -2
- package/src/callback.d.ts +9 -11
- package/src/callback.d.ts.map +1 -1
- package/src/callback.js +16 -10
- package/src/config.d.ts +19 -0
- package/src/config.d.ts.map +1 -1
- package/src/config.js +21 -0
- package/src/debug.d.ts +4 -1
- package/src/debug.d.ts.map +1 -1
- package/src/debug.js +26 -13
- package/src/index.d.ts +1 -1
- package/src/index.js +9 -1
- package/src/js-utils.d.ts +6 -2
- package/src/js-utils.d.ts.map +1 -1
- package/src/js-utils.js +23 -1
- package/src/lib-chainStorage.d.ts +23 -12
- package/src/lib-chainStorage.d.ts.map +1 -1
- package/src/lib-chainStorage.js +18 -18
- package/src/lib-nodejs/spawnSubprocessWorker.d.ts +0 -2
- package/src/lib-nodejs/spawnSubprocessWorker.d.ts.map +1 -1
- package/src/lib-nodejs/spawnSubprocessWorker.js +5 -3
- package/src/lib-nodejs/waitUntilQuiescent.d.ts +3 -0
- package/src/lib-nodejs/waitUntilQuiescent.d.ts.map +1 -1
- package/src/lib-nodejs/waitUntilQuiescent.js +5 -1
- package/src/marshal/board-client-utils.d.ts +19 -0
- package/src/marshal/board-client-utils.d.ts.map +1 -0
- package/src/{marshal.js → marshal/board-client-utils.js} +27 -52
- package/src/marshal/cap-data.d.ts +3 -0
- package/src/marshal/cap-data.d.ts.map +1 -0
- package/src/marshal/cap-data.js +20 -0
- package/src/marshal/inaccessible-val.d.ts +2 -0
- package/src/marshal/inaccessible-val.d.ts.map +1 -0
- package/src/marshal/inaccessible-val.js +15 -0
- package/src/marshal/pure-data.d.ts +8 -0
- package/src/marshal/pure-data.d.ts.map +1 -0
- package/src/marshal/pure-data.js +14 -0
- package/src/marshal/wrap-marshaller.d.ts +33 -0
- package/src/marshal/wrap-marshaller.d.ts.map +1 -0
- package/src/marshal/wrap-marshaller.js +439 -0
- package/src/natural-sort.d.ts.map +1 -1
- package/src/natural-sort.js +47 -12
- package/src/node/buffer-line-transform.d.ts +10 -5
- package/src/node/buffer-line-transform.d.ts.map +1 -1
- package/src/node/buffer-line-transform.js +8 -4
- package/src/node/fs-stream.d.ts +4 -1
- package/src/node/fs-stream.d.ts.map +1 -1
- package/src/node/fs-stream.js +8 -6
- package/src/node/shutdown.d.ts.map +1 -1
- package/src/node/shutdown.js +2 -0
- package/src/priority-senders.d.ts +2 -1
- package/src/priority-senders.d.ts.map +1 -1
- package/src/priority-senders.js +6 -4
- package/src/ses-utils.d.ts +15 -4
- package/src/ses-utils.d.ts.map +1 -1
- package/src/ses-utils.js +112 -14
- package/src/storage-test-utils.d.ts +13 -3
- package/src/storage-test-utils.d.ts.map +1 -1
- package/src/storage-test-utils.js +61 -7
- package/src/typeGuards.d.ts +6 -2
- package/src/typeGuards.d.ts.map +1 -1
- package/src/typeGuards.js +5 -1
- package/src/types.d.ts +18 -17
- package/src/types.d.ts.map +1 -1
- package/src/types.ts +22 -18
- package/src/work-pool.d.ts +13 -0
- package/src/work-pool.d.ts.map +1 -0
- package/src/work-pool.js +233 -0
- package/src/marshal.d.ts +0 -33
- package/src/marshal.d.ts.map +0 -1
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { makeCacheMapKit } from '@endo/cache-map';
|
|
3
|
+
import { Fail, q } from '@endo/errors';
|
|
4
|
+
import { E } from '@endo/eventual-send';
|
|
5
|
+
import { Far } from '@endo/far';
|
|
6
|
+
import { PASS_STYLE } from '@endo/pass-style';
|
|
7
|
+
import { makeMarshal } from '@endo/marshal';
|
|
8
|
+
import { makeInaccessibleVal } from './inaccessible-val.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @import {WeakMapAPI} from '@endo/cache-map';
|
|
12
|
+
* @import {EOnly} from '@endo/eventual-send';
|
|
13
|
+
* @import {RemotableObject, Simplify} from '@endo/pass-style';
|
|
14
|
+
* @import {CapData, Passable, Marshal, MakeMarshalOptions} from '@endo/marshal';
|
|
15
|
+
* @import {ERemote} from '../types.js';
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A Marshaller which methods may be async. Use this type to indicate accepting
|
|
20
|
+
* either a sync or async marshaller, usually through `E` eventual-sends.
|
|
21
|
+
*
|
|
22
|
+
* @template [Slot=unknown]
|
|
23
|
+
* @typedef {Simplify<EOnly<Marshal<Slot>>>} EMarshaller
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const { slotToWrapper, wrapperToSlot } = (() => {
|
|
27
|
+
/** @typedef {'Remotable' | `Alleged: ${string}`} InterfaceSpec */
|
|
28
|
+
|
|
29
|
+
/** @template [Slot=unknown] */
|
|
30
|
+
class SlotWrapper {
|
|
31
|
+
/** @type {Slot} */
|
|
32
|
+
#slot;
|
|
33
|
+
|
|
34
|
+
/** @type {InterfaceSpec} */
|
|
35
|
+
[Symbol.toStringTag];
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {Slot} slot
|
|
39
|
+
* @param {string} [iface]
|
|
40
|
+
*/
|
|
41
|
+
constructor(slot, iface) {
|
|
42
|
+
if (iface == null || iface === 'Remotable') {
|
|
43
|
+
iface = 'Remotable';
|
|
44
|
+
} else if (!iface.startsWith('Alleged: ')) {
|
|
45
|
+
iface = `Alleged: ${iface}`;
|
|
46
|
+
}
|
|
47
|
+
this.#slot = slot;
|
|
48
|
+
this[Symbol.toStringTag] = /** @type {InterfaceSpec} */ (iface);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** @param {SlotWrapper} wrapper */
|
|
52
|
+
static getSlot(wrapper) {
|
|
53
|
+
return wrapper.#slot;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
Object.defineProperties(SlotWrapper.prototype, {
|
|
57
|
+
[PASS_STYLE]: { value: 'remotable' },
|
|
58
|
+
[Symbol.toStringTag]: { value: 'Alleged: SlotWrapper' },
|
|
59
|
+
});
|
|
60
|
+
Reflect.deleteProperty(SlotWrapper.prototype, 'constructor');
|
|
61
|
+
harden(SlotWrapper);
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @type {<Slot = unknown>(
|
|
65
|
+
* wrapper: SlotWrapper<Slot> & RemotableObject<InterfaceSpec>,
|
|
66
|
+
* ) => Slot}
|
|
67
|
+
*/
|
|
68
|
+
const getSlot = SlotWrapper.getSlot;
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
/**
|
|
72
|
+
* @template [Slot=unknown]
|
|
73
|
+
* @param {Slot} slot
|
|
74
|
+
* @param {string} [iface]
|
|
75
|
+
*/
|
|
76
|
+
slotToWrapper: (slot, iface) =>
|
|
77
|
+
/** @type {SlotWrapper<Slot> & RemotableObject<InterfaceSpec>} */ (
|
|
78
|
+
harden(new SlotWrapper(slot, iface))
|
|
79
|
+
),
|
|
80
|
+
|
|
81
|
+
wrapperToSlot: getSlot,
|
|
82
|
+
};
|
|
83
|
+
})();
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @template [Slot=unknown] @typedef {ReturnType<typeof slotToWrapper<Slot>>}
|
|
87
|
+
* SlotWrapper
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
const capacityOfDefaultCache = 50;
|
|
91
|
+
|
|
92
|
+
// TODO(https://github.com/Agoric/agoric-sdk/issues/12111)
|
|
93
|
+
// Check cost of using virtual-aware WeakMap in liveslots
|
|
94
|
+
/**
|
|
95
|
+
* @template K
|
|
96
|
+
* @template V
|
|
97
|
+
* @param {boolean} [weakKey]
|
|
98
|
+
*/
|
|
99
|
+
const makeDefaultCacheMap = weakKey =>
|
|
100
|
+
/** @type {WeakMapAPI<K, V>} */ (
|
|
101
|
+
makeCacheMapKit(capacityOfDefaultCache, {
|
|
102
|
+
makeMap: weakKey ? WeakMap : Map,
|
|
103
|
+
}).cache
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Wraps a marshaller, either sync or async, local or remote, into a local async
|
|
108
|
+
* marshaller which only sends slots for resolution to the wrapped marshaller.
|
|
109
|
+
* Optionally and by default, caches the resolution of slots.
|
|
110
|
+
*
|
|
111
|
+
* Assumes that a null-ish slot value is a severed presence that can be resolved
|
|
112
|
+
* locally. By default if a presence is mapped to a null-ish slot by the wrapped
|
|
113
|
+
* marshaller, that mapping is not cached, allowing the wrapped marshaller to
|
|
114
|
+
* create a mapping in the future.
|
|
115
|
+
*
|
|
116
|
+
* @template [Slot=unknown]
|
|
117
|
+
* @param {ERemote<Pick<EMarshaller<Slot>, 'fromCapData' | 'toCapData'>>} marshaller
|
|
118
|
+
* @param {MakeMarshalOptions} [marshalOptions]
|
|
119
|
+
* @param {object} [caches]
|
|
120
|
+
* @param {WeakMapAPI<object, Slot> | null} [caches.valToSlot]
|
|
121
|
+
* @param {WeakMapAPI<Slot, object> | null} [caches.slotToVal]
|
|
122
|
+
* @param {boolean} [caches.cacheSeveredVal]
|
|
123
|
+
* @returns {ReturnType<typeof Far<EMarshaller<Slot>>>}
|
|
124
|
+
*/
|
|
125
|
+
export const wrapRemoteMarshallerSendSlotsOnly = (
|
|
126
|
+
marshaller,
|
|
127
|
+
{
|
|
128
|
+
serializeBodyFormat = 'smallcaps',
|
|
129
|
+
errorTagging = 'off', // Disable error tagging by default
|
|
130
|
+
...otherMarshalOptions
|
|
131
|
+
} = {},
|
|
132
|
+
{
|
|
133
|
+
valToSlot = makeDefaultCacheMap(true),
|
|
134
|
+
slotToVal = makeDefaultCacheMap(false),
|
|
135
|
+
cacheSeveredVal = false,
|
|
136
|
+
} = {},
|
|
137
|
+
) => {
|
|
138
|
+
const marshalOptions = harden({
|
|
139
|
+
serializeBodyFormat,
|
|
140
|
+
errorTagging,
|
|
141
|
+
...otherMarshalOptions,
|
|
142
|
+
});
|
|
143
|
+
// The implementation of this wrapped marshaller internally uses 2 marshallers
|
|
144
|
+
// to transform the CapData into a Passable structure and vice-versa:
|
|
145
|
+
// - A cap pass-through marshaller which places capabilities as-is in the slots.
|
|
146
|
+
// When unserializing CapData with null-ish slots, a severed presence is created.
|
|
147
|
+
// This pass-through marshaller is used to locally process the structure, and
|
|
148
|
+
// separate capabilities into a slots array for potential resolution by the
|
|
149
|
+
// wrapped marshaller.
|
|
150
|
+
// - A "SlotWrapper" marshaller used to wrap into remotables the slots of the
|
|
151
|
+
// wrapped marshaller. When unserializing CapData, it is used to recreate
|
|
152
|
+
// CapData of a simple array of non-severed capabilities for resolution by
|
|
153
|
+
// the wrapped marshaller. When serializing to CapData, it allows extracting
|
|
154
|
+
// the slots from the capabilities array serialized by the wrapped marshaller.
|
|
155
|
+
|
|
156
|
+
/** @type {Marshal<object | null>} */
|
|
157
|
+
const passThroughMarshaller = makeMarshal(
|
|
158
|
+
undefined,
|
|
159
|
+
(slot, iface) => slot ?? makeInaccessibleVal(iface),
|
|
160
|
+
marshalOptions,
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
/** @type {Map<Slot, SlotWrapper<NonNullable<Slot>>>} */
|
|
164
|
+
const currentSlotToWrapper = new Map();
|
|
165
|
+
|
|
166
|
+
const convertWrapperToSlot = /** @type {typeof wrapperToSlot<Slot>} */ (
|
|
167
|
+
wrapperToSlot
|
|
168
|
+
);
|
|
169
|
+
/**
|
|
170
|
+
* @param {Slot} slot
|
|
171
|
+
* @param {string | undefined} [iface]
|
|
172
|
+
*/
|
|
173
|
+
const convertSlotToWrapper = (slot, iface) => {
|
|
174
|
+
if (slot == null) {
|
|
175
|
+
// The wrapped marshaller may send us CapData with a null slot. These are not
|
|
176
|
+
// meant to be considered equivalent with each other, so bypass mapping.
|
|
177
|
+
return slotToWrapper(slot, iface);
|
|
178
|
+
}
|
|
179
|
+
let wrapper = currentSlotToWrapper.get(slot);
|
|
180
|
+
if (!wrapper) {
|
|
181
|
+
wrapper = slotToWrapper(slot, iface);
|
|
182
|
+
currentSlotToWrapper.set(slot, wrapper);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return wrapper;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
/** @type {Pick<Marshal<Slot>, 'toCapData' | 'fromCapData'>} */
|
|
189
|
+
const slotWrapperMarshaller = makeMarshal(
|
|
190
|
+
convertWrapperToSlot,
|
|
191
|
+
convertSlotToWrapper,
|
|
192
|
+
marshalOptions,
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Resolves an array of wrapped marshaller's slots to an array of
|
|
197
|
+
* capabilities.
|
|
198
|
+
*
|
|
199
|
+
* This is used by `fromCapData` to map slots before using the pass-through
|
|
200
|
+
* marshaller to recreate the passable data.
|
|
201
|
+
*
|
|
202
|
+
* @param {Slot[]} slots
|
|
203
|
+
* @param {(index: number) => SlotWrapper<NonNullable<Slot>>} getWrapper
|
|
204
|
+
* @returns {Promise<(object | null)[]>}
|
|
205
|
+
*/
|
|
206
|
+
const mapSlotsToCaps = async (slots, getWrapper) => {
|
|
207
|
+
let hasRemoteCap = false;
|
|
208
|
+
const { length } = slots;
|
|
209
|
+
/** @type {(SlotWrapper<NonNullable<Slot>> | null | undefined)[]} */
|
|
210
|
+
const slotWrapperMappedSlots = Array.from({ length });
|
|
211
|
+
/** @type {(object | null | undefined)[]} */
|
|
212
|
+
const locallyResolvedCapSlots = Array.from({ length });
|
|
213
|
+
|
|
214
|
+
for (const [index, slot] of slots.entries()) {
|
|
215
|
+
if (slot === null) {
|
|
216
|
+
const nullSlot = /** @type {null} */ (slot);
|
|
217
|
+
slotWrapperMappedSlots[index] = nullSlot;
|
|
218
|
+
locallyResolvedCapSlots[index] = nullSlot;
|
|
219
|
+
} else if (slot !== undefined) {
|
|
220
|
+
const cachedCap = slotToVal?.get(slot);
|
|
221
|
+
if (cachedCap !== undefined) {
|
|
222
|
+
valToSlot?.set(cachedCap, slot);
|
|
223
|
+
locallyResolvedCapSlots[index] = cachedCap;
|
|
224
|
+
} else {
|
|
225
|
+
hasRemoteCap = true;
|
|
226
|
+
slotWrapperMappedSlots[index] = getWrapper(index);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
await null;
|
|
232
|
+
if (hasRemoteCap) {
|
|
233
|
+
harden(slotWrapperMappedSlots);
|
|
234
|
+
const slotsOnlyCapData = slotWrapperMarshaller.toCapData(
|
|
235
|
+
slotWrapperMappedSlots,
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
/** @type {(object | null | undefined)[]} */
|
|
239
|
+
const remotelyResolvedCapSlots =
|
|
240
|
+
await E(marshaller).fromCapData(slotsOnlyCapData);
|
|
241
|
+
|
|
242
|
+
for (const [index, val] of remotelyResolvedCapSlots.entries()) {
|
|
243
|
+
if (val != null) {
|
|
244
|
+
const slot = slots[index];
|
|
245
|
+
slotToVal?.set(slot, val);
|
|
246
|
+
valToSlot?.set(val, slot);
|
|
247
|
+
locallyResolvedCapSlots[index] = val;
|
|
248
|
+
} else if (locallyResolvedCapSlots[index] === undefined) {
|
|
249
|
+
const slot = slots[index];
|
|
250
|
+
console.warn('⚠️ Unresolved local slot in wrapped marshaller', {
|
|
251
|
+
index,
|
|
252
|
+
slot,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return harden(locallyResolvedCapSlots);
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Resolves an array of capabilities into an array of slots of the wrapped
|
|
263
|
+
* marshaller.
|
|
264
|
+
*
|
|
265
|
+
* This is used by `toCapData` to map slots after the pass-through marshaller
|
|
266
|
+
* has serialized the passable data.
|
|
267
|
+
*
|
|
268
|
+
* @param {object[]} caps
|
|
269
|
+
* @returns {Promise<Slot[]>}
|
|
270
|
+
*/
|
|
271
|
+
const mapCapsToSlots = async caps => {
|
|
272
|
+
if (caps.length === 0) {
|
|
273
|
+
return caps;
|
|
274
|
+
}
|
|
275
|
+
let hasRemoteCap = false;
|
|
276
|
+
const { length } = caps;
|
|
277
|
+
/** @type {(Slot | null | undefined)[]} */
|
|
278
|
+
const locallyResolvedSlots = Array.from({ length });
|
|
279
|
+
/** @type {(object | null | undefined)[]} */
|
|
280
|
+
const remoteCapsToResolve = Array.from({ length });
|
|
281
|
+
|
|
282
|
+
for (const [index, cap] of caps.entries()) {
|
|
283
|
+
if (cap === null) {
|
|
284
|
+
// We shouldn't get null caps here, but we mirror handle them anyway
|
|
285
|
+
const nullCap = /** @type {null} */ (cap);
|
|
286
|
+
remoteCapsToResolve[index] = nullCap;
|
|
287
|
+
locallyResolvedSlots[index] = nullCap;
|
|
288
|
+
} else if (cap !== undefined) {
|
|
289
|
+
const cachedSlot = valToSlot?.get(cap);
|
|
290
|
+
if (cachedSlot !== undefined) {
|
|
291
|
+
if (cachedSlot !== null) {
|
|
292
|
+
slotToVal?.set(cachedSlot, cap);
|
|
293
|
+
}
|
|
294
|
+
locallyResolvedSlots[index] = cachedSlot;
|
|
295
|
+
} else {
|
|
296
|
+
hasRemoteCap = true;
|
|
297
|
+
remoteCapsToResolve[index] = cap;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
await null;
|
|
303
|
+
if (hasRemoteCap) {
|
|
304
|
+
const remotelyResolvedSlotsCapData =
|
|
305
|
+
await E(marshaller).toCapData(remoteCapsToResolve);
|
|
306
|
+
try {
|
|
307
|
+
/** @type {(SlotWrapper<Slot> | null | undefined)[]} */
|
|
308
|
+
const slotWrapperMappedSlots = slotWrapperMarshaller.fromCapData(
|
|
309
|
+
remotelyResolvedSlotsCapData,
|
|
310
|
+
);
|
|
311
|
+
for (const [index, slotWrapper] of slotWrapperMappedSlots.entries()) {
|
|
312
|
+
if (slotWrapper != null) {
|
|
313
|
+
const slot = convertWrapperToSlot(slotWrapper);
|
|
314
|
+
const val = caps[index];
|
|
315
|
+
locallyResolvedSlots[index] = slot;
|
|
316
|
+
if (slot != null) {
|
|
317
|
+
slotToVal?.set(slot, val);
|
|
318
|
+
}
|
|
319
|
+
if (slot != null || cacheSeveredVal) {
|
|
320
|
+
valToSlot?.set(val, slot);
|
|
321
|
+
}
|
|
322
|
+
} else if (locallyResolvedSlots[index] === undefined) {
|
|
323
|
+
const cap = caps[index];
|
|
324
|
+
console.warn('⚠️ Unresolved local slot in wrapped marshaller', {
|
|
325
|
+
index,
|
|
326
|
+
cap,
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
} finally {
|
|
331
|
+
// We're done with the slotWrapperMarshaller, clear its state
|
|
332
|
+
currentSlotToWrapper.clear();
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// All slots should have been resolved by now (or warned about)
|
|
337
|
+
return /** @type {Slot[]} */ (harden(locallyResolvedSlots));
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Unfortunately CapData only contains iface information for slotted
|
|
342
|
+
* capabilities nested inside the body, which means we need to process the
|
|
343
|
+
* body to extract it. Maybe in the future CapData could be extended to carry
|
|
344
|
+
* this separately. See https://github.com/endojs/endo/issues/2991
|
|
345
|
+
*
|
|
346
|
+
* Since this helper is used internally to ultimately provide SlotWrapper
|
|
347
|
+
* objects to the corresponding marshaller, and that we use the same
|
|
348
|
+
* marshaller to extract the iface information, directly return the full
|
|
349
|
+
* SlotWrapper object instead of just the iface.
|
|
350
|
+
*
|
|
351
|
+
* @param {CapData<Slot>} data
|
|
352
|
+
*/
|
|
353
|
+
const makeIfaceExtractor = data => {
|
|
354
|
+
const { slots } = data;
|
|
355
|
+
/** @param {number} index */
|
|
356
|
+
const getWrapper = index => {
|
|
357
|
+
const slot = slots[index];
|
|
358
|
+
let wrapper = currentSlotToWrapper.get(slot);
|
|
359
|
+
if (!wrapper) {
|
|
360
|
+
void slotWrapperMarshaller.fromCapData(data);
|
|
361
|
+
}
|
|
362
|
+
wrapper = currentSlotToWrapper.get(slot);
|
|
363
|
+
if (!wrapper) {
|
|
364
|
+
throw Fail`Marshaller didn't create wrapper for slot ${q(slot)} (index=${q(index)})`;
|
|
365
|
+
}
|
|
366
|
+
return wrapper;
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
return getWrapper;
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* @param {Passable} val
|
|
374
|
+
* @returns {Promise<CapData<Slot>>}
|
|
375
|
+
*/
|
|
376
|
+
const toCapData = async val => {
|
|
377
|
+
const capData = passThroughMarshaller.toCapData(val);
|
|
378
|
+
const mappedSlots = await mapCapsToSlots(capData.slots);
|
|
379
|
+
return harden({ ...capData, slots: mappedSlots });
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* @param {CapData<Slot>} data
|
|
384
|
+
* @returns {Promise<Passable>}
|
|
385
|
+
*/
|
|
386
|
+
const fromCapData = async data => {
|
|
387
|
+
const getWrapper = makeIfaceExtractor(data);
|
|
388
|
+
await null;
|
|
389
|
+
try {
|
|
390
|
+
const mappedSlots = await mapSlotsToCaps(data.slots, getWrapper);
|
|
391
|
+
return passThroughMarshaller.fromCapData({ ...data, slots: mappedSlots });
|
|
392
|
+
} finally {
|
|
393
|
+
currentSlotToWrapper.clear();
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
return Far('wrapped remote marshaller', {
|
|
398
|
+
toCapData,
|
|
399
|
+
fromCapData,
|
|
400
|
+
|
|
401
|
+
// for backwards compatibility
|
|
402
|
+
/** @deprecated use toCapData */
|
|
403
|
+
serialize: toCapData,
|
|
404
|
+
/** @deprecated use fromCapData */
|
|
405
|
+
unserialize: fromCapData,
|
|
406
|
+
});
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* @template [Slot=unknown]
|
|
411
|
+
* @param {ERemote<Pick<EMarshaller<Slot>, 'fromCapData' | 'toCapData'>>} marshaller
|
|
412
|
+
* @returns {ReturnType<typeof Far<EMarshaller<Slot>>>}
|
|
413
|
+
*/
|
|
414
|
+
export const wrapRemoteMarshallerDirectSend = marshaller => {
|
|
415
|
+
/**
|
|
416
|
+
* @param {Passable} val
|
|
417
|
+
* @returns {Promise<CapData<Slot>>}
|
|
418
|
+
*/
|
|
419
|
+
const toCapData = val => E(marshaller).toCapData(val);
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* @param {CapData<Slot>} data
|
|
423
|
+
* @returns {Promise<Passable>}
|
|
424
|
+
*/
|
|
425
|
+
const fromCapData = data => E(marshaller).fromCapData(data);
|
|
426
|
+
|
|
427
|
+
return Far('wrapped remote marshaller', {
|
|
428
|
+
toCapData,
|
|
429
|
+
fromCapData,
|
|
430
|
+
|
|
431
|
+
// for backwards compatibility
|
|
432
|
+
/** @deprecated use toCapData */
|
|
433
|
+
serialize: toCapData,
|
|
434
|
+
/** @deprecated use fromCapData */
|
|
435
|
+
unserialize: fromCapData,
|
|
436
|
+
});
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
export const wrapRemoteMarshaller = wrapRemoteMarshallerSendSlotsOnly;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"natural-sort.d.ts","sourceRoot":"","sources":["natural-sort.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"natural-sort.d.ts","sourceRoot":"","sources":["natural-sort.js"],"names":[],"mappings":"AAgDO,kCAJI,MAAM,KACN,MAAM,GACJ,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAmCtB"}
|
package/src/natural-sort.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { provideLazyMap } from './js-utils.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* @param {string} a
|
|
3
5
|
* @param {string} b
|
|
@@ -22,27 +24,60 @@ const compareNats = (a, b) => {
|
|
|
22
24
|
// eslint-disable-next-line no-nested-ternary
|
|
23
25
|
const compareStrings = (a, b) => (a > b ? 1 : a < b ? -1 : 0);
|
|
24
26
|
|
|
25
|
-
const
|
|
27
|
+
const rCaptureDigits = /([0-9]+)/;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Splitting by regular expression can be expensive; we don't want to repeat
|
|
31
|
+
* that for every comparison against the same string.
|
|
32
|
+
*
|
|
33
|
+
* @type {Map<string, string[]>}
|
|
34
|
+
*/
|
|
35
|
+
const partsCache = new Map();
|
|
26
36
|
|
|
27
37
|
/**
|
|
28
|
-
* Perform a
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* ['ko', 100]
|
|
38
|
+
* Perform a multi-level natural-sort comparison, finding the decimal digit
|
|
39
|
+
* sequences in each operand and comparing first by each ([possibly empty]
|
|
40
|
+
* string prefix, integer) pair in turn, with a final comparision by string
|
|
41
|
+
* suffix as necessary (e.g., sorting 'ko42' before 'ko100' as ['ko', 42] vs.
|
|
42
|
+
* ['ko', 100] and 'parent1.child8' before 'parent1.child10' as ['parent', 1,
|
|
43
|
+
* 'child', 8] vs. ['parent', 1, 'child', 10]).
|
|
33
44
|
*
|
|
34
45
|
* @param {string} a
|
|
35
46
|
* @param {string} b
|
|
36
47
|
* @returns {-1 | 0 | 1}
|
|
37
48
|
*/
|
|
38
49
|
export const naturalCompare = (a, b) => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
50
|
+
// We want to maintain a cache only for the duration of each call to
|
|
51
|
+
// array.sort, and leverage the synchronous nature of that method in the first
|
|
52
|
+
// invocation of each turn (indicated by an empty cache) to schedule cache
|
|
53
|
+
// clearing in the *next* turn.
|
|
54
|
+
if (!partsCache.size) void Promise.resolve().then(() => partsCache.clear());
|
|
55
|
+
|
|
56
|
+
const aParts = provideLazyMap(partsCache, a, () => a.split(rCaptureDigits));
|
|
57
|
+
const bParts = provideLazyMap(partsCache, b, () => b.split(rCaptureDigits));
|
|
58
|
+
|
|
59
|
+
// An even index corresponds with a string part; an odd one with a digit part.
|
|
60
|
+
let i = 0;
|
|
61
|
+
for (; i + 1 < aParts.length; i += 2) {
|
|
62
|
+
if (i + 1 < bParts.length) {
|
|
63
|
+
// Both `a` and `b` have a digit part here, but we compare the preceding
|
|
64
|
+
// string part first in case those are unequal.
|
|
65
|
+
const result =
|
|
66
|
+
compareStrings(aParts[i], bParts[i]) ||
|
|
67
|
+
compareNats(aParts[i + 1], bParts[i + 1]);
|
|
68
|
+
if (result) return result;
|
|
69
|
+
} else {
|
|
70
|
+
// After a (possibly empty) common prefix, `a` has digits where `b` does
|
|
71
|
+
// not, so we use string comparison of `${aString}${aDigits}` vs.
|
|
72
|
+
// `${bString}`.
|
|
73
|
+
return compareStrings(`${aParts[i]}${aParts[i + 1]}`, bParts[i]);
|
|
44
74
|
}
|
|
45
75
|
}
|
|
46
|
-
|
|
76
|
+
if (bParts.length > aParts.length) {
|
|
77
|
+
// `b` has digits where `a` does not.
|
|
78
|
+
return compareStrings(aParts[i], `${bParts[i]}${bParts[i + 1]}`);
|
|
79
|
+
}
|
|
80
|
+
// If `a` and `b` differ, it's only in the final string suffix.
|
|
81
|
+
return compareStrings(aParts[i], bParts[i]);
|
|
47
82
|
};
|
|
48
83
|
harden(naturalCompare);
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import {TransformOptions} from 'node:stream';
|
|
3
|
+
* @import {TransformCallback} from 'node:stream';
|
|
4
|
+
*/
|
|
1
5
|
/**
|
|
2
6
|
* @typedef {object} BufferLineTransformOptions
|
|
3
7
|
* @property {Buffer | string | number} [break] line break matcher for
|
|
@@ -10,10 +14,9 @@ export default class BufferLineTransform extends Transform {
|
|
|
10
14
|
* The BufferLineTransform is reading String or Buffer content from a Readable
|
|
11
15
|
* stream and writing each line as a Buffer in object mode
|
|
12
16
|
*
|
|
13
|
-
* @param {
|
|
14
|
-
* BufferLineTransformOptions} [options]
|
|
17
|
+
* @param {TransformOptions & BufferLineTransformOptions} [options]
|
|
15
18
|
*/
|
|
16
|
-
constructor(options?:
|
|
19
|
+
constructor(options?: TransformOptions & BufferLineTransformOptions);
|
|
17
20
|
_breakValue: string | number | Buffer<ArrayBufferLike>;
|
|
18
21
|
_breakEncoding: BufferEncoding | undefined;
|
|
19
22
|
_breakLength: number;
|
|
@@ -22,10 +25,10 @@ export default class BufferLineTransform extends Transform {
|
|
|
22
25
|
/**
|
|
23
26
|
* @param {any} chunk
|
|
24
27
|
* @param {BufferEncoding | 'buffer'} encoding
|
|
25
|
-
* @param {
|
|
28
|
+
* @param {TransformCallback} cb
|
|
26
29
|
* @override
|
|
27
30
|
*/
|
|
28
|
-
override _transform(chunk: any, encoding: BufferEncoding | "buffer", cb:
|
|
31
|
+
override _transform(chunk: any, encoding: BufferEncoding | "buffer", cb: TransformCallback): void;
|
|
29
32
|
/** @param {Buffer} line */
|
|
30
33
|
_writeItem(line: Buffer): void;
|
|
31
34
|
}
|
|
@@ -42,4 +45,6 @@ export type BufferLineTransformOptions = {
|
|
|
42
45
|
breakEncoding?: BufferEncoding | undefined;
|
|
43
46
|
};
|
|
44
47
|
import { Transform } from 'node:stream';
|
|
48
|
+
import type { TransformCallback } from 'node:stream';
|
|
49
|
+
import type { TransformOptions } from 'node:stream';
|
|
45
50
|
//# sourceMappingURL=buffer-line-transform.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buffer-line-transform.d.ts","sourceRoot":"","sources":["buffer-line-transform.js"],"names":[],"mappings":"AAKA;;;;;;GAMG;AAEH;IACE
|
|
1
|
+
{"version":3,"file":"buffer-line-transform.d.ts","sourceRoot":"","sources":["buffer-line-transform.js"],"names":[],"mappings":"AAKA;;;GAGG;AAEH;;;;;;GAMG;AAEH;IACE;;;;;OAKG;IACH,sBAFW,gBAAgB,GAAG,0BAA0B,EAyBvD;IAhBC,uDAAmC;IACnC,2CAAmC;IAWnC,qBAA+B;IAE/B,uBAAuB;IACvB,SADW,MAAM,EAAE,CACF;IAGnB;;;;;OAKG;IACH,2BALW,GAAG,YACH,cAAc,GAAG,QAAQ,MACzB,iBAAiB,QAiD3B;IAeD,2BAA2B;IAC3B,iBADY,MAAM,QAOjB;CACF;;;;;;;;;;;;;0BA1HyB,aAAa;uCAIH,aAAa;sCADd,aAAa"}
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
|
|
4
4
|
import { Transform } from 'node:stream';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @import {TransformOptions} from 'node:stream';
|
|
8
|
+
* @import {TransformCallback} from 'node:stream';
|
|
9
|
+
*/
|
|
10
|
+
|
|
6
11
|
/**
|
|
7
12
|
* @typedef {object} BufferLineTransformOptions
|
|
8
13
|
* @property {Buffer | string | number} [break] line break matcher for
|
|
@@ -16,8 +21,7 @@ export default class BufferLineTransform extends Transform {
|
|
|
16
21
|
* The BufferLineTransform is reading String or Buffer content from a Readable
|
|
17
22
|
* stream and writing each line as a Buffer in object mode
|
|
18
23
|
*
|
|
19
|
-
* @param {
|
|
20
|
-
* BufferLineTransformOptions} [options]
|
|
24
|
+
* @param {TransformOptions & BufferLineTransformOptions} [options]
|
|
21
25
|
*/
|
|
22
26
|
constructor(options) {
|
|
23
27
|
const {
|
|
@@ -47,7 +51,7 @@ export default class BufferLineTransform extends Transform {
|
|
|
47
51
|
/**
|
|
48
52
|
* @param {any} chunk
|
|
49
53
|
* @param {BufferEncoding | 'buffer'} encoding
|
|
50
|
-
* @param {
|
|
54
|
+
* @param {TransformCallback} cb
|
|
51
55
|
* @override
|
|
52
56
|
*/
|
|
53
57
|
_transform(chunk, encoding, cb) {
|
|
@@ -99,7 +103,7 @@ export default class BufferLineTransform extends Transform {
|
|
|
99
103
|
}
|
|
100
104
|
|
|
101
105
|
/**
|
|
102
|
-
* @param {
|
|
106
|
+
* @param {TransformCallback} cb
|
|
103
107
|
* @override
|
|
104
108
|
*/
|
|
105
109
|
_flush(cb) {
|
package/src/node/fs-stream.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
export function fsStreamReady(stream:
|
|
1
|
+
export function fsStreamReady(stream: ReadStream | WriteStream | Socket): Promise<void>;
|
|
2
2
|
export function makeFsStreamWriter(filePath: string | undefined | null): Promise<{
|
|
3
3
|
write: (data: any) => Promise<void>;
|
|
4
4
|
flush: () => Promise<void>;
|
|
5
5
|
close: () => Promise<void>;
|
|
6
6
|
} | undefined>;
|
|
7
7
|
export type FsStreamWriter = NonNullable<Awaited<ReturnType<typeof makeFsStreamWriter>>>;
|
|
8
|
+
import type { ReadStream } from 'fs';
|
|
9
|
+
import type { WriteStream } from 'fs';
|
|
10
|
+
import type { Socket } from 'net';
|
|
8
11
|
//# sourceMappingURL=fs-stream.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs-stream.d.ts","sourceRoot":"","sources":["fs-stream.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fs-stream.d.ts","sourceRoot":"","sources":["fs-stream.js"],"names":[],"mappings":"AAcO,sCAHI,UAAU,GAAG,WAAW,GAAG,MAAM,GAC/B,OAAO,CAAC,IAAI,CAAC,CAgCtB;AAIG,6CADK,MAAM,GAAG,SAAS,GAAG,IAAI;;;;eAsEpC;6BAvEa,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,CAAC;gCAzC5C,IAAI;iCACH,IAAI;4BACT,KAAK"}
|
package/src/node/fs-stream.js
CHANGED
|
@@ -3,9 +3,13 @@ import process from 'node:process';
|
|
|
3
3
|
import { promisify } from 'node:util';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* @
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* @import {ReadStream} from 'fs';
|
|
7
|
+
* @import {WriteStream} from 'fs';
|
|
8
|
+
* @import {Socket} from 'net';
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {ReadStream | WriteStream | Socket} stream
|
|
9
13
|
* @returns {Promise<void>}
|
|
10
14
|
*/
|
|
11
15
|
export const fsStreamReady = stream =>
|
|
@@ -60,9 +64,7 @@ export const makeFsStreamWriter = async filePath => {
|
|
|
60
64
|
const closeAsync =
|
|
61
65
|
useStdout || !(/** @type {any} */ (stream).close)
|
|
62
66
|
? undefined
|
|
63
|
-
: promisify(
|
|
64
|
-
/** @type {import('fs').WriteStream} */ (stream).close.bind(stream),
|
|
65
|
-
);
|
|
67
|
+
: promisify(/** @type {WriteStream} */ (stream).close.bind(stream));
|
|
66
68
|
|
|
67
69
|
let flushed = Promise.resolve();
|
|
68
70
|
let closed = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shutdown.d.ts","sourceRoot":"","sources":["shutdown.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"shutdown.d.ts","sourceRoot":"","sources":["shutdown.js"],"names":[],"mappings":"AAOO;;EA8DN;AAGM,wDAON"}
|
package/src/node/shutdown.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
2
|
import anylogger from 'anylogger';
|
|
3
3
|
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
5
|
+
// @ts-ignore TODO remove when anylogger has types
|
|
4
6
|
const console = anylogger('shutdown');
|
|
5
7
|
|
|
6
8
|
export const makeFreshShutdown = (verbose = true) => {
|