Skip to content

Commit 16a1114

Browse files
committed
refactor(pass-style): use confirm/reject pattern in pass-style
1 parent 5debed5 commit 16a1114

File tree

13 files changed

+245
-295
lines changed

13 files changed

+245
-295
lines changed

packages/pass-style/src/byteArray.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ const { immutableArrayBufferPrototype, immutableGetter } =
5353
export const ByteArrayHelper = harden({
5454
styleName: 'byteArray',
5555

56-
canBeValid: (candidate, check = undefined) =>
56+
confirmCanBeValid: (candidate, reject) =>
5757
(candidate instanceof ArrayBuffer &&
5858
// @ts-expect-error TODO How do I add it to the ArrayBuffer type?
5959
candidate.immutable) ||
60-
(!!check && check(false, X`Immutable ArrayBuffer expected: ${candidate}`)),
60+
(reject && reject`Immutable ArrayBuffer expected: ${candidate}`),
6161

6262
assertRestValid: (candidate, _passStyleOfRecur) => {
6363
getPrototypeOf(candidate) === immutableArrayBufferPrototype ||

packages/pass-style/src/copyArray.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/// <reference types="ses"/>
22

3-
import { X } from '@endo/errors';
4-
import { assertChecker, getOwnDataDescriptor } from './passStyle-helpers.js';
3+
import { Fail, X } from '@endo/errors';
4+
import { confirmOwnDataDescriptor } from './passStyle-helpers.js';
55

66
const { getPrototypeOf } = Object;
77
const { ownKeys } = Reflect;
@@ -14,23 +14,22 @@ const { isArray, prototype: arrayPrototype } = Array;
1414
export const CopyArrayHelper = harden({
1515
styleName: 'copyArray',
1616

17-
canBeValid: (candidate, check = undefined) =>
18-
isArray(candidate) ||
19-
(!!check && check(false, X`Array expected: ${candidate}`)),
17+
confirmCanBeValid: (candidate, reject) =>
18+
isArray(candidate) || (reject && reject`Array expected: ${candidate}`),
2019

2120
assertRestValid: (candidate, passStyleOfRecur) => {
2221
getPrototypeOf(candidate) === arrayPrototype ||
2322
assert.fail(X`Malformed array: ${candidate}`, TypeError);
2423
// Since we're already ensured candidate is an array, it should not be
2524
// possible for the following get to fail.
2625
const len = /** @type {number} */ (
27-
getOwnDataDescriptor(candidate, 'length', false, assertChecker).value
26+
confirmOwnDataDescriptor(candidate, 'length', false, Fail).value
2827
);
2928
// Validate that each index property is own/data/enumerable
3029
// and its associated value is recursively passable.
3130
for (let i = 0; i < len; i += 1) {
3231
passStyleOfRecur(
33-
getOwnDataDescriptor(candidate, i, true, assertChecker).value,
32+
confirmOwnDataDescriptor(candidate, i, true, Fail).value,
3433
);
3534
}
3635
// Expect one key per index plus one for 'length'.

packages/pass-style/src/copyRecord.js

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,70 @@
11
/// <reference types="ses"/>
22

3-
/** @import {Checker} from './types.js' */
4-
5-
import {
6-
assertChecker,
7-
getOwnDataDescriptor,
8-
CX,
9-
} from './passStyle-helpers.js';
3+
import { Fail } from '@endo/errors';
4+
import { confirmOwnDataDescriptor } from './passStyle-helpers.js';
105
import { canBeMethod } from './remotable.js';
116

7+
/**
8+
* @import {Rejector} from '@endo/errors/rejector.js';
9+
* @import {PassStyleHelper} from './internal-types.js';
10+
*/
11+
1212
const { ownKeys } = Reflect;
1313
const { getPrototypeOf, prototype: objectPrototype } = Object;
1414

1515
/**
1616
* @param {unknown} candidate
17-
* @param {Checker} [check]
17+
* @param {Rejector} reject
1818
*/
19-
const checkObjectPrototype = (candidate, check = undefined) => {
19+
const confirmObjectPrototype = (candidate, reject) => {
2020
return (
2121
getPrototypeOf(candidate) === objectPrototype ||
22-
(!!check &&
23-
CX(check)`Records must inherit from Object.prototype: ${candidate}`)
22+
(reject && reject`Records must inherit from Object.prototype: ${candidate}`)
2423
);
2524
};
2625

2726
/**
2827
* @param {unknown} candidate
2928
* @param {PropertyKey} key
3029
* @param {unknown} value
31-
* @param {Checker} [check]
30+
* @param {Rejector} reject
3231
*/
33-
const checkPropertyCanBeValid = (candidate, key, value, check = undefined) => {
32+
const confirmPropertyCanBeValid = (candidate, key, value, reject) => {
3433
return (
3534
(typeof key === 'string' ||
36-
(!!check &&
37-
CX(
38-
check,
39-
)`Records can only have string-named properties: ${candidate}`)) &&
35+
(reject &&
36+
reject`Records can only have string-named properties: ${candidate}`)) &&
4037
(!canBeMethod(value) ||
41-
(!!check &&
38+
(reject &&
4239
// TODO: Update message now that there is no such thing as "implicit Remotable".
43-
CX(
44-
check,
45-
)`Records cannot contain non-far functions because they may be methods of an implicit Remotable: ${candidate}`))
40+
reject`Records cannot contain non-far functions because they may be methods of an implicit Remotable: ${candidate}`))
4641
);
4742
};
4843

4944
/**
5045
*
51-
* @type {import('./internal-types.js').PassStyleHelper}
46+
* @type {PassStyleHelper}
5247
*/
5348
export const CopyRecordHelper = harden({
5449
styleName: 'copyRecord',
5550

56-
canBeValid: (candidate, check = undefined) => {
51+
confirmCanBeValid: (candidate, reject) => {
5752
return (
58-
checkObjectPrototype(candidate, check) &&
53+
confirmObjectPrototype(candidate, reject) &&
5954
// Reject any candidate with a symbol-keyed property or method-like property
6055
// (such input is potentially a Remotable).
6156
ownKeys(candidate).every(key =>
62-
checkPropertyCanBeValid(candidate, key, candidate[key], check),
57+
confirmPropertyCanBeValid(candidate, key, candidate[key], reject),
6358
)
6459
);
6560
},
6661

6762
assertRestValid: (candidate, passStyleOfRecur) => {
6863
// Validate that each own property has a recursively passable associated
69-
// value (we already know from canBeValid that the other constraints are
64+
// value (we already know from confirmCanBeValid that the other constraints are
7065
// satisfied).
7166
for (const name of ownKeys(candidate)) {
72-
const { value } = getOwnDataDescriptor(
73-
candidate,
74-
name,
75-
true,
76-
assertChecker,
77-
);
67+
const { value } = confirmOwnDataDescriptor(candidate, name, true, Fail);
7868
passStyleOfRecur(value);
7969
}
8070
},

packages/pass-style/src/error.js

Lines changed: 39 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
/// <reference types="ses"/>
22

3-
import { q } from '@endo/errors';
4-
import { assertChecker, CX } from './passStyle-helpers.js';
3+
import { Fail, q } from '@endo/errors';
54

6-
/** @import {PassStyleHelper} from './internal-types.js' */
7-
/** @import {Checker, PassStyle, PassStyleOf} from './types.js' */
5+
/**
6+
* @import {Rejector} from '@endo/errors/rejector.js';
7+
* @import {PassStyleHelper} from './internal-types.js';
8+
* @import {PassStyle} from './types.js';
9+
*/
810

911
const { getPrototypeOf, getOwnPropertyDescriptors, hasOwn, entries } = Object;
1012

@@ -50,17 +52,17 @@ harden(getErrorConstructor);
5052

5153
/**
5254
* @param {unknown} candidate
53-
* @param {Checker} [check]
55+
* @param {Rejector} reject
5456
* @returns {boolean}
5557
*/
56-
const checkErrorLike = (candidate, check = undefined) => {
58+
const confirmErrorLike = (candidate, reject) => {
5759
// TODO: Need a better test than instanceof
5860
return (
5961
candidate instanceof Error ||
60-
(!!check && CX(check)`Error expected: ${candidate}`)
62+
(reject && reject`Error expected: ${candidate}`)
6163
);
6264
};
63-
harden(checkErrorLike);
65+
harden(confirmErrorLike);
6466
/// <reference types="ses"/>
6567

6668
/**
@@ -81,34 +83,34 @@ harden(checkErrorLike);
8183
* @param {unknown} candidate
8284
* @returns {boolean}
8385
*/
84-
export const isErrorLike = candidate => checkErrorLike(candidate);
86+
export const isErrorLike = candidate => confirmErrorLike(candidate, false);
8587
harden(isErrorLike);
8688

8789
/**
8890
* @param {string} propName
8991
* @param {PropertyDescriptor} desc
9092
* @param {(val: any) => PassStyle} passStyleOfRecur
91-
* @param {Checker} [check]
93+
* @param {Rejector} reject
9294
* @returns {boolean}
9395
*/
94-
export const checkRecursivelyPassableErrorPropertyDesc = (
96+
export const confirmRecursivelyPassableErrorPropertyDesc = (
9597
propName,
9698
desc,
9799
passStyleOfRecur,
98-
check = undefined,
100+
reject,
99101
) => {
100102
if (desc.enumerable) {
101103
return (
102-
!!check &&
103-
CX(check)`Passable Error ${q(
104+
reject &&
105+
reject`Passable Error ${q(
104106
propName,
105107
)} own property must not be enumerable: ${desc}`
106108
);
107109
}
108110
if (!hasOwn(desc, 'value')) {
109111
return (
110-
!!check &&
111-
CX(check)`Passable Error ${q(
112+
reject &&
113+
reject`Passable Error ${q(
112114
propName,
113115
)} own property must be a data property: ${desc}`
114116
);
@@ -119,95 +121,90 @@ export const checkRecursivelyPassableErrorPropertyDesc = (
119121
case 'stack': {
120122
return (
121123
typeof value === 'string' ||
122-
(!!check &&
123-
CX(check)`Passable Error ${q(
124+
(reject &&
125+
reject`Passable Error ${q(
124126
propName,
125127
)} own property must be a string: ${value}`)
126128
);
127129
}
128130
case 'cause': {
129131
// eslint-disable-next-line no-use-before-define
130-
return checkRecursivelyPassableError(value, passStyleOfRecur, check);
132+
return confirmRecursivelyPassableError(value, passStyleOfRecur, reject);
131133
}
132134
case 'errors': {
133135
if (!Array.isArray(value) || passStyleOfRecur(value) !== 'copyArray') {
134136
return (
135-
!!check &&
136-
CX(check)`Passable Error ${q(
137+
reject &&
138+
reject`Passable Error ${q(
137139
propName,
138140
)} own property must be a copyArray: ${value}`
139141
);
140142
}
141143
return value.every(err =>
142144
// eslint-disable-next-line no-use-before-define
143-
checkRecursivelyPassableError(err, passStyleOfRecur, check),
145+
confirmRecursivelyPassableError(err, passStyleOfRecur, reject),
144146
);
145147
}
146148
default: {
147149
break;
148150
}
149151
}
150152
return (
151-
!!check &&
152-
CX(check)`Passable Error has extra unpassed property ${q(propName)}`
153+
reject && reject`Passable Error has extra unpassed property ${q(propName)}`
153154
);
154155
};
155-
harden(checkRecursivelyPassableErrorPropertyDesc);
156+
harden(confirmRecursivelyPassableErrorPropertyDesc);
156157

157158
/**
158159
* @param {unknown} candidate
159160
* @param {(val: any) => PassStyle} passStyleOfRecur
160-
* @param {Checker} [check]
161+
* @param {Rejector} reject
161162
* @returns {boolean}
162163
*/
163-
export const checkRecursivelyPassableError = (
164+
export const confirmRecursivelyPassableError = (
164165
candidate,
165166
passStyleOfRecur,
166-
check = undefined,
167+
reject,
167168
) => {
168-
if (!checkErrorLike(candidate, check)) {
169+
if (!confirmErrorLike(candidate, reject)) {
169170
return false;
170171
}
171172
const proto = getPrototypeOf(candidate);
172173
const { name } = proto;
173174
const errConstructor = getErrorConstructor(name);
174175
if (errConstructor === undefined || errConstructor.prototype !== proto) {
175176
return (
176-
!!check &&
177-
CX(
178-
check,
179-
)`Passable Error must inherit from an error class .prototype: ${candidate}`
177+
reject &&
178+
reject`Passable Error must inherit from an error class .prototype: ${candidate}`
180179
);
181180
}
182181
const descs = getOwnPropertyDescriptors(candidate);
183182
if (!('message' in descs)) {
184183
return (
185-
!!check &&
186-
CX(
187-
check,
188-
)`Passable Error must have an own "message" string property: ${candidate}`
184+
reject &&
185+
reject`Passable Error must have an own "message" string property: ${candidate}`
189186
);
190187
}
191188

192189
return entries(descs).every(([propName, desc]) =>
193-
checkRecursivelyPassableErrorPropertyDesc(
190+
confirmRecursivelyPassableErrorPropertyDesc(
194191
propName,
195192
desc,
196193
passStyleOfRecur,
197-
check,
194+
reject,
198195
),
199196
);
200197
};
201-
harden(checkRecursivelyPassableError);
198+
harden(confirmRecursivelyPassableError);
202199

203200
/**
204201
* @type {PassStyleHelper}
205202
*/
206203
export const ErrorHelper = harden({
207204
styleName: 'error',
208205

209-
canBeValid: checkErrorLike,
206+
confirmCanBeValid: confirmErrorLike,
210207

211208
assertRestValid: (candidate, passStyleOfRecur) =>
212-
checkRecursivelyPassableError(candidate, passStyleOfRecur, assertChecker),
209+
confirmRecursivelyPassableError(candidate, passStyleOfRecur, Fail),
213210
});

packages/pass-style/src/internal-types.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
export {};
22

3-
/** @import {Checker} from './types.js' */
4-
/** @import {PassStyle} from './types.js' */
5-
/** @import {PassStyleOf} from './types.js' */
3+
/**
4+
* @import {Rejector} from '@endo/errors/rejector.js';
5+
* @import {PassStyle} from './types.js';
6+
*/
67

78
/**
89
* The PassStyleHelper are only used to make a `passStyleOf` function.
@@ -17,11 +18,12 @@ export {};
1718
*
1819
* @typedef {object} PassStyleHelper
1920
* @property {PassStyle} styleName
20-
* @property {(candidate: any, check?: Checker) => boolean} canBeValid
21-
* If `canBeValid` returns true, then the candidate would
21+
* @property {(candidate: any, reject: Rejector) => boolean} confirmCanBeValid
22+
* If `confirmCanBeValid` returns true, then the candidate would
2223
* definitely not be valid for any of the other helpers.
2324
* `assertRestValid` still needs to be called to determine if it
24-
* actually is valid, but only after the `canBeValid` check has passed.
25+
* actually is valid, but only after the `confirmCanBeValid` check has passed.
26+
*
2527
* @property {(candidate: any,
2628
* passStyleOfRecur: (val: any) => PassStyle
2729
* ) => void} assertRestValid

0 commit comments

Comments
 (0)