@agoric/zone 0.2.3-dev-ff34bdf.0 → 0.2.3-dev-c4e4693.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/README.md +4 -4
- package/durable.d.ts +2 -0
- package/durable.d.ts.map +1 -0
- package/heap.d.ts +2 -0
- package/heap.d.ts.map +1 -0
- package/heap.js +1 -1
- package/jsconfig.build.json +11 -0
- package/jsconfig.json +3 -12
- package/package.json +7 -5
- package/src/durable.d.ts +2 -0
- package/src/durable.d.ts.map +1 -0
- package/src/durable.js +5 -3
- package/src/exports.d.ts +8 -0
- package/src/exports.js +2 -0
- package/src/index.d.ts +3 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js +3 -37
- package/src/virtual.d.ts +2 -0
- package/src/virtual.d.ts.map +1 -0
- package/src/virtual.js +5 -3
- package/test/test-exos.js +18 -160
- package/virtual.d.ts +2 -0
- package/virtual.d.ts.map +1 -0
- package/src/heap.js +0 -62
- package/src/is-passable.js +0 -23
- package/src/keys.js +0 -14
- package/src/make-once.js +0 -86
package/README.md
CHANGED
|
@@ -12,18 +12,18 @@ An example of making a Zone-aware vat might look something like this:
|
|
|
12
12
|
|
|
13
13
|
```js
|
|
14
14
|
import { makeDurableZone } from '@agoric/zone/durable.js';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
15
|
+
import { prepareFrobulator } from 'frob-package';
|
|
16
|
+
import { prepareWidget } from 'widget-package';
|
|
17
17
|
|
|
18
18
|
export const buildRootObject = (vatPowers, _args, baggage) => {
|
|
19
19
|
const zone = makeDurableZone(baggage);
|
|
20
20
|
|
|
21
21
|
// Ensure that Widgets cannot interfere with Frobs.
|
|
22
|
-
const makeWidget =
|
|
22
|
+
const makeWidget = prepareWidget(zone.subZone('Widgets'));
|
|
23
23
|
|
|
24
24
|
// Create a collection of frobulators.
|
|
25
25
|
const frobZone = zone.subZone('Frobs');
|
|
26
|
-
const makeFrobulator =
|
|
26
|
+
const makeFrobulator = prepareFrobulator(frobZone);
|
|
27
27
|
const widgetToFrob = frobZone.mapStore('widgetToFrob');
|
|
28
28
|
|
|
29
29
|
return Far('WidgetFrobulator', {
|
package/durable.d.ts
ADDED
package/durable.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable.d.ts","sourceRoot":"","sources":["durable.js"],"names":[],"mappings":""}
|
package/heap.d.ts
ADDED
package/heap.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heap.d.ts","sourceRoot":"","sources":["heap.js"],"names":[],"mappings":""}
|
package/heap.js
CHANGED
package/jsconfig.json
CHANGED
|
@@ -1,19 +1,10 @@
|
|
|
1
1
|
// This file can contain .js-specific Typescript compiler config.
|
|
2
2
|
{
|
|
3
|
-
"
|
|
4
|
-
"target": "esnext",
|
|
5
|
-
"module": "esnext",
|
|
6
|
-
"checkJs": true,
|
|
7
|
-
"noEmit": true,
|
|
8
|
-
"downlevelIteration": true,
|
|
9
|
-
"strictNullChecks": true,
|
|
10
|
-
"noImplicitThis": true,
|
|
11
|
-
"moduleResolution": "node",
|
|
12
|
-
},
|
|
3
|
+
"extends": "../../tsconfig.json",
|
|
13
4
|
"include": [
|
|
14
5
|
"*.js",
|
|
15
6
|
"scripts",
|
|
16
|
-
"src",
|
|
17
|
-
"test",
|
|
7
|
+
"src/**/*.js",
|
|
8
|
+
"test/**/*.js",
|
|
18
9
|
],
|
|
19
10
|
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/zone",
|
|
3
|
-
"version": "0.2.3-dev-
|
|
3
|
+
"version": "0.2.3-dev-c4e4693.0+c4e4693",
|
|
4
4
|
"description": "Allocation zone abstraction for objects on the heap, persistent stores, etc.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": "https://github.com/Agoric/agoric-sdk",
|
|
7
7
|
"main": "./src/index.js",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "exit 0",
|
|
10
|
+
"prepack": "tsc --build jsconfig.build.json",
|
|
11
|
+
"postpack": "git clean -f '*.d.ts*'",
|
|
10
12
|
"test": "ava",
|
|
11
13
|
"test:c8": "c8 $C8_OPTIONS ava --config=ava-nesm.config.js",
|
|
12
14
|
"test:xs": "exit 0",
|
|
@@ -25,13 +27,13 @@
|
|
|
25
27
|
"author": "Agoric",
|
|
26
28
|
"license": "Apache-2.0",
|
|
27
29
|
"dependencies": {
|
|
28
|
-
"@agoric/
|
|
29
|
-
"@
|
|
30
|
+
"@agoric/base-zone": "0.1.1-dev-c4e4693.0+c4e4693",
|
|
31
|
+
"@agoric/vat-data": "0.5.3-dev-c4e4693.0+c4e4693",
|
|
30
32
|
"@endo/far": "^0.2.19",
|
|
31
33
|
"@endo/pass-style": "^0.1.4"
|
|
32
34
|
},
|
|
33
35
|
"devDependencies": {
|
|
34
|
-
"@agoric/swingset-liveslots": "0.10.3-dev-
|
|
36
|
+
"@agoric/swingset-liveslots": "0.10.3-dev-c4e4693.0+c4e4693",
|
|
35
37
|
"@endo/patterns": "^0.2.3",
|
|
36
38
|
"ava": "^5.3.0"
|
|
37
39
|
},
|
|
@@ -48,5 +50,5 @@
|
|
|
48
50
|
"timeout": "20m",
|
|
49
51
|
"workerThreads": false
|
|
50
52
|
},
|
|
51
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "c4e469386a2a8c813182dc84cc63c8a660d22ecc"
|
|
52
54
|
}
|
package/src/durable.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable.d.ts","sourceRoot":"","sources":["durable.js"],"names":[],"mappings":"AA6EO,yCAJI,OAAO,kBAAkB,EAAE,OAAO,mCAEhC,OAAO,GAAG,EAAE,IAAI,CA2C5B"}
|
package/src/durable.js
CHANGED
|
@@ -14,9 +14,11 @@ import {
|
|
|
14
14
|
provideDurableWeakSetStore,
|
|
15
15
|
} from '@agoric/vat-data';
|
|
16
16
|
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
import {
|
|
18
|
+
agoricVatDataKeys as keys,
|
|
19
|
+
isPassable,
|
|
20
|
+
makeOnceKit,
|
|
21
|
+
} from '@agoric/base-zone';
|
|
20
22
|
|
|
21
23
|
const { Fail } = assert;
|
|
22
24
|
|
package/src/exports.d.ts
ADDED
package/src/exports.js
ADDED
package/src/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":""}
|
package/src/index.js
CHANGED
|
@@ -1,38 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
export { makeHeapZone } from '@agoric/base-zone/heap.js';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export * from './heap.js';
|
|
6
|
-
|
|
7
|
-
// References to allow the below typeofs to succeed.
|
|
8
|
-
makeExo;
|
|
9
|
-
defineExoClass;
|
|
10
|
-
defineExoClassKit;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @typedef {ExoZone & Stores} Zone A bag of methods for creating defensible objects and
|
|
14
|
-
* collections with the same allocation semantics (ephemeral, persistent, etc)
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @typedef {object} ExoZone
|
|
19
|
-
* @property {typeof makeExo} exo create a singleton exo-object instance bound to this zone
|
|
20
|
-
* @property {typeof defineExoClass} exoClass create a maker function that can be used to create exo-objects bound to this zone
|
|
21
|
-
* @property {typeof defineExoClassKit} exoClassKit create a "kit" maker function that can be used to create a record of exo-objects sharing the same state
|
|
22
|
-
* @property {<T>(key: string, maker: (key: string) => T) => T} makeOnce create or retrieve a singleton object bound to this zone
|
|
23
|
-
* @property {(label: string, options?: StoreOptions) => Zone} subZone create a new Zone that can be passed to untrusted consumers without exposing the storage of the parent zone
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @typedef {object} Stores
|
|
28
|
-
* @property {() => Stores} detached obtain store providers which are detached (the stores are anonymous rather than bound to `label` in the zone)
|
|
29
|
-
* @property {(specimen: unknown) => boolean} isStorable return true if the specimen can be stored in the zone, whether as exo-object state or in a store
|
|
30
|
-
* @property {<K,V>(label: string, options?: StoreOptions) => MapStore<K, V>} mapStore provide a Map-like store named `label` in the zone
|
|
31
|
-
* @property {<K>(label: string, options?: StoreOptions) => SetStore<K>} setStore provide a Set-like store named `label` in the zone
|
|
32
|
-
* @property {<K,V>(
|
|
33
|
-
* label: string, options?: StoreOptions) => WeakMapStore<K, V>
|
|
34
|
-
* } weakMapStore provide a WeakMap-like store named `label` in the zone
|
|
35
|
-
* @property {<K>(
|
|
36
|
-
* label: string, options?: StoreOptions) => WeakSetStore<K>
|
|
37
|
-
* } weakSetStore provide a WeakSet-like store named `label` in the zone
|
|
38
|
-
*/
|
|
3
|
+
// eslint-disable-next-line import/export
|
|
4
|
+
export * from './exports.js';
|
package/src/virtual.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"virtual.d.ts","sourceRoot":"","sources":["virtual.js"],"names":[],"mappings":"AAiEO,iEAFM,OAAO,GAAG,EAAE,IAAI,CA8B5B"}
|
package/src/virtual.js
CHANGED
|
@@ -11,9 +11,11 @@ import {
|
|
|
11
11
|
makeScalarBigWeakSetStore,
|
|
12
12
|
} from '@agoric/vat-data';
|
|
13
13
|
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
import {
|
|
15
|
+
agoricVatDataKeys as keys,
|
|
16
|
+
isPassable,
|
|
17
|
+
makeOnceKit,
|
|
18
|
+
} from '@agoric/base-zone';
|
|
17
19
|
|
|
18
20
|
const emptyRecord = harden({});
|
|
19
21
|
const initEmpty = harden(() => emptyRecord);
|
package/test/test-exos.js
CHANGED
|
@@ -6,106 +6,20 @@ import {
|
|
|
6
6
|
test,
|
|
7
7
|
} from './prepare-test-env-ava.js';
|
|
8
8
|
|
|
9
|
-
import { M } from '@endo/patterns';
|
|
10
9
|
import * as vatData from '@agoric/vat-data';
|
|
11
10
|
|
|
11
|
+
import { agoricVatDataKeys as keys } from '@agoric/base-zone';
|
|
12
|
+
import {
|
|
13
|
+
agoricVatDataCompatibleKeys,
|
|
14
|
+
testFirstZoneIncarnation,
|
|
15
|
+
testSecondZoneIncarnation,
|
|
16
|
+
testGreeter,
|
|
17
|
+
} from '@agoric/base-zone/tools/testers.js';
|
|
18
|
+
import * as g from '@agoric/base-zone/tools/greeter.js';
|
|
19
|
+
|
|
12
20
|
import { makeDurableZone } from '../durable.js';
|
|
13
21
|
import { makeHeapZone } from '../heap.js';
|
|
14
22
|
import { makeVirtualZone } from '../virtual.js';
|
|
15
|
-
import { agoricVatDataKeys as keys } from '../src/keys.js';
|
|
16
|
-
|
|
17
|
-
/** @typedef {import('../src/index.js').Zone} Zone */
|
|
18
|
-
|
|
19
|
-
// CAUTION: Do not modify this list; it exists to ensure that future versions
|
|
20
|
-
// of @agoric/zone are compatible with the baggage created by older versions,
|
|
21
|
-
// including the legacy implementation of @agoric/vat-data.
|
|
22
|
-
const agoricVatDataCompatibleKeys = [
|
|
23
|
-
'Greeter_kindHandle',
|
|
24
|
-
'GreeterKit_kindHandle',
|
|
25
|
-
'a_kindHandle',
|
|
26
|
-
'a_singleton',
|
|
27
|
-
'mappish',
|
|
28
|
-
'subsub',
|
|
29
|
-
].sort();
|
|
30
|
-
|
|
31
|
-
const bindAllMethodsTo = (obj, that = obj) =>
|
|
32
|
-
Object.fromEntries(
|
|
33
|
-
Object.entries(obj).map(([name, fn]) => [name, fn.bind(that)]),
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
const greetGuard = M.interface('Greeter', {
|
|
37
|
-
greet: M.call().optional(M.string()).returns(M.string()),
|
|
38
|
-
});
|
|
39
|
-
const greetFacet = {
|
|
40
|
-
greet(greeting = 'Hello') {
|
|
41
|
-
return `${greeting}, ${this.state.nick}`;
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const adminGuard = M.interface('GreeterAdmin', {
|
|
46
|
-
setNick: M.call(M.string()).returns(),
|
|
47
|
-
});
|
|
48
|
-
const adminFacet = {
|
|
49
|
-
setNick(nick) {
|
|
50
|
-
this.state.nick = nick;
|
|
51
|
-
},
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const combinedGuard = M.interface('GreeterWithAdmin', {
|
|
55
|
-
...greetGuard.methodGuards,
|
|
56
|
-
...adminGuard.methodGuards,
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const alreadyExceptionSpec = {
|
|
60
|
-
message: /has already been used/,
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const prepareGreeterSingleton = (zone, label, nick) => {
|
|
64
|
-
const myThis = Object.freeze({ state: { nick } });
|
|
65
|
-
return zone.exo(label, combinedGuard, {
|
|
66
|
-
...bindAllMethodsTo(greetFacet, myThis),
|
|
67
|
-
...bindAllMethodsTo(adminFacet, myThis),
|
|
68
|
-
});
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const prepareGreeter = zone =>
|
|
72
|
-
zone.exoClass('Greeter', combinedGuard, nick => ({ nick }), {
|
|
73
|
-
...greetFacet,
|
|
74
|
-
...adminFacet,
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
const prepareGreeterKit = zone =>
|
|
78
|
-
zone.exoClassKit(
|
|
79
|
-
'GreeterKit',
|
|
80
|
-
{ greeter: greetGuard, admin: adminGuard },
|
|
81
|
-
nick => ({ nick }),
|
|
82
|
-
{
|
|
83
|
-
greeter: greetFacet,
|
|
84
|
-
admin: adminFacet,
|
|
85
|
-
},
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
const testGreeter = (t, nick, obj, adminObj = obj) => {
|
|
89
|
-
t.is(obj.greet('Greetings'), `Greetings, ${nick}`);
|
|
90
|
-
t.is(obj.greet(), `Hello, ${nick}`);
|
|
91
|
-
adminObj.setNick(`${nick}2`);
|
|
92
|
-
t.is(obj.greet('Greetings'), `Greetings, ${nick}2`);
|
|
93
|
-
t.is(obj.greet(), `Hello, ${nick}2`);
|
|
94
|
-
adminObj.setNick(nick);
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* @template T
|
|
99
|
-
* @param {import('ava').Assertions} t
|
|
100
|
-
* @param {() => T} fn
|
|
101
|
-
* @param {*} spec
|
|
102
|
-
* @returns {T}
|
|
103
|
-
*/
|
|
104
|
-
const secondThrows = (t, fn, spec = alreadyExceptionSpec) => {
|
|
105
|
-
const ret = fn();
|
|
106
|
-
t.throws(fn, spec);
|
|
107
|
-
return ret;
|
|
108
|
-
};
|
|
109
23
|
|
|
110
24
|
/**
|
|
111
25
|
* @param {import('ava').Assertions} t
|
|
@@ -115,20 +29,20 @@ const testFirstVatDataIncarnation = (t, baggage) => {
|
|
|
115
29
|
const subBaggage = vatData.provideDurableMapStore(baggage, 'sub');
|
|
116
30
|
|
|
117
31
|
const myThis = Object.freeze({ state: { nick: 'Singly' } });
|
|
118
|
-
const singly = vatData.prepareExo(subBaggage, 'a', combinedGuard, {
|
|
119
|
-
...bindAllMethodsTo(greetFacet, myThis),
|
|
120
|
-
...bindAllMethodsTo(adminFacet, myThis),
|
|
32
|
+
const singly = vatData.prepareExo(subBaggage, 'a', g.combinedGuard, {
|
|
33
|
+
...g.bindAllMethodsTo(g.greetFacet, myThis),
|
|
34
|
+
...g.bindAllMethodsTo(g.adminFacet, myThis),
|
|
121
35
|
});
|
|
122
36
|
testGreeter(t, 'Singly', singly);
|
|
123
37
|
|
|
124
38
|
const makeGreeter = vatData.prepareExoClass(
|
|
125
39
|
subBaggage,
|
|
126
40
|
'Greeter',
|
|
127
|
-
combinedGuard,
|
|
41
|
+
g.combinedGuard,
|
|
128
42
|
nick => ({ nick }),
|
|
129
43
|
{
|
|
130
|
-
...greetFacet,
|
|
131
|
-
...adminFacet,
|
|
44
|
+
...g.greetFacet,
|
|
45
|
+
...g.adminFacet,
|
|
132
46
|
},
|
|
133
47
|
);
|
|
134
48
|
const classy = makeGreeter('Classy');
|
|
@@ -137,11 +51,11 @@ const testFirstVatDataIncarnation = (t, baggage) => {
|
|
|
137
51
|
const makeGreeterKit = vatData.prepareExoClassKit(
|
|
138
52
|
subBaggage,
|
|
139
53
|
'GreeterKit',
|
|
140
|
-
{ greeter: greetGuard, admin: adminGuard },
|
|
54
|
+
{ greeter: g.greetGuard, admin: g.adminGuard },
|
|
141
55
|
nick => ({ nick }),
|
|
142
56
|
{
|
|
143
|
-
greeter: greetFacet,
|
|
144
|
-
admin: adminFacet,
|
|
57
|
+
greeter: g.greetFacet,
|
|
58
|
+
admin: g.adminFacet,
|
|
145
59
|
},
|
|
146
60
|
);
|
|
147
61
|
const { greeter: kitty, admin: kittyAdmin } = makeGreeterKit('Kitty');
|
|
@@ -156,62 +70,6 @@ const testFirstVatDataIncarnation = (t, baggage) => {
|
|
|
156
70
|
vatData.provideDurableMapStore(subBaggage, 'subsub');
|
|
157
71
|
};
|
|
158
72
|
|
|
159
|
-
/**
|
|
160
|
-
* @param {import('ava').Assertions} t
|
|
161
|
-
* @param {Zone} rootZone
|
|
162
|
-
*/
|
|
163
|
-
const testFirstZoneIncarnation = (t, rootZone) => {
|
|
164
|
-
const subZone = secondThrows(t, () => rootZone.subZone('sub'));
|
|
165
|
-
const singly = secondThrows(t, () =>
|
|
166
|
-
prepareGreeterSingleton(subZone, 'a', 'Singly'),
|
|
167
|
-
);
|
|
168
|
-
testGreeter(t, 'Singly', singly);
|
|
169
|
-
|
|
170
|
-
const makeGreeter = secondThrows(t, () => prepareGreeter(subZone));
|
|
171
|
-
const classy = makeGreeter('Classy');
|
|
172
|
-
testGreeter(t, 'Classy', classy);
|
|
173
|
-
|
|
174
|
-
const makeGreeterKit = secondThrows(t, () => prepareGreeterKit(subZone));
|
|
175
|
-
|
|
176
|
-
const { greeter: kitty, admin: kittyAdmin } = makeGreeterKit('Kitty');
|
|
177
|
-
testGreeter(t, 'Kitty', kitty, kittyAdmin);
|
|
178
|
-
|
|
179
|
-
const mappish = secondThrows(t, () => subZone.mapStore('mappish'));
|
|
180
|
-
mappish.init('singly', singly);
|
|
181
|
-
mappish.init('classy', classy);
|
|
182
|
-
mappish.init('kitty', kitty);
|
|
183
|
-
mappish.init('kittyAdmin', kittyAdmin);
|
|
184
|
-
|
|
185
|
-
secondThrows(t, () => subZone.subZone('subsub'));
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* @param {import('ava').Assertions} t
|
|
190
|
-
* @param {Zone} rootZone
|
|
191
|
-
*/
|
|
192
|
-
const testSecondZoneIncarnation = (t, rootZone) => {
|
|
193
|
-
const subZone = secondThrows(t, () => rootZone.subZone('sub'));
|
|
194
|
-
const mappish = secondThrows(t, () => subZone.mapStore('mappish'));
|
|
195
|
-
|
|
196
|
-
const singlyReload = secondThrows(t, () =>
|
|
197
|
-
prepareGreeterSingleton(subZone, 'a', 'Singly'),
|
|
198
|
-
);
|
|
199
|
-
const makeGreeter = secondThrows(t, () => prepareGreeter(subZone));
|
|
200
|
-
const makeGreeterKit = secondThrows(t, () => prepareGreeterKit(subZone));
|
|
201
|
-
|
|
202
|
-
const singly = mappish.get('singly');
|
|
203
|
-
t.is(singlyReload, singly);
|
|
204
|
-
testGreeter(t, 'Singly', singly);
|
|
205
|
-
testGreeter(t, 'Classy', mappish.get('classy'));
|
|
206
|
-
testGreeter(t, 'Kitty', mappish.get('kitty'), mappish.get('kittyAdmin'));
|
|
207
|
-
|
|
208
|
-
const classy2 = makeGreeter('Classy2');
|
|
209
|
-
testGreeter(t, 'Classy2', classy2);
|
|
210
|
-
|
|
211
|
-
const { greeter: kitty2, admin: kittyAdmin2 } = makeGreeterKit('Kitty2');
|
|
212
|
-
testGreeter(t, 'Kitty2', kitty2, kittyAdmin2);
|
|
213
|
-
};
|
|
214
|
-
|
|
215
73
|
test('heapZone', t => {
|
|
216
74
|
const zone = makeHeapZone();
|
|
217
75
|
testFirstZoneIncarnation(t, zone);
|
package/virtual.d.ts
ADDED
package/virtual.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"virtual.d.ts","sourceRoot":"","sources":["virtual.js"],"names":[],"mappings":""}
|
package/src/heap.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
// @jessie-check
|
|
3
|
-
|
|
4
|
-
import { Far } from '@endo/far';
|
|
5
|
-
import { makeExo, defineExoClass, defineExoClassKit } from '@endo/exo';
|
|
6
|
-
import {
|
|
7
|
-
makeScalarMapStore,
|
|
8
|
-
makeScalarSetStore,
|
|
9
|
-
makeScalarWeakMapStore,
|
|
10
|
-
makeScalarWeakSetStore,
|
|
11
|
-
} from '@agoric/vat-data';
|
|
12
|
-
|
|
13
|
-
import { makeOnceKit } from './make-once.js';
|
|
14
|
-
import { agoricVatDataKeys as keys } from './keys.js';
|
|
15
|
-
import { isPassable } from './is-passable.js';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @type {import('.').Stores}
|
|
19
|
-
*/
|
|
20
|
-
const detachedHeapStores = Far('heapStores', {
|
|
21
|
-
detached: () => detachedHeapStores,
|
|
22
|
-
isStorable: isPassable,
|
|
23
|
-
|
|
24
|
-
setStore: makeScalarSetStore,
|
|
25
|
-
mapStore: makeScalarMapStore,
|
|
26
|
-
weakMapStore: makeScalarWeakMapStore,
|
|
27
|
-
weakSetStore: makeScalarWeakSetStore,
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Create a heap (in-memory) zone that uses the default exo and store implementations.
|
|
32
|
-
*
|
|
33
|
-
* @param {string} [baseLabel]
|
|
34
|
-
* @returns {import('.').Zone}
|
|
35
|
-
*/
|
|
36
|
-
export const makeHeapZone = (baseLabel = 'heapZone') => {
|
|
37
|
-
const { makeOnce, wrapProvider } = makeOnceKit(baseLabel, detachedHeapStores);
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @param {string} label
|
|
41
|
-
* @param {any} _options
|
|
42
|
-
*/
|
|
43
|
-
const makeSubZone = (label, _options) =>
|
|
44
|
-
makeHeapZone(`${baseLabel}.${label}`);
|
|
45
|
-
|
|
46
|
-
return Far('heapZone', {
|
|
47
|
-
exo: wrapProvider(makeExo, keys.exo),
|
|
48
|
-
exoClass: wrapProvider(defineExoClass, keys.exoClass),
|
|
49
|
-
exoClassKit: wrapProvider(defineExoClassKit, keys.exoClassKit),
|
|
50
|
-
subZone: wrapProvider(makeSubZone),
|
|
51
|
-
|
|
52
|
-
makeOnce,
|
|
53
|
-
detached: detachedHeapStores.detached,
|
|
54
|
-
isStorable: detachedHeapStores.isStorable,
|
|
55
|
-
|
|
56
|
-
mapStore: wrapProvider(detachedHeapStores.mapStore),
|
|
57
|
-
setStore: wrapProvider(detachedHeapStores.setStore),
|
|
58
|
-
weakMapStore: wrapProvider(detachedHeapStores.weakMapStore),
|
|
59
|
-
weakSetStore: wrapProvider(detachedHeapStores.weakSetStore),
|
|
60
|
-
});
|
|
61
|
-
};
|
|
62
|
-
harden(makeHeapZone);
|
package/src/is-passable.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { passStyleOf } from '@endo/pass-style';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Is `specimen` Passable? This returns true iff `passStyleOf(specimen)`
|
|
5
|
-
* returns a string. This returns `false` iff `passStyleOf(specimen)` throws.
|
|
6
|
-
* Under no normal circumstance should `isPassable(specimen)` throw.
|
|
7
|
-
*
|
|
8
|
-
* TODO implement an isPassable that does not rely on try/catch, and
|
|
9
|
-
* move it to @endo/pass-style.
|
|
10
|
-
* This implementation is just a standin until then
|
|
11
|
-
*
|
|
12
|
-
* @param {any} specimen
|
|
13
|
-
* @returns {specimen is Passable}
|
|
14
|
-
*/
|
|
15
|
-
export const isPassable = specimen => {
|
|
16
|
-
try {
|
|
17
|
-
// In fact, it never returns undefined. It either returns a
|
|
18
|
-
// string or throws.
|
|
19
|
-
return passStyleOf(specimen) !== undefined;
|
|
20
|
-
} catch (_) {
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
};
|
package/src/keys.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/** @param {string} label */
|
|
2
|
-
const kind = label => `${label}_kindHandle`;
|
|
3
|
-
/** @param {string} label */
|
|
4
|
-
const singleton = label => `${label}_singleton`;
|
|
5
|
-
|
|
6
|
-
/** @type {Record<'exoClass' | 'exoClassKit' | 'exo' | 'store' | 'zone', (label: string) => string[]>} */
|
|
7
|
-
export const agoricVatDataKeys = {
|
|
8
|
-
exoClass: label => harden([kind(label)]),
|
|
9
|
-
exoClassKit: label => harden([kind(label)]),
|
|
10
|
-
exo: label => harden([kind(label), singleton(label)]),
|
|
11
|
-
store: label => harden([label]),
|
|
12
|
-
zone: label => harden([label]),
|
|
13
|
-
};
|
|
14
|
-
harden(agoricVatDataKeys);
|
package/src/make-once.js
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
const { Fail } = assert;
|
|
3
|
-
|
|
4
|
-
/** @param {string} label */
|
|
5
|
-
const defaultLabelToKeys = label => harden([label]);
|
|
6
|
-
harden(defaultLabelToKeys);
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @param {string} debugName Only used internally for diagnostics, not available to user code
|
|
10
|
-
* @param {import('.').Stores} stores
|
|
11
|
-
* @param {import('@agoric/swingset-liveslots').MapStore<string, any>} [backingStore]
|
|
12
|
-
*/
|
|
13
|
-
export const makeOnceKit = (debugName, stores, backingStore = undefined) => {
|
|
14
|
-
// We need a detached setStore so that it isn't persisted as part of the zone.
|
|
15
|
-
// That way, our usedKeys are only tracked for the current incarnation, which
|
|
16
|
-
// is what we want. Using `debugName` in the label is good for diagnostics,
|
|
17
|
-
// and since it is only for a detached store, it should not be visible to the
|
|
18
|
-
// backing store.
|
|
19
|
-
const usedKeys = stores.detached().setStore(`${debugName} used keys`);
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @param {string} key
|
|
23
|
-
*/
|
|
24
|
-
const assertOnlyOnce = key => {
|
|
25
|
-
typeof key === 'string' || Fail`key ${key} must be a string`;
|
|
26
|
-
!usedKeys.has(key) ||
|
|
27
|
-
Fail`key ${key} has already been used in this zone and incarnation`;
|
|
28
|
-
|
|
29
|
-
// Mark this key as used. We make no attempt to recover from invalid makers
|
|
30
|
-
// or backingStores.
|
|
31
|
-
usedKeys.add(key);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Ensure the wrapped function is only called once per incarnation. It is
|
|
36
|
-
* expected to update the backing store directly.
|
|
37
|
-
*
|
|
38
|
-
* @template {(key: string, ...rest: unknown[]) => any} T
|
|
39
|
-
* @param {T} provider
|
|
40
|
-
* @param {(label: string) => string[]} [labelToKeys]
|
|
41
|
-
* @returns {T}
|
|
42
|
-
*/
|
|
43
|
-
const wrapProvider = (provider, labelToKeys = defaultLabelToKeys) => {
|
|
44
|
-
/** @type {(...args: Parameters<T>) => ReturnType<T>} */
|
|
45
|
-
const wrapper = (label, ...rest) => {
|
|
46
|
-
for (const key of labelToKeys(label)) {
|
|
47
|
-
assertOnlyOnce(key);
|
|
48
|
-
}
|
|
49
|
-
return provider(label, ...rest);
|
|
50
|
-
};
|
|
51
|
-
return /** @type {T} */ (wrapper);
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* The best way to understand the purpose of `makeOnce` is to first understand
|
|
56
|
-
* what `makeOnce` does on a durable zone. Used correctly, `makeOnce` should only
|
|
57
|
-
* be called at most once on any zone,key pair during any vat incarnation.
|
|
58
|
-
* Given that constraint, if there is already a value bound to that
|
|
59
|
-
* zone,key pair, it must have been left there by a previous incarnation and
|
|
60
|
-
* `makeOnce` will simply return it. If not, then `maker(key)` is called to
|
|
61
|
-
* determine the initial value of that slot, which will normally be preserved
|
|
62
|
-
* by similar calls to `makeOnce` in future incarnations --- though that will be
|
|
63
|
-
* up to them.
|
|
64
|
-
*
|
|
65
|
-
* Also ensures the maker returns a storable value.
|
|
66
|
-
*
|
|
67
|
-
* @template V
|
|
68
|
-
* @param {string} key The string name of the Zone slot to provide.
|
|
69
|
-
* @param {(key: string) => V} maker Called to create a fresh value to fill an empty slot.
|
|
70
|
-
* @returns {V} The value of the key's slot.
|
|
71
|
-
*/
|
|
72
|
-
const makeOnce = (key, maker) => {
|
|
73
|
-
assertOnlyOnce(key);
|
|
74
|
-
if (backingStore && backingStore.has(key)) {
|
|
75
|
-
return backingStore.get(key);
|
|
76
|
-
}
|
|
77
|
-
const value = maker(key);
|
|
78
|
-
stores.isStorable(value) ||
|
|
79
|
-
Fail`maker return value ${value} is not storable`;
|
|
80
|
-
backingStore && backingStore.init(key, value);
|
|
81
|
-
return value;
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
return harden({ makeOnce, wrapProvider });
|
|
85
|
-
};
|
|
86
|
-
harden(makeOnceKit);
|