-
Notifications
You must be signed in to change notification settings - Fork 74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: support M.raw()
in method guards
#1831
Changes from all commits
bf593d8
58a3d42
c8126dc
c50ee18
5b94530
12624f5
22bd9c3
df16978
77d04b2
a0b3a5c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -13,6 +13,12 @@ const DEBUG = getEnvironmentOption('DEBUG', ''); | |||||
// Turn on to give each exo instance its own toStringTag value. | ||||||
const LABEL_INSTANCES = DEBUG.split(',').includes('label-instances'); | ||||||
|
||||||
/** | ||||||
* @template {{}} T | ||||||
* @param {T} proto | ||||||
* @param {number} instanceCount | ||||||
* @returns {T} | ||||||
*/ | ||||||
const makeSelf = (proto, instanceCount) => { | ||||||
const self = create(proto); | ||||||
if (LABEL_INSTANCES) { | ||||||
|
@@ -82,6 +88,21 @@ export const initEmpty = () => emptyRecord; | |||||
* @property {ReceiveRevoker} [receiveRevoker] | ||||||
*/ | ||||||
|
||||||
/** | ||||||
* @template {Methods} M | ||||||
* @typedef {M & import('@endo/eventual-send').RemotableBrand<{}, M>} Farable | ||||||
*/ | ||||||
|
||||||
/** | ||||||
* @template {Methods} M | ||||||
* @typedef {Farable<M & import('./get-interface.js').GetInterfaceGuard<M>>} Guarded | ||||||
*/ | ||||||
|
||||||
/** | ||||||
* @template {Record<FacetName, Methods>} F | ||||||
* @typedef {{ [K in keyof F]: Guarded<F[K]> }} GuardedKit | ||||||
*/ | ||||||
|
||||||
/** | ||||||
* @template {(...args: any[]) => any} I init function | ||||||
* @template {Methods} M methods | ||||||
|
@@ -90,9 +111,9 @@ export const initEmpty = () => emptyRecord; | |||||
* [K in keyof M]: import("@endo/patterns").MethodGuard | ||||||
* }> | undefined} interfaceGuard | ||||||
* @param {I} init | ||||||
* @param {M & ThisType<{ self: M, state: ReturnType<I> }>} methods | ||||||
* @param {M & ThisType<{ self: Guarded<M>, state: ReturnType<I> }>} methods | ||||||
* @param {FarClassOptions<ClassContext<ReturnType<I>, M>>} [options] | ||||||
* @returns {(...args: Parameters<I>) => (M & import('@endo/eventual-send').RemotableBrand<{}, M>)} | ||||||
* @returns {(...args: Parameters<I>) => Guarded<M>} | ||||||
*/ | ||||||
export const defineExoClass = ( | ||||||
tag, | ||||||
|
@@ -120,7 +141,6 @@ export const defineExoClass = ( | |||||
// Be careful not to freeze the state record | ||||||
const state = seal(init(...args)); | ||||||
instanceCount += 1; | ||||||
/** @type {M} */ | ||||||
const self = makeSelf(proto, instanceCount); | ||||||
|
||||||
// Be careful not to freeze the state record | ||||||
|
@@ -130,9 +150,7 @@ export const defineExoClass = ( | |||||
if (finish) { | ||||||
finish(context); | ||||||
} | ||||||
return /** @type {M & import('@endo/eventual-send').RemotableBrand<{}, M>} */ ( | ||||||
self | ||||||
); | ||||||
return self; | ||||||
michaelfig marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
}; | ||||||
|
||||||
if (receiveRevoker) { | ||||||
|
@@ -149,13 +167,13 @@ harden(defineExoClass); | |||||
* @template {(...args: any[]) => any} I init function | ||||||
* @template {Record<FacetName, Methods>} F facet methods | ||||||
* @param {string} tag | ||||||
* @param {{ [K in keyof F]: import("@endo/patterns").InterfaceGuard<{ | ||||||
* [M in keyof F[K]]: import("@endo/patterns").MethodGuard; | ||||||
* }> } | undefined} interfaceGuardKit | ||||||
* @param {{ [K in keyof F]: | ||||||
* InterfaceGuard<{[M in keyof F[K]]: MethodGuard; }> | ||||||
* } | undefined} interfaceGuardKit | ||||||
* @param {I} init | ||||||
* @param {F & ThisType<{ facets: F, state: ReturnType<I> }> } methodsKit | ||||||
* @param {FarClassOptions<KitContext<ReturnType<I>,F>>} [options] | ||||||
* @returns {(...args: Parameters<I>) => F} | ||||||
* @param {F & { [K in keyof F]: ThisType<{ facets: GuardedKit<F>, state: ReturnType<I> }> }} methodsKit | ||||||
* @param {FarClassOptions<KitContext<ReturnType<I>, GuardedKit<F>>>} [options] | ||||||
* @returns {(...args: Parameters<I>) => GuardedKit<F>} | ||||||
*/ | ||||||
export const defineExoClassKit = ( | ||||||
tag, | ||||||
|
@@ -186,8 +204,8 @@ export const defineExoClassKit = ( | |||||
// Be careful not to freeze the state record | ||||||
const state = seal(init(...args)); | ||||||
// Don't freeze context until we add facets | ||||||
/** @type {KitContext<ReturnType<I>,F>} */ | ||||||
const context = { state, facets: {} }; | ||||||
/** @type {{ state: ReturnType<I>, facets: unknown }} */ | ||||||
const context = { state, facets: null }; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is null here correct? The original
Suggested change
seems more correct. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I intended for the |
||||||
instanceCount += 1; | ||||||
const facets = objectMap(prototypeKit, (proto, facetName) => { | ||||||
const self = makeSelf(proto, instanceCount); | ||||||
|
@@ -200,7 +218,7 @@ export const defineExoClassKit = ( | |||||
if (finish) { | ||||||
finish(context); | ||||||
} | ||||||
return context.facets; | ||||||
return /** @type {GuardedKit<F>} */ (context.facets); | ||||||
}; | ||||||
|
||||||
if (receiveRevoker) { | ||||||
|
@@ -222,7 +240,7 @@ harden(defineExoClassKit); | |||||
* }> | undefined} interfaceGuard CAVEAT: static typing does not yet support `callWhen` transformation | ||||||
* @param {T} methods | ||||||
* @param {FarClassOptions<ClassContext<{},T>>} [options] | ||||||
* @returns {T & import('@endo/eventual-send').RemotableBrand<{}, T>} | ||||||
michaelfig marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
* @returns {Guarded<T>} | ||||||
*/ | ||||||
export const makeExo = (tag, interfaceGuard, methods, options = undefined) => { | ||||||
const makeInstance = defineExoClass( | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarity/repository consistency nit:
(details)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are not the same.
Object.create(proto)
is a type error unlessproto extends {}
.