@blamejs/pki 0.5.14 → 0.5.16

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/lib/guard-all.js CHANGED
@@ -67,6 +67,7 @@ var compress = require("./guard-compress");
67
67
  var secret = require("./guard-secret");
68
68
  var parsed = require("./guard-parsed");
69
69
  var async_ = require("./guard-async");
70
+ var intrinsic = require("./guard-intrinsic");
70
71
 
71
72
  module.exports = {
72
73
  bytes: bytes,
@@ -85,4 +86,5 @@ module.exports = {
85
86
  secret: secret,
86
87
  parsed: parsed,
87
88
  async: async_,
89
+ intrinsic: intrinsic,
88
90
  };
@@ -1,6 +1,15 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // Copyright (c) blamejs contributors
3
3
  "use strict";
4
+
5
+ // The two settle operations, taken at load and uncurried so the call sites read no property of
6
+ // them. These are how a synchronous fault becomes the rejection this guard promises, so a replaced
7
+ // `reject` returning a resolved promise turns a refusal into a pass at the one place the exit shape
8
+ // is decided. See guard-intrinsic for the whole captured set.
9
+ var _intrinsic = require("./guard-intrinsic");
10
+ var _resolve = _intrinsic.uncurry(_intrinsic.promiseResolve);
11
+ var _reject = _intrinsic.uncurry(_intrinsic.promiseReject);
12
+ var _Promise = Promise;
4
13
  //
5
14
  // @internal -- no operator-facing namespace. The documented surface is every verb whose
6
15
  // @signature says `-> Promise<...>`; this is how each of them refuses.
@@ -29,9 +38,12 @@
29
38
  // test/layer-0-primitives/promise-contract.test.js, which reads every `-> Promise<` @signature out
30
39
  // of lib/ and calls each verb to prove the refusal arrives as a rejection. A new verb is in
31
40
  // scope the day it is documented, so no list here can go stale.
41
+ // Both taken at load. These are how a synchronous fault becomes the rejection this guard promises,
42
+ // so a replaced `reject` returning a resolved promise turns a refusal into a pass at the one place
43
+ // the exit shape is decided. See guard-intrinsic for the whole captured set.
32
44
  function deferred(body) {
33
- try { return Promise.resolve(body()); }
34
- catch (e) { return Promise.reject(e); }
45
+ try { return _resolve(_Promise, body()); }
46
+ catch (e) { return _reject(_Promise, e); }
35
47
  }
36
48
 
37
49
  module.exports = { deferred: deferred };
@@ -9,7 +9,63 @@
9
9
  var async = require("./guard-async");
10
10
  var identifier = require("./guard-identifier");
11
11
  var time = require("./guard-time");
12
- var util = require("util");
12
+ var intrinsic = require("./guard-intrinsic");
13
+ // The slot predicates, snapshotted at load. `util.types` is an ordinary object, so reading a
14
+ // predicate off it at call time would let a caller decide what this guard calls a typed array, a
15
+ // DataView, an ArrayBuffer or a Proxy -- which is every question this module asks about a value it
16
+ // was handed.
17
+ var util = { types: intrinsic.types };
18
+ var _isArray = intrinsic.isArray;
19
+ // The Buffer constructor, taken at load. It is how this module turns a backing store into
20
+ // something the toolkit can read or clear, so one returning a buffer over DIFFERENT memory hands
21
+ // every later step a decoy: a wipe then zeroes the decoy while the plaintext it was aimed at stays
22
+ // readable, and every check in between still passes.
23
+ var _bufferFrom = intrinsic.bufferFrom;
24
+ // The rest of what this module reads from the runtime while it is deciding something. `isView` is
25
+ // how it recognizes the shape whose backing store must be refused when shared, and the reflective
26
+ // operations are how it inspects a value honestly; a replacement for any of them answers the
27
+ // question this guard asked on the caller's behalf. See guard-intrinsic for the whole set.
28
+ var _isView = intrinsic.isView;
29
+ var _isBuffer = intrinsic.isBuffer;
30
+ var _create = intrinsic.create;
31
+ var _getPrototypeOf = intrinsic.getPrototypeOf;
32
+ var _getOwnPropertyDescriptor = intrinsic.getOwnPropertyDescriptor;
33
+ var _defineProperty = intrinsic.defineProperty;
34
+ var _objectKeys = intrinsic.keys;
35
+ var _isExtensible = intrinsic.isExtensible;
36
+ var _ownKeys = intrinsic.ownKeys;
37
+ var _stringify = intrinsic.stringify;
38
+ // The array operations, uncurried. They run on arrays this module owns, so `Array.prototype` is
39
+ // what a caller can still reach; a `forEach` replaced with a no-op makes a walk over real elements
40
+ // report nothing, and whatever is keyed on that walk then passes vacuously.
41
+ var _forEach = intrinsic.forEach;
42
+ var _map = intrinsic.map;
43
+ var _filter = intrinsic.filter;
44
+ var _reTest = intrinsic.uncurry(RegExp.prototype.test);
45
+ var _setForEach = intrinsic.uncurry(Set.prototype.forEach);
46
+ var _mapForEach = intrinsic.uncurry(Map.prototype.forEach);
47
+ var _String = intrinsic.String;
48
+ // The constructor the private copy of a caller's Date is built with. A replacement returns an
49
+ // object of its own choosing, and the snapshot that is supposed to be ours carries the caller's
50
+ // instant only if they let it.
51
+ var _Date = intrinsic.Date;
52
+ var _apply = intrinsic.apply;
53
+ var _promiseFinally = intrinsic.promiseFinally;
54
+ var _ArrayBuffer = intrinsic.ArrayBuffer;
55
+ var _Uint8Array = intrinsic.Uint8Array;
56
+ var _DataView = intrinsic.DataView;
57
+ var _ObjectProto = intrinsic.ObjectProto;
58
+ // The collection operations. The cycle-safe chain walks are a `Set` this module owns, and the copy
59
+ // writes bytes through the typed-array `set`; a replacement for either decides what the walk sees
60
+ // or what the copy contains.
61
+ var _setAdd = intrinsic.setAdd;
62
+ var _setHas = intrinsic.setHas;
63
+ var _mapSet = intrinsic.mapSet;
64
+ var _taSet = intrinsic.typedArraySet;
65
+ var _Set = intrinsic.Set;
66
+ var _Map = intrinsic.Map;
67
+ // Appended by index rather than through `push`, so the growth reads no prototype method at all.
68
+ function _append(arr, v) { _defineProperty(arr, arr.length, { value: v, writable: true, enumerable: true, configurable: true }); }
13
69
 
14
70
  // isByteSource(x) -> boolean: is this one of the four forms the toolkit calls bytes?
15
71
  //
@@ -21,13 +77,13 @@ var util = require("util");
21
77
  // @enforced-by behavioral -- a narrowed restatement of a list has no rename-proof code shape;
22
78
  // the RED vector (a byte form accepted by one door and refused by the other) is the guard.
23
79
  function isByteSource(x) {
24
- return Buffer.isBuffer(x) || ArrayBuffer.isView(x) || _isArrayBuffer(x);
80
+ return _isBuffer(x) || _isView(x) || _isArrayBuffer(x);
25
81
  }
26
82
 
27
83
  // Is this value a byte store, asked of the internal slot rather than the prototype?
28
84
  //
29
85
  // `v instanceof ArrayBuffer` answers what a value inherits from, which is a different question
30
- // from what it holds. `Object.create(ArrayBuffer.prototype)` inherits everything and holds no
86
+ // from what it holds. `_create(ArrayBuffer.prototype)` inherits everything and holds no
31
87
  // bytes, so it passes and the read that follows throws a raw TypeError out of a boundary whose
32
88
  // contract is a typed error. The same test also misses a real buffer from another realm, whose
33
89
  // prototype is that realm's. `util.types` reads the slot, so both answers come out right.
@@ -48,35 +104,30 @@ function _isArrayBuffer(v) {
48
104
  // The getters are taken off the prototypes the language installs them on and called against the
49
105
  // view, which reaches the internal slot whatever the value's own class says. A subclass override
50
106
  // is then what it is -- a property of the caller's object -- and answers no question asked here.
51
- var _TYPED_ARRAY_PROTO = Object.getPrototypeOf(Uint8Array.prototype);
107
+ var _TYPED_ARRAY_PROTO = _getPrototypeOf(Uint8Array.prototype);
52
108
 
53
- function _intrinsicGetter(proto, name, who) {
54
- var d = Object.getOwnPropertyDescriptor(proto, name);
55
- if (!d || typeof d.get !== "function") {
56
- throw new TypeError("guard.bytes: this runtime has no intrinsic " + who + "." + name +
57
- " accessor, so a view's backing store cannot be read without invoking the value's own");
58
- }
59
- return d.get;
60
- }
61
-
62
- var _taBuffer = _intrinsicGetter(_TYPED_ARRAY_PROTO, "buffer", "%TypedArray%.prototype");
63
- var _taByteOffset = _intrinsicGetter(_TYPED_ARRAY_PROTO, "byteOffset", "%TypedArray%.prototype");
64
- var _taByteLength = _intrinsicGetter(_TYPED_ARRAY_PROTO, "byteLength", "%TypedArray%.prototype");
65
- var _dvBuffer = _intrinsicGetter(DataView.prototype, "buffer", "DataView.prototype");
66
- var _dvByteOffset = _intrinsicGetter(DataView.prototype, "byteOffset", "DataView.prototype");
67
- var _dvByteLength = _intrinsicGetter(DataView.prototype, "byteLength", "DataView.prototype");
109
+ // Uncurried as they are captured, so the reads below invoke them directly. A getter taken off a
110
+ // prototype is still reachable there, and an own `call` assigned to it would shadow
111
+ // `Function.prototype.call` and hand back whatever store, offset and length a caller chose. The
112
+ // capture and the refusal for a runtime that lacks the accessor both live in guard-intrinsic, so
113
+ // every guard measuring a view measures it the same way.
114
+ var _uncurriedGetter = intrinsic.getter;
115
+ var _taBuffer = _uncurriedGetter(_TYPED_ARRAY_PROTO, "buffer", "%TypedArray%.prototype");
116
+ var _taByteOffset = _uncurriedGetter(_TYPED_ARRAY_PROTO, "byteOffset", "%TypedArray%.prototype");
117
+ var _dvBuffer = _uncurriedGetter(DataView.prototype, "buffer", "DataView.prototype");
118
+ var _dvByteOffset = _uncurriedGetter(DataView.prototype, "byteOffset", "DataView.prototype");
68
119
 
69
120
  // A DataView carries its own accessors rather than the typed-array ones, so the pair is chosen by
70
121
  // the value's slot. Either getter refuses a receiver with no slot behind it, which is the same
71
122
  // refusal a detached store gets, and every caller here already types that.
72
- function _storeOf(v) { return util.types.isDataView(v) ? _dvBuffer.call(v) : _taBuffer.call(v); }
73
- function _offsetOf(v) { return util.types.isDataView(v) ? _dvByteOffset.call(v) : _taByteOffset.call(v); }
74
- function _lengthOf(v) { return util.types.isDataView(v) ? _dvByteLength.call(v) : _taByteLength.call(v); }
123
+ function _storeOf(v) { return util.types.isDataView(v) ? _dvBuffer(v) : _taBuffer(v); }
124
+ function _offsetOf(v) { return util.types.isDataView(v) ? _dvByteOffset(v) : _taByteOffset(v); }
125
+ function _lengthOf(v) { return intrinsic.sizeOf(v); }
75
126
 
76
127
  // The Buffer over a view's own bytes. The single place this module turns a view into a Buffer, so
77
128
  // the intrinsic reads above cannot be skipped at one of the two call sites and kept at the other.
78
129
  function _reView(v) {
79
- return Buffer.from(_storeOf(v), _offsetOf(v), _lengthOf(v));
130
+ return _bufferFrom(_storeOf(v), _offsetOf(v), _lengthOf(v));
80
131
  }
81
132
 
82
133
  // Which concrete typed-array kind a value is, decided by its slot and answered with this realm's
@@ -97,13 +148,21 @@ function _reView(v) {
97
148
  // `util.types` is an ordinary object: replacing a predicate on it after this module loads would
98
149
  // hand the kind decision, and with it the constructor the copy is built from, to whoever did.
99
150
  // Reading it once at load leaves nothing to replace.
100
- var _CONCRETE_KINDS = Object.keys(util.types)
101
- .filter(function (name) { return /^is[A-Za-z0-9]+Array$/.test(name); })
102
- .map(function (name) { return [util.types[name], globalThis[name.slice(2)]]; })
103
- .filter(function (row) {
151
+ // The two string operations in this table run AT LOAD, in the same statement that reads
152
+ // `util.types` once and for the same reason. Nothing a caller can replace has run yet, so there is
153
+ // no live read to remove; capturing them would only move the question one line earlier.
154
+ var _CONCRETE_KINDS = _filter(
155
+ _map(
156
+ // allow:guard-reads-runtime-live -- module-init, see above
157
+ _filter(_objectKeys(util.types), function (name) { return _reTest(/^is[A-Za-z0-9]+Array$/, name); }),
158
+ // allow:guard-reads-runtime-live -- module-init, see above
159
+ function (name) { return [util.types[name], globalThis[name.slice(2)]]; }
160
+ ),
161
+ function (row) {
104
162
  return typeof row[0] === "function" && typeof row[1] === "function" &&
105
163
  typeof row[1].BYTES_PER_ELEMENT === "number" && row[1].BYTES_PER_ELEMENT > 0;
106
- });
164
+ }
165
+ );
107
166
 
108
167
  function _concreteKindOf(v) {
109
168
  for (var i = 0; i < _CONCRETE_KINDS.length; i++) {
@@ -116,11 +175,11 @@ function _concreteKindOf(v) {
116
175
  // `v.constructor.name` is two ordinary property reads a caller answers: a getter under either one
117
176
  // took the refusal below out through the caller's exception, in place of the typed error whose
118
177
  // whole purpose here is to say why the value was refused.
119
- var _NAMED_KINDS = [
178
+ var _NAMED_KINDS = _filter([
120
179
  ["isNativeError", "Error"], ["isRegExp", "RegExp"], ["isPromise", "Promise"],
121
180
  ["isWeakMap", "WeakMap"], ["isWeakSet", "WeakSet"], ["isMap", "Map"], ["isSet", "Set"],
122
181
  ["isDate", "Date"], ["isProxy", "Proxy"]
123
- ].filter(function (row) { return typeof util.types[row[0]] === "function"; });
182
+ ], function (row) { return typeof util.types[row[0]] === "function"; });
124
183
 
125
184
  function _kindName(v) {
126
185
  for (var i = 0; i < _NAMED_KINDS.length; i++) {
@@ -129,7 +188,7 @@ function _kindName(v) {
129
188
  return typeof v === "function" ? "function" : "value";
130
189
  }
131
190
 
132
- function _article(name) { return /^[AEIOU]/i.test(name) ? "an" : "a"; }
191
+ function _article(name) { return _reTest(/^[AEIOU]/i, name) ? "an" : "a"; }
133
192
 
134
193
  // outputView(input, ErrorClass, code, label) -> a Buffer aliasing a caller's view, for WRITING.
135
194
  //
@@ -145,7 +204,7 @@ function _article(name) { return /^[AEIOU]/i.test(name) ? "an" : "a"; }
145
204
  // @enforced-by behavioral -- an input door reaching for this instead of `view` has no rename-proof
146
205
  // code shape; the RED vectors (a shared view filled here, and a detached one refused) are the guard.
147
206
  function outputView(input, ErrorClass, code, label) {
148
- if (!util.types.isUint8Array(input) && !ArrayBuffer.isView(input)) {
207
+ if (!util.types.isUint8Array(input) && !_isView(input)) {
149
208
  throw _raise(ErrorClass, code, label + ": expected a Buffer / TypedArray to write into");
150
209
  }
151
210
  try {
@@ -159,7 +218,7 @@ function outputView(input, ErrorClass, code, label) {
159
218
  //
160
219
  // For the boundaries that size a value rather than read it: a response-body cap, an emptiness
161
220
  // test. `length` is an accessor on the shared typed-array prototype AND shadowable by an own
162
- // property on any instance, so `Object.defineProperty(buf, "length", { get: () => 0 })` answers
221
+ // property on any instance, so `_defineProperty(buf, "length", { get: () => 0 })` answers
163
222
  // for a Buffer holding megabytes. A cap measured that way is a cap its caller sets.
164
223
  // @enforced-by behavioral -- `x.length` is the ordinary spelling wherever the value is this
165
224
  // toolkit's own, so the misuse has no rename-proof code shape; the RED vector (a planted `length`
@@ -178,7 +237,7 @@ function lengthOf(view) {
178
237
  // container" about a container that plainly holds bytes reads as the toolkit being wrong.
179
238
  function _refuseShared(v, ErrorClass, code, label) {
180
239
  if (util.types.isSharedArrayBuffer(v) ||
181
- (ArrayBuffer.isView(v) && util.types.isSharedArrayBuffer(_storeOf(v)))) {
240
+ (_isView(v) && util.types.isSharedArrayBuffer(_storeOf(v)))) {
182
241
  throw _raise(ErrorClass, code, label + ": shared memory cannot be used here, because another " +
183
242
  "thread can rewrite it after it has been checked; pass a Buffer or a Uint8Array over " +
184
243
  "memory this process owns");
@@ -192,7 +251,7 @@ function _refuseShared(v, ErrorClass, code, label) {
192
251
  //
193
252
  // Defends the detached-buffer fail-OPEN: a transferred / structuredClone'd
194
253
  // Buffer or view has a detached backing ArrayBuffer and reads as ZERO-LENGTH.
195
- // An identity fast-path (`Buffer.isBuffer(x) return x`) that skips the re-view
254
+ // An identity fast-path (`_isBuffer(x) return x`) that skips the re-view
196
255
  // hands the caller an empty buffer, so a downstream digest / signature / parse
197
256
  // silently processes EMPTY input instead of failing (CWE-20 improper input
198
257
  // validation feeding a CWE-347-style verification-of-nothing). Always re-viewing
@@ -218,8 +277,24 @@ function _refuseShared(v, ErrorClass, code, label) {
218
277
  // would otherwise have to hand-roll the re-view to reach this guard at all, which is precisely what
219
278
  // the re-inline detector forbids, so accept either: a class (its prototype is an Error) is
220
279
  // constructed, anything else is called.
280
+ // Whether E's instances would be Errors, decided by walking the prototype chain with the captured
281
+ // `getPrototypeOf` rather than by `instanceof`, which asks `Error[Symbol.hasInstance]` at call time.
282
+ // The walk carries the same visited set _protoChainIsCyclic uses, because a Proxy can report a
283
+ // cyclic chain and an unbounded walk would hang here rather than at the boundary that refuses one.
284
+ var _ErrorProto = Error.prototype;
285
+ function _isErrorClass(E) {
286
+ if (typeof E !== "function") return false;
287
+ var seen = new _Set();
288
+ for (var p = E.prototype; p !== null && typeof p === "object"; p = _getPrototypeOf(p)) {
289
+ if (p === _ErrorProto) return true;
290
+ if (_setHas(seen, p)) return false;
291
+ _setAdd(seen, p);
292
+ }
293
+ return false;
294
+ }
295
+
221
296
  function _raise(E, code, message, cause) {
222
- return (E.prototype instanceof Error) ? new E(code, message, cause) : E(code, message, cause);
297
+ return _isErrorClass(E) ? new E(code, message, cause) : E(code, message, cause);
223
298
  }
224
299
 
225
300
  // view(input, ErrorClass, code, label) -> Buffer view | throws ErrorClass(code, msg, cause)
@@ -228,7 +303,7 @@ function _raise(E, code, message, cause) {
228
303
  // threaded as the cause).
229
304
  // The kind is read from the slot. A prototype test turns away a real Uint8Array built in another
230
305
  // realm, whose prototype is that realm's, and tells the caller their bytes are not bytes. It
231
- // admits the mirror shape, `Object.create(Uint8Array.prototype)`, which holds none; that one comes
306
+ // admits the mirror shape, `_create(Uint8Array.prototype)`, which holds none; that one comes
232
307
  // back as this guard's own code either way, since the read below is wrapped, so reading the slot
233
308
  // only moves the refusal to the door from the failing read.
234
309
  // @enforced-by guard-shape-reinlined
@@ -261,9 +336,9 @@ function view(input, ErrorClass, code, label) {
261
336
  function source(input, ErrorClass, code, label) {
262
337
  _refuseShared(input, ErrorClass, code, label);
263
338
  var isAb = _isArrayBuffer(input);
264
- if (isAb || ArrayBuffer.isView(input)) {
339
+ if (isAb || _isView(input)) {
265
340
  try {
266
- return isAb ? Buffer.from(input) : _reView(input);
341
+ return isAb ? _bufferFrom(input) : _reView(input);
267
342
  } catch (e) {
268
343
  throw _raise(ErrorClass, code, label + ": input is not a usable byte source (detached backing buffer?)", e);
269
344
  }
@@ -292,7 +367,7 @@ function source(input, ErrorClass, code, label) {
292
367
  // that mutates the caller's buffer between parse and verify and asserts the
293
368
  // verdict still describes the bytes that were verified.
294
369
  function snapshot(input, ErrorClass, code, label) {
295
- return Buffer.from(view(input, ErrorClass, code, label));
370
+ return _bufferFrom(view(input, ErrorClass, code, label));
296
371
  }
297
372
 
298
373
  // snapshotSource(input, ErrorClass, code, label) -> private Buffer copy | throws
@@ -304,7 +379,7 @@ function snapshot(input, ErrorClass, code, label) {
304
379
  // @enforced-by behavioral -- a copy has no rename-proof shape to detect; the guard
305
380
  // is the RED vector that mutates the caller's backing buffer across the await.
306
381
  function snapshotSource(input, ErrorClass, code, label) {
307
- return Buffer.from(source(input, ErrorClass, code, label));
382
+ return _bufferFrom(source(input, ErrorClass, code, label));
308
383
  }
309
384
 
310
385
  // snapshotDeep(value, ErrorClass, code, label) -> a private copy of every byte leaf | throws
@@ -369,8 +444,8 @@ function snapshotDeep(value, ErrorClass, code, label, opts) {
369
444
  // `Symbol.toStringTag` is on every surface: it is the language's own name for what a value is, a
370
445
  // key handle carries it as a non-enumerable own property, and it answers no named option.
371
446
  function _surface(names) {
372
- var t = Object.create(null);
373
- names.forEach(function (n) { t[n] = 1; });
447
+ var t = _create(null);
448
+ _forEach(names, function (n) { t[n] = 1; });
374
449
  t[Symbol.toStringTag] = 1;
375
450
  return t;
376
451
  }
@@ -399,20 +474,26 @@ var _THENABLE_SURFACE = _surface(["then", "catch", "finally"]);
399
474
  // object literal is never opaque whatever it looks like: it is data this module can read and copy,
400
475
  // and isCryptoKeyLike is structural by design so a literal can wear the key shape.
401
476
  function _opaqueSurface(v, ErrorClass, code, label) {
402
- var proto = Object.getPrototypeOf(v);
403
- if (proto === Object.prototype || proto === null) return null;
404
- if (util.types.isWeakMap(v) || util.types.isWeakSet(v)) return {}; // deliberately not enumerable
405
- if (v instanceof Error) return _ERROR_SURFACE;
477
+ var proto = _getPrototypeOf(v);
478
+ if (proto === _ObjectProto || proto === null) return null;
479
+ // Deliberately empty, and null-prototype so it stays empty: this surface is the allowed-field set
480
+ // for a value with no enumerable contents, and on a `{}` a planted `Object.prototype[name]` reads
481
+ // back as an allowed field, so a mutable one the caller added would pass the refusal.
482
+ if (util.types.isWeakMap(v) || util.types.isWeakSet(v)) return _create(null);
483
+ // The slot, not the prototype. This picks which surface an opaque object is copied through, and
484
+ // `instanceof` asks `Error[Symbol.hasInstance]`, which a caller can answer. It also admits a real
485
+ // Error from another realm, whose prototype is that realm's and which the prototype test refuses.
486
+ if (util.types.isNativeError(v)) return _ERROR_SURFACE;
406
487
  if (util.types.isRegExp(v)) return _REGEXP_SURFACE;
407
488
  // A node:crypto KeyObject, read off its internal slot. `pki.hpke` documents one as a key input
408
489
  // and `pki.ct` names it too, and a copy of a key handle is not a key: its material lives behind
409
490
  // the slot, so what the copy holds is the shape of a key and none of the key. Recognized here so
410
491
  // it reaches the verb as itself, which is the same treatment a WebCrypto CryptoKey gets.
411
492
  // `util.types.isKeyObject` reads the slot, so it answers for a handle from any realm and says no
412
- // to `Object.create(KeyObject.prototype)`.
493
+ // to `_create(KeyObject.prototype)`.
413
494
  if (util.types.isKeyObject(v)) return _CRYPTO_KEY_SURFACE;
414
495
  // Asking whether it is key-shaped reads its properties, and a value wearing a key's prototype
415
- // without a key behind it answers with a getter that throws: `Object.create(KeyObject.prototype)`
496
+ // without a key behind it answers with a getter that throws: `_create(KeyObject.prototype)`
416
497
  // raises a raw TypeError from inside `type`. Typed here, like the `then` read below, so a
417
498
  // question this module asked on its own behalf cannot escape as somebody else's error.
418
499
  var keyLike;
@@ -451,17 +532,17 @@ function _opaqueSurface(v, ErrorClass, code, label) {
451
532
  // call and change what an inherited name answers. That is true of every value passed by reference,
452
533
  // and a platform object's prototype is the platform's.
453
534
  function _canChangeAfterTheCheck(v, name) {
454
- var visited = new Set();
455
- for (var o = v; o && !visited.has(o); o = Object.getPrototypeOf(o)) {
456
- visited.add(o);
457
- var d = Object.getOwnPropertyDescriptor(o, name);
535
+ var visited = new _Set();
536
+ for (var o = v; o && !_setHas(visited, o); o = _getPrototypeOf(o)) {
537
+ _setAdd(visited, o);
538
+ var d = _getOwnPropertyDescriptor(o, name);
458
539
  if (!d) continue;
459
540
  if (d.get || d.set || d.writable || d.configurable) return true;
460
541
  // Settled where it sits. Reached through the chain it is settled only while nothing can be put
461
542
  // in front of it: an extensible receiver takes an own property of the same name at any time,
462
543
  // and the read then answers with that one. Own on the value itself, or a value nothing can be
463
544
  // added to, is the case where what was read is what stays.
464
- return o !== v && Object.isExtensible(v);
545
+ return o !== v && _isExtensible(v);
465
546
  }
466
547
  return false;
467
548
  }
@@ -541,13 +622,18 @@ function _opaqueFieldOutsideSurface(v, surface, ErrorClass, code, label, depth)
541
622
  // field takes, so the copy preserves the type and the validator still sees what it was given.
542
623
  function _copyBytesSameKind(v, ErrorClass, code, label, collect) {
543
624
  var src = source(v, ErrorClass, code, label); // re-views; a detached backing store is refused
544
- var owned = new ArrayBuffer(src.length);
545
- new Uint8Array(owned).set(src);
625
+ // Sized once, from the slot. `src.length` is a replaceable accessor, and it decides three things
626
+ // here at once: how large the private store is, how much of it the returned view covers, and how
627
+ // much of it goes on the wipe list. A number smaller than the truth puts a short Buffer on that
628
+ // list, so `release` clears the front of a copy that still holds the rest of the secret.
629
+ var srcLen = _lengthOf(src);
630
+ var owned = new _ArrayBuffer(srcLen);
631
+ _taSet(new _Uint8Array(owned), src);
546
632
  // What `release` clears: a Buffer over the whole private store, whatever kind is handed back.
547
- if (collect) collect.push(Buffer.from(owned, 0, src.length));
548
- if (Buffer.isBuffer(v)) return Buffer.from(owned, 0, src.length);
633
+ if (collect) _append(collect, _bufferFrom(owned, 0, srcLen));
634
+ if (_isBuffer(v)) return _bufferFrom(owned, 0, srcLen);
549
635
  if (_isArrayBuffer(v)) return owned;
550
- if (util.types.isDataView(v)) return new DataView(owned);
636
+ if (util.types.isDataView(v)) return new _DataView(owned);
551
637
  // The kind comes from the value's slot, never from `v.constructor` or `v.BYTES_PER_ELEMENT`.
552
638
  // Both are ordinary properties a subclass answers: a `constructor` that threw took this module
553
639
  // out through the caller's own exception, and a `BYTES_PER_ELEMENT` that lied built the copy
@@ -558,7 +644,7 @@ function _copyBytesSameKind(v, ErrorClass, code, label, collect) {
558
644
  (util.types.isTypedArray(v) ? "typed array of a kind this runtime added" : "byte view") +
559
645
  " cannot be copied while keeping its kind; pass a Buffer or a Uint8Array");
560
646
  }
561
- return new Ctor(owned, 0, src.length / Ctor.BYTES_PER_ELEMENT);
647
+ return new Ctor(owned, 0, srcLen / Ctor.BYTES_PER_ELEMENT);
562
648
  }
563
649
 
564
650
  // Is this value's prototype chain cyclic? A Proxy whose `getPrototypeOf` trap returns the proxy
@@ -572,10 +658,10 @@ function _copyBytesSameKind(v, ErrorClass, code, label, collect) {
572
658
  // Naming the shape is the fail-closed answer. An options bag cannot need a prototype chain that
573
659
  // loops, and copying one has no meaning to fall back to.
574
660
  function _protoChainIsCyclic(v) {
575
- var visited = new Set();
576
- for (var o = v; o; o = Object.getPrototypeOf(o)) {
577
- if (visited.has(o)) return true;
578
- visited.add(o);
661
+ var visited = new _Set();
662
+ for (var o = v; o; o = _getPrototypeOf(o)) {
663
+ if (_setHas(visited, o)) return true;
664
+ _setAdd(visited, o);
579
665
  }
580
666
  return false;
581
667
  }
@@ -584,9 +670,9 @@ function _protoChainIsCyclic(v) {
584
670
  // above a plain object decides what the copy takes while the original answers reads from its
585
671
  // `get` trap. Testing only the value handed in leaves that one line of indirection open.
586
672
  function _protoChainHasProxy(v) {
587
- var visited = new Set();
588
- for (var o = v; o && !visited.has(o); o = Object.getPrototypeOf(o)) {
589
- visited.add(o);
673
+ var visited = new _Set();
674
+ for (var o = v; o && !_setHas(visited, o); o = _getPrototypeOf(o)) {
675
+ _setAdd(visited, o);
590
676
  if (util.types.isProxy(o)) return true;
591
677
  }
592
678
  return false;
@@ -594,7 +680,7 @@ function _protoChainHasProxy(v) {
594
680
 
595
681
  // Give the copy of a collection the same prototype the original carries.
596
682
  //
597
- // The object branch does this with `Object.create(Object.getPrototypeOf(v))`, so an instance of a
683
+ // The object branch does this with `_create(_getPrototypeOf(v))`, so an instance of a
598
684
  // caller's class keeps its methods. A collection branch builds a plain `[]`, `Map` or `Set`, and
599
685
  // a subclass of one holds its additions on a prototype above that. Copying the chain down onto a
600
686
  // plain array turns `class Opts extends Array { describe() {} }` into an array with `describe` as
@@ -646,7 +732,7 @@ function _deep(v, ErrorClass, code, label, cap, depth, collect) {
646
732
  throw _raise(ErrorClass, code, label + ": its prototype chain is a cycle, so it cannot be " +
647
733
  "read or copied; pass a plain object");
648
734
  }
649
- if (Buffer.isBuffer(v) || ArrayBuffer.isView(v) || _isArrayBuffer(v)) {
735
+ if (_isBuffer(v) || _isView(v) || _isArrayBuffer(v)) {
650
736
  var bytesCopy = _copyBytesSameKind(v, ErrorClass, code, label, collect);
651
737
  // A byte value can carry named properties too, and a verb reads an option by name whatever the
652
738
  // argument's type: `opts = new Uint8Array(0); opts.pem = true` is an options object as far as
@@ -678,11 +764,11 @@ function _deep(v, ErrorClass, code, label, cap, depth, collect) {
678
764
  // signing time was encoded. Normalizing the prototype does not reach an own shadow, so the
679
765
  // shadow is left behind here. The excluded set is read off `Date.prototype` rather than
680
766
  // written out, so it cannot fall behind the language.
681
- var dateCopy = new Date(time.instantOf(v));
767
+ var dateCopy = new _Date(time.instantOf(v));
682
768
  _copyNamed(v, dateCopy, ErrorClass, code, label, cap, depth, collect, _DATE_BEHAVIOR);
683
769
  return _plainCopy(dateCopy);
684
770
  }
685
- if (Array.isArray(v)) {
771
+ if (_isArray(v)) {
686
772
  var arr = [];
687
773
  // The indices a read on the array resolves, rather than a count from zero to `length`. An
688
774
  // array is sparse whenever a caller sets a high index or assigns `length`, and
@@ -705,7 +791,7 @@ function _deep(v, ErrorClass, code, label, cap, depth, collect) {
705
791
  // it pays, an element answering as a trusted signer to the check and as another afterwards.
706
792
  // The argument itself, not everything under it, matching the rule for names.
707
793
  if (depth === 0) identifier.refuseAccessorFields(v, indices, indexE, code, label);
708
- indices.forEach(function (k) {
794
+ _forEach(indices, function (k) {
709
795
  // Reading an element can run a caller's accessor, the same as reading a named field: an
710
796
  // index can carry a getter too, and one that threw escaped as itself from a boundary whose
711
797
  // contract is a typed error. Typed here with the raw fault as its cause, as the named walk
@@ -735,15 +821,15 @@ function _deep(v, ErrorClass, code, label, cap, depth, collect) {
735
821
  var carried = _opaqueFieldOutsideSurface(v, surface, ErrorClass, code, label);
736
822
  if (carried === null) return v;
737
823
  throw _raise(ErrorClass, code, label + ": " + _article(_kindName(v)) + " " + _kindName(v) +
738
- " carrying its own field " + JSON.stringify(String(carried)) + " cannot be used here -- its " +
824
+ " carrying its own field " + _stringify(_String(carried)) + " cannot be used here -- its " +
739
825
  "state cannot be copied, so that field would stay changeable after it was checked; pass the " +
740
826
  "fields as a plain object");
741
827
  }
742
828
  if (util.types.isMap(v)) {
743
- return _plainCopy(_copyEntries(v, new Map(), ErrorClass, code, label, cap, depth, collect));
829
+ return _plainCopy(_copyEntries(v, new _Map(), ErrorClass, code, label, cap, depth, collect));
744
830
  }
745
831
  if (util.types.isSet(v)) {
746
- return _plainCopy(_copyEntries(v, new Set(), ErrorClass, code, label, cap, depth, collect));
832
+ return _plainCopy(_copyEntries(v, new _Set(), ErrorClass, code, label, cap, depth, collect));
747
833
  }
748
834
  // A plain object, or a dictionary with no prototype at all -- never the caller's class.
749
835
  //
@@ -752,11 +838,11 @@ function _deep(v, ErrorClass, code, label, cap, depth, collect) {
752
838
  // begun. The names the copy reports do not depend on it, which the vectors measure rather than
753
839
  // assume, and no verb calls a method on an options bag.
754
840
  //
755
- // Having NO prototype is different and is kept. `Object.create(null)` and what `JSON.parse`
841
+ // Having NO prototype is different and is kept. `_create(null)` and what `JSON.parse`
756
842
  // produces inherit nothing, and a copy that gained `Object.prototype` would inherit whatever a
757
843
  // runtime has planted there -- names the original never answered, reported against a caller who
758
844
  // never wrote them.
759
- var out = Object.create(Object.getPrototypeOf(v) === null ? null : Object.prototype);
845
+ var out = _create(_getPrototypeOf(v) === null ? null : _ObjectProto);
760
846
  _copyNamed(v, out, ErrorClass, code, label, cap, depth, collect);
761
847
  return out;
762
848
  }
@@ -782,7 +868,7 @@ function _deep(v, ErrorClass, code, label, cap, depth, collect) {
782
868
  // One walk answers for both questions, because a second walk here drifts from it and the two then
783
869
  // disagree about one value. A walk that stops at whatever object is identical to `Object.prototype`
784
870
  // reads a foreign realm's root as caller data and copies `__proto__` down as a field. One that
785
- // reads every level outside a collection gives `Object.create(Array.prototype)` an own `length`
871
+ // reads every level outside a collection gives `_create(Array.prototype)` an own `length`
786
872
  // and `Symbol.unscopables`. Either way the copy holds a different set than the check accepted, and
787
873
  // a bag that passes the check is refused once it has been copied.
788
874
  //
@@ -810,12 +896,14 @@ function _copyEntries(src, dst, ErrorClass, code, label, cap, depth, collect) {
810
896
  // The walk uses the intrinsic `forEach`, called against the collection. `forEach` is an ordinary
811
897
  // method on `Map.prototype` and `Set.prototype`, so an own one or a subclass's answers instead:
812
898
  // one that threw took this module out through the caller's own exception, and one that yielded
813
- // different entries filled the copy with something other than what the collection holds.
814
- var walk = util.types.isSet(src) ? Set.prototype.forEach : Map.prototype.forEach;
815
- walk.call(src, function (value, key) {
899
+ // different entries filled the copy with something other than what the collection holds. Both are
900
+ // taken at load and invoked uncurried, so neither the method nor the `call` that reaches it is
901
+ // read off a prototype while a caller is in a position to have replaced it.
902
+ var walk = util.types.isSet(src) ? _setForEach : _mapForEach;
903
+ walk(src, function (value, key) {
816
904
  var copiedValue = _deep(value, ErrorClass, code, label, cap, depth + 1, collect);
817
- if (util.types.isSet(dst)) dst.add(copiedValue);
818
- else dst.set(_deep(key, ErrorClass, code, label, cap, depth + 1, collect), copiedValue);
905
+ if (util.types.isSet(dst)) _setAdd(dst, copiedValue);
906
+ else _mapSet(dst, _deep(key, ErrorClass, code, label, cap, depth + 1, collect), copiedValue);
819
907
  });
820
908
  _copyNamed(src, dst, ErrorClass, code, label, cap, depth, collect);
821
909
  return dst;
@@ -832,8 +920,8 @@ function _copyEntries(src, dst, ErrorClass, code, label, cap, depth, collect) {
832
920
  // The names `Date.prototype` supplies, read off the language rather than written out, so a method
833
921
  // the language gains later is behavior here on the day it lands.
834
922
  var _DATE_BEHAVIOR = (function () {
835
- var t = Object.create(null);
836
- Reflect.ownKeys(Date.prototype).forEach(function (n) { t[n] = 1; });
923
+ var t = _create(null);
924
+ _forEach(_ownKeys(Date.prototype), function (n) { t[n] = 1; });
837
925
  return t;
838
926
  })();
839
927
 
@@ -849,7 +937,7 @@ function _copyNamed(src, dst, ErrorClass, code, label, cap, depth, collect, beha
849
937
  // like any other: the fault gets this boundary's typed code with the raw error as its cause,
850
938
  // and never escapes as itself from inside a verb the caller called for something else.
851
939
  try { value = src[keys[k]]; }
852
- catch (e) { throw _raise(ErrorClass, code, label + ": reading " + JSON.stringify(keys[k]) + " threw", e); }
940
+ catch (e) { throw _raise(ErrorClass, code, label + ": reading " + _stringify(keys[k]) + " threw", e); }
853
941
  // A name the destination's KIND already defines, holding a FUNCTION, is a shadow of that
854
942
  // kind's own method: copying it down would make the copy answer with the caller's code where
855
943
  // the original answered with the language's. The value decides, not the name -- a plain
@@ -860,7 +948,7 @@ function _copyNamed(src, dst, ErrorClass, code, label, cap, depth, collect, beha
860
948
  // still carried. Dropping it changed what the caller passed: an unknown spec
861
949
  // field whose value happened to be a function stopped reaching the verb's own key check, so a
862
950
  // typo that used to be refused was silently accepted.
863
- Object.defineProperty(dst, keys[k], {
951
+ _defineProperty(dst, keys[k], {
864
952
  value: typeof value === "function" ? value
865
953
  : _deep(value, ErrorClass, code, label, cap, depth + 1, collect),
866
954
  writable: true, enumerable: _wasEnumerable(src, keys[k]), configurable: true,
@@ -871,8 +959,8 @@ function _copyNamed(src, dst, ErrorClass, code, label, cap, depth, collect, beha
871
959
  // Whether a name lookup on `v` would have found this property as an enumerable one, anywhere on
872
960
  // the chain -- so the copy's own keys enumerate the way the original's did.
873
961
  function _wasEnumerable(v, name) {
874
- for (var o = v; o && o !== Object.prototype; o = Object.getPrototypeOf(o)) {
875
- var d = Object.getOwnPropertyDescriptor(o, name);
962
+ for (var o = v; o && o !== _ObjectProto; o = _getPrototypeOf(o)) {
963
+ var d = _getOwnPropertyDescriptor(o, name);
876
964
  if (d) return !!d.enumerable;
877
965
  }
878
966
  return false;
@@ -908,7 +996,7 @@ function fixArguments(ErrorClass, code, args) {
908
996
  }
909
997
  try {
910
998
  for (var i = 0; i < args.length; i++) {
911
- values.push(snapshotDeep(args[i][0], ErrorClass, code, args[i][1], { collect: copies }));
999
+ _append(values, snapshotDeep(args[i][0], ErrorClass, code, args[i][1], { collect: copies }));
912
1000
  }
913
1001
  } catch (e) {
914
1002
  // The copying itself can fail partway (a detached leaf, a structure past the depth cap, a
@@ -936,10 +1024,12 @@ function fixArguments(ErrorClass, code, args) {
936
1024
  // including a fault raised by the copy itself) and the per-verb entry-value vectors.
937
1025
  function fixedCall(ErrorClass, code, args, body) {
938
1026
  var handle = null;
939
- return async.deferred(function () {
1027
+ // Both halves through captures. `body.apply` and `.finally` are prototype reads, and between them
1028
+ // they decide whether the verb runs and whether the copies it was handed are ever cleared.
1029
+ return _promiseFinally(async.deferred(function () {
940
1030
  handle = fixArguments(ErrorClass, code, args);
941
- return body.apply(null, handle.values);
942
- }).finally(function () { if (handle) handle.release(); });
1031
+ return _apply(body, null, handle.values);
1032
+ }), function () { if (handle) handle.release(); });
943
1033
  }
944
1034
 
945
1035
  module.exports = {