@agoric/base-zone 0.1.1-other-dev-3eb1a1d.0 → 0.1.1-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/package.json +19 -19
- package/src/heap.d.ts +2 -1
- package/src/heap.d.ts.map +1 -1
- package/src/heap.js +7 -2
- package/src/is-passable.d.ts +1 -0
- package/src/is-passable.d.ts.map +1 -1
- package/src/is-passable.js +4 -0
- package/src/keys.d.ts +3 -2
- package/src/keys.d.ts.map +1 -1
- package/src/keys.js +5 -1
- package/src/make-once.d.ts +4 -2
- package/src/make-once.d.ts.map +1 -1
- package/src/make-once.js +7 -2
- package/src/prepare-attenuator.d.ts +33 -0
- package/src/prepare-attenuator.d.ts.map +1 -0
- package/src/prepare-attenuator.js +175 -0
- package/src/prepare-revocable.d.ts +10 -5
- package/src/prepare-revocable.d.ts.map +1 -1
- package/src/prepare-revocable.js +47 -52
- package/src/types.d.ts +6 -1
- package/src/types.d.ts.map +1 -1
- package/src/types.js +2 -1
- package/test/prepare-attenuator.test.js +110 -0
- package/tools/greeter.js +7 -3
- package/tools/testers.js +12 -7
- package/tsconfig.build.tsbuildinfo +1 -1
- package/zone-helpers.d.ts +1 -0
- package/zone-helpers.js +1 -0
package/package.json
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/base-zone",
|
|
3
|
-
"version": "0.1.1-other-dev-
|
|
3
|
+
"version": "0.1.1-other-dev-d15096d.0.d15096d",
|
|
4
4
|
"description": "Allocation zone abstraction library and heap implementation",
|
|
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 tsconfig.build.json",
|
|
11
|
-
"postpack": "git clean -f '*.d
|
|
10
|
+
"prepack": "yarn run -T tsc --build tsconfig.build.json",
|
|
11
|
+
"postpack": "git clean -f '*.d.*ts*' '*.tsbuildinfo'",
|
|
12
12
|
"test": "ava",
|
|
13
|
-
"test:c8": "c8 --all $C8_OPTIONS ava",
|
|
13
|
+
"test:c8": "c8 --all ${C8_OPTIONS:-} ava",
|
|
14
14
|
"test:xs": "exit 0",
|
|
15
15
|
"lint-fix": "yarn lint:eslint --fix",
|
|
16
|
-
"lint": "run-s --continue-on-error lint:*",
|
|
17
|
-
"lint:types": "tsc",
|
|
18
|
-
"lint:eslint": "eslint ."
|
|
16
|
+
"lint": "yarn run -T run-s --continue-on-error 'lint:*'",
|
|
17
|
+
"lint:types": "yarn run -T tsc",
|
|
18
|
+
"lint:eslint": "yarn run -T eslint ."
|
|
19
19
|
},
|
|
20
20
|
"exports": {
|
|
21
21
|
".": "./src/index.js",
|
|
@@ -27,24 +27,24 @@
|
|
|
27
27
|
"author": "Agoric",
|
|
28
28
|
"license": "Apache-2.0",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@agoric/store": "0.9.3-other-dev-
|
|
31
|
-
"@endo/common": "^1.2.
|
|
32
|
-
"@endo/errors": "^1.2.
|
|
33
|
-
"@endo/exo": "^1.5.
|
|
34
|
-
"@endo/far": "^1.1.
|
|
35
|
-
"@endo/pass-style": "^1.
|
|
36
|
-
"@endo/patterns": "^1.
|
|
30
|
+
"@agoric/store": "0.9.3-other-dev-d15096d.0.d15096d",
|
|
31
|
+
"@endo/common": "^1.2.13",
|
|
32
|
+
"@endo/errors": "^1.2.13",
|
|
33
|
+
"@endo/exo": "^1.5.12",
|
|
34
|
+
"@endo/far": "^1.1.14",
|
|
35
|
+
"@endo/pass-style": "^1.6.3",
|
|
36
|
+
"@endo/patterns": "^1.7.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@endo/init": "^1.1.
|
|
40
|
-
"@endo/ses-ava": "^1.2
|
|
39
|
+
"@endo/init": "^1.1.12",
|
|
40
|
+
"@endo/ses-ava": "^1.3.2",
|
|
41
41
|
"ava": "^5.3.0"
|
|
42
42
|
},
|
|
43
43
|
"publishConfig": {
|
|
44
44
|
"access": "public"
|
|
45
45
|
},
|
|
46
46
|
"engines": {
|
|
47
|
-
"node": "^
|
|
47
|
+
"node": "^20.9 || ^22.11"
|
|
48
48
|
},
|
|
49
49
|
"ava": {
|
|
50
50
|
"files": [
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"workerThreads": false
|
|
58
58
|
},
|
|
59
59
|
"typeCoverage": {
|
|
60
|
-
"atLeast":
|
|
60
|
+
"atLeast": 93.22
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "d15096dc4ff8b96e9b6cd11954c20d3a9efbb393"
|
|
63
63
|
}
|
package/src/heap.d.ts
CHANGED
package/src/heap.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heap.d.ts","sourceRoot":"","sources":["heap.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"heap.d.ts","sourceRoot":"","sources":["heap.js"],"names":[],"mappings":"AAwCO,yCAHI,MAAM,GACJ,IAAI,CA4BhB;0BAhDsB,YAAY"}
|
package/src/heap.js
CHANGED
|
@@ -15,7 +15,12 @@ import { agoricVatDataKeys as keys } from './keys.js';
|
|
|
15
15
|
import { watchPromise } from './watch-promise.js';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* @
|
|
18
|
+
* @import {Stores} from './types.js';
|
|
19
|
+
* @import {Zone} from './types.js';
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @type {Stores}
|
|
19
24
|
*/
|
|
20
25
|
const detachedHeapStores = Far('heapStores', {
|
|
21
26
|
detached: () => detachedHeapStores,
|
|
@@ -31,7 +36,7 @@ const detachedHeapStores = Far('heapStores', {
|
|
|
31
36
|
* Create a heap (in-memory) zone that uses the default exo and store implementations.
|
|
32
37
|
*
|
|
33
38
|
* @param {string} [baseLabel]
|
|
34
|
-
* @returns {
|
|
39
|
+
* @returns {Zone}
|
|
35
40
|
*/
|
|
36
41
|
export const makeHeapZone = (baseLabel = 'heapZone') => {
|
|
37
42
|
const { makeOnce, wrapProvider } = makeOnceKit(baseLabel, detachedHeapStores);
|
package/src/is-passable.d.ts
CHANGED
package/src/is-passable.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"is-passable.d.ts","sourceRoot":"","sources":["is-passable.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"is-passable.d.ts","sourceRoot":"","sources":["is-passable.js"],"names":[],"mappings":"AAWO,qCAHI,GAAG,GACD,QAAQ,IAAI,QAAQ,CAE6B;8BARnC,kBAAkB"}
|
package/src/is-passable.js
CHANGED
package/src/keys.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* KeyMakers compatible with `@agoric/vat-data`.
|
|
3
3
|
*
|
|
4
|
-
* @type {
|
|
4
|
+
* @type {KeyMakers}
|
|
5
5
|
*/
|
|
6
|
-
export const agoricVatDataKeys:
|
|
6
|
+
export const agoricVatDataKeys: KeyMakers;
|
|
7
|
+
import type { KeyMakers } from './types.js';
|
|
7
8
|
//# sourceMappingURL=keys.d.ts.map
|
package/src/keys.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["keys.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["keys.js"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,gCAFU,SAAS,CAQjB;+BApB0B,YAAY"}
|
package/src/keys.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @import {KeyMakers} from './types.js';
|
|
5
|
+
*/
|
|
6
|
+
|
|
3
7
|
/** @param {string} label */
|
|
4
8
|
const kind = label => `${label}_kindHandle`;
|
|
5
9
|
|
|
@@ -9,7 +13,7 @@ const singleton = label => `${label}_singleton`;
|
|
|
9
13
|
/**
|
|
10
14
|
* KeyMakers compatible with `@agoric/vat-data`.
|
|
11
15
|
*
|
|
12
|
-
* @type {
|
|
16
|
+
* @type {KeyMakers}
|
|
13
17
|
*/
|
|
14
18
|
export const agoricVatDataKeys = {
|
|
15
19
|
exoClass: label => harden([kind(label)]),
|
package/src/make-once.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
export function makeOnceKit(debugName: string, stores:
|
|
1
|
+
export function makeOnceKit(debugName: string, stores: Stores, backingStore?: MapStore<string, any>): {
|
|
2
2
|
makeOnce: <V>(key: string, maker: (key: string) => V) => V;
|
|
3
|
-
wrapProvider: <T extends (key: string, ...rest: any[]) => any>(provider: T, labelToKeys?: (
|
|
3
|
+
wrapProvider: <T extends (key: string, ...rest: any[]) => any>(provider: T, labelToKeys?: (label: string) => string[]) => T;
|
|
4
4
|
};
|
|
5
|
+
import type { Stores } from './types.js';
|
|
6
|
+
import type { MapStore } from '@agoric/swingset-liveslots';
|
|
5
7
|
//# sourceMappingURL=make-once.d.ts.map
|
package/src/make-once.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"make-once.d.ts","sourceRoot":"","sources":["make-once.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"make-once.d.ts","sourceRoot":"","sources":["make-once.js"],"names":[],"mappings":"AAiBO,uCAJI,MAAM,UACN,MAAM,iBACN,SAAS,MAAM,EAAE,GAAG,CAAC;eAwDjB,CAAC,OACH,MAAM,SACN,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,KAChB,CAAC;mBAhCsC,CAAC,SAAxC,CAAE,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAI,YACxC,CAAC,gBACD,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,EAAE,KACzB,CAAC;EA4Cf;4BArFwB,YAAY;8BACV,4BAA4B"}
|
package/src/make-once.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { Fail } from '@endo/errors';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @import {Stores} from './types.js';
|
|
6
|
+
* @import {MapStore} from '@agoric/swingset-liveslots';
|
|
7
|
+
*/
|
|
8
|
+
|
|
4
9
|
/** @param {string} label */
|
|
5
10
|
const defaultLabelToKeys = label => harden([label]);
|
|
6
11
|
harden(defaultLabelToKeys);
|
|
7
12
|
|
|
8
13
|
/**
|
|
9
14
|
* @param {string} debugName Only used internally for diagnostics, not available to user code
|
|
10
|
-
* @param {
|
|
11
|
-
* @param {
|
|
15
|
+
* @param {Stores} stores
|
|
16
|
+
* @param {MapStore<string, any>} [backingStore]
|
|
12
17
|
*/
|
|
13
18
|
export const makeOnceKit = (debugName, stores, backingStore = undefined) => {
|
|
14
19
|
// We need a detached setStore so that it isn't persisted as part of the zone.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export function wrapperMethods(wrapperKindName: string, uMethodNames: PropertyKey[], extraMethods?: Record<PropertyKey, (...args: any[]) => any>): {
|
|
2
|
+
[x: string]: ((...args: any[]) => any) | ((...args: any[]) => any);
|
|
3
|
+
};
|
|
4
|
+
export function prepareAttenuatorMaker<U = any>(zone: Zone, uKindName: string, uMethodNames: (keyof U)[], options?: AttenuatorOptions<U>): MakeAttenuator;
|
|
5
|
+
export function attenuateOne<U extends unknown>(underlying: U, uMethodNames: (keyof U)[], options?: AttenuatorOptions<U>): Partial<U>;
|
|
6
|
+
export type MakeAttenuator<U = any> = (underlying: U) => Partial<U>;
|
|
7
|
+
export type AttenuatorThis<U = any> = {
|
|
8
|
+
self: Partial<U>;
|
|
9
|
+
state: {
|
|
10
|
+
underlying: U;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export type AttenuatorOptions<U = any> = {
|
|
14
|
+
/**
|
|
15
|
+
* The `interfaceName` of the underlying interface guard.
|
|
16
|
+
* Defaults to the `uKindName`.
|
|
17
|
+
*/
|
|
18
|
+
uInterfaceName?: string | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* For guarding the `extraMethods`, if you include them below. These appear
|
|
21
|
+
* only on the synthesized interface guard for the attenuator, and
|
|
22
|
+
* do not necessarily correspond to any method of the underlying.
|
|
23
|
+
*/
|
|
24
|
+
extraMethodGuards?: Record<PropertyKey, MethodGuard> | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Extra methods adding behavior only to the attenuator, and
|
|
27
|
+
* do not necessarily correspond to any methods of the underlying.
|
|
28
|
+
*/
|
|
29
|
+
extraMethods?: Record<PropertyKey, (this: AttenuatorThis<U>, ...args: any[]) => any> | undefined;
|
|
30
|
+
};
|
|
31
|
+
import type { Zone } from '@agoric/base-zone';
|
|
32
|
+
import type { MethodGuard } from '@endo/patterns';
|
|
33
|
+
//# sourceMappingURL=prepare-attenuator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepare-attenuator.d.ts","sourceRoot":"","sources":["prepare-attenuator.js"],"names":[],"mappings":"AAgCO,gDAJI,MAAM,gBACN,WAAW,EAAE,iBACb,MAAM,CAAC,WAAW,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;4BAAd,GAAG,EAAE,KAAK,GAAG;EA6BlD;AAoDG,uCAVO,CAAC,cACJ,IAAI,aACJ,MAAM,gBAEN,CAAC,MAAM,CAAC,CAAC,EAAE,YAGX,iBAAiB,CAAC,CAAC,CAAC,GAClB,cAAc,CA8B1B;AAqBM,6BANY,CAAC,8BACT,CAAC,gBACD,CAAC,MAAM,CAAC,CAAC,EAAE,YACX,iBAAiB,CAAC,CAAC,CAAC,GAClB,OAAO,CAAC,CAAC,CAAC,CAetB;2BA9Ga,CAAC,uBAEJ,CAAC,KACC,OAAO,CAAC,CAAC,CAAC;2BAIT,CAAC;UAED,OAAO,CAAC,CAAC,CAAC;WACV;QAAE,UAAU,EAAE,CAAC,CAAA;KAAE;;8BAIjB,CAAC;;;;;;;;;;;;;;;;8CAcH,cAAc,CAAC,CAAC,CAAC,WAAW,GAAG,EAAE,KAAK,GAAG;;0BApF9B,mBAAmB;iCADZ,gBAAgB"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { Fail, q } from '@endo/errors';
|
|
2
|
+
import { fromUniqueEntries } from '@endo/common/from-unique-entries.js';
|
|
3
|
+
import { M } from '@endo/patterns';
|
|
4
|
+
import { makeHeapZone } from './heap.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @import {MethodGuard} from '@endo/patterns';
|
|
8
|
+
* @import {Zone} from '@agoric/base-zone';
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// This attenuator implementation is just a simplification of the
|
|
12
|
+
// revocable kit implementation in prepare-revocable.js. The revocable kit
|
|
13
|
+
// provides both attenuation and revocation, since we can have both for the
|
|
14
|
+
// price of just one level of indirection. But if you don't need revocation,
|
|
15
|
+
// the revocable kit has more API complexity than you need.
|
|
16
|
+
//
|
|
17
|
+
// We could have built `prepareAttenuatorMaker` as a trivial wrapper around
|
|
18
|
+
// `prepareRevocableMakerKit`. But then we'd have the weird artifact that the
|
|
19
|
+
// `extraMethods` would see a `{ state, facets: { revocable, revoker }}` context
|
|
20
|
+
// rather than a `{ state, self }` context. So instead, we copied and edited it
|
|
21
|
+
// down. Please co-maintain these two modules.
|
|
22
|
+
|
|
23
|
+
// Because the attenuator just uses an exo class rather than a class kit,
|
|
24
|
+
// it cannot support the privilege separation of a distinct revoker facet.
|
|
25
|
+
// But it can still support `selfRevoke` as a separate `extraMethod`, as shown
|
|
26
|
+
// in a testcase at `prepare-attenuator.test.js`
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {string} wrapperKindName
|
|
30
|
+
* @param {PropertyKey[]} uMethodNames
|
|
31
|
+
* @param {Record<PropertyKey, (...args: any[]) => any>} [extraMethods]
|
|
32
|
+
*/
|
|
33
|
+
export const wrapperMethods = (
|
|
34
|
+
wrapperKindName,
|
|
35
|
+
uMethodNames,
|
|
36
|
+
extraMethods = {},
|
|
37
|
+
) =>
|
|
38
|
+
harden({
|
|
39
|
+
...fromUniqueEntries(
|
|
40
|
+
uMethodNames.map(name => [
|
|
41
|
+
name,
|
|
42
|
+
{
|
|
43
|
+
// Use concise method syntax for exo methods
|
|
44
|
+
[name](...args) {
|
|
45
|
+
// @ts-expect-error normal exo-this typing confusion
|
|
46
|
+
const { underlying } = this.state;
|
|
47
|
+
|
|
48
|
+
// Because attenuators still support someone adding `selfRevoke`
|
|
49
|
+
// as an `extraMethod`, this test is still useful. See the
|
|
50
|
+
// testcase in `prepare-attenuator.test.js`.
|
|
51
|
+
underlying !== undefined || Fail`${q(wrapperKindName)} revoked`;
|
|
52
|
+
|
|
53
|
+
return underlying[name](...args);
|
|
54
|
+
},
|
|
55
|
+
// @ts-expect-error using possible symbol as index type
|
|
56
|
+
}[name],
|
|
57
|
+
]),
|
|
58
|
+
),
|
|
59
|
+
...extraMethods,
|
|
60
|
+
});
|
|
61
|
+
harden(wrapperMethods);
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @template [U=any]
|
|
65
|
+
* @callback MakeAttenuator
|
|
66
|
+
* @param {U} underlying
|
|
67
|
+
* @returns {Partial<U>}
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @template [U=any]
|
|
72
|
+
* @typedef {object} AttenuatorThis
|
|
73
|
+
* @property {Partial<U>} self
|
|
74
|
+
* @property {{ underlying: U }} state
|
|
75
|
+
*/
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @template [U=any]
|
|
79
|
+
* @typedef {object} AttenuatorOptions
|
|
80
|
+
* @property {string} [uInterfaceName]
|
|
81
|
+
* The `interfaceName` of the underlying interface guard.
|
|
82
|
+
* Defaults to the `uKindName`.
|
|
83
|
+
* @property {Record<
|
|
84
|
+
* PropertyKey,
|
|
85
|
+
* MethodGuard
|
|
86
|
+
* >} [extraMethodGuards]
|
|
87
|
+
* For guarding the `extraMethods`, if you include them below. These appear
|
|
88
|
+
* only on the synthesized interface guard for the attenuator, and
|
|
89
|
+
* do not necessarily correspond to any method of the underlying.
|
|
90
|
+
* @property {Record<
|
|
91
|
+
* PropertyKey,
|
|
92
|
+
* (this: AttenuatorThis<U>, ...args: any[]) => any
|
|
93
|
+
* >} [extraMethods]
|
|
94
|
+
* Extra methods adding behavior only to the attenuator, and
|
|
95
|
+
* do not necessarily correspond to any methods of the underlying.
|
|
96
|
+
*/
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Make an exo class for wrapping an underlying exo class,
|
|
100
|
+
* where the wrapper is an attenuator of the underlying.
|
|
101
|
+
*
|
|
102
|
+
* @template [U=any]
|
|
103
|
+
* @param {Zone} zone
|
|
104
|
+
* @param {string} uKindName
|
|
105
|
+
* The `kindName` of the underlying exo class
|
|
106
|
+
* @param {(keyof U)[]} uMethodNames
|
|
107
|
+
* The method names of the underlying exo class that should be represented
|
|
108
|
+
* by transparently-forwarding methods of the attenuator.
|
|
109
|
+
* @param {AttenuatorOptions<U>} [options]
|
|
110
|
+
* @returns {MakeAttenuator}
|
|
111
|
+
*/
|
|
112
|
+
export const prepareAttenuatorMaker = (
|
|
113
|
+
zone,
|
|
114
|
+
uKindName,
|
|
115
|
+
uMethodNames,
|
|
116
|
+
options = {},
|
|
117
|
+
) => {
|
|
118
|
+
const {
|
|
119
|
+
uInterfaceName = uKindName,
|
|
120
|
+
extraMethodGuards = {},
|
|
121
|
+
extraMethods = {},
|
|
122
|
+
} = options;
|
|
123
|
+
const AttenuatorI = M.interface(
|
|
124
|
+
`${uInterfaceName}_attenuator`,
|
|
125
|
+
extraMethodGuards,
|
|
126
|
+
{ defaultGuards: 'raw' },
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const attenuatorKindName = `${uKindName}_attenuator`;
|
|
130
|
+
|
|
131
|
+
return zone.exoClass(
|
|
132
|
+
attenuatorKindName,
|
|
133
|
+
AttenuatorI,
|
|
134
|
+
underlying => ({ underlying }),
|
|
135
|
+
wrapperMethods(attenuatorKindName, uMethodNames, extraMethods),
|
|
136
|
+
{
|
|
137
|
+
stateShape: { underlying: M.opt(M.remotable('underlying')) },
|
|
138
|
+
},
|
|
139
|
+
);
|
|
140
|
+
};
|
|
141
|
+
harden(prepareAttenuatorMaker);
|
|
142
|
+
|
|
143
|
+
// cf. https://endojs.github.io/endo/functions/_endo_pass_style.Remotable.html
|
|
144
|
+
const RemotablePrefixRE = /^(Alleged: |DebugName: )/;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* A convenience above `prepareAttenuatorMaker` for doing a singleton
|
|
148
|
+
* ephemeral attenuator, i.e., a new attenuator instance (and hidden class)
|
|
149
|
+
* that is allocated in the heap zone, and therefore ephemeral. The underlying
|
|
150
|
+
* can be durable or not, with no conflict with the attenuator being
|
|
151
|
+
* ephemeral. The price of this convenience is the allocation of the hidden
|
|
152
|
+
* class and wrapper methods per `attenuateOne` call, i.e., per attenuator
|
|
153
|
+
* instance.
|
|
154
|
+
*
|
|
155
|
+
* @template {any} U
|
|
156
|
+
* @param {U} underlying
|
|
157
|
+
* @param {(keyof U)[]} uMethodNames
|
|
158
|
+
* @param {AttenuatorOptions<U>} [options]
|
|
159
|
+
* @returns {Partial<U>}
|
|
160
|
+
*/
|
|
161
|
+
export const attenuateOne = (underlying, uMethodNames, options = undefined) => {
|
|
162
|
+
const heapZone = makeHeapZone();
|
|
163
|
+
const uKindName = (underlying[Symbol.toStringTag] || 'Underlying').replace(
|
|
164
|
+
RemotablePrefixRE,
|
|
165
|
+
'',
|
|
166
|
+
);
|
|
167
|
+
const makeAttenuator = prepareAttenuatorMaker(
|
|
168
|
+
heapZone,
|
|
169
|
+
uKindName,
|
|
170
|
+
uMethodNames,
|
|
171
|
+
options,
|
|
172
|
+
);
|
|
173
|
+
return makeAttenuator(underlying);
|
|
174
|
+
};
|
|
175
|
+
harden(attenuateOne);
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
export function prepareRevocableMakerKit<U = any>(zone:
|
|
1
|
+
export function prepareRevocableMakerKit<U = any>(zone: Zone, uKindName: string, uMethodNames: PropertyKey[], options?: RevocableKitOptions<U>): RevocableMakerKit<U>;
|
|
2
|
+
export type MakeRevocable<U = any> = (underlying: U) => Partial<U>;
|
|
3
|
+
export type MakeRevocableKit<U = any> = (underlying: U) => RevocableKit<U>;
|
|
2
4
|
export type RevocableMakerKit<U = any> = {
|
|
3
5
|
revoke: (revocable: U) => boolean;
|
|
4
6
|
/**
|
|
5
7
|
* Forwards to the underlying exo object, until revoked
|
|
6
8
|
*/
|
|
7
|
-
makeRevocable:
|
|
9
|
+
makeRevocable: MakeRevocable<U>;
|
|
10
|
+
makeRevocableKit: MakeRevocableKit<U>;
|
|
8
11
|
};
|
|
9
12
|
export type RevokerFacet = {
|
|
10
13
|
revoke: () => boolean;
|
|
@@ -14,7 +17,7 @@ export type RevocableKit<U = any> = {
|
|
|
14
17
|
/**
|
|
15
18
|
* Forwards to the underlying exo object, until revoked
|
|
16
19
|
*/
|
|
17
|
-
revocable: U
|
|
20
|
+
revocable: Partial<U>;
|
|
18
21
|
};
|
|
19
22
|
export type RevocableKitThis<U = any> = {
|
|
20
23
|
facets: RevocableKit<U>;
|
|
@@ -33,11 +36,13 @@ export type RevocableKitOptions<U = any> = {
|
|
|
33
36
|
* only on the synthesized interface guard for the revocable caretaker, and
|
|
34
37
|
* do not necessarily correspond to any method of the underlying.
|
|
35
38
|
*/
|
|
36
|
-
extraMethodGuards?: Record<
|
|
39
|
+
extraMethodGuards?: Record<PropertyKey, MethodGuard> | undefined;
|
|
37
40
|
/**
|
|
38
41
|
* Extra methods adding behavior only to the revocable caretaker, and
|
|
39
42
|
* do not necessarily correspond to any methods of the underlying.
|
|
40
43
|
*/
|
|
41
|
-
extraMethods?: Record<
|
|
44
|
+
extraMethods?: Record<PropertyKey, (this: RevocableKitThis<U>, ...args: any[]) => any> | undefined;
|
|
42
45
|
};
|
|
46
|
+
import type { Zone } from '@agoric/base-zone';
|
|
47
|
+
import type { MethodGuard } from '@endo/patterns';
|
|
43
48
|
//# sourceMappingURL=prepare-revocable.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare-revocable.d.ts","sourceRoot":"","sources":["prepare-revocable.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prepare-revocable.d.ts","sourceRoot":"","sources":["prepare-revocable.js"],"names":[],"mappings":"AA6FO,yCAVO,CAAC,cACJ,IAAI,aACJ,MAAM,gBAEN,WAAW,EAAE,YAGb,mBAAmB,CAAC,CAAC,CAAC,GACpB,iBAAiB,CAAC,CAAC,CAAC,CA4EhC;0BAvJa,CAAC,uBAEJ,CAAC,KACC,OAAO,CAAC,CAAC,CAAC;6BAIT,CAAC,uBAEJ,CAAC,KACC,YAAY,CAAC,CAAC,CAAC;8BAId,CAAC;YAED,CAAC,SAAS,EAAE,CAAC,KAAK,OAAO;;;;mBACzB,aAAa,CAAC,CAAC,CAAC;sBAEhB,gBAAgB,CAAC,CAAC,CAAC;;;YAKnB,MAAM,OAAO;;yBAIb,CAAC;aAED,YAAY;;;;eACZ,OAAO,CAAC,CAAC,CAAC;;6BAKV,CAAC;YAED,YAAY,CAAC,CAAC,CAAC;WACf;QAAE,UAAU,EAAE,CAAC,CAAA;KAAE;;gCAIjB,CAAC;;;;;;;;;;;;;;;;8CAcH,gBAAgB,CAAC,CAAC,CAAC,WAAW,GAAG,EAAE,KAAK,GAAG;;0BAnEhC,mBAAmB;iCADZ,gBAAgB"}
|
package/src/prepare-revocable.js
CHANGED
|
@@ -1,15 +1,39 @@
|
|
|
1
|
-
import { Fail, q } from '@endo/errors';
|
|
2
|
-
import { fromUniqueEntries } from '@endo/common/from-unique-entries.js';
|
|
3
1
|
import { M } from '@endo/patterns';
|
|
2
|
+
import { wrapperMethods } from './prepare-attenuator.js';
|
|
4
3
|
|
|
5
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* @import {Amplify} from '@endo/exo';
|
|
6
|
+
* @import {MethodGuard} from '@endo/patterns';
|
|
7
|
+
* @import {Zone} from '@agoric/base-zone';
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// This revocable kit implementation provides for both attenuation and
|
|
11
|
+
// revocation, since both can be provided at the cost of one level of
|
|
12
|
+
// indirection. But if you just need attenuation without revocation, better to
|
|
13
|
+
// use the attenuator implementation in prepare-attenuator.js.
|
|
14
|
+
// Please co-maintain these two modules.
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @template [U=any]
|
|
18
|
+
* @callback MakeRevocable
|
|
19
|
+
* @param {U} underlying
|
|
20
|
+
* @returns {Partial<U>}
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @template [U=any]
|
|
25
|
+
* @callback MakeRevocableKit
|
|
26
|
+
* @param {U} underlying
|
|
27
|
+
* @returns {RevocableKit<U>}
|
|
28
|
+
*/
|
|
6
29
|
|
|
7
30
|
/**
|
|
8
31
|
* @template [U=any]
|
|
9
32
|
* @typedef {object} RevocableMakerKit
|
|
10
33
|
* @property {(revocable: U) => boolean} revoke
|
|
11
|
-
* @property {
|
|
34
|
+
* @property {MakeRevocable<U>} makeRevocable
|
|
12
35
|
* Forwards to the underlying exo object, until revoked
|
|
36
|
+
* @property {MakeRevocableKit<U>} makeRevocableKit
|
|
13
37
|
*/
|
|
14
38
|
|
|
15
39
|
/**
|
|
@@ -21,7 +45,7 @@ import { M } from '@endo/patterns';
|
|
|
21
45
|
* @template [U=any]
|
|
22
46
|
* @typedef {object} RevocableKit
|
|
23
47
|
* @property {RevokerFacet} revoker
|
|
24
|
-
* @property {U} revocable
|
|
48
|
+
* @property {Partial<U>} revocable
|
|
25
49
|
* Forwards to the underlying exo object, until revoked
|
|
26
50
|
*/
|
|
27
51
|
|
|
@@ -39,14 +63,14 @@ import { M } from '@endo/patterns';
|
|
|
39
63
|
* The `interfaceName` of the underlying interface guard.
|
|
40
64
|
* Defaults to the `uKindName`.
|
|
41
65
|
* @property {Record<
|
|
42
|
-
*
|
|
43
|
-
*
|
|
66
|
+
* PropertyKey,
|
|
67
|
+
* MethodGuard
|
|
44
68
|
* >} [extraMethodGuards]
|
|
45
69
|
* For guarding the `extraMethods`, if you include them below. These appear
|
|
46
70
|
* only on the synthesized interface guard for the revocable caretaker, and
|
|
47
71
|
* do not necessarily correspond to any method of the underlying.
|
|
48
72
|
* @property {Record<
|
|
49
|
-
*
|
|
73
|
+
* PropertyKey,
|
|
50
74
|
* (this: RevocableKitThis<U>, ...args: any[]) => any
|
|
51
75
|
* >} [extraMethods]
|
|
52
76
|
* Extra methods adding behavior only to the revocable caretaker, and
|
|
@@ -58,13 +82,13 @@ import { M } from '@endo/patterns';
|
|
|
58
82
|
* where the wrapper is a revocable forwarder.
|
|
59
83
|
*
|
|
60
84
|
* @template [U=any]
|
|
61
|
-
* @param {
|
|
85
|
+
* @param {Zone} zone
|
|
62
86
|
* @param {string} uKindName
|
|
63
87
|
* The `kindName` of the underlying exo class
|
|
64
|
-
* @param {
|
|
88
|
+
* @param {PropertyKey[]} uMethodNames
|
|
65
89
|
* The method names of the underlying exo class that should be represented
|
|
66
90
|
* by transparently-forwarding methods of the revocable caretaker.
|
|
67
|
-
* @param {RevocableKitOptions} [options]
|
|
91
|
+
* @param {RevocableKitOptions<U>} [options]
|
|
68
92
|
* @returns {RevocableMakerKit<U>}
|
|
69
93
|
*/
|
|
70
94
|
export const prepareRevocableMakerKit = (
|
|
@@ -75,22 +99,16 @@ export const prepareRevocableMakerKit = (
|
|
|
75
99
|
) => {
|
|
76
100
|
const {
|
|
77
101
|
uInterfaceName = uKindName,
|
|
78
|
-
extraMethodGuards =
|
|
79
|
-
extraMethods =
|
|
102
|
+
extraMethodGuards = {},
|
|
103
|
+
extraMethods = {},
|
|
80
104
|
} = options;
|
|
81
105
|
const RevocableIKit = harden({
|
|
82
106
|
revoker: M.interface(`${uInterfaceName}_revoker`, {
|
|
83
107
|
revoke: M.call().returns(M.boolean()),
|
|
84
108
|
}),
|
|
85
|
-
revocable: M.interface(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
...extraMethodGuards,
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
defaultGuards: 'raw',
|
|
92
|
-
},
|
|
93
|
-
),
|
|
109
|
+
revocable: M.interface(`${uInterfaceName}_revocable`, extraMethodGuards, {
|
|
110
|
+
defaultGuards: 'raw',
|
|
111
|
+
}),
|
|
94
112
|
});
|
|
95
113
|
|
|
96
114
|
const revocableKindName = `${uKindName}_caretaker`;
|
|
@@ -101,9 +119,7 @@ export const prepareRevocableMakerKit = (
|
|
|
101
119
|
const makeRevocableKit = zone.exoClassKit(
|
|
102
120
|
revocableKindName,
|
|
103
121
|
RevocableIKit,
|
|
104
|
-
underlying => ({
|
|
105
|
-
underlying,
|
|
106
|
-
}),
|
|
122
|
+
underlying => ({ underlying }),
|
|
107
123
|
{
|
|
108
124
|
revoker: {
|
|
109
125
|
revoke() {
|
|
@@ -115,30 +131,10 @@ export const prepareRevocableMakerKit = (
|
|
|
115
131
|
return true;
|
|
116
132
|
},
|
|
117
133
|
},
|
|
118
|
-
revocable:
|
|
119
|
-
...fromUniqueEntries(
|
|
120
|
-
uMethodNames.map(name => [
|
|
121
|
-
name,
|
|
122
|
-
{
|
|
123
|
-
// Use concise method syntax for exo methods
|
|
124
|
-
[name](...args) {
|
|
125
|
-
// @ts-expect-error normal exo-this typing confusion
|
|
126
|
-
const { underlying } = this.state;
|
|
127
|
-
underlying !== undefined ||
|
|
128
|
-
Fail`${q(revocableKindName)} revoked`;
|
|
129
|
-
return underlying[name](...args);
|
|
130
|
-
},
|
|
131
|
-
// @ts-expect-error using possible symbol as index type
|
|
132
|
-
}[name],
|
|
133
|
-
]),
|
|
134
|
-
),
|
|
135
|
-
...extraMethods,
|
|
136
|
-
},
|
|
134
|
+
revocable: wrapperMethods(revocableKindName, uMethodNames, extraMethods),
|
|
137
135
|
},
|
|
138
136
|
{
|
|
139
|
-
stateShape: {
|
|
140
|
-
underlying: M.opt(M.remotable('underlying')),
|
|
141
|
-
},
|
|
137
|
+
stateShape: { underlying: M.opt(M.remotable('underlying')) },
|
|
142
138
|
receiveAmplifier: amp => {
|
|
143
139
|
amplifier = amp;
|
|
144
140
|
},
|
|
@@ -146,12 +142,9 @@ export const prepareRevocableMakerKit = (
|
|
|
146
142
|
);
|
|
147
143
|
|
|
148
144
|
/**
|
|
149
|
-
* @
|
|
150
|
-
* @returns {U}
|
|
145
|
+
* @type {MakeRevocable}
|
|
151
146
|
*/
|
|
152
|
-
const makeRevocable = underlying =>
|
|
153
|
-
// @ts-expect-error some confusion about UU vs Guarded<U> I think
|
|
154
|
-
makeRevocableKit(underlying).revocable;
|
|
147
|
+
const makeRevocable = underlying => makeRevocableKit(underlying).revocable;
|
|
155
148
|
|
|
156
149
|
/**
|
|
157
150
|
* @param {U} revocable
|
|
@@ -169,6 +162,8 @@ export const prepareRevocableMakerKit = (
|
|
|
169
162
|
return harden({
|
|
170
163
|
revoke,
|
|
171
164
|
makeRevocable,
|
|
165
|
+
/** @type {MakeRevocableKit} */
|
|
166
|
+
makeRevocableKit,
|
|
172
167
|
});
|
|
173
168
|
};
|
|
174
169
|
harden(prepareRevocableMakerKit);
|
package/src/types.d.ts
CHANGED
|
@@ -43,7 +43,7 @@ export type Stores = {
|
|
|
43
43
|
/**
|
|
44
44
|
* provide a Map-like store named `label` in the zone
|
|
45
45
|
*/
|
|
46
|
-
mapStore: (label: string, options?: StoreOptions) => MapStore<
|
|
46
|
+
mapStore: <K, V>(label: string, options?: StoreOptions) => MapStore<K, V>;
|
|
47
47
|
/**
|
|
48
48
|
* provide a Set-like store named `label` in the zone
|
|
49
49
|
*/
|
|
@@ -60,5 +60,10 @@ export type Stores = {
|
|
|
60
60
|
import { makeExo } from '@endo/exo';
|
|
61
61
|
import { defineExoClass } from '@endo/exo';
|
|
62
62
|
import { defineExoClassKit } from '@endo/exo';
|
|
63
|
+
import type { StoreOptions } from '@agoric/store';
|
|
63
64
|
import { watchPromise } from './watch-promise.js';
|
|
65
|
+
import type { MapStore } from '@agoric/store';
|
|
66
|
+
import type { SetStore } from '@agoric/store';
|
|
67
|
+
import type { WeakMapStore } from '@agoric/store';
|
|
68
|
+
import type { WeakSetStore } from '@agoric/store';
|
|
64
69
|
//# sourceMappingURL=types.d.ts.map
|
package/src/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.js"],"names":[],"mappings":"4BAcc,UAAU,GAAG,aAAa,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM;wBACrD,MAAM,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;;;;;mBAGnD,OAAO,GAAG,MAAM;;;;;SAMf,OAAO,OAAO;;;;cACd,OAAO,cAAc;;;;iBACrB,OAAO,iBAAiB;;;;cACxB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,KAAK,CAAC;;;;aAChD,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,IAAI;;;;kBAC/C,OAAO,YAAY;;;;;;cAKnB,MAAM,MAAM;;;;gBACZ,CAAC,QAAQ,EAAE,OAAO,KAAK,OAAO;;;;cAC9B,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,SAAS,CAAC,EAAE,CAAC,CAAC;;;;cAC/D,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,SAAS,CAAC,CAAC;;;;kBACzD,CAAC,CAAC,EAAE,CAAC,EACd,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,aAAa,CAAC,EAAE,CAAC,CAAC;;;;kBAEnD,CAAC,CAAC,EACX,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,aAAa,CAAC,CAAC;;wBAzCH,WAAW;+BAAX,WAAW;kCAAX,WAAW;kCAQS,eAAe;6BANjE,oBAAoB;8BAM8B,eAAe;8BAAf,eAAe;kCAAf,eAAe;kCAAf,eAAe"}
|
package/src/types.js
CHANGED
|
@@ -7,6 +7,7 @@ import { watchPromise } from './watch-promise.js';
|
|
|
7
7
|
export {};
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
+
* @import {MapStore, SetStore, StoreOptions, WeakMapStore, WeakSetStore} from '@agoric/store';
|
|
10
11
|
* @import {Key} from '@endo/patterns';
|
|
11
12
|
* @import {Passable} from '@endo/pass-style';
|
|
12
13
|
*/
|
|
@@ -33,7 +34,7 @@ export {};
|
|
|
33
34
|
* @typedef {object} Stores
|
|
34
35
|
* @property {() => Stores} detached obtain store providers which are detached (the stores are anonymous rather than bound to `label` in the zone)
|
|
35
36
|
* @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
|
|
36
|
-
* @property {(label: string, options?: StoreOptions) => MapStore<
|
|
37
|
+
* @property {<K, V>(label: string, options?: StoreOptions) => MapStore<K, V>} mapStore provide a Map-like store named `label` in the zone
|
|
37
38
|
* @property {<K>(label: string, options?: StoreOptions) => SetStore<K>} setStore provide a Set-like store named `label` in the zone
|
|
38
39
|
* @property {<K, V>(
|
|
39
40
|
* label: string, options?: StoreOptions) => WeakMapStore<K, V>
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// Modeled on test-heap-classes.js
|
|
2
|
+
|
|
3
|
+
import { test } from './prepare-test-env-ava.js';
|
|
4
|
+
|
|
5
|
+
// eslint-disable-next-line import/order
|
|
6
|
+
import { M } from '@endo/patterns';
|
|
7
|
+
import { makeHeapZone } from '../src/heap.js';
|
|
8
|
+
import { prepareAttenuatorMaker } from '../src/prepare-attenuator.js';
|
|
9
|
+
|
|
10
|
+
const CounterI = M.interface('Counter', {
|
|
11
|
+
incr: M.call()
|
|
12
|
+
// TODO M.number() should not be needed to get a better error message
|
|
13
|
+
.optional(M.and(M.number(), M.gte(0)))
|
|
14
|
+
.returns(M.number()),
|
|
15
|
+
decr: M.call()
|
|
16
|
+
// TODO M.number() should not be needed to get a better error message
|
|
17
|
+
.optional(M.and(M.number(), M.gte(0)))
|
|
18
|
+
.returns(M.number()),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('test attenuate defineVirtualExoClass', t => {
|
|
22
|
+
const zone = makeHeapZone('rootZone');
|
|
23
|
+
|
|
24
|
+
const makeUnderlyingCounter = zone.exoClass(
|
|
25
|
+
'Counter',
|
|
26
|
+
CounterI,
|
|
27
|
+
/** @param {number} [x] */
|
|
28
|
+
(x = 0) => ({ x }),
|
|
29
|
+
{
|
|
30
|
+
incr(y = 1) {
|
|
31
|
+
const { state } = this;
|
|
32
|
+
state.x += y;
|
|
33
|
+
return state.x;
|
|
34
|
+
},
|
|
35
|
+
decr(y = 1) {
|
|
36
|
+
const { state } = this;
|
|
37
|
+
state.x -= y;
|
|
38
|
+
return state.x;
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const makeUpAttenuator = prepareAttenuatorMaker(zone, 'UpCounter', ['incr']);
|
|
44
|
+
|
|
45
|
+
const makeUpCounter = x => makeUpAttenuator(makeUnderlyingCounter(x));
|
|
46
|
+
|
|
47
|
+
const upCounter = makeUpCounter(3);
|
|
48
|
+
t.is(upCounter.incr(5), 8);
|
|
49
|
+
t.throws(() => upCounter.decr(1), {
|
|
50
|
+
message: 'upCounter.decr is not a function',
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('test revoke defineVirtualExoClassKit', t => {
|
|
55
|
+
const zone = makeHeapZone('rootZone');
|
|
56
|
+
|
|
57
|
+
const makeUnderlyingCounter = zone.exoClass(
|
|
58
|
+
'Counter',
|
|
59
|
+
CounterI,
|
|
60
|
+
/** @param {number} [x] */
|
|
61
|
+
(x = 0) => ({ x }),
|
|
62
|
+
{
|
|
63
|
+
incr(y = 1) {
|
|
64
|
+
const { state } = this;
|
|
65
|
+
state.x += y;
|
|
66
|
+
return state.x;
|
|
67
|
+
},
|
|
68
|
+
decr(y = 1) {
|
|
69
|
+
const { state } = this;
|
|
70
|
+
state.x -= y;
|
|
71
|
+
return state.x;
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const makeDownAttenuator = prepareAttenuatorMaker(
|
|
77
|
+
zone,
|
|
78
|
+
'DownCounter',
|
|
79
|
+
['decr'],
|
|
80
|
+
{
|
|
81
|
+
extraMethodGuards: {
|
|
82
|
+
selfRevoke: M.call().returns(M.boolean()),
|
|
83
|
+
},
|
|
84
|
+
extraMethods: {
|
|
85
|
+
selfRevoke() {
|
|
86
|
+
const { state } = this;
|
|
87
|
+
if (state.underlying === undefined) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
// @ts-expect-error Setting this to `undefined` is purposely outside
|
|
91
|
+
// the type system.
|
|
92
|
+
state.underlying = undefined;
|
|
93
|
+
return true;
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const makeDownCounter = x => makeDownAttenuator(makeUnderlyingCounter(x));
|
|
100
|
+
|
|
101
|
+
const downCounter = makeDownCounter(3);
|
|
102
|
+
t.throws(() => downCounter.incr(1), {
|
|
103
|
+
message: 'downCounter.incr is not a function',
|
|
104
|
+
});
|
|
105
|
+
t.is(downCounter.decr(), 2);
|
|
106
|
+
t.is(downCounter.selfRevoke(), true);
|
|
107
|
+
t.throws(() => downCounter.decr(3), {
|
|
108
|
+
message: '"DownCounter_attenuator" revoked',
|
|
109
|
+
});
|
|
110
|
+
});
|
package/tools/greeter.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { M, getInterfaceGuardPayload } from '@endo/patterns';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @import {Zone} from '../src/types.js';
|
|
5
|
+
*/
|
|
6
|
+
|
|
3
7
|
/**
|
|
4
8
|
* @template {{}} T
|
|
5
9
|
* @param {T} obj
|
|
@@ -38,7 +42,7 @@ export const GreeterWithAdminI = M.interface('GreeterWithAdmin', {
|
|
|
38
42
|
});
|
|
39
43
|
|
|
40
44
|
/**
|
|
41
|
-
* @param {
|
|
45
|
+
* @param {Zone} zone
|
|
42
46
|
* @param {string} label
|
|
43
47
|
* @param {string} nick
|
|
44
48
|
*/
|
|
@@ -51,7 +55,7 @@ export const prepareGreeterSingleton = (zone, label, nick) => {
|
|
|
51
55
|
};
|
|
52
56
|
|
|
53
57
|
/**
|
|
54
|
-
* @param {
|
|
58
|
+
* @param {Zone} zone
|
|
55
59
|
*/
|
|
56
60
|
export const prepareGreeter = zone =>
|
|
57
61
|
zone.exoClass('Greeter', GreeterWithAdminI, nick => ({ nick }), {
|
|
@@ -60,7 +64,7 @@ export const prepareGreeter = zone =>
|
|
|
60
64
|
});
|
|
61
65
|
|
|
62
66
|
/**
|
|
63
|
-
* @param {
|
|
67
|
+
* @param {Zone} zone
|
|
64
68
|
*/
|
|
65
69
|
export const prepareGreeterKit = zone =>
|
|
66
70
|
zone.exoClassKit(
|
package/tools/testers.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import * as g from './greeter.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @
|
|
5
|
-
* @
|
|
4
|
+
* @import {Assertions} from 'ava';
|
|
5
|
+
* @import {Zone} from '../src/index.js';
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {Assertions} t
|
|
10
|
+
* @param {Zone} rootZone
|
|
6
11
|
*/
|
|
7
12
|
export const testMakeOnce = (t, rootZone) => {
|
|
8
13
|
const subZone = rootZone.subZone('sub');
|
|
@@ -52,7 +57,7 @@ const alreadyExceptionSpec = {
|
|
|
52
57
|
|
|
53
58
|
/**
|
|
54
59
|
* @template T
|
|
55
|
-
* @param {
|
|
60
|
+
* @param {Assertions} t
|
|
56
61
|
* @param {() => T} fn
|
|
57
62
|
* @param {*} spec
|
|
58
63
|
* @returns {T}
|
|
@@ -64,8 +69,8 @@ const secondThrows = (t, fn, spec = alreadyExceptionSpec) => {
|
|
|
64
69
|
};
|
|
65
70
|
|
|
66
71
|
/**
|
|
67
|
-
* @param {
|
|
68
|
-
* @param {
|
|
72
|
+
* @param {Assertions} t
|
|
73
|
+
* @param {Zone} rootZone
|
|
69
74
|
*/
|
|
70
75
|
export const testFirstZoneIncarnation = (t, rootZone) => {
|
|
71
76
|
const subZone = secondThrows(t, () => rootZone.subZone('sub'));
|
|
@@ -93,8 +98,8 @@ export const testFirstZoneIncarnation = (t, rootZone) => {
|
|
|
93
98
|
};
|
|
94
99
|
|
|
95
100
|
/**
|
|
96
|
-
* @param {
|
|
97
|
-
* @param {
|
|
101
|
+
* @param {Assertions} t
|
|
102
|
+
* @param {Zone} rootZone
|
|
98
103
|
*/
|
|
99
104
|
export const testSecondZoneIncarnation = (t, rootZone) => {
|
|
100
105
|
const subZone = secondThrows(t, () => rootZone.subZone('sub'));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./heap.js","./zone-helpers.js","./src/heap.js","./src/index.js","./src/is-passable.js","./src/keys.js","./src/make-once.js","./src/prepare-revocable.js","./src/types.js","./src/watch-promise.js"],"version":"5.
|
|
1
|
+
{"root":["./heap.js","./zone-helpers.js","./src/heap.js","./src/index.js","./src/is-passable.js","./src/keys.js","./src/make-once.js","./src/prepare-attenuator.js","./src/prepare-revocable.js","./src/types.js","./src/watch-promise.js"],"version":"5.9.3"}
|
package/zone-helpers.d.ts
CHANGED
package/zone-helpers.js
CHANGED