@blamejs/pki 0.6.13 → 0.6.15
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/CHANGELOG.md +22 -1
- package/README.md +1 -1
- package/index.js +1 -1
- package/lib/acme.js +59 -815
- package/lib/asn1-der.js +7 -245
- package/lib/attrcert-sign.js +12 -260
- package/lib/attrcert-verify.js +1 -7
- package/lib/byte-reader.js +0 -8
- package/lib/byte-writer.js +0 -11
- package/lib/cbor-det.js +0 -54
- package/lib/cmc-build.js +15 -357
- package/lib/cmc-verify.js +6 -239
- package/lib/cmp-build.js +41 -317
- package/lib/cmp-session.js +73 -760
- package/lib/cmp-verify.js +32 -488
- package/lib/cms-compress.js +3 -32
- package/lib/cms-decrypt.js +29 -294
- package/lib/cms-encrypt.js +14 -234
- package/lib/cms-sign.js +29 -324
- package/lib/cms-verify.js +9 -500
- package/lib/composite-kem.js +2 -102
- package/lib/composite-sig.js +1 -77
- package/lib/constants.js +0 -249
- package/lib/crl-sign.js +9 -237
- package/lib/crl-verify.js +1 -10
- package/lib/crmf-sign.js +19 -198
- package/lib/crmf-verify.js +1 -12
- package/lib/csr-sign.js +3 -34
- package/lib/csr-verify.js +1 -12
- package/lib/ct.js +28 -253
- package/lib/edwards-point.js +10 -44
- package/lib/est.js +28 -764
- package/lib/framework-error.js +4 -182
- package/lib/guard-all.js +1 -58
- package/lib/guard-async.js +1 -36
- package/lib/guard-bytes.js +6 -650
- package/lib/guard-compress.js +5 -102
- package/lib/guard-crypto.js +1 -40
- package/lib/guard-der.js +2 -93
- package/lib/guard-encoding.js +2 -60
- package/lib/guard-header.js +1 -36
- package/lib/guard-identifier.js +7 -531
- package/lib/guard-intrinsic.js +1 -150
- package/lib/guard-json.js +10 -73
- package/lib/guard-limits.js +1 -77
- package/lib/guard-list.js +1 -49
- package/lib/guard-name.js +3 -209
- package/lib/guard-parsed.js +7 -335
- package/lib/guard-range.js +1 -71
- package/lib/guard-secret.js +1 -102
- package/lib/guard-text.js +1 -64
- package/lib/guard-time.js +1 -97
- package/lib/hpke.js +3 -105
- package/lib/http-digest.js +14 -142
- package/lib/http-retry-after.js +1 -47
- package/lib/http-transport.js +21 -131
- package/lib/inspect.js +30 -284
- package/lib/ip-utils.js +6 -47
- package/lib/jose.js +7 -142
- package/lib/key.js +2 -67
- package/lib/lint.js +9 -194
- package/lib/merkle.js +1 -27
- package/lib/mime.js +9 -82
- package/lib/ocsp-request-verify.js +1 -14
- package/lib/ocsp-verify.js +1 -82
- package/lib/ocsp.js +11 -169
- package/lib/oid.js +5 -337
- package/lib/path-validate.js +103 -1492
- package/lib/pbes2.js +2 -89
- package/lib/pkcs12-build.js +31 -379
- package/lib/pki-build.js +64 -290
- package/lib/rc2.js +2 -18
- package/lib/rfc3339.js +4 -27
- package/lib/scep.js +59 -233
- package/lib/schema-all.js +0 -122
- package/lib/schema-attrcert.js +4 -146
- package/lib/schema-c509.js +153 -802
- package/lib/schema-cmc.js +5 -220
- package/lib/schema-cmp.js +2 -223
- package/lib/schema-cms.js +13 -427
- package/lib/schema-crl.js +5 -68
- package/lib/schema-crmf.js +6 -167
- package/lib/schema-csr.js +1 -54
- package/lib/schema-csrattrs.js +2 -87
- package/lib/schema-engine.js +0 -152
- package/lib/schema-ocsp.js +0 -117
- package/lib/schema-pkcs12.js +2 -93
- package/lib/schema-pkcs8.js +3 -35
- package/lib/schema-pkix.js +24 -655
- package/lib/schema-smime.js +0 -54
- package/lib/schema-tsp.js +3 -99
- package/lib/schema-x509.js +4 -63
- package/lib/shbs.js +11 -95
- package/lib/sign-scheme.js +2 -97
- package/lib/sigstore.js +9 -169
- package/lib/sleep.js +2 -8
- package/lib/smime.js +15 -408
- package/lib/tls-cert-compress.js +0 -62
- package/lib/trust.js +19 -185
- package/lib/tsp-sign.js +16 -270
- package/lib/validator-all.js +1 -30
- package/lib/validator-attcert.js +2 -46
- package/lib/validator-cose.js +2 -153
- package/lib/validator-keydesc.js +1 -37
- package/lib/validator-sig.js +1 -46
- package/lib/validator-tls.js +1 -88
- package/lib/validator-tpm.js +19 -122
- package/lib/verify-seam.js +1 -24
- package/lib/webauthn-mds.js +3 -400
- package/lib/webauthn.js +12 -833
- package/lib/webcrypto.js +5 -485
- package/lib/x509-sign.js +4 -108
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/guard-identifier.js
CHANGED
|
@@ -3,40 +3,8 @@
|
|
|
3
3
|
"use strict";
|
|
4
4
|
var intrinsic = require("./guard-intrinsic");
|
|
5
5
|
var util = { types: intrinsic.types };
|
|
6
|
-
//
|
|
7
|
-
// @internal -- no operator-facing namespace. The documented surface is the
|
|
8
|
-
// consumers whose identifier-string integrity composes this guard (pki.oid
|
|
9
|
-
// name/arc resolution, pki.asn1 OID encoding, pki.path.validate requiredEku /
|
|
10
|
-
// userInitialPolicySet key checking).
|
|
11
|
-
//
|
|
12
|
-
// guard-identifier -- fail-closed canonicalization of the structured-identifier
|
|
13
|
-
// STRINGS the toolkit compares and encodes. An identifier used as a lookup /
|
|
14
|
-
// comparison key must be in one canonical form, or the string form and the
|
|
15
|
-
// decoded form of the same identifier silently disagree.
|
|
16
|
-
//
|
|
17
|
-
// Defends the canonicalization-divergence class (CWE-20): a dotted-decimal OID
|
|
18
|
-
// with a leading-zero arc ("2.05.29.15") round-trips to a DIFFERENT OID
|
|
19
|
-
// ("2.5.29.15"), and an arc outside the X.660 bounds can never DER-encode at all.
|
|
20
|
-
// A hand-rolled string check that accepts either lets `build.oid` emit bytes that
|
|
21
|
-
// decode to a different OID than the string names, or lets a non-canonical policy /
|
|
22
|
-
// EKU key compare unequal to the canonical decoder output it is matched against (a
|
|
23
|
-
// silent false-reject). Every string-form identifier check routes through here so
|
|
24
|
-
// the string and DER forms cannot diverge.
|
|
6
|
+
// @internal
|
|
25
7
|
|
|
26
|
-
// Everything this module reads from the runtime, taken at load. `util.types` above is the slot
|
|
27
|
-
// predicate set, which answers whether a value is a Proxy -- the question that decides whether an
|
|
28
|
-
// options bag can be asked honestly what it holds at all.
|
|
29
|
-
//
|
|
30
|
-
// The array test decides whether a value is walked as a list, so one answering `false` makes the
|
|
31
|
-
// index scan report nothing and every index rule keyed on that scan applies to nothing, which is
|
|
32
|
-
// how an accessor under index 0 reaches a copy loop the refusal should have turned the call away
|
|
33
|
-
// for. The reflective operations are this module's honesty walk itself: `getOwnPropertyDescriptor`
|
|
34
|
-
// learns whether a field is an accessor, `getPrototypeOf` and `ownKeys` walk a chain, and a
|
|
35
|
-
// replacement for either lets an options bag report one shape while answering as another. The array
|
|
36
|
-
// and collection operations run on lists and sets this module owns, where `Array.prototype` and
|
|
37
|
-
// `Set.prototype` are what a caller can still reach: a `forEach` replaced with a no-op makes the
|
|
38
|
-
// name scan report nothing over perfectly real keys, and a `has` answering `true` ends a chain walk
|
|
39
|
-
// at the first prototype. See guard-intrinsic for the whole captured set.
|
|
40
8
|
var _isArray = intrinsic.isArray;
|
|
41
9
|
var _create = intrinsic.create;
|
|
42
10
|
var _getPrototypeOf = intrinsic.getPrototypeOf;
|
|
@@ -64,65 +32,33 @@ var _Set = intrinsic.Set;
|
|
|
64
32
|
var _Map = intrinsic.Map;
|
|
65
33
|
var _charCodeAt = intrinsic.uncurry(String.prototype.charCodeAt);
|
|
66
34
|
var _strSplit = intrinsic.uncurry(String.prototype.split);
|
|
67
|
-
// This module's whole job is deciding whether a caller's name is in a known set, and that decision
|
|
68
|
-
// is one `hasOwnProperty` call. Reading it and its `call` off their prototypes leaves the answer
|
|
69
|
-
// with whoever replaced either, which classifies an unknown option as an allowed one.
|
|
70
35
|
var _hasOwn = intrinsic.hasOwn;
|
|
71
|
-
// The index test below IS `String(Number(k)) === k`, and the readable-index scan orders and bounds
|
|
72
|
-
// its results with the same two conversions. Both are writable properties of globalThis: one
|
|
73
|
-
// replacement decides which own names this module reports as elements, in what order, and where the
|
|
74
|
-
// scan stops -- which is what every consumer's density and accessor refusal is built on.
|
|
75
36
|
var _String = intrinsic.String;
|
|
76
37
|
var _Number = intrinsic.Number;
|
|
77
38
|
var _BigInt = intrinsic.BigInt;
|
|
78
39
|
var _Object = intrinsic.Object;
|
|
79
40
|
var _BufferProto = intrinsic.BufferProto;
|
|
80
|
-
// Appended by index rather than through `push`, so the growth reads no prototype method at all.
|
|
81
41
|
function _append(arr, v) { _defineProperty(arr, arr.length, { value: v, writable: true, enumerable: true, configurable: true }); }
|
|
82
42
|
|
|
83
|
-
// The dotted-decimal grammar, walked instead of matched. `(0|[1-9]\d*)(\.(0|[1-9]\d*))+`
|
|
84
|
-
// nests a quantified group inside a quantified group with an alternation in each,
|
|
85
|
-
// which is the shape whose cost on a rejecting string is a property of the pattern
|
|
86
|
-
// and not of the length, and this guard's whole job is to be handed strings that
|
|
87
|
-
// reject. Walking the string is one pass, one comparison per character, and it
|
|
88
|
-
// states the two rules plainly: an arc is one or more digits, and an arc longer than
|
|
89
|
-
// one digit does not start with zero (the leading-zero form round-trips to a
|
|
90
|
-
// DIFFERENT OID, which is the divergence this guard exists to stop).
|
|
91
43
|
function _isDottedDecimal(str) {
|
|
92
44
|
if (str.length === 0) return false;
|
|
93
45
|
var arcs = 0, digits = 0, leadingZero = false;
|
|
94
46
|
for (var i = 0; i < str.length; i++) {
|
|
95
47
|
var c = _charCodeAt(str, i);
|
|
96
|
-
if (c === 0x2e) {
|
|
97
|
-
if (digits === 0 || leadingZero) return false;
|
|
48
|
+
if (c === 0x2e) {
|
|
49
|
+
if (digits === 0 || leadingZero) return false;
|
|
98
50
|
arcs++; digits = 0; leadingZero = false;
|
|
99
51
|
continue;
|
|
100
52
|
}
|
|
101
|
-
if (c < 0x30 || c > 0x39) return false;
|
|
53
|
+
if (c < 0x30 || c > 0x39) return false;
|
|
102
54
|
if (digits === 1 && _charCodeAt(str, i - 1) === 0x30) leadingZero = true;
|
|
103
55
|
digits++;
|
|
104
56
|
}
|
|
105
|
-
if (digits === 0 || leadingZero) return false;
|
|
106
|
-
return arcs >= 1;
|
|
57
|
+
if (digits === 0 || leadingZero) return false;
|
|
58
|
+
return arcs >= 1;
|
|
107
59
|
}
|
|
108
60
|
|
|
109
|
-
// assertCanonicalOid(str, E, code, label, boundsCode) -> str | throws
|
|
110
|
-
// A canonical dotted-decimal object identifier string: two or more arcs, each a
|
|
111
|
-
// non-negative decimal integer with no leading zero (the syntax), and, unless
|
|
112
|
-
// bounds are waived, the root arc 0..2 with the second arc 0..39 under roots 0
|
|
113
|
-
// and 1 (the X.660 encodability bounds: the first two arcs pack into a single
|
|
114
|
-
// sub-identifier as 40*root+second). E is the (code, message) typed-error factory:
|
|
115
|
-
// - a syntax fault always throws E(code, ...).
|
|
116
|
-
// - boundsCode === null waives the arc-bound check, for a lookup key (oid.name
|
|
117
|
-
// / oid.has), where a well-formed but non-encodable OID is simply not
|
|
118
|
-
// registered (a miss) and not an error.
|
|
119
|
-
// - otherwise an out-of-range arc throws E(boundsCode, ...) (boundsCode defaults
|
|
120
|
-
// to code), so a caller distinguishing the two reasons (oid.js: oid/bad-input
|
|
121
|
-
// syntax vs oid/bad-arc bounds) keeps both codes.
|
|
122
61
|
// @enforced-by behavioral -- string-form OID canonicalization has no rename-proof
|
|
123
|
-
// code shape distinct from the arc-based bounds check oid.js legitimately keeps
|
|
124
|
-
// for the arc path; the divergence RED vectors (build.oid / oid.toArcs / requiredEku
|
|
125
|
-
// reject a non-canonical OID) driving the composing consumers are the guard.
|
|
126
62
|
function assertCanonicalOid(str, E, code, label, boundsCode) {
|
|
127
63
|
var who = label || "OID";
|
|
128
64
|
if (typeof str !== "string" || !_isDottedDecimal(str)) {
|
|
@@ -130,13 +66,7 @@ function assertCanonicalOid(str, E, code, label, boundsCode) {
|
|
|
130
66
|
}
|
|
131
67
|
if (boundsCode === null) return str;
|
|
132
68
|
var bcode = boundsCode === undefined ? code : boundsCode;
|
|
133
|
-
// The arc bound below is a bound on THESE parts, so the split that produces them settles it. One
|
|
134
|
-
// returning different pieces has the check read a first and second arc the identifier does not
|
|
135
|
-
// carry, and an out-of-range OID passes a range test performed on other numbers.
|
|
136
69
|
var parts = _strSplit(str, ".");
|
|
137
|
-
// Captured: these two arcs are what the bound below is a bound ON, and `BigInt` is a writable
|
|
138
|
-
// property of globalThis, so a replacement returns whatever it likes for the arcs and the range
|
|
139
|
-
// test is then performed on numbers the identifier does not carry.
|
|
140
70
|
var root = _BigInt(parts[0]);
|
|
141
71
|
var second = _BigInt(parts[1]);
|
|
142
72
|
if (root > 2n) throw E(bcode, who + " root arc must be 0, 1, or 2 (X.660)");
|
|
@@ -144,63 +74,18 @@ function assertCanonicalOid(str, E, code, label, boundsCode) {
|
|
|
144
74
|
return str;
|
|
145
75
|
}
|
|
146
76
|
|
|
147
|
-
// assertKnownKeys(obj, known, E, code, label): every own key of `obj` must appear in `known`.
|
|
148
|
-
//
|
|
149
|
-
// The shape this replaces was hand-written in a dozen callers, and it is worth one home because
|
|
150
|
-
// getting it wrong fails open in the quietest possible way: an options object whose key is
|
|
151
|
-
// misspelled silently carries the default, so a caller who asked for a stricter check gets the
|
|
152
|
-
// looser behavior and no error. Two details are easy to lose in a re-inline and are fixed here.
|
|
153
|
-
// `known` is consulted with hasOwnProperty and not a truthiness test, so an inherited Object
|
|
154
|
-
// member ("constructor", "toString") cannot read as a recognized key; and the walk is over own
|
|
155
|
-
// enumerable keys, so a `__proto__` arriving from JSON is inspected instead of skipped.
|
|
156
|
-
//
|
|
157
77
|
// @enforced-by behavioral -- an options-shape walk has no rename-proof code shape; the RED vectors
|
|
158
|
-
// (an unknown key, an inherited name, a JSON-borne __proto__) are the guard.
|
|
159
|
-
//
|
|
160
|
-
// `message` is the caller's own wording, so routing an existing check through this guard changes
|
|
161
|
-
// what is checked, never what the operator reads: a string is the prefix the quoted key is appended
|
|
162
|
-
// to, and a function (key) -> string builds the whole sentence, for the many callers that name the
|
|
163
|
-
// key mid-sentence and follow it with the hint that says what to pass instead.
|
|
164
|
-
//
|
|
165
|
-
// `known` and `message` are the module's own, and `obj` is the only argument here that a caller
|
|
166
|
-
// supplies. Questions asked of `obj` are typed, since a caller can answer them with a trap or a
|
|
167
|
-
// getter that throws; questions asked of the other two are not, because a table or a wording that
|
|
168
|
-
// throws is this toolkit's own wiring mistake. Handing either one a value off a caller would put
|
|
169
|
-
// an untyped exception on a boundary that promises a typed one, so neither takes one.
|
|
170
|
-
//
|
|
171
78
|
// @enforced-by guard-shape-reinlined
|
|
172
|
-
// The shape requires the throw: an identical walk whose body filters on the same table (copying the
|
|
173
|
-
// recognized keys onward instead of rejecting the unrecognized ones) is a different operation with
|
|
174
|
-
// no fail-open risk, and must not be dragged through a guard that only knows how to reject.
|
|
175
79
|
// @guard-shape Object\.keys\(\w+(?:\.\w+)*\)\.forEach\(function \((\w+)\) \{\s*if \(![\w.]+\[\1\]\) (?:\{\s*)?throw
|
|
176
80
|
function assertKnownKeys(obj, known, E, code, message) {
|
|
177
81
|
_refuseUnenumerable(obj, E, code, "the options");
|
|
178
82
|
var describe = typeof message === "function" ? message : function (k) { return message + _stringify(k); };
|
|
179
83
|
_forEach(_readableNames(obj), function (k) {
|
|
180
84
|
if (_hasOwn(known, k)) return;
|
|
181
|
-
// A Symbol reaches the message as its description, before either form of `message` sees it.
|
|
182
|
-
// JSON.stringify returns undefined for one, so a caller's own builder (which stringifies the
|
|
183
|
-
// key itself) would name the refused option "undefined" and leave nothing to search for.
|
|
184
|
-
// Normalizing here rather than in the default builder keeps both forms reading the same.
|
|
185
85
|
throw E(code, describe(typeof k === "symbol" ? _String(k) : k));
|
|
186
86
|
});
|
|
187
87
|
}
|
|
188
88
|
|
|
189
|
-
// What Object.prototype carries, per ECMA-262, written out rather than read from the runtime.
|
|
190
|
-
//
|
|
191
|
-
// Stopping the walk at Object.prototype excludes the whole object, so a runtime whose prototype
|
|
192
|
-
// carries `Object.prototype.password = "pw"` answers `opts.password` on a plain `{}` and
|
|
193
|
-
// `pki.key.export` hands back an unprotected key for a bag holding nothing. Naming the members
|
|
194
|
-
// instead reports anything else there.
|
|
195
|
-
//
|
|
196
|
-
// Reading the names off the live Object.prototype at load looks equivalent and is not: it is the
|
|
197
|
-
// runtime under attack answering the question, so a name planted before this module loads is
|
|
198
|
-
// captured as a built-in and is thereafter invisible. The spec list holds whoever loaded first.
|
|
199
|
-
// A guard-identifier test asserts it against the live object, so an engine that adds a member
|
|
200
|
-
// fails there rather than silently reporting it to every caller as an unknown option.
|
|
201
|
-
//
|
|
202
|
-
// The residual is a planted function REPLACING one of these twelve. No verb reads `opts.toString`
|
|
203
|
-
// as an option, so that smuggles nothing; it breaks the runtime at large, not this check.
|
|
204
89
|
var _PRISTINE_OBJECT_PROTO = (function () {
|
|
205
90
|
var s = _create(null);
|
|
206
91
|
_forEach(["constructor", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "toLocaleString",
|
|
@@ -209,33 +94,10 @@ var _PRISTINE_OBJECT_PROTO = (function () {
|
|
|
209
94
|
return s;
|
|
210
95
|
})();
|
|
211
96
|
|
|
212
|
-
// Is this descriptor shaped like a member of Object.prototype rather than a planted value? Every
|
|
213
|
-
// real one is a data property holding a function, or the `__proto__` accessor. Nothing there is a
|
|
214
|
-
// data property holding a string, a number or an object, so a planted `password: "pw"` fails this
|
|
215
|
-
// test whatever the snapshot above says about its name.
|
|
216
97
|
function _looksBuiltIn(d) {
|
|
217
98
|
return !!d && (!!d.get || !!d.set || typeof d.value === "function");
|
|
218
99
|
}
|
|
219
100
|
|
|
220
|
-
// Can this object be asked honestly what it holds?
|
|
221
|
-
//
|
|
222
|
-
// A Proxy answers `ownKeys` and `get` from two independent traps, so the two need not agree. One
|
|
223
|
-
// reporting no keys while its `get` returns "pw" for `password` presents an object that every
|
|
224
|
-
// enumeration calls empty and every read calls populated. No walk can close that: the readable
|
|
225
|
-
// names are whatever the trap decides at the moment it is asked, and asking again may differ.
|
|
226
|
-
// So the enumeration is not made more thorough, the object is refused. That is the same rule
|
|
227
|
-
// guard-bytes states for a value it cannot copy: there are two honest outcomes for a caller's
|
|
228
|
-
// argument, and "read it and hope the enumeration was truthful" is not one of them.
|
|
229
|
-
//
|
|
230
|
-
// The check is by identity through `util.types.isProxy`, never by behavior. Probing traps to
|
|
231
|
-
// catch a liar is a race a liar wins: it can answer consistently until the check is over.
|
|
232
|
-
// The WHOLE chain, not the object. `obj.password` resolves through every prototype above it, so a
|
|
233
|
-
// plain object inheriting from a lying Proxy answers the read while enumerating empty and is not
|
|
234
|
-
// itself a Proxy. Testing only the object handed in leaves that one line of indirection open.
|
|
235
|
-
// The error factory is validated before it is needed, for the same reason a guard taking a bound
|
|
236
|
-
// validates the bound: the one moment it is called is the moment something has already gone
|
|
237
|
-
// wrong, and a factory that is not one turns the refusal into a TypeError from inside the guard.
|
|
238
|
-
// This is a caller's wiring mistake rather than untrusted input, so it throws plainly.
|
|
239
101
|
function _requireFactory(E) {
|
|
240
102
|
if (typeof E !== "function") {
|
|
241
103
|
throw new TypeError("guard.identifier needs an error factory called as E(code, message); " +
|
|
@@ -255,18 +117,6 @@ function _refuseUnenumerable(v, E, code, label) {
|
|
|
255
117
|
}
|
|
256
118
|
}
|
|
257
119
|
|
|
258
|
-
// Does the prototype chain above `from` supply `k` as a data property holding `fn`? That is what
|
|
259
|
-
// makes `k` a method. Asking it by value identity is what makes the answer survive
|
|
260
|
-
// guard.bytes.snapshotDeep.
|
|
261
|
-
//
|
|
262
|
-
// The snapshot copies every readable name onto the copy and keeps the prototype, so a class's
|
|
263
|
-
// method arrives as an own property while the identical function is still reachable above it. A
|
|
264
|
-
// rule that asks "is this name own?" therefore calls the same method an option on the copy and
|
|
265
|
-
// behavior on the original, and every check running after a snapshot refuses an options bag that
|
|
266
|
-
// is an instance of the caller's own class.
|
|
267
|
-
//
|
|
268
|
-
// The walk stops at an object already seen, since a prototype chain is finite only while it is
|
|
269
|
-
// acyclic and a Proxy can make it otherwise. See the note on _readableNames.
|
|
270
120
|
function _isMethodOf(from, k, fn) {
|
|
271
121
|
var visited = new _Set();
|
|
272
122
|
for (var o = from; o && !_setHas(visited, o); o = _getPrototypeOf(o)) {
|
|
@@ -278,92 +128,16 @@ function _isMethodOf(from, k, fn) {
|
|
|
278
128
|
return false;
|
|
279
129
|
}
|
|
280
130
|
|
|
281
|
-
// Every name that can supply a value to a later `obj.foo`. `Object.keys` reports a subset of
|
|
282
|
-
// those: own enumerable names only. Four ordinary object shapes answer the lookup while showing
|
|
283
|
-
// that enumeration nothing. A value on the prototype (`_create({ password: "pw" })`). A
|
|
284
|
-
// non-enumerable own value (`_defineProperty(o, "password", { enumerable: false })`). A
|
|
285
|
-
// class getter, which class syntax also defines non-enumerable. And a polluted
|
|
286
|
-
// `Object.prototype`. On each of them `pki.key.export` accepts the bag, ignores the password it
|
|
287
|
-
// can read, and returns the private key in the clear, which is the case the refusal exists to
|
|
288
|
-
// prevent.
|
|
289
|
-
//
|
|
290
131
|
// @enforced-by behavioral -- a property-surface walk has no rename-proof code shape. The RED
|
|
291
|
-
// vectors are the guard, and they are the shapes that got past it in turn: a prototype data
|
|
292
|
-
// property, a non-enumerable own property, a class getter, a polluted Object.prototype, and a
|
|
293
|
-
// prototype method that must still be allowed through.
|
|
294
|
-
//
|
|
295
|
-
// So the walk covers the whole chain and skips one thing: a method, meaning a data property
|
|
296
|
-
// holding a function that the chain above it also supplies under that name. A method is behavior
|
|
297
|
-
// the bag's class defines. This repository has settled that an instance of a caller's own class
|
|
298
|
-
// is a legitimate options bag, since guard.bytes.snapshotDeep copies one and keeps its prototype
|
|
299
|
-
// so its methods resolve, and flagging them would reject calls that work today.
|
|
300
|
-
//
|
|
301
|
-
// Neither enumerability nor ownness decides that test. Each records how the name arrived, which
|
|
302
|
-
// is a different question from what it means. Enumerability records how a method was written,
|
|
303
|
-
// and the two ways differ: class syntax defines methods non-enumerable while `Proto.m = fn`
|
|
304
|
-
// defines them enumerable, so a rule keyed on it accepts one style and rejects the other.
|
|
305
|
-
// Ownness records whether the object has been through a snapshot, which flips the same method
|
|
306
|
-
// from inherited to own, so a rule keyed on it calls that method behavior at one check site and
|
|
307
|
-
// an unknown option at the next. Value identity against the chain above answers the same on both
|
|
308
|
-
// sides, which is what lets a check sit before or after a snapshot and reach one verdict.
|
|
309
|
-
//
|
|
310
|
-
// An accessor is never a method, whichever way it was written. A getter exists to answer with a
|
|
311
|
-
// value, which is exactly what an option does.
|
|
312
|
-
//
|
|
313
|
-
// One case is traded away, and it is written down here rather than left implicit. An unknown
|
|
314
|
-
// option supplied as a method is not reported: its value would have to be a function, and the
|
|
315
|
-
// prototype chain would have to supply that same function under that name. So `class Options {
|
|
316
|
-
// typo() {} }` passes, and `opts.typo` does resolve. The function-valued options here
|
|
317
|
-
// (revocationChecker, verifier, transport) are passed as own properties, so reaching the hole
|
|
318
|
-
// needs a caller to misspell one AND define it as a method rather than assign it. That is the
|
|
319
|
-
// price of keeping class instances usable, which this repository has settled, and it is the one
|
|
320
|
-
// gap in "every name a later obj.foo can resolve is reported".
|
|
321
|
-
// Is this string an array index, as the language defines one: an integer in [0, 2^32 - 2] whose
|
|
322
|
-
// canonical decimal spelling is the string itself?
|
|
323
|
-
//
|
|
324
|
-
// `String(Number(k)) === k` looks like that test and is not. It also admits "-1", "1.5", "NaN",
|
|
325
|
-
// "Infinity" and "4294967295" (one past the last index), every one of which is an ordinary named
|
|
326
|
-
// property on an array rather than an element. Treating them as structure means an unknown option
|
|
327
|
-
// under one of those names is passed over here and dropped by the copy in guard-bytes, so it
|
|
328
|
-
// reaches neither the check nor the verb. A leading zero is excluded by the same comparison,
|
|
329
|
-
// since "01" is a named property too.
|
|
330
132
|
function _isArrayIndex(k) {
|
|
331
133
|
var n = _Number(k);
|
|
332
134
|
return _isInteger(n) && n >= 0 && n < 4294967295 && _String(n) === k;
|
|
333
135
|
}
|
|
334
136
|
|
|
335
|
-
// Is this value one whose own `length` and indices are structure rather than supplied names?
|
|
336
|
-
//
|
|
337
|
-
// The value itself, never anything it inherits from. An object merely sitting over an array is a
|
|
338
|
-
// plain object: a `0` or a `length` of its own is a field its caller wrote, and reading the kind
|
|
339
|
-
// off the chain suppressed exactly those. What such a bag inherits from the array beneath it is a
|
|
340
|
-
// separate question, answered by the level test in the walk.
|
|
341
|
-
//
|
|
342
|
-
// A DataView is a byte view and is not one of these. It reads its bytes through methods and has no
|
|
343
|
-
// integer-indexed elements and no `length`, so `dv.length = 9` and `dv[0] = "x"` are ordinary
|
|
344
|
-
// properties that stay set and answer on a later read. Counting it as indexed drops both from the
|
|
345
|
-
// names reported and from the copy the verb is handed.
|
|
346
137
|
function _isIndexedKind(v) {
|
|
347
138
|
return _isArray(v) || (_isView(v) && !util.types.isDataView(v));
|
|
348
139
|
}
|
|
349
140
|
|
|
350
|
-
// The names the built-in collection kinds define on their prototypes, written out rather than
|
|
351
|
-
// read from the runtime, for the same reason the root's twelve are: reading a prototype to learn
|
|
352
|
-
// what belongs on it asks the polluted object to vouch for itself.
|
|
353
|
-
//
|
|
354
|
-
// One set covering every kind, because a LEVEL is what gets read and a level's kind cannot be
|
|
355
|
-
// established without asking a prototype who it is. `_create(Map.prototype)` holds no map
|
|
356
|
-
// and inherits `size`; a foreign array's prototype is not this realm's. Both are answered by
|
|
357
|
-
// asking whether the NAME is one a kind defines, which no realm and no lookalike changes.
|
|
358
|
-
//
|
|
359
|
-
// Being on the list is not enough on its own: the member also has to be shaped like one, so a
|
|
360
|
-
// planted `Array.prototype.password` is reported while `Array.prototype.length` is not.
|
|
361
|
-
// One list per prototype, holding exactly what THAT prototype defines. Sharing a list across
|
|
362
|
-
// kinds that merely resemble each other exempts a name its holder never had, which is a caller's
|
|
363
|
-
// option passed over in silence: a weak collection counts nothing and has no `size`, a
|
|
364
|
-
// SharedArrayBuffer is `growable` where an ArrayBuffer is `resizable` and `detached`, a DataView
|
|
365
|
-
// has no `length`, and `BYTES_PER_ELEMENT` belongs to a concrete typed array rather than the
|
|
366
|
-
// prototype they share.
|
|
367
141
|
var _ARRAY_PROTO_MEMBERS = ["length", Symbol.unscopables];
|
|
368
142
|
var _REGEXP_PROTO_MEMBERS = ["source", "flags", "global", "ignoreCase", "multiline",
|
|
369
143
|
"dotAll", "unicode", "unicodeSets", "sticky", "hasIndices"];
|
|
@@ -375,16 +149,8 @@ var _SHARED_PROTO_MEMBERS = ["byteLength", "maxByteLength", "growable", Symbol.t
|
|
|
375
149
|
var _DATAVIEW_PROTO_MEMBERS = ["buffer", "byteLength", "byteOffset", Symbol.toStringTag];
|
|
376
150
|
var _TYPED_PROTO_MEMBERS = ["buffer", "byteLength", "byteOffset", "length", Symbol.toStringTag];
|
|
377
151
|
var _CONCRETE_TYPED_MEMBERS = ["BYTES_PER_ELEMENT"];
|
|
378
|
-
// Node puts these two on Buffer.prototype, beneath the ECMAScript typed-array prototype.
|
|
379
152
|
var _BUFFER_PROTO_MEMBERS = ["parent", "offset"];
|
|
380
153
|
|
|
381
|
-
// What a whole kind carries, as against what one prototype defines. This is what answers for a
|
|
382
|
-
// value whose chain holds no prototype of this realm, where the level cannot be recognized and
|
|
383
|
-
// the kind read from the value's own slot is all there is.
|
|
384
|
-
// A kind carries what its own prototypes hold and nothing a neighboring kind holds. Answering a
|
|
385
|
-
// buffer with both buffer kinds' members exempts `growable` on an ArrayBuffer and `detached` on a
|
|
386
|
-
// SharedArrayBuffer, neither of which the language defines there, so a caller's getter under
|
|
387
|
-
// either name is passed over.
|
|
388
154
|
var _ARRAY_MEMBERS = _ARRAY_PROTO_MEMBERS;
|
|
389
155
|
var _REGEXP_MEMBERS = ["lastIndex"].concat(_REGEXP_PROTO_MEMBERS);
|
|
390
156
|
var _VIEW_MEMBERS = _TYPED_PROTO_MEMBERS.concat(_CONCRETE_TYPED_MEMBERS);
|
|
@@ -393,27 +159,6 @@ var _DATAVIEW_MEMBERS = _DATAVIEW_PROTO_MEMBERS;
|
|
|
393
159
|
var _ARRAYBUFFER_MEMBERS = _ARRAYBUFFER_PROTO_MEMBERS;
|
|
394
160
|
var _SHARED_MEMBERS = _SHARED_PROTO_MEMBERS;
|
|
395
161
|
|
|
396
|
-
// Which of those a value carries, taken from its internal slot.
|
|
397
|
-
//
|
|
398
|
-
// The value's own kind, not the union, because a name belongs to a kind and a caller's accessor
|
|
399
|
-
// can borrow one that a different kind defines. `class Opts extends Array { get buffer() {} }` is
|
|
400
|
-
// an array, `buffer` is a byte view's member and not an array's, so that getter is the caller's
|
|
401
|
-
// option and gets reported.
|
|
402
|
-
//
|
|
403
|
-
// A value with no collection slot answers with nothing. `_create(Map.prototype)` holds no
|
|
404
|
-
// map and still inherits `size`, and that is settled by the level test in the walk, which reads
|
|
405
|
-
// the members off the prototype the name was found on.
|
|
406
|
-
// The prototypes this realm installs a kind's members on. A level that IS one carries the
|
|
407
|
-
// language's members whatever the value in front of it turns out to be, which is how
|
|
408
|
-
// `_create(Map.prototype)` keeps `size` while holding no map.
|
|
409
|
-
//
|
|
410
|
-
// Typed arrays are recognized through the prototype they all share rather than by naming each
|
|
411
|
-
// constructor, so a kind the list never mentioned is covered: `Float16Array` arrived on Node 24
|
|
412
|
-
// and an enumeration would have gone on reporting its `BYTES_PER_ELEMENT` as a caller's option.
|
|
413
|
-
// Each one paired with the members IT defines, never the union of every kind's. A level carries
|
|
414
|
-
// only its own: `size` on `Array.prototype` is nothing the language put there, so exempting it
|
|
415
|
-
// because some other kind has a member by that name hands back the hole this walk exists to
|
|
416
|
-
// close, for anyone who plants it in a shape that reads as built-in.
|
|
417
162
|
var _TYPED_ARRAY_PROTO = _getPrototypeOf(Uint8Array.prototype);
|
|
418
163
|
var _INTRINSIC_HOLDERS = (function () {
|
|
419
164
|
var m = new _Map([[_TYPED_ARRAY_PROTO, _TYPED_PROTO_MEMBERS]]);
|
|
@@ -426,19 +171,6 @@ var _INTRINSIC_HOLDERS = (function () {
|
|
|
426
171
|
pair(typeof SharedArrayBuffer === "function" ? SharedArrayBuffer : null, _SHARED_PROTO_MEMBERS);
|
|
427
172
|
pair(DataView, _DATAVIEW_PROTO_MEMBERS);
|
|
428
173
|
pair(Buffer, _BUFFER_PROTO_MEMBERS);
|
|
429
|
-
// Every concrete typed-array kind the runtime actually provides, found by asking it rather than
|
|
430
|
-
// by naming them, so a kind added later is covered the day it lands -- Float16Array was.
|
|
431
|
-
//
|
|
432
|
-
// Registered as identities. Recognizing them by their PARENT instead admitted anything a caller
|
|
433
|
-
// built over `%TypedArray%.prototype`, and a bag inheriting `BYTES_PER_ELEMENT` from such an
|
|
434
|
-
// object then read as an intrinsic member rather than as the unknown option it was.
|
|
435
|
-
//
|
|
436
|
-
// Read the DESCRIPTOR, never the value through the runtime. `globalThis[n]` invokes a getter, and a
|
|
437
|
-
// host may define one that warns on read -- Node exposes `localStorage` and `WASI` as lazy accessors
|
|
438
|
-
// that emit an ExperimentalWarning the moment they are touched, so a plain read here printed that
|
|
439
|
-
// warning on every import -- or one that throws. A typed-array constructor is a plain data property, so
|
|
440
|
-
// taking `d.value` finds every concrete kind without ever invoking an accessor, which also means such
|
|
441
|
-
// an accessor can neither warn nor fault this load over a name it does not need.
|
|
442
174
|
_forEach(_getOwnPropertyNames(globalThis), function (n) {
|
|
443
175
|
var d = _getOwnPropertyDescriptor(globalThis, n);
|
|
444
176
|
if (!d || typeof d.value !== "function") return;
|
|
@@ -450,22 +182,10 @@ var _INTRINSIC_HOLDERS = (function () {
|
|
|
450
182
|
return m;
|
|
451
183
|
})();
|
|
452
184
|
|
|
453
|
-
// The members a chain level defines, or null where the level is not one the language installs
|
|
454
|
-
// members on. Membership is by identity: every prototype the language installs members on is in
|
|
455
|
-
// the table above, the concrete typed-array ones included, so an object that merely sits over one
|
|
456
|
-
// of them is a caller's and its names are theirs.
|
|
457
185
|
function _holderMembers(o) {
|
|
458
186
|
return _mapHas(_INTRINSIC_HOLDERS, o) ? _mapGet(_INTRINSIC_HOLDERS, o) : null;
|
|
459
187
|
}
|
|
460
188
|
|
|
461
|
-
// Is this one of Node's Buffers? A byte view whose chain reaches `Buffer.prototype`, asked by
|
|
462
|
-
// walking it rather than through `Buffer.isBuffer`.
|
|
463
|
-
//
|
|
464
|
-
// `Buffer.isBuffer` is an `instanceof`, and `Buffer` is an ordinary extensible function, so
|
|
465
|
-
// defining `Buffer[Symbol.hasInstance]` on it hands the answer to whoever did. That is the same
|
|
466
|
-
// pollution this walk exists to survive on `Object.prototype` and `Array.prototype`, and it can
|
|
467
|
-
// throw as well as lie: a caller's argument then leaves a door whose contract is a typed error
|
|
468
|
-
// carrying somebody else's exception. A prototype identity is not writable from outside.
|
|
469
189
|
function _isNodeBuffer(v) {
|
|
470
190
|
if (!util.types.isUint8Array(v)) return false;
|
|
471
191
|
var visited = new _Set();
|
|
@@ -477,9 +197,6 @@ function _isNodeBuffer(v) {
|
|
|
477
197
|
}
|
|
478
198
|
|
|
479
199
|
function _kindMembers(v) {
|
|
480
|
-
// The value's own slot, never a kind it merely inherits from. Whatever a real intrinsic
|
|
481
|
-
// prototype in the chain supplies is handled by the level test at the walk; a name that only
|
|
482
|
-
// looks like a member, on a class of the caller's, is the option they wrote.
|
|
483
200
|
if (v === null || v === undefined) return [];
|
|
484
201
|
if (_isArray(v)) return _ARRAY_MEMBERS;
|
|
485
202
|
if (_isNodeBuffer(v)) return _BUFFER_KIND_MEMBERS;
|
|
@@ -493,36 +210,15 @@ function _kindMembers(v) {
|
|
|
493
210
|
return [];
|
|
494
211
|
}
|
|
495
212
|
|
|
496
|
-
// The names a kind puts on the value itself rather than on its prototype, which are structure the
|
|
497
|
-
// same way an array's `length` is: `opts.lastIndex` on a RegExp answers with the match position
|
|
498
|
-
// whatever a caller meant by it, so no option can be supplied under that name.
|
|
499
213
|
function _isOwnStructuralName(v, k) {
|
|
500
214
|
return util.types.isRegExp(v) && k === "lastIndex";
|
|
501
215
|
}
|
|
502
216
|
|
|
503
|
-
// The shape a member the language put there has, and a planted one does not: an accessor, a
|
|
504
|
-
// function, or a data property the language pinned. `Symbol.toStringTag` and `BYTES_PER_ELEMENT`
|
|
505
|
-
// are non-writable; `Array.prototype.length` is writable and non-configurable. A name added by
|
|
506
|
-
// assignment or by an ordinary defineProperty is neither, so it stays reported.
|
|
507
217
|
function _looksIntrinsic(d) {
|
|
508
218
|
return !!d && (!!d.get || !!d.set || typeof d.value === "function" ||
|
|
509
219
|
d.writable === false || d.configurable === false);
|
|
510
220
|
}
|
|
511
221
|
|
|
512
|
-
// The member descriptors this realm's collection prototypes actually carry, taken at load and
|
|
513
|
-
// keyed by the accessor or value they hold.
|
|
514
|
-
//
|
|
515
|
-
// The name and the shape together are not enough on their own: a caller's class can extend a
|
|
516
|
-
// collection and define one of its own members over the top, and
|
|
517
|
-
// `class Opts extends Map { get size() {} }` is then an accessor named `size` on a value that is
|
|
518
|
-
// a Map. What tells the two apart is where the name sits, and that answers in any realm: the
|
|
519
|
-
// language installs a member once, so an intrinsic one is the only level of the chain carrying
|
|
520
|
-
// that name, while an override shadows the intrinsic still sitting above it. A name found twice
|
|
521
|
-
// is a caller's.
|
|
522
|
-
//
|
|
523
|
-
// Reading it that way also settles a kind this list would have to be extended for. `Float16Array`
|
|
524
|
-
// is on Node 24 and was not among the constructors named here, and the moment a typed array of an
|
|
525
|
-
// unlisted kind arrived its `BYTES_PER_ELEMENT` read as an option its caller never wrote.
|
|
526
222
|
function _shadowsAnother(v, k, holder) {
|
|
527
223
|
var visited = new _Set();
|
|
528
224
|
var past = false;
|
|
@@ -537,100 +233,30 @@ function _shadowsAnother(v, k, holder) {
|
|
|
537
233
|
function _readableNames(obj) {
|
|
538
234
|
var seen = _create(null);
|
|
539
235
|
var out = [];
|
|
540
|
-
// A primitive supplies no option names, and `Reflect.ownKeys` refuses one outright. The walk
|
|
541
|
-
// starts above it rather than on it, so a caller who hands a number or a string where an
|
|
542
|
-
// options bag belongs gets their own verb's refusal for the wrong type from the door that
|
|
543
|
-
// checks types, instead of a raw TypeError from in here about a reflection method they never
|
|
544
|
-
// called. `null` and `undefined` have no chain at all and stop immediately.
|
|
545
|
-
// Boxed through the captured `Object`. This decides which names the scan below then examines, so
|
|
546
|
-
// a replacement wraps a primitive as an object of its own choosing and the guard reads a name set
|
|
547
|
-
// and a prototype chain the caller supplied rather than the value's.
|
|
548
236
|
var o = (obj === null || obj === undefined) ? null : _Object(obj);
|
|
549
|
-
// Whether the value's own `length` and indices are structure. That is true of an array and a
|
|
550
|
-
// byte view and of nothing else: a Map, a Set and an ArrayBuffer have no own `length`, so
|
|
551
|
-
// skipping the name there would discard one the caller had put on themselves.
|
|
552
|
-
//
|
|
553
|
-
// A verb reads an option by name whatever the argument's type, and `opts = []; opts.pem = true`
|
|
554
|
-
// is an options bag as far as `opts.pem` is concerned, so these kinds have to work. Their
|
|
555
|
-
// prototypes carry names the caller did not supply, and the per-level test below is what
|
|
556
|
-
// handles those. Refusing to read the chain at all leaves a bag whose chain holds nothing
|
|
557
|
-
// intrinsic unread.
|
|
558
237
|
var indexedSelf = _isIndexedKind(o);
|
|
559
238
|
var members = _kindMembers(o);
|
|
560
|
-
// A prototype chain is finite only while it is acyclic, and a Proxy can make it otherwise.
|
|
561
|
-
// While its target stays extensible a `getPrototypeOf` trap may return the proxy itself. The
|
|
562
|
-
// walk therefore stops at an object it has already visited. A second lap over the same objects
|
|
563
|
-
// yields no name the first did not, so the reported names stay complete. Without the test a
|
|
564
|
-
// caller's argument hangs the verb before a single option has been read.
|
|
565
239
|
var visited = new _Set();
|
|
566
240
|
while (o && !_setHas(visited, o)) {
|
|
567
241
|
_setAdd(visited, o);
|
|
568
242
|
var inherited = (o !== obj);
|
|
569
243
|
var above = _getPrototypeOf(o);
|
|
570
|
-
// The root of the chain is the last level before null, which is what `Object.prototype` is.
|
|
571
|
-
// Its position holds in every realm. A value built in a `vm` context or a worker thread
|
|
572
|
-
// carries that realm's root above it, so an identity test against the local object misses it
|
|
573
|
-
// and the foreign `__proto__` accessor reads as a name the caller supplied.
|
|
574
|
-
//
|
|
575
|
-
// The level has to be an inherited one. A caller's own `_create(null)` has no prototype
|
|
576
|
-
// either, and treating the bag itself as a root skips the names they set on it.
|
|
577
244
|
var atObjectProto = inherited && above === null;
|
|
578
|
-
// A kind's own prototype gets no exemption as a level. Passing one over whole hides anything
|
|
579
|
-
// added to it, and `Array.prototype.password = "pw"` is then invisible while `opts.password`
|
|
580
|
-
// resolves, which handed `pki.key.export` an unprotected private key for `[]` as the bag.
|
|
581
|
-
// Object.prototype was already read for that reason; every level is now read the same way,
|
|
582
|
-
// and what a kind puts on its prototype is passed over by name below.
|
|
583
|
-
//
|
|
584
|
-
// Reflect.ownKeys, because Object.getOwnPropertyNames never returns a Symbol key and a
|
|
585
|
-
// caller can write one. Such a name cannot answer `opts.password`, so it reaches no verb,
|
|
586
|
-
// but it is still an option supplied and not read, which is the whole thing being refused.
|
|
587
245
|
_forEach(_ownKeys(o), function (k) {
|
|
588
246
|
if (seen[k]) return;
|
|
589
|
-
// The indices of an array or a byte view are its structure, whichever level they are read
|
|
590
|
-
// from. Both kinds answer an integer-keyed read from their elements before any prototype is
|
|
591
|
-
// consulted, so no caller can supply an option under such a name.
|
|
592
247
|
if (indexedSelf && typeof k === "string" && _isArrayIndex(k)) return;
|
|
593
|
-
// `length` is structure only where the language puts it on the value itself, which an array
|
|
594
|
-
// does and a byte view does not. On an array it is an own non-configurable property that no
|
|
595
|
-
// prototype can shadow, so `opts.length` is always the count. A byte view carries it as a
|
|
596
|
-
// prototype accessor, and `class Opts extends Uint8Array { get length() {} }` shadows that
|
|
597
|
-
// one: `opts.length` then answers with what the caller wrote, so it is an option they
|
|
598
|
-
// supplied. Passing the name over for both kinds hid exactly that. Left to the level test
|
|
599
|
-
// below, which exempts the accessor where the language installed it and reports an override.
|
|
600
248
|
if (indexedSelf && k === "length" && !inherited) return;
|
|
601
249
|
if (_isOwnStructuralName(obj, k)) return;
|
|
602
250
|
var d = _getOwnPropertyDescriptor(o, k);
|
|
603
|
-
// A name a built-in kind defines, on a level above the value and shaped the way the
|
|
604
|
-
// language leaves it. Own is deliberately excluded: an own `detached` on a buffer shadows
|
|
605
|
-
// the intrinsic getter, so `opts.detached` answers with what the caller wrote, and
|
|
606
|
-
// pki.cms.sign reads an option under exactly that name.
|
|
607
|
-
// A member of the value's own kind, or one sitting on a prototype the language installs
|
|
608
|
-
// members on. The second is what carries `_create(Map.prototype)`, which holds no map
|
|
609
|
-
// and inherits `size` all the same. Neither alone is enough: without the level test a class
|
|
610
|
-
// of the caller's could name a getter after any kind's member and have it passed over.
|
|
611
251
|
var here = _holderMembers(o);
|
|
612
252
|
if (inherited && _looksIntrinsic(d) && !_shadowsAnother(obj, k, o) &&
|
|
613
253
|
(here === null ? _indexOf(members, k) !== -1 : _indexOf(here, k) !== -1)) return;
|
|
614
|
-
// Object.prototype is decided here and nowhere else. A member is one of the twelve the spec
|
|
615
|
-
// names, still shaped like one: a data property holding a function, or the `__proto__`
|
|
616
|
-
// accessor. Anything else on it was planted and is reported.
|
|
617
|
-
//
|
|
618
|
-
// The method rule below must not run on it. That rule exempts an inherited function so a
|
|
619
|
-
// caller's class keeps its methods, and a planted `password` function is inherited and a
|
|
620
|
-
// function, so the rule would rescue exactly the value this check exists to find. A class
|
|
621
|
-
// defines its methods on its own prototype, and nothing legitimate puts one on the root.
|
|
622
254
|
if (atObjectProto) {
|
|
623
255
|
if (_PRISTINE_OBJECT_PROTO[k] && _looksBuiltIn(d)) return;
|
|
624
256
|
seen[k] = 1;
|
|
625
257
|
_append(out, k);
|
|
626
258
|
return;
|
|
627
259
|
}
|
|
628
|
-
// A method: a data property holding a function that is either inherited, where a class
|
|
629
|
-
// defines one, or also supplied under that name by the chain above, where a snapshot has
|
|
630
|
-
// copied one down onto the object. Both readings are needed. The first alone calls a
|
|
631
|
-
// promoted method an option. The second alone misses a method at the level that defines
|
|
632
|
-
// it, where nothing above carries the same function. An accessor is never a method,
|
|
633
|
-
// whichever way it was written, since a getter exists to answer with a value.
|
|
634
260
|
if (d && !d.get && !d.set && typeof d.value === "function" &&
|
|
635
261
|
(inherited || _isMethodOf(above, k, d.value))) return;
|
|
636
262
|
seen[k] = 1;
|
|
@@ -641,50 +267,13 @@ function _readableNames(obj) {
|
|
|
641
267
|
return out;
|
|
642
268
|
}
|
|
643
269
|
|
|
644
|
-
// The exported form of the property walk, which takes the caller's error factory like every
|
|
645
|
-
// other guard function.
|
|
646
|
-
//
|
|
647
|
-
// The internal walk reads the prototype chain, and reading a chain runs a `getPrototypeOf` trap,
|
|
648
|
-
// so a hostile one throws its own raw error out of a module whose whole contract is a typed one.
|
|
649
|
-
// `assertKnownKeys` and `optionsObject` refuse a Proxy before they walk; this door has to do the
|
|
650
|
-
// same, because a caller reaching for the names directly is exactly the caller who has not
|
|
651
|
-
// already checked. Taking `(E, code, label)` is what makes that possible, and it puts the one
|
|
652
|
-
// guard function that did not follow the family convention back inside it.
|
|
653
|
-
//
|
|
654
270
|
// @enforced-by behavioral -- a missing refusal has no rename-proof code shape; the RED vector
|
|
655
|
-
// (a hostile trap escaping as its own Error from this door) is the guard.
|
|
656
271
|
function readableNames(obj, E, code, label) {
|
|
657
272
|
_refuseUnenumerable(obj, E, code, label);
|
|
658
273
|
return _readableNames(obj);
|
|
659
274
|
}
|
|
660
275
|
|
|
661
|
-
// The indices an ordinary read on an array resolves, ascending, own and inherited.
|
|
662
|
-
//
|
|
663
|
-
// The name walk above drops every index of an indexed kind, since an index is structure rather
|
|
664
|
-
// than a name a caller supplied. Something still has to answer which indices there ARE, and the
|
|
665
|
-
// answer is not `Reflect.ownKeys`: an array consults its prototype chain for a hole, so
|
|
666
|
-
// `_setPrototypeOf([,], {0: signer})` reads `[signer]` to a `for` loop, to `forEach`, and to
|
|
667
|
-
// every consumer of the value, while its own keys report an empty array. A copy built from the own
|
|
668
|
-
// keys alone holds a hole where the original answers, which is the same divergence between the
|
|
669
|
-
// value checked and the value used that this family exists to close - here it silently shortens a
|
|
670
|
-
// signer list rather than lengthening it.
|
|
671
|
-
//
|
|
672
|
-
// Arrays only. A typed array answers a canonical index from its elements and never consults the
|
|
673
|
-
// chain, in bounds or out, so its indices are exactly its own. A DataView is an ordinary object
|
|
674
|
-
// whose numeric keys ARE caller-supplied names, and the name walk above already reports them.
|
|
675
|
-
//
|
|
676
|
-
// `length` is read off the own descriptor, which for an array is the non-configurable count the
|
|
677
|
-
// language maintains and no prototype can shadow. Inherited indices at or above it are left out:
|
|
678
|
-
// a read past `length` resolves, but no length-bounded traversal reaches it, and carrying one
|
|
679
|
-
// across would lengthen the copy past what the caller passed.
|
|
680
|
-
//
|
|
681
|
-
// The work stays bounded by what the value and its chain actually hold, so a caller who writes
|
|
682
|
-
// `a.length = 4e9` costs what a sparse array costs and not four billion steps. The walk stops at
|
|
683
|
-
// an object already visited for the reason the name walk does: a `getPrototypeOf` trap can hand
|
|
684
|
-
// back a fresh proxy forever, and a chain that never ends hangs the verb.
|
|
685
|
-
//
|
|
686
276
|
// @enforced-by behavioral -- an enumeration gap has no rename-proof code shape; the RED vector
|
|
687
|
-
// (a length-one array holding its only element on its prototype, copied to a hole) is the guard.
|
|
688
277
|
function readableIndices(obj, E, code, label) {
|
|
689
278
|
_refuseUnenumerable(obj, E, code, label);
|
|
690
279
|
if (!_isArray(obj)) return [];
|
|
@@ -705,22 +294,6 @@ function readableIndices(obj, E, code, label) {
|
|
|
705
294
|
return _sort(out, function (a, b) { return _Number(a) - _Number(b); });
|
|
706
295
|
}
|
|
707
296
|
|
|
708
|
-
// The object kinds that are never an options bag, named so the refusal says which mistake was
|
|
709
|
-
// made. Buffer is handled beside the type check, being the argument-order slip.
|
|
710
|
-
//
|
|
711
|
-
// A boxed primitive is the one that has to be here rather than left to the unknown-option check.
|
|
712
|
-
// `new Number(0)` and `new Boolean(false)` carry no readable name at all, so nothing is reported
|
|
713
|
-
// and they pass as a bag with no options in it: the same silence `0` and `false` used to buy,
|
|
714
|
-
// one wrapper away. The rest carry names the language installed, so each is refused already; what
|
|
715
|
-
// they gain is a message that names the argument rather than one of the engine's own fields.
|
|
716
|
-
//
|
|
717
|
-
// Every one read off the value's slot, so a lookalike built over the prototype does not answer for
|
|
718
|
-
// one, a real one from a `vm` context or a worker thread does, and the value is asked nothing.
|
|
719
|
-
//
|
|
720
|
-
// That last part is the reason none of these is a type tag. `Object.prototype.toString` reads
|
|
721
|
-
// `Symbol.toStringTag`, which a caller can back with a getter that throws, so classifying a bag
|
|
722
|
-
// that way put the caller's own exception on a boundary whose contract is a typed error, and a
|
|
723
|
-
// caller could name any object an arguments object by writing the tag themselves.
|
|
724
297
|
function _notAnOptionsBag(v) {
|
|
725
298
|
if (util.types.isBoxedPrimitive(v)) return "a boxed primitive";
|
|
726
299
|
if (util.types.isNativeError(v)) return "an Error";
|
|
@@ -729,22 +302,6 @@ function _notAnOptionsBag(v) {
|
|
|
729
302
|
return null;
|
|
730
303
|
}
|
|
731
304
|
|
|
732
|
-
// Normalize a verb's options argument and return it. The order of the two steps decides whether
|
|
733
|
-
// the check runs on the caller's value, and returning is what makes the safe order the easy one.
|
|
734
|
-
//
|
|
735
|
-
// The idiom this replaces was `opts = opts || {}` followed by a type check. That reads as though
|
|
736
|
-
// it validates, and does not: `||` treats `false`, `0`, `""` and `NaN` as absent too, so those
|
|
737
|
-
// four were rewritten to `{}` before the check could see them and sailed through as valid
|
|
738
|
-
// options. Every entry point that reached for the idiom inherited the hole, including three that
|
|
739
|
-
// had shipped with it.
|
|
740
|
-
//
|
|
741
|
-
// Only `null` and `undefined` mean "no options given". Anything else non-object is a caller
|
|
742
|
-
// error and says so. A Buffer is excluded because it is an object and is never an options bag --
|
|
743
|
-
// passing one is an argument-order mistake, which is worth naming rather than treating as empty.
|
|
744
|
-
//
|
|
745
|
-
// A built-in exotic whose data lives in internal slots rather than own enumerable keys, recognized by
|
|
746
|
-
// identity so a cross-realm instance is caught too. `util.types` covers each such kind; an array is not
|
|
747
|
-
// among them and is checked separately by the caller.
|
|
748
305
|
function _isBuiltinExotic(v) {
|
|
749
306
|
var t = util.types;
|
|
750
307
|
return t.isDate(v) || t.isMap(v) || t.isSet(v) || t.isWeakMap(v) || t.isWeakSet(v) || t.isRegExp(v) ||
|
|
@@ -752,44 +309,17 @@ function _isBuiltinExotic(v) {
|
|
|
752
309
|
t.isBoxedPrimitive(v) || t.isNativeError(v) || t.isArgumentsObject(v) || t.isGeneratorObject(v);
|
|
753
310
|
}
|
|
754
311
|
|
|
755
|
-
// assertPlainRecord(v, E, code, label): v MUST be a plain data record -- a non-null object that is not an
|
|
756
|
-
// array, a Buffer, a Proxy, or a built-in exotic (a Date, Map, Set, boxed primitive, ...). A caller's
|
|
757
|
-
// `typeof v === "object"` gate admits an array or a Date, which then passes assertKnownKeys with no own
|
|
758
|
-
// key to reject and reads as a keyless record -- every field `undefined` and silently defaulted. This
|
|
759
|
-
// door refuses that shape, so a malformed container is a refusal rather than a request assembled from
|
|
760
|
-
// defaults. Composes BEFORE assertKnownKeys, which only
|
|
761
|
-
// judges the keys that are present, not whether the value is a record at all.
|
|
762
|
-
//
|
|
763
|
-
// The prototype is NOT consulted, so a record built by a caller's own class, or one from another realm
|
|
764
|
-
// (a vm context, a worker) whose prototype is a different Object.prototype, is accepted -- it holds its
|
|
765
|
-
// fields as own enumerable properties like any record. Only a built-in exotic that keeps its data in
|
|
766
|
-
// internal slots (a Date, Map, Set, boxed primitive, ...), an array (index-keyed), a Buffer, or a Proxy
|
|
767
|
-
// is refused, each recognized by identity through `util.types` / `Array.isArray` so a cross-realm
|
|
768
|
-
// instance is caught where an `instanceof` or a prototype check would miss it.
|
|
769
|
-
//
|
|
770
312
|
// @enforced-by behavioral -- a plain-record refusal has no single rename-proof code shape worth a
|
|
771
|
-
// tree-wide detector; the RED vectors (an array, a Date, and a Proxy at each routed entry point, and a
|
|
772
|
-
// cross-realm/subclass record that must still be ACCEPTED) are the guard.
|
|
773
313
|
function assertPlainRecord(v, E, code, label) {
|
|
774
314
|
_requireFactory(E);
|
|
775
315
|
if (v === null || typeof v !== "object" || _isNodeBuffer(v) || _isArray(v)) throw E(code, label + " must be a plain object");
|
|
776
|
-
_refuseUnenumerable(v, E, code, label);
|
|
316
|
+
_refuseUnenumerable(v, E, code, label);
|
|
777
317
|
if (_isBuiltinExotic(v)) throw E(code, label + " must be a plain object (a built-in exotic such as a Date or Map is refused)");
|
|
778
318
|
}
|
|
779
319
|
|
|
780
320
|
// @enforced-by behavioral -- the defect is an ordering, which has no rename-proof code shape; the
|
|
781
|
-
// RED vector (a verb handed `false` accepting it as `{}`) is the guard.
|
|
782
321
|
function optionsObject(opts, E, code, label) {
|
|
783
|
-
// No options supplied gets a bag with NO prototype, so it inherits nothing. A plain `{}` here
|
|
784
|
-
// would inherit whatever Object.prototype carries, and on a runtime where that has been
|
|
785
|
-
// polluted the caller is then refused for a name they never wrote. A caller who does pass `{}`
|
|
786
|
-
// is a different case and keeps the refusal: `opts.password` answers on their object, so the
|
|
787
|
-
// option is readable and unread, which is exactly what is being refused.
|
|
788
322
|
if (opts === null || opts === undefined) return _create(null);
|
|
789
|
-
// `typeof` asks the value nothing, so it is safe on any argument. Every question after it comes
|
|
790
|
-
// once the value has been refused as a Proxy, because each one walks the prototype chain and so
|
|
791
|
-
// runs a `getPrototypeOf` trap, which took this door out through the caller's own exception
|
|
792
|
-
// rather than the typed one it promises.
|
|
793
323
|
if (typeof opts !== "object") throw E(code, label + " must be an object");
|
|
794
324
|
_refuseUnenumerable(opts, E, code, label);
|
|
795
325
|
if (_isNodeBuffer(opts)) throw E(code, label + " must be an object");
|
|
@@ -798,42 +328,6 @@ function optionsObject(opts, E, code, label) {
|
|
|
798
328
|
return _settle(opts, E, code, label);
|
|
799
329
|
}
|
|
800
330
|
|
|
801
|
-
// The caller's bag, once its option names have been shown to hold still while they are read.
|
|
802
|
-
//
|
|
803
|
-
// Reading an option can run a caller's getter, and a getter can add a name to the bag it was read
|
|
804
|
-
// from. `{ get format() { this.password = "pw"; return "der"; } }` shows only `format` while the
|
|
805
|
-
// unknown-option check runs, and grows `password` when the verb reads `format` afterwards, so the
|
|
806
|
-
// names that were checked are not the names the verb ends up carrying. `pki.key.export` took such
|
|
807
|
-
// a bag and returned a private key in the clear, which is the case the check exists to prevent.
|
|
808
|
-
//
|
|
809
|
-
// Every readable name is therefore read here, before anything is checked, and the names are taken
|
|
810
|
-
// again afterwards. A bag that grew or dropped one is refused, because a bag that rewrites itself
|
|
811
|
-
// as it is read has no set of names that can be checked at all.
|
|
812
|
-
//
|
|
813
|
-
// The bag itself is handed back, never a copy of it. Which names a caller supplied is decided by
|
|
814
|
-
// where they sit: own is theirs, inherited is machinery unless the chain says otherwise. Copying
|
|
815
|
-
// the readable ones onto a new object destroys exactly that, and every attempt to keep it turned
|
|
816
|
-
// into its own defect: a bare copy dropped `pki.path.build`'s inherited `transport` and sent the
|
|
817
|
-
// verb to the network the caller meant to replace, and a copy built over the original inherited
|
|
818
|
-
// native accessors onto a receiver with no slot behind them, so an `ArrayBuffer` options bag
|
|
819
|
-
// raised a raw TypeError from `opts.detached`.
|
|
820
|
-
//
|
|
821
|
-
// An accessor cannot be one, and that is the whole rule: a getter answers a different question
|
|
822
|
-
// every time it is asked, so a name checked once says nothing about what the verb reads next.
|
|
823
|
-
//
|
|
824
|
-
// Every narrower attempt to keep them was measured and each carried its own defect. Reading once
|
|
825
|
-
// and re-taking the names catches a getter that mutates immediately and misses one that waits for
|
|
826
|
-
// a later read. Freezing the bag closes that and then throws a raw TypeError on a non-empty typed
|
|
827
|
-
// array, which cannot be frozen at all, while still leaving a mutable PROTOTYPE for an inherited
|
|
828
|
-
// getter to grow. Copying the bag instead loses which names were the caller's own, drops an
|
|
829
|
-
// inherited option a verb reads, and leaves a native accessor on a receiver with no slot for it.
|
|
830
|
-
//
|
|
831
|
-
// Refusing is the one rule with nothing behind it. A plain object, a class instance with methods,
|
|
832
|
-
// a collection, a bag from another realm are all still options bags; what is asked is that the
|
|
833
|
-
// options themselves be values. The names are read once even so, since an accessor can hide on a
|
|
834
|
-
// prototype and this is where that gets found.
|
|
835
|
-
// The descriptor a name resolves to, from wherever on the chain it is found. Only the first
|
|
836
|
-
// level carrying it matters, since that is the one a read reaches.
|
|
837
331
|
function _descriptorHolder(v, k) {
|
|
838
332
|
var visited = new _Set();
|
|
839
333
|
for (var o = v; o !== null && o !== undefined && !_setHas(visited, o); o = _getPrototypeOf(o)) {
|
|
@@ -844,15 +338,7 @@ function _descriptorHolder(v, k) {
|
|
|
844
338
|
return null;
|
|
845
339
|
}
|
|
846
340
|
|
|
847
|
-
// refuseAccessorFields(obj, names, E, code, label) -> undefined | throws E(code, msg)
|
|
848
|
-
//
|
|
849
|
-
// Every door that decides what a caller supplied asks this, because a door that reads an accessor
|
|
850
|
-
// before another door checks for one leaves nothing behind to find: guard.bytes.snapshotDeep runs
|
|
851
|
-
// a spec's getters while copying and writes what they returned as plain data, so the option check
|
|
852
|
-
// that follows sees values and cannot tell there was ever an accessor there.
|
|
853
|
-
//
|
|
854
341
|
// @enforced-by behavioral -- reading an accessor before it is refused has no rename-proof code
|
|
855
|
-
// shape; the RED vectors (a getter on an options bag and on a signing spec) are the guard.
|
|
856
342
|
function refuseAccessorFields(obj, names, E, code, label) {
|
|
857
343
|
for (var i = 0; i < names.length; i++) {
|
|
858
344
|
var holder = _descriptorHolder(obj, names[i]);
|
|
@@ -866,8 +352,6 @@ function refuseAccessorFields(obj, names, E, code, label) {
|
|
|
866
352
|
}
|
|
867
353
|
|
|
868
354
|
function _settle(opts, E, code, label) {
|
|
869
|
-
// A caller's accessor can throw, and that fault gets this boundary's typed code rather than
|
|
870
|
-
// escaping as itself from a verb the caller called for something else.
|
|
871
355
|
function readAll(names) {
|
|
872
356
|
for (var i = 0; i < names.length; i++) {
|
|
873
357
|
try { void opts[names[i]]; }
|
|
@@ -890,20 +374,12 @@ function _settle(opts, E, code, label) {
|
|
|
890
374
|
return opts;
|
|
891
375
|
}
|
|
892
376
|
|
|
893
|
-
// Frozen for the reason the family header gives: a boundary reads its guard off this object at the
|
|
894
|
-
// call, so a writable export would let a caller replace the check rather than pass it.
|
|
895
377
|
module.exports = intrinsic.freeze({
|
|
896
378
|
assertCanonicalOid: assertCanonicalOid,
|
|
897
379
|
assertKnownKeys: assertKnownKeys,
|
|
898
380
|
assertPlainRecord: assertPlainRecord,
|
|
899
381
|
optionsObject: optionsObject,
|
|
900
382
|
refuseAccessorFields: refuseAccessorFields,
|
|
901
|
-
// Exported so a caller that forwards an options bag copies the same surface this module
|
|
902
|
-
// accepts. A narrower enumeration such as `Object.keys` admits a name here and then drops
|
|
903
|
-
// it on the way, which is worse than refusing it. The option is reported valid and then
|
|
904
|
-
// does nothing at the place it was meant to act.
|
|
905
383
|
readableNames: readableNames,
|
|
906
|
-
// Exported for the same reason as its sibling: a caller copying an array has to reach the
|
|
907
|
-
// elements a read reaches, and the own keys are not that set.
|
|
908
384
|
readableIndices: readableIndices
|
|
909
385
|
});
|