diff --git a/.prettierrc.json5 b/.prettierrc.json5 index ffcd04d01b8..3d1ea86f4e3 100644 --- a/.prettierrc.json5 +++ b/.prettierrc.json5 @@ -11,6 +11,7 @@ 'packages/store/**/*.js', 'packages/smart-wallet/**/*.js', 'packages/vats/**/*.js', + 'packages/vat-data/**/*.js', ], options: { plugins: ['prettier-plugin-jsdoc'], diff --git a/packages/ERTP/package.json b/packages/ERTP/package.json index d7537b902b7..e6f71c0e492 100644 --- a/packages/ERTP/package.json +++ b/packages/ERTP/package.json @@ -86,6 +86,6 @@ "access": "public" }, "typeCoverage": { - "atLeast": 91.22 + "atLeast": 91.23 } } diff --git a/packages/ERTP/src/paymentLedger.js b/packages/ERTP/src/paymentLedger.js index dcf3baffcc6..45835366b5d 100644 --- a/packages/ERTP/src/paymentLedger.js +++ b/packages/ERTP/src/paymentLedger.js @@ -15,13 +15,15 @@ import { BrandI, makeIssuerInterfaces } from './typeGuards.js'; /** * @import {Amount, AssetKind, DisplayInfo, PaymentLedger, Payment, Brand, RecoverySetsOption, Purse, Issuer, Mint} from './types.js' * @import {ShutdownWithFailure} from '@agoric/swingset-vat' - * @import {Key} from '@endo/patterns'; + * @import {TypedPattern} from '@agoric/internal'; */ /** + * @template {AssetKind} K * @param {Brand} brand - * @param {AssetKind} assetKind + * @param {K} assetKind * @param {Pattern} elementShape + * @returns {TypedPattern>} */ const amountShapeFromElementShape = (brand, assetKind, elementShape) => { let valueShape; diff --git a/packages/SwingSet/package.json b/packages/SwingSet/package.json index a67c8dc0ac1..29ed8e179a1 100644 --- a/packages/SwingSet/package.json +++ b/packages/SwingSet/package.json @@ -100,6 +100,6 @@ "access": "public" }, "typeCoverage": { - "atLeast": 75.02 + "atLeast": 75.1 } } diff --git a/packages/agoric-cli/package.json b/packages/agoric-cli/package.json index 033ba869677..6b7db016abb 100644 --- a/packages/agoric-cli/package.json +++ b/packages/agoric-cli/package.json @@ -99,6 +99,6 @@ "workerThreads": false }, "typeCoverage": { - "atLeast": 76.99 + "atLeast": 77.3 } } diff --git a/packages/async-flow/package.json b/packages/async-flow/package.json index 3a6903cad39..e1462adada2 100644 --- a/packages/async-flow/package.json +++ b/packages/async-flow/package.json @@ -61,6 +61,6 @@ "workerThreads": false }, "typeCoverage": { - "atLeast": 77.32 + "atLeast": 76.95 } } diff --git a/packages/base-zone/package.json b/packages/base-zone/package.json index deab47bb793..c6821f2ec18 100644 --- a/packages/base-zone/package.json +++ b/packages/base-zone/package.json @@ -57,6 +57,6 @@ "workerThreads": false }, "typeCoverage": { - "atLeast": 91.11 + "atLeast": 91.4 } } diff --git a/packages/boot/package.json b/packages/boot/package.json index a376630a8a6..35cb46ea959 100644 --- a/packages/boot/package.json +++ b/packages/boot/package.json @@ -90,6 +90,6 @@ "workerThreads": false }, "typeCoverage": { - "atLeast": 87.28 + "atLeast": 86.66 } } diff --git a/packages/builders/package.json b/packages/builders/package.json index 6d633969182..3cb3ff12678 100644 --- a/packages/builders/package.json +++ b/packages/builders/package.json @@ -79,6 +79,6 @@ "workerThreads": false }, "typeCoverage": { - "atLeast": 74.36 + "atLeast": 76.03 } } diff --git a/packages/casting/package.json b/packages/casting/package.json index 30cd54a6831..b21961e462c 100644 --- a/packages/casting/package.json +++ b/packages/casting/package.json @@ -60,6 +60,6 @@ "workerThreads": false }, "typeCoverage": { - "atLeast": 88.94 + "atLeast": 88.92 } } diff --git a/packages/cosmic-swingset/package.json b/packages/cosmic-swingset/package.json index ce99220035c..09d3a7056d6 100644 --- a/packages/cosmic-swingset/package.json +++ b/packages/cosmic-swingset/package.json @@ -68,6 +68,6 @@ "timeout": "20m" }, "typeCoverage": { - "atLeast": 80.49 + "atLeast": 80.6 } } diff --git a/packages/deploy-script-support/package.json b/packages/deploy-script-support/package.json index 57b4443dda5..3f3f5a6c927 100644 --- a/packages/deploy-script-support/package.json +++ b/packages/deploy-script-support/package.json @@ -72,6 +72,6 @@ "access": "public" }, "typeCoverage": { - "atLeast": 81.63 + "atLeast": 82.44 } } diff --git a/packages/governance/package.json b/packages/governance/package.json index 140c98c5c6f..0a2bed98035 100644 --- a/packages/governance/package.json +++ b/packages/governance/package.json @@ -76,6 +76,6 @@ "access": "public" }, "typeCoverage": { - "atLeast": 89.31 + "atLeast": 89.35 } } diff --git a/packages/inter-protocol/src/auction/auctionBook.js b/packages/inter-protocol/src/auction/auctionBook.js index be91b29a370..11b0da04228 100644 --- a/packages/inter-protocol/src/auction/auctionBook.js +++ b/packages/inter-protocol/src/auction/auctionBook.js @@ -31,6 +31,7 @@ import { /** * @import {Baggage} from '@agoric/vat-data'; * @import {PriceAuthority, PriceDescription, PriceQuote, PriceQuoteValue, PriceQuery,} from '@agoric/zoe/tools/types.js'; + * @import {TypedPattern} from '@agoric/internal'; */ const { makeEmpty } = AmountMath; @@ -172,9 +173,7 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => { const bookDataKit = makeRecorderKit( node, - /** @type {import('@agoric/zoe/src/contractSupport/recorder.js').TypedPattern} */ ( - M.any() - ), + /** @type {TypedPattern} */ (M.any()), ); return { diff --git a/packages/inter-protocol/src/auction/auctioneer.js b/packages/inter-protocol/src/auction/auctioneer.js index b2d480ab3dd..3b475137f5c 100644 --- a/packages/inter-protocol/src/auction/auctioneer.js +++ b/packages/inter-protocol/src/auction/auctioneer.js @@ -36,6 +36,7 @@ import { makeScheduler } from './scheduler.js'; import { AuctionState } from './util.js'; /** + * @import {TypedPattern} from '@agoric/internal'; * @import {Baggage} from '@agoric/vat-data'; * @import {PriceAuthority, PriceDescription, PriceQuote, PriceQuoteValue, PriceQuery,} from '@agoric/zoe/tools/types.js'; */ @@ -440,9 +441,7 @@ export const start = async (zcf, privateArgs, baggage) => { const scheduleKit = makeERecorderKit( E(privateArgs.storageNode).makeChildNode('schedule'), /** - * @type {import('@agoric/zoe/src/contractSupport/recorder.js').TypedPattern< - * import('./scheduler.js').ScheduleNotification - * >} + * @type {TypedPattern} */ (M.any()), ); diff --git a/packages/inter-protocol/src/price/fluxAggregatorKit.js b/packages/inter-protocol/src/price/fluxAggregatorKit.js index 70b3e1d58ed..e538b207dfc 100644 --- a/packages/inter-protocol/src/price/fluxAggregatorKit.js +++ b/packages/inter-protocol/src/price/fluxAggregatorKit.js @@ -18,7 +18,10 @@ import { Far } from '@endo/marshal'; import { prepareOracleAdminKit } from './priceOracleKit.js'; import { prepareRoundsManagerKit } from './roundsManager.js'; -/** @import {PriceAuthority, PriceDescription, PriceQuote, PriceQuoteValue, PriceQuery,} from '@agoric/zoe/tools/types.js'; */ +/** + * @import {TypedPattern} from '@agoric/internal'; + * @import {PriceAuthority, PriceDescription, PriceQuote, PriceQuoteValue, PriceQuery,} from '@agoric/zoe/tools/types.js'; + */ const trace = makeTracer('FlxAgg', true); @@ -144,18 +147,14 @@ export const prepareFluxAggregatorKit = async ( priceKit: () => makeRecorderKit( storageNode, - /** @type {import('@agoric/zoe/src/contractSupport/recorder.js').TypedPattern} */ ( - M.any() - ), + /** @type {TypedPattern} */ (M.any()), ), latestRoundKit: () => E.when(E(storageNode).makeChildNode('latestRound'), node => makeRecorderKit( node, /** - * @type {import('@agoric/zoe/src/contractSupport/recorder.js').TypedPattern< - * import('./roundsManager.js').LatestRound - * >} + * @type {TypedPattern} */ (M.any()), ), ), diff --git a/packages/inter-protocol/src/psm/psm.js b/packages/inter-protocol/src/psm/psm.js index 113a6f7ab6e..246d138979f 100644 --- a/packages/inter-protocol/src/psm/psm.js +++ b/packages/inter-protocol/src/psm/psm.js @@ -59,7 +59,10 @@ import { makeNatAmountShape } from '../contractSupport.js'; * given by this contract */ -/** @import {Baggage} from '@agoric/vat-data' */ +/** + * @import {TypedPattern} from '@agoric/internal'; + * @import {Baggage} from '@agoric/vat-data' + */ /** @type {ContractMeta} */ export const meta = { @@ -174,9 +177,7 @@ export const start = async (zcf, privateArgs, baggage) => { E.when(E(privateArgs.storageNode).makeChildNode('metrics'), node => makeRecorderKit( node, - /** @type {import('@agoric/zoe/src/contractSupport/recorder.js').TypedPattern} */ ( - M.any() - ), + /** @type {TypedPattern} */ (M.any()), ), ), }); diff --git a/packages/inter-protocol/src/reserve/assetReserveKit.js b/packages/inter-protocol/src/reserve/assetReserveKit.js index 673901e46de..d4e5971ccf0 100644 --- a/packages/inter-protocol/src/reserve/assetReserveKit.js +++ b/packages/inter-protocol/src/reserve/assetReserveKit.js @@ -13,6 +13,10 @@ import { UnguardedHelperI } from '@agoric/internal/src/typeGuards.js'; const trace = makeTracer('ReserveKit', true); +/** + * @import {TypedPattern} from '@agoric/internal'; + */ + /** * @typedef {object} MetricsNotification * @property {AmountKeywordRecord} allocations @@ -88,9 +92,7 @@ export const prepareAssetReserveKit = async ( keywordForBrand, metricsKit: makeRecorderKit( metricsNode, - /** @type {import('@agoric/zoe/src/contractSupport/recorder.js').TypedPattern} */ ( - M.any() - ), + /** @type {TypedPattern} */ (M.any()), ), totalFeeMinted: emptyAmount, totalFeeBurned: emptyAmount, diff --git a/packages/inter-protocol/src/vaultFactory/vaultDirector.js b/packages/inter-protocol/src/vaultFactory/vaultDirector.js index cb221c938b3..7eccd809648 100644 --- a/packages/inter-protocol/src/vaultFactory/vaultDirector.js +++ b/packages/inter-protocol/src/vaultFactory/vaultDirector.js @@ -40,6 +40,10 @@ import { provideAndStartVaultManagerKits, } from './vaultManager.js'; +/** + * @import {TypedPattern} from '@agoric/internal'; + */ + const trace = makeTracer('VD', true); /** @@ -131,9 +135,7 @@ const prepareVaultDirector = ( const metricsKit = makeERecorderKit( metricsNode, - /** @type {import('@agoric/zoe/src/contractSupport/recorder.js').TypedPattern} */ ( - M.any() - ), + /** @type {TypedPattern} */ (M.any()), ); const managersNode = E(storageNode).makeChildNode('managers'); diff --git a/packages/internal/package.json b/packages/internal/package.json index f580d315df8..f6f71938a38 100755 --- a/packages/internal/package.json +++ b/packages/internal/package.json @@ -34,6 +34,7 @@ "jessie.js": "^0.3.4" }, "devDependencies": { + "@endo/exo": "^1.5.0", "@endo/init": "^1.1.2", "ava": "^5.3.0", "tsd": "^0.31.1" @@ -56,6 +57,6 @@ "access": "public" }, "typeCoverage": { - "atLeast": 93.89 + "atLeast": 93.78 } } diff --git a/packages/internal/src/index.js b/packages/internal/src/index.js index a9b3a7b0a3b..28e9139d3f3 100644 --- a/packages/internal/src/index.js +++ b/packages/internal/src/index.js @@ -7,6 +7,7 @@ export * from './debug.js'; export * from './errors.js'; export * from './utils.js'; export * from './method-tools.js'; +export * from './typeCheck.js'; export * from './typeGuards.js'; // eslint-disable-next-line import/export -- just types diff --git a/packages/internal/src/typeCheck.js b/packages/internal/src/typeCheck.js new file mode 100644 index 00000000000..657d3e72c6b --- /dev/null +++ b/packages/internal/src/typeCheck.js @@ -0,0 +1,23 @@ +// @ts-check +import { mustMatch as typelessMustMatch } from '@endo/patterns'; + +/** + * @import {MustMatch, PatternType, TypedPattern} from './types.js'; + */ + +/** @type {MustMatch} */ +export const mustMatch = typelessMustMatch; + +/** + * @template M + * @param {unknown} specimen + * @param {TypedPattern} patt + * @returns {M} + */ +export const cast = (specimen, patt) => { + // mustMatch throws if they don't, which means that `cast` also narrows the + // type but a function can't both narrow and return a type. That is by design: + // https://github.com/microsoft/TypeScript/issues/34636#issuecomment-545025916 + mustMatch(specimen, patt); + return specimen; +}; diff --git a/packages/internal/src/types.d.ts b/packages/internal/src/types.d.ts index 2053dee53ff..806e5882cf5 100644 --- a/packages/internal/src/types.d.ts +++ b/packages/internal/src/types.d.ts @@ -64,3 +64,33 @@ export type Remote> = export type FarRef> = ERef< Remote >; + +/* + * Stop-gap until https://github.com/Agoric/agoric-sdk/issues/6160 + * explictly specify the type that the Pattern will verify through a match. + * + * TODO move all this pattern typing stuff to @endo/patterns + */ +declare const validatedType: unique symbol; +/** + * Tag a pattern with the static type it represents. + */ +export type TypedPattern = Pattern & { [validatedType]?: T }; + +export declare type PatternType> = + TM extends TypedPattern ? T : never; + +// TODO make Endo's mustMatch do this +/** + * Returning normally indicates success. Match failure is indicated by + * throwing. + * + * Note: remotables can only be matched as "remotable", not the specific kind. + * + * @see {import('@endo/patterns').mustMatch} for the implementation. This one has a type annotation to narrow if the pattern is a TypedPattern. + */ +export declare type MustMatch =

( + specimen: unknown, + pattern: P, + label?: string | number, +) => asserts specimen is P extends TypedPattern ? PatternType

: unknown; diff --git a/packages/internal/test/typeCheck.test.js b/packages/internal/test/typeCheck.test.js new file mode 100644 index 00000000000..e1745ed447d --- /dev/null +++ b/packages/internal/test/typeCheck.test.js @@ -0,0 +1,55 @@ +// @ts-check +import test from 'ava'; + +import { makeExo } from '@endo/exo'; +import { M } from '@endo/patterns'; +import { cast, mustMatch } from '../src/typeCheck.js'; + +/** + * @import {TypedPattern} from '@agoric/internal'; + * @import {RemotableObject} from '@endo/marshal'; + */ + +const Mstring = /** @type {TypedPattern} */ (M.string()); +const MremotableFoo = /** @type {TypedPattern>} */ ( + M.remotable('Foo') +); +const MremotableBar = /** @type {TypedPattern>} */ ( + M.remotable('Bar') +); + +const unknownString = /** @type {unknown} */ (''); + +test('cast', t => { + // @ts-expect-error unknown type + unknownString.length; + // @ts-expect-error not any + cast(unknownString, Mstring).missing; + cast(unknownString, Mstring).length; + t.pass(); +}); + +test('mustMatch', t => { + // @ts-expect-error unknown type + unknownString.length; + mustMatch(unknownString, Mstring); + unknownString.length; + t.pass(); +}); + +test('remotable', t => { + const maybeFoo = makeExo(`Remotable1`, undefined, {}); + mustMatch(maybeFoo, MremotableFoo); + maybeFoo; // narrowed to Foo + + const maybeBar = makeExo(`Remotable2`, undefined, {}); + mustMatch(maybeBar, MremotableBar); + maybeBar; // narrowed to Bar + + mustMatch(maybeFoo, MremotableBar); + maybeFoo; // further narrowed to never + mustMatch(maybeBar, MremotableFoo); + maybeBar; // further narrowed to never + + t.pass(); +}); diff --git a/packages/network/package.json b/packages/network/package.json index dae88c70df4..6f9fea25ed6 100644 --- a/packages/network/package.json +++ b/packages/network/package.json @@ -66,6 +66,6 @@ "workerThreads": false }, "typeCoverage": { - "atLeast": 89.7 + "atLeast": 90.69 } } diff --git a/packages/notifier/package.json b/packages/notifier/package.json index 0e05299584e..b20c2ec2614 100644 --- a/packages/notifier/package.json +++ b/packages/notifier/package.json @@ -76,6 +76,6 @@ "timeout": "2m" }, "typeCoverage": { - "atLeast": 90.34 + "atLeast": 90.33 } } diff --git a/packages/orchestration/src/typeGuards.js b/packages/orchestration/src/typeGuards.js index ef26c6e566a..201546cfa4b 100644 --- a/packages/orchestration/src/typeGuards.js +++ b/packages/orchestration/src/typeGuards.js @@ -2,6 +2,11 @@ import { AmountShape } from '@agoric/ertp'; import { VowShape } from '@agoric/vow'; import { M } from '@endo/patterns'; +/** + * @import {TypedPattern} from '@agoric/internal'; + * @import {CosmosChainInfo} from './cosmos-api.js'; + */ + /** * Used for IBC Channel Connections that only send outgoing transactions. If * your channel expects incoming transactions, please extend this interface to @@ -76,6 +81,9 @@ export const IBCConnectionInfoShape = M.splitRecord({ transferChannel: IBCChannelInfoShape, }); +/** + * @type {TypedPattern} + */ export const CosmosChainInfoShape = M.splitRecord( { chainId: M.string(), diff --git a/packages/pegasus/package.json b/packages/pegasus/package.json index 24328ef4325..aa15b76c817 100644 --- a/packages/pegasus/package.json +++ b/packages/pegasus/package.json @@ -70,6 +70,6 @@ "access": "public" }, "typeCoverage": { - "atLeast": 90.6 + "atLeast": 91.18 } } diff --git a/packages/smart-wallet/package.json b/packages/smart-wallet/package.json index 3a641ae7680..d6768b15a68 100644 --- a/packages/smart-wallet/package.json +++ b/packages/smart-wallet/package.json @@ -69,6 +69,6 @@ "access": "public" }, "typeCoverage": { - "atLeast": 94.36 + "atLeast": 94.51 } } diff --git a/packages/smart-wallet/src/invitations.js b/packages/smart-wallet/src/invitations.js index 75243d55b1f..ae4ee732901 100644 --- a/packages/smart-wallet/src/invitations.js +++ b/packages/smart-wallet/src/invitations.js @@ -1,8 +1,8 @@ -import { Fail } from '@endo/errors'; -import { E } from '@endo/far'; import { AmountMath } from '@agoric/ertp'; import { mustMatch } from '@agoric/store'; -import { InvitationHandleShape } from '@agoric/zoe/src/typeGuards.js'; +import { InvitationShape } from '@agoric/zoe/src/typeGuards.js'; +import { Fail } from '@endo/errors'; +import { E } from '@endo/far'; import { shape } from './typeGuards.js'; // A safety limit @@ -92,7 +92,7 @@ export const makeInvitationsHelper = ( } const invitation = await eref; - mustMatch(invitation, InvitationHandleShape); + mustMatch(invitation, InvitationShape); return invitation; }, /** @type {(spec: ContractInvitationSpec) => Promise} */ diff --git a/packages/solo/package.json b/packages/solo/package.json index 49c99ac28c1..70aa147efed 100644 --- a/packages/solo/package.json +++ b/packages/solo/package.json @@ -78,6 +78,6 @@ "workerThreads": false }, "typeCoverage": { - "atLeast": 73.11 + "atLeast": 73.21 } } diff --git a/packages/spawner/package.json b/packages/spawner/package.json index a284d4d537c..3795a1038a4 100644 --- a/packages/spawner/package.json +++ b/packages/spawner/package.json @@ -62,6 +62,6 @@ "timeout": "2m" }, "typeCoverage": { - "atLeast": 54.79 + "atLeast": 55.05 } } diff --git a/packages/stat-logger/package.json b/packages/stat-logger/package.json index d0db79beda8..63782d4b75c 100644 --- a/packages/stat-logger/package.json +++ b/packages/stat-logger/package.json @@ -38,6 +38,6 @@ "access": "public" }, "typeCoverage": { - "atLeast": 63.21 + "atLeast": 63.11 } } diff --git a/packages/store/package.json b/packages/store/package.json index 1f1b530638c..d5459a898c5 100644 --- a/packages/store/package.json +++ b/packages/store/package.json @@ -59,6 +59,6 @@ "timeout": "2m" }, "typeCoverage": { - "atLeast": 89.45 + "atLeast": 89.39 } } diff --git a/packages/store/src/index.js b/packages/store/src/index.js index cbfe2aa7aa6..447fcefd688 100755 --- a/packages/store/src/index.js +++ b/packages/store/src/index.js @@ -1,3 +1,8 @@ +/** + * @import {MustMatch} from '@agoric/internal'; + */ +import { mustMatch as typelessMustMatch } from '@endo/patterns'; + export { makeScalarWeakSetStore } from './stores/scalarWeakSetStore.js'; export { makeScalarSetStore } from './stores/scalarSetStore.js'; export { makeScalarWeakMapStore } from './stores/scalarWeakMapStore.js'; @@ -51,11 +56,15 @@ export { isPattern, assertPattern, matches, - mustMatch, isCopySet, isCopyMap, } from '@endo/patterns'; +// XXX @agoric/store should not depend on @agoric/internal +// TODO move to Endo +/** @type {MustMatch} */ +export const mustMatch = typelessMustMatch; + export { initEmpty, defineExoClass, diff --git a/packages/swingset-liveslots/package.json b/packages/swingset-liveslots/package.json index 82706c32f80..f9eea238ed8 100644 --- a/packages/swingset-liveslots/package.json +++ b/packages/swingset-liveslots/package.json @@ -21,7 +21,6 @@ "@agoric/internal": "^0.3.2", "@agoric/store": "^0.9.2", "@endo/env-options": "^1.1.4", - "@endo/errors": "^1.2.2", "@endo/eventual-send": "^1.2.2", "@endo/exo": "^1.5.0", "@endo/far": "^1.1.2", @@ -67,6 +66,6 @@ "access": "public" }, "typeCoverage": { - "atLeast": 75.29 + "atLeast": 75.35 } } diff --git a/packages/swingset-runner/package.json b/packages/swingset-runner/package.json index 3b43718ee38..e5315a01019 100644 --- a/packages/swingset-runner/package.json +++ b/packages/swingset-runner/package.json @@ -59,6 +59,6 @@ "timeout": "2m" }, "typeCoverage": { - "atLeast": 54.95 + "atLeast": 55.08 } } diff --git a/packages/swingset-xsnap-supervisor/package.json b/packages/swingset-xsnap-supervisor/package.json index 89e2b2f20b1..eeaddddf5ae 100644 --- a/packages/swingset-xsnap-supervisor/package.json +++ b/packages/swingset-xsnap-supervisor/package.json @@ -52,6 +52,6 @@ "workerThreads": false }, "typeCoverage": { - "atLeast": 83.64 + "atLeast": 83.68 } } diff --git a/packages/time/package.json b/packages/time/package.json index 18e541a7295..ed5962f41fb 100644 --- a/packages/time/package.json +++ b/packages/time/package.json @@ -31,6 +31,7 @@ }, "homepage": "https://github.com/Agoric/agoric-sdk#readme", "dependencies": { + "@agoric/store": "^0.9.2", "@endo/errors": "^1.2.2", "@endo/nat": "^5.0.7", "@endo/patterns": "^1.4.0" @@ -57,6 +58,6 @@ "access": "public" }, "typeCoverage": { - "atLeast": 87.29 + "atLeast": 88.77 } } diff --git a/packages/time/src/timeMath.js b/packages/time/src/timeMath.js index 925eb59cc04..2deef471443 100644 --- a/packages/time/src/timeMath.js +++ b/packages/time/src/timeMath.js @@ -1,9 +1,11 @@ import { Nat } from '@endo/nat'; import { Fail, q } from '@endo/errors'; -import { mustMatch } from '@endo/patterns'; +import { mustMatch } from '@agoric/store'; import { RelativeTimeRecordShape, TimestampRecordShape } from './typeGuards.js'; -/** @import {RelativeTime, RelativeTimeValue, TimerBrand, TimeMathType, Timestamp, TimestampRecord, TimestampValue} from './types.js' */ +/** + * @import {RelativeTime, RelativeTimeValue, TimerBrand, TimeMathType, Timestamp, TimestampRecord, TimestampValue} from './types.js'; + */ /** * `agreedTimerBrand` is internal to this module. diff --git a/packages/time/src/typeGuards.js b/packages/time/src/typeGuards.js index bb95a3d8945..65a4f5d800c 100644 --- a/packages/time/src/typeGuards.js +++ b/packages/time/src/typeGuards.js @@ -1,20 +1,31 @@ import { M } from '@endo/patterns'; +/** + * @import {TypedPattern} from '@agoric/internal'; + * @import {TimestampRecord, TimestampValue, RelativeTimeValue, RelativeTimeRecord} from './types.js'; + */ + export const TimerBrandShape = M.remotable('TimerBrand'); +/** @type {TypedPattern} */ export const TimestampValueShape = M.nat(); +/** @type {TypedPattern} */ export const RelativeTimeValueShape = M.nat(); // Should we allow negatives? +/** @type {TypedPattern} */ export const TimestampRecordShape = harden({ timerBrand: TimerBrandShape, absValue: TimestampValueShape, }); +/** @type {TypedPattern} */ export const RelativeTimeRecordShape = harden({ timerBrand: TimerBrandShape, relValue: RelativeTimeValueShape, }); +/** @type {TypedPattern} */ export const TimestampShape = M.or(TimestampRecordShape, TimestampValueShape); +/** @type {TypedPattern} */ export const RelativeTimeShape = M.or( RelativeTimeRecordShape, RelativeTimeValueShape, diff --git a/packages/vat-data/src/exo-utils.js b/packages/vat-data/src/exo-utils.js index 9d64c5b3ca4..c898bae3cce 100644 --- a/packages/vat-data/src/exo-utils.js +++ b/packages/vat-data/src/exo-utils.js @@ -20,10 +20,12 @@ import { provide, VatData as globalVatData } from './vat-data-bindings.js'; */ /** - * Make a version of the argument function that takes a kind context but - * ignores it. + * Make a version of the argument function that takes a kind context but ignores + * it. * - * @type { any>(fn: T) => import('@agoric/swingset-liveslots').PlusContext} + * @type { any>( + * fn: T, + * ) => import('@agoric/swingset-liveslots').PlusContext} */ export const ignoreContext = fn => @@ -96,13 +98,14 @@ export const makeExoUtils = VatData => { * @param {string} tag * @param {InterfaceGuard | undefined} interfaceGuard * @param {I} init - * @param {T & ThisType<{ - * self: T, - * state: StateResult - * }>} methods + * @param {T & + * ThisType<{ + * self: T; + * state: StateResult; + * }>} methods * @param {DefineKindOptions<{ - * self: T, - * state: StateResult + * self: T; + * state: StateResult; * }>} [options] * @returns {(...args: Parameters) => import('@endo/exo').Guarded} */ @@ -121,13 +124,14 @@ export const makeExoUtils = VatData => { * @param {string} tag * @param {InterfaceGuardKit | undefined} interfaceGuardKit * @param {I} init - * @param {T & ThisType<{ - * facets: import('@endo/exo').GuardedKit, - * state: StateResult - * }> } facets + * @param {T & + * ThisType<{ + * facets: import('@endo/exo').GuardedKit; + * state: StateResult; + * }>} facets * @param {DefineKindOptions<{ - * facets: T, - * state: StateResult + * facets: T; + * state: StateResult; * }>} [options] * @returns {(...args: Parameters) => import('@endo/exo').GuardedKit} */ @@ -152,13 +156,14 @@ export const makeExoUtils = VatData => { * @param {DurableKindHandle} kindHandle * @param {InterfaceGuard | undefined} interfaceGuard * @param {I} init - * @param {T & ThisType<{ - * self: T, - * state: StateResult - * }>} methods + * @param {T & + * ThisType<{ + * self: T; + * state: StateResult; + * }>} methods * @param {DefineKindOptions<{ - * self: T, - * state: StateResult + * self: T; + * state: StateResult; * }>} [options] * @returns {(...args: Parameters) => import('@endo/exo').Guarded} */ @@ -183,13 +188,14 @@ export const makeExoUtils = VatData => { * @param {DurableKindHandle} kindHandle * @param {InterfaceGuardKit | undefined} interfaceGuardKit * @param {I} init - * @param {T & ThisType<{ - * facets: import('@endo/exo').GuardedKit, - * state: StateResult - * }> } facets + * @param {T & + * ThisType<{ + * facets: import('@endo/exo').GuardedKit; + * state: StateResult; + * }>} facets * @param {DefineKindOptions<{ - * facets: T, - * state: StateResult + * facets: T; + * state: StateResult; * }>} [options] * @returns {(...args: Parameters) => import('@endo/exo').GuardedKit} */ @@ -215,13 +221,14 @@ export const makeExoUtils = VatData => { * @param {string} kindName * @param {InterfaceGuard | undefined} interfaceGuard * @param {I} init - * @param {T & ThisType<{ - * self: RemotableObject & T, - * state: StateResult - * }>} methods + * @param {T & + * ThisType<{ + * self: RemotableObject & T; + * state: StateResult; + * }>} methods * @param {DefineKindOptions<{ - * self: T, - * state: StateResult + * self: T; + * state: StateResult; * }>} [options] * @returns {(...args: Parameters) => import('@endo/exo').Guarded} */ @@ -249,13 +256,14 @@ export const makeExoUtils = VatData => { * @param {string} kindName * @param {InterfaceGuardKit | undefined} interfaceGuardKit * @param {I} init - * @param {T & ThisType<{ - * facets: import('@endo/exo').GuardedKit, - * state: StateResult - * }> } facets + * @param {T & + * ThisType<{ + * facets: import('@endo/exo').GuardedKit; + * state: StateResult; + * }>} facets * @param {DefineKindOptions<{ - * facets: T, - * state: StateResult + * facets: T; + * state: StateResult; * }>} [options] * @returns {(...args: Parameters) => import('@endo/exo').GuardedKit} */ @@ -306,8 +314,8 @@ export const makeExoUtils = VatData => { harden(prepareExo); /** - * @template {Record} M methods * @deprecated Use prepareExo instead. + * @template {Record} M methods * @param {Baggage} baggage * @param {string} kindName * @param {M} methods diff --git a/packages/vat-data/src/index.js b/packages/vat-data/src/index.js index 1ae559129ec..226cd949b24 100644 --- a/packages/vat-data/src/index.js +++ b/packages/vat-data/src/index.js @@ -43,7 +43,11 @@ export { } from './exo-utils.js'; // TODO re-export these -/** @template T @typedef {import('@agoric/swingset-liveslots').DefineKindOptions} DefineKindOptions */ +/** + * @template T @typedef + * {import('@agoric/swingset-liveslots').DefineKindOptions} + * DefineKindOptions + */ // Copy this type because aliasing it by `import('@agoric/swingset-liveslots').Baggage` // causes this error in typedoc: Expected a symbol for node with kind Identifier /** @typedef {MapStore} Baggage */ diff --git a/packages/vat-data/src/vat-data-bindings.js b/packages/vat-data/src/vat-data-bindings.js index c4264ebce6e..395bbedde25 100644 --- a/packages/vat-data/src/vat-data-bindings.js +++ b/packages/vat-data/src/vat-data-bindings.js @@ -57,7 +57,8 @@ export const { } = VatDataGlobal; /** - * When making a multi-facet kind, it's common to pick one facet to expose. E.g., + * When making a multi-facet kind, it's common to pick one facet to expose. + * E.g., * * const makeFoo = (a, b, c, d) => makeFooBase(a, b, c, d).self; * @@ -89,36 +90,39 @@ harden(partialAssign); /** @import {StoreOptions} from '@agoric/store' */ /** - * Unlike `provideLazy`, `provide` should be called at most once - * within any vat incarnation with a given `baggage`,`key` pair. + * Unlike `provideLazy`, `provide` should be called at most once within any vat + * incarnation with a given `baggage`,`key` pair. * - * `provide` should only be used to populate baggage, - * where the total number of calls to `provide` must be - * low cardinality, since we keep the bookkeeping to detect collisions - * in normal language-heap memory. All the other baggage-oriented - * `provide*` and `prepare*` functions call `provide`, - * and so impose the same constraints. This is consistent with - * our expected durability patterns: What we store in baggage are - * * kindHandles, which are per kind, which must be low cardinality - * * data "variables" for reestablishing the lexical scope, especially - * of singletons - * * named non-baggage collections at the leaves of the baggage tree. + * `provide` should only be used to populate baggage, where the total number of + * calls to `provide` must be low cardinality, since we keep the bookkeeping to + * detect collisions in normal language-heap memory. All the other + * baggage-oriented `provide*` and `prepare*` functions call `provide`, and so + * impose the same constraints. This is consistent with our expected durability + * patterns: What we store in baggage are * - * What is expected to be high cardinality are the instances of the kinds, - * and the members of the non-bagggage collections. + * - kindHandles, which are per kind, which must be low cardinality + * - data "variables" for reestablishing the lexical scope, especially of + * singletons + * - named non-baggage collections at the leaves of the baggage tree. * - * TODO https://github.com/Agoric/agoric-sdk/pull/5875 : - * Implement development-time instrumentation to detect when - * `provide` violates the above prescription, and is called more - * than once in the same vat incarnation with the same - * baggage,key pair. + * What is expected to be high cardinality are the instances of the kinds, and + * the members of the non-bagggage collections. + * + * TODO https://github.com/Agoric/agoric-sdk/pull/5875 : Implement + * development-time instrumentation to detect when `provide` violates the above + * prescription, and is called more than once in the same vat incarnation with + * the same baggage,key pair. */ export const provide = // XXX cast because provideLazy is `any` due to broken type import - /** @type {(baggage: Baggage, key: K, makeValue: (key: K) => V) => V} */ ( - provideLazy - ); + /** + * @type {( + * baggage: Baggage, + * key: K, + * makeValue: (key: K) => V, + * ) => V} + */ (provideLazy); // TODO: Find a good home for this function used by @agoric/vat-data and testing code /** @param {VatData} VatData */ diff --git a/packages/vats/package.json b/packages/vats/package.json index 848e8899cde..d77dc771cfd 100644 --- a/packages/vats/package.json +++ b/packages/vats/package.json @@ -76,6 +76,6 @@ "workerThreads": false }, "typeCoverage": { - "atLeast": 91.21 + "atLeast": 91.41 } } diff --git a/packages/vow/package.json b/packages/vow/package.json index e304c696c14..cf76ec21198 100755 --- a/packages/vow/package.json +++ b/packages/vow/package.json @@ -54,6 +54,6 @@ "access": "public" }, "typeCoverage": { - "atLeast": 89.6 + "atLeast": 90.06 } } diff --git a/packages/xsnap/package.json b/packages/xsnap/package.json index ad22a5f5f3b..eb2914b77d2 100644 --- a/packages/xsnap/package.json +++ b/packages/xsnap/package.json @@ -76,6 +76,6 @@ "workerThreads": false }, "typeCoverage": { - "atLeast": 93.95 + "atLeast": 93.99 } } diff --git a/packages/zoe/package.json b/packages/zoe/package.json index b5cdefd3f06..834acd44146 100644 --- a/packages/zoe/package.json +++ b/packages/zoe/package.json @@ -141,6 +141,6 @@ "access": "public" }, "typeCoverage": { - "atLeast": 84.92 + "atLeast": 85 } } diff --git a/packages/zoe/src/contractSupport/recorder.js b/packages/zoe/src/contractSupport/recorder.js index a0c81562400..620fb04619d 100644 --- a/packages/zoe/src/contractSupport/recorder.js +++ b/packages/zoe/src/contractSupport/recorder.js @@ -9,6 +9,10 @@ import { mustMatch } from '@agoric/store'; import { M, makeScalarBigMapStore, prepareExoClass } from '@agoric/vat-data'; import { E } from '@endo/eventual-send'; +/** + * @import {TypedPattern} from '@agoric/internal'; + */ + /** * Recorders support publishing data to vstorage. * @@ -56,7 +60,7 @@ export const prepareRecorder = (baggage, marshaller) => { * @template T * @param {PublishKit['publisher']} publisher * @param {Awaited>} storageNode - * @param {TypedPattern} [valueShape] + * @param {TypedPattern} [valueShape] */ ( publisher, @@ -258,16 +262,3 @@ export const prepareMockRecorderKitMakers = () => { storageNode: makeFakeStorage('mock recorder storage'), }; }; - -/** - * Stop-gap until https://github.com/Agoric/agoric-sdk/issues/6160 - * explictly specify the type that the Pattern will verify through a match. - * - * @template T - * @typedef {import('@endo/patterns').Pattern & { validatedType?: T }} TypedPattern - */ - -/** - * @template {TypedPattern} TM - * @typedef {TM extends TypedPattern ? T : never} MatchedType - */ diff --git a/packages/zoe/src/typeGuards.js b/packages/zoe/src/typeGuards.js index f2642599293..a6109a34798 100644 --- a/packages/zoe/src/typeGuards.js +++ b/packages/zoe/src/typeGuards.js @@ -13,12 +13,19 @@ import { SubscriberShape } from '@agoric/notifier'; import { M } from '@agoric/store'; import { TimestampShape } from '@agoric/time'; +/** + * @import {TypedPattern} from '@agoric/internal'; + */ + // keywords have an initial cap export const KeywordShape = M.string(); +/** @type {TypedPattern} */ export const InvitationHandleShape = M.remotable('InvitationHandle'); +/** @type {TypedPattern} */ export const InvitationShape = M.remotable('Invitation'); export const InstanceHandleShape = M.remotable('InstanceHandle'); +/** @type {TypedPattern} */ export const InstallationShape = M.remotable('Installation'); export const SeatShape = M.remotable('Seat');