fast-check
Version:
Property based testing framework for JavaScript (like QuickCheck)
1,698 lines • 350 kB
JavaScript
import { t as __exportAll } from "./chunk-pbuEa-1d.js";
import { congruential32 } from "pure-rand/generator/congruential32";
import { mersenne } from "pure-rand/generator/mersenne";
import { xorshift128plus } from "pure-rand/generator/xorshift128plus";
import { xoroshiro128plus } from "pure-rand/generator/xoroshiro128plus";
import { skipN } from "pure-rand/utils/skipN";
import { uniformBigInt } from "pure-rand/distribution/uniformBigInt";
import { uniformInt } from "pure-rand/distribution/uniformInt";
//#region src/check/precondition/PreconditionFailure.ts
/** @internal */
const SharedFootPrint = Symbol.for("fast-check/PreconditionFailure");
/**
* Error type produced whenever a precondition fails
* @remarks Since 2.2.0
* @public
*/
var PreconditionFailure = class extends Error {
constructor(interruptExecution = false) {
super();
this.interruptExecution = interruptExecution;
this.footprint = SharedFootPrint;
}
static isFailure(err) {
return err !== null && err !== void 0 && err.footprint === SharedFootPrint;
}
};
//#endregion
//#region src/check/precondition/Pre.ts
/**
* Add pre-condition checks inside a property execution
* @param expectTruthy - cancel the run whenever this value is falsy
* @remarks Since 1.3.0
* @public
*/
function pre(expectTruthy) {
if (!expectTruthy) throw new PreconditionFailure();
}
//#endregion
//#region src/stream/StreamHelpers.ts
var Nil = class {
[Symbol.iterator]() {
return this;
}
next(value) {
return {
value,
done: true
};
}
};
/** @internal */
const nil = new Nil();
/** @internal */
function nilHelper() {
return nil;
}
/** @internal */
function* mapHelper(g, f) {
for (const v of g) yield f(v);
}
/** @internal */
function* flatMapHelper(g, f) {
for (const v of g) yield* f(v);
}
/** @internal */
function* filterHelper(g, f) {
for (const v of g) if (f(v)) yield v;
}
/** @internal */
function* takeNHelper(g, n) {
for (let i = 0; i < n; ++i) {
const cur = g.next();
if (cur.done) break;
yield cur.value;
}
}
/** @internal */
function* takeWhileHelper(g, f) {
let cur = g.next();
while (!cur.done && f(cur.value)) {
yield cur.value;
cur = g.next();
}
}
/** @internal */
function* joinHelper(g, others) {
for (let cur = g.next(); !cur.done; cur = g.next()) yield cur.value;
for (const s of others) for (let cur = s.next(); !cur.done; cur = s.next()) yield cur.value;
}
//#endregion
//#region src/stream/Stream.ts
const safeSymbolIterator$1 = Symbol.iterator;
/**
* Wrapper around `IterableIterator` interface
* offering a set of helpers to deal with iterations in a simple way
*
* @remarks Since 0.0.7
* @public
*/
var Stream = class Stream {
/**
* Create an empty stream of T
* @remarks Since 0.0.1
*/
static nil() {
return new Stream(nilHelper());
}
/**
* Create a stream of T from a variable number of elements
*
* @param elements - Elements used to create the Stream
* @remarks Since 2.12.0
*/
static of(...elements) {
return new Stream(elements[safeSymbolIterator$1]());
}
/**
* Create a Stream based on `g`
* @param g - Underlying data of the Stream
*/
constructor(g) {
this.g = g;
}
next() {
return this.g.next();
}
[Symbol.iterator]() {
return this.g;
}
/**
* Map all elements of the Stream using `f`
*
* WARNING: It closes the current stream
*
* @param f - Mapper function
* @remarks Since 0.0.1
*/
map(f) {
return new Stream(mapHelper(this.g, f));
}
/**
* Flat map all elements of the Stream using `f`
*
* WARNING: It closes the current stream
*
* @param f - Mapper function
* @remarks Since 0.0.1
*/
flatMap(f) {
return new Stream(flatMapHelper(this.g, f));
}
/**
* Drop elements from the Stream while `f(element) === true`
*
* WARNING: It closes the current stream
*
* @param f - Drop condition
* @remarks Since 0.0.1
*/
dropWhile(f) {
let foundEligible = false;
function* helper(v) {
if (foundEligible || !f(v)) {
foundEligible = true;
yield v;
}
}
return this.flatMap(helper);
}
/**
* Drop `n` first elements of the Stream
*
* WARNING: It closes the current stream
*
* @param n - Number of elements to drop
* @remarks Since 0.0.1
*/
drop(n) {
if (n <= 0) return this;
let idx = 0;
function helper() {
return idx++ < n;
}
return this.dropWhile(helper);
}
/**
* Take elements from the Stream while `f(element) === true`
*
* WARNING: It closes the current stream
*
* @param f - Take condition
* @remarks Since 0.0.1
*/
takeWhile(f) {
return new Stream(takeWhileHelper(this.g, f));
}
/**
* Take `n` first elements of the Stream
*
* WARNING: It closes the current stream
*
* @param n - Number of elements to take
* @remarks Since 0.0.1
*/
take(n) {
return new Stream(takeNHelper(this.g, n));
}
filter(f) {
return new Stream(filterHelper(this.g, f));
}
/**
* Check whether all elements of the Stream are successful for `f`
*
* WARNING: It closes the current stream
*
* @param f - Condition to check
* @remarks Since 0.0.1
*/
every(f) {
for (const v of this.g) if (!f(v)) return false;
return true;
}
/**
* Check whether one of the elements of the Stream is successful for `f`
*
* WARNING: It closes the current stream
*
* @param f - Condition to check
* @remarks Since 0.0.1
*/
has(f) {
for (const v of this.g) if (f(v)) return [true, v];
return [false, null];
}
/**
* Join `others` Stream to the current Stream
*
* WARNING: It closes the current stream and the other ones (as soon as it iterates over them)
*
* @param others - Streams to join to the current Stream
* @remarks Since 0.0.1
*/
join(...others) {
return new Stream(joinHelper(this.g, others));
}
/**
* Take the `nth` element of the Stream of the last (if it does not exist)
*
* WARNING: It closes the current stream
*
* @param nth - Position of the element to extract
* @remarks Since 0.0.12
*/
getNthOrLast(nth) {
let remaining = nth;
let last = null;
for (const v of this.g) {
if (remaining-- === 0) return v;
last = v;
}
return last;
}
};
/**
* Create a Stream based on `g`
*
* @param g - Underlying data of the Stream
*
* @remarks Since 0.0.7
* @public
*/
function stream(g) {
return new Stream(g);
}
//#endregion
//#region src/check/symbols.ts
/**
* Generated instances having a method [cloneMethod]
* will be automatically cloned whenever necessary
*
* This is pretty useful for statefull generated values.
* For instance, whenever you use a Stream you directly impact it.
* Implementing [cloneMethod] on the generated Stream would force
* the framework to clone it whenever it has to re-use it
* (mainly required for chrinking process)
*
* @remarks Since 1.8.0
* @public
*/
const cloneMethod = Symbol.for("fast-check/cloneMethod");
/**
* Check if an instance has to be clone
* @remarks Since 2.15.0
* @public
*/
function hasCloneMethod(instance) {
return instance !== null && (typeof instance === "object" || typeof instance === "function") && cloneMethod in instance && typeof instance[cloneMethod] === "function";
}
/**
* Clone an instance if needed
* @remarks Since 2.15.0
* @public
*/
function cloneIfNeeded(instance) {
return hasCloneMethod(instance) ? instance[cloneMethod]() : instance;
}
//#endregion
//#region src/check/arbitrary/definition/Value.ts
const safeObjectDefineProperty$4 = Object.defineProperty;
/**
* A `Value<T, TShrink = T>` holds an internal value of type `T`
* and its associated context
*
* @remarks Since 3.0.0 (previously called `NextValue` in 2.15.0)
* @public
*/
var Value = class {
/**
* @param value_ - Internal value of the shrinkable
* @param context - Context associated to the generated value (useful for shrink)
* @param customGetValue - Limited to internal usages (to ease migration to next), it will be removed on next major
*/
constructor(value_, context, customGetValue = void 0) {
this.value_ = value_;
this.context = context;
this.hasToBeCloned = customGetValue !== void 0 || hasCloneMethod(value_);
this.readOnce = false;
if (this.hasToBeCloned) safeObjectDefineProperty$4(this, "value", { get: customGetValue !== void 0 ? customGetValue : this.getValue });
else this.value = value_;
}
/** @internal */
getValue() {
if (this.hasToBeCloned) {
if (!this.readOnce) {
this.readOnce = true;
return this.value_;
}
return this.value_[cloneMethod]();
}
return this.value_;
}
};
//#endregion
//#region src/check/arbitrary/definition/Arbitrary.ts
/**
* Abstract class able to generate values on type `T`
*
* The values generated by an instance of Arbitrary can be previewed - with {@link sample} - or classified - with {@link statistics}.
*
* @remarks Since 0.0.7
* @public
*/
var Arbitrary = class {
filter(refinement) {
return new FilterArbitrary(this, refinement);
}
/**
* Create another arbitrary by mapping all produced values using the provided `mapper`
* Values produced by the new arbitrary are the result of applying `mapper` value by value
*
* @example
* ```typescript
* const rgbChannels: Arbitrary<{r:number,g:number,b:number}> = ...;
* const color: Arbitrary<string> = rgbChannels.map(ch => `#${(ch.r*65536 + ch.g*256 + ch.b).toString(16).padStart(6, '0')}`);
* // transform an Arbitrary producing {r,g,b} integers into an Arbitrary of '#rrggbb'
* ```
*
* @param mapper - Map function, to produce a new element based on an old one
* @param unmapper - Optional unmap function, it will never be used except when shrinking user defined values. Must throw if value is not compatible (since 3.0.0)
* @returns New arbitrary with mapped elements
*
* @remarks Since 0.0.1
*/
map(mapper, unmapper) {
return new MapArbitrary(this, mapper, unmapper);
}
/**
* Create another arbitrary by mapping a value from a base Arbirary using the provided `fmapper`
* Values produced by the new arbitrary are the result of the arbitrary generated by applying `fmapper` to a value
* @example
* ```typescript
* const arrayAndLimitArbitrary = fc.nat().chain((c: number) => fc.tuple( fc.array(fc.nat(c)), fc.constant(c)));
* ```
*
* @param chainer - Chain function, to produce a new Arbitrary using a value from another Arbitrary
* @returns New arbitrary of new type
*
* @remarks Since 1.2.0
*/
chain(chainer) {
return new ChainArbitrary(this, chainer);
}
};
/** @internal */
var ChainArbitrary = class extends Arbitrary {
constructor(arb, chainer) {
super();
this.arb = arb;
this.chainer = chainer;
}
generate(mrng, biasFactor) {
const clonedMrng = mrng.clone();
const src = this.arb.generate(mrng, biasFactor);
return this.valueChainer(src, mrng, clonedMrng, biasFactor);
}
canShrinkWithoutContext(value) {
return false;
}
shrink(value, context) {
if (this.isSafeContext(context)) return (!context.stoppedForOriginal ? this.arb.shrink(context.originalValue, context.originalContext).map((v) => this.valueChainer(v, context.clonedMrng.clone(), context.clonedMrng, context.originalBias)) : Stream.nil()).join(context.chainedArbitrary.shrink(value, context.chainedContext).map((dst) => {
const newContext = {
...context,
chainedContext: dst.context,
stoppedForOriginal: true
};
return new Value(dst.value_, newContext);
}));
return Stream.nil();
}
valueChainer(v, generateMrng, clonedMrng, biasFactor) {
const chainedArbitrary = this.chainer(v.value_);
const dst = chainedArbitrary.generate(generateMrng, biasFactor);
const context = {
originalBias: biasFactor,
originalValue: v.value_,
originalContext: v.context,
stoppedForOriginal: false,
chainedArbitrary,
chainedContext: dst.context,
clonedMrng
};
return new Value(dst.value_, context);
}
isSafeContext(context) {
return context !== null && context !== void 0 && typeof context === "object" && "originalBias" in context && "originalValue" in context && "originalContext" in context && "stoppedForOriginal" in context && "chainedArbitrary" in context && "chainedContext" in context && "clonedMrng" in context;
}
};
/** @internal */
var MapArbitrary = class extends Arbitrary {
constructor(arb, mapper, unmapper) {
super();
this.arb = arb;
this.mapper = mapper;
this.unmapper = unmapper;
this.bindValueMapper = (v) => this.valueMapper(v);
}
generate(mrng, biasFactor) {
const g = this.arb.generate(mrng, biasFactor);
return this.valueMapper(g);
}
canShrinkWithoutContext(value) {
if (this.unmapper !== void 0) try {
const unmapped = this.unmapper(value);
return this.arb.canShrinkWithoutContext(unmapped);
} catch {
return false;
}
return false;
}
shrink(value, context) {
if (this.isSafeContext(context)) return this.arb.shrink(context.originalValue, context.originalContext).map(this.bindValueMapper);
if (this.unmapper !== void 0) {
const unmapped = this.unmapper(value);
return this.arb.shrink(unmapped, void 0).map(this.bindValueMapper);
}
return Stream.nil();
}
mapperWithCloneIfNeeded(v) {
const sourceValue = v.value;
const mappedValue = this.mapper(sourceValue);
if (v.hasToBeCloned && (typeof mappedValue === "object" && mappedValue !== null || typeof mappedValue === "function") && Object.isExtensible(mappedValue) && !hasCloneMethod(mappedValue)) Object.defineProperty(mappedValue, cloneMethod, { get: () => () => this.mapperWithCloneIfNeeded(v)[0] });
return [mappedValue, sourceValue];
}
valueMapper(v) {
const [mappedValue, sourceValue] = this.mapperWithCloneIfNeeded(v);
return new Value(mappedValue, {
originalValue: sourceValue,
originalContext: v.context
});
}
isSafeContext(context) {
return context !== null && context !== void 0 && typeof context === "object" && "originalValue" in context && "originalContext" in context;
}
};
/** @internal */
var FilterArbitrary = class extends Arbitrary {
constructor(arb, refinement) {
super();
this.arb = arb;
this.refinement = refinement;
this.bindRefinementOnValue = (v) => this.refinementOnValue(v);
}
generate(mrng, biasFactor) {
while (true) {
const g = this.arb.generate(mrng, biasFactor);
if (this.refinementOnValue(g)) return g;
}
}
canShrinkWithoutContext(value) {
return this.arb.canShrinkWithoutContext(value) && this.refinement(value);
}
shrink(value, context) {
return this.arb.shrink(value, context).filter(this.bindRefinementOnValue);
}
refinementOnValue(v) {
return this.refinement(v.value);
}
};
/**
* Ensure an instance is an instance of Arbitrary
* @param instance - The instance to be checked
* @internal
*/
function isArbitrary(instance) {
return typeof instance === "object" && instance !== null && "generate" in instance && "shrink" in instance && "canShrinkWithoutContext" in instance;
}
/**
* Ensure an instance is an instance of Arbitrary
* @param instance - The instance to be checked
* @internal
*/
function assertIsArbitrary(instance) {
if (!isArbitrary(instance)) throw new Error("Unexpected value received: not an instance of Arbitrary");
}
//#endregion
//#region src/utils/apply.ts
const untouchedApply = Function.prototype.apply;
const ApplySymbol = Symbol("apply");
/**
* Extract apply or return undefined
* @param f - Function to extract apply from
* @internal
*/
function safeExtractApply(f) {
try {
return f.apply;
} catch {
return;
}
}
/**
* Equivalent to `f.apply(instance, args)` but temporary altering the instance
* @internal
*/
function safeApplyHacky(f, instance, args) {
const ff = f;
ff[ApplySymbol] = untouchedApply;
const out = ff[ApplySymbol](instance, args);
delete ff[ApplySymbol];
return out;
}
/**
* Equivalent to `f.apply(instance, args)`
* @internal
*/
function safeApply(f, instance, args) {
if (safeExtractApply(f) === untouchedApply) return f.apply(instance, args);
return safeApplyHacky(f, instance, args);
}
//#endregion
//#region src/utils/globals.ts
const SArray = Array;
const SBigInt = BigInt;
const SBigInt64Array = BigInt64Array;
const SBigUint64Array = BigUint64Array;
const SBoolean = Boolean;
const SDate = Date;
const SError = Error;
const SFloat32Array = Float32Array;
const SFloat64Array = Float64Array;
const SInt8Array = Int8Array;
const SInt16Array = Int16Array;
const SInt32Array = Int32Array;
const SNumber = Number;
const SString = String;
const SSet = Set;
const SUint8Array = Uint8Array;
const SUint8ClampedArray = Uint8ClampedArray;
const SUint16Array = Uint16Array;
const SUint32Array = Uint32Array;
const SencodeURIComponent = encodeURIComponent;
const SMap$1 = Map;
const SSymbol = Symbol;
const untouchedForEach = Array.prototype.forEach;
const untouchedIndexOf = Array.prototype.indexOf;
const untouchedJoin = Array.prototype.join;
const untouchedMap = Array.prototype.map;
const untouchedFlat = Array.prototype.flat;
const untouchedFilter = Array.prototype.filter;
const untouchedPush = Array.prototype.push;
const untouchedPop = Array.prototype.pop;
const untouchedSplice = Array.prototype.splice;
const untouchedSlice = Array.prototype.slice;
const untouchedSort = Array.prototype.sort;
const untouchedEvery = Array.prototype.every;
function extractForEach(instance) {
try {
return instance.forEach;
} catch {
return;
}
}
function extractIndexOf(instance) {
try {
return instance.indexOf;
} catch {
return;
}
}
function extractJoin(instance) {
try {
return instance.join;
} catch {
return;
}
}
function extractMap(instance) {
try {
return instance.map;
} catch {
return;
}
}
function extractFlat(instance) {
try {
return instance.flat;
} catch {
return;
}
}
function extractFilter(instance) {
try {
return instance.filter;
} catch {
return;
}
}
function extractPush(instance) {
try {
return instance.push;
} catch {
return;
}
}
function extractPop(instance) {
try {
return instance.pop;
} catch {
return;
}
}
function extractSplice(instance) {
try {
return instance.splice;
} catch {
return;
}
}
function extractSlice(instance) {
try {
return instance.slice;
} catch {
return;
}
}
function extractSort(instance) {
try {
return instance.sort;
} catch {
return;
}
}
function extractEvery(instance) {
try {
return instance.every;
} catch {
return;
}
}
function safeForEach(instance, fn) {
if (extractForEach(instance) === untouchedForEach) return instance.forEach(fn);
return safeApply(untouchedForEach, instance, [fn]);
}
function safeIndexOf(instance, ...args) {
if (extractIndexOf(instance) === untouchedIndexOf) return instance.indexOf(...args);
return safeApply(untouchedIndexOf, instance, args);
}
function safeJoin(instance, ...args) {
if (extractJoin(instance) === untouchedJoin) return instance.join(...args);
return safeApply(untouchedJoin, instance, args);
}
function safeMap(instance, fn) {
if (extractMap(instance) === untouchedMap) return instance.map(fn);
return safeApply(untouchedMap, instance, [fn]);
}
function safeFlat(instance, depth) {
if (extractFlat(instance) === untouchedFlat) {
[].flat();
return instance.flat(depth);
}
return safeApply(untouchedFlat, instance, [depth]);
}
function safeFilter(instance, predicate) {
if (extractFilter(instance) === untouchedFilter) return instance.filter(predicate);
return safeApply(untouchedFilter, instance, [predicate]);
}
function safePush(instance, ...args) {
if (extractPush(instance) === untouchedPush) return instance.push(...args);
return safeApply(untouchedPush, instance, args);
}
function safePop$1(instance) {
if (extractPop(instance) === untouchedPop) return instance.pop();
return safeApply(untouchedPop, instance, []);
}
function safeSplice(instance, ...args) {
if (extractSplice(instance) === untouchedSplice) return instance.splice(...args);
return safeApply(untouchedSplice, instance, args);
}
function safeSlice(instance, ...args) {
if (extractSlice(instance) === untouchedSlice) return instance.slice(...args);
return safeApply(untouchedSlice, instance, args);
}
function safeSort(instance, ...args) {
if (extractSort(instance) === untouchedSort) return instance.sort(...args);
return safeApply(untouchedSort, instance, args);
}
function safeEvery(instance, ...args) {
if (extractEvery(instance) === untouchedEvery) return instance.every(...args);
return safeApply(untouchedEvery, instance, args);
}
const untouchedGetTime = Date.prototype.getTime;
const untouchedToISOString = Date.prototype.toISOString;
function extractGetTime(instance) {
try {
return instance.getTime;
} catch {
return;
}
}
function extractToISOString(instance) {
try {
return instance.toISOString;
} catch {
return;
}
}
function safeGetTime(instance) {
if (extractGetTime(instance) === untouchedGetTime) return instance.getTime();
return safeApply(untouchedGetTime, instance, []);
}
function safeToISOString(instance) {
if (extractToISOString(instance) === untouchedToISOString) return instance.toISOString();
return safeApply(untouchedToISOString, instance, []);
}
const untouchedAdd = Set.prototype.add;
const untouchedHas = Set.prototype.has;
function extractAdd(instance) {
try {
return instance.add;
} catch {
return;
}
}
function extractHas(instance) {
try {
return instance.has;
} catch (err) {
return;
}
}
function safeAdd(instance, value) {
if (extractAdd(instance) === untouchedAdd) return instance.add(value);
return safeApply(untouchedAdd, instance, [value]);
}
function safeHas(instance, value) {
if (extractHas(instance) === untouchedHas) return instance.has(value);
return safeApply(untouchedHas, instance, [value]);
}
const untouchedSet = WeakMap.prototype.set;
const untouchedGet = WeakMap.prototype.get;
function extractSet(instance) {
try {
return instance.set;
} catch (err) {
return;
}
}
function extractGet(instance) {
try {
return instance.get;
} catch (err) {
return;
}
}
function safeSet(instance, key, value) {
if (extractSet(instance) === untouchedSet) return instance.set(key, value);
return safeApply(untouchedSet, instance, [key, value]);
}
function safeGet(instance, key) {
if (extractGet(instance) === untouchedGet) return instance.get(key);
return safeApply(untouchedGet, instance, [key]);
}
const untouchedMapSet = Map.prototype.set;
const untouchedMapGet = Map.prototype.get;
const untouchedMapHas = Map.prototype.has;
function extractMapSet(instance) {
try {
return instance.set;
} catch (err) {
return;
}
}
function extractMapGet(instance) {
try {
return instance.get;
} catch (err) {
return;
}
}
function extractMapHas(instance) {
try {
return instance.has;
} catch (err) {
return;
}
}
function safeMapSet(instance, key, value) {
if (extractMapSet(instance) === untouchedMapSet) return instance.set(key, value);
return safeApply(untouchedMapSet, instance, [key, value]);
}
function safeMapGet(instance, key) {
if (extractMapGet(instance) === untouchedMapGet) return instance.get(key);
return safeApply(untouchedMapGet, instance, [key]);
}
function safeMapHas(instance, key) {
if (extractMapHas(instance) === untouchedMapHas) return instance.has(key);
return safeApply(untouchedMapHas, instance, [key]);
}
const untouchedSplit = String.prototype.split;
const untouchedStartsWith = String.prototype.startsWith;
const untouchedEndsWith = String.prototype.endsWith;
const untouchedSubstring = String.prototype.substring;
const untouchedToLowerCase = String.prototype.toLowerCase;
const untouchedToUpperCase = String.prototype.toUpperCase;
const untouchedPadStart = String.prototype.padStart;
const untouchedCharCodeAt = String.prototype.charCodeAt;
const untouchedNormalize = String.prototype.normalize;
const untouchedReplace = String.prototype.replace;
function extractSplit(instance) {
try {
return instance.split;
} catch {
return;
}
}
function extractStartsWith(instance) {
try {
return instance.startsWith;
} catch {
return;
}
}
function extractEndsWith(instance) {
try {
return instance.endsWith;
} catch {
return;
}
}
function extractSubstring(instance) {
try {
return instance.substring;
} catch {
return;
}
}
function extractToLowerCase(instance) {
try {
return instance.toLowerCase;
} catch {
return;
}
}
function extractToUpperCase(instance) {
try {
return instance.toUpperCase;
} catch {
return;
}
}
function extractPadStart(instance) {
try {
return instance.padStart;
} catch {
return;
}
}
function extractCharCodeAt(instance) {
try {
return instance.charCodeAt;
} catch {
return;
}
}
function extractNormalize(instance) {
try {
return instance.normalize;
} catch (err) {
return;
}
}
function extractReplace(instance) {
try {
return instance.replace;
} catch {
return;
}
}
function safeSplit(instance, ...args) {
if (extractSplit(instance) === untouchedSplit) return instance.split(...args);
return safeApply(untouchedSplit, instance, args);
}
function safeStartsWith(instance, ...args) {
if (extractStartsWith(instance) === untouchedStartsWith) return instance.startsWith(...args);
return safeApply(untouchedStartsWith, instance, args);
}
function safeEndsWith(instance, ...args) {
if (extractEndsWith(instance) === untouchedEndsWith) return instance.endsWith(...args);
return safeApply(untouchedEndsWith, instance, args);
}
function safeSubstring(instance, ...args) {
if (extractSubstring(instance) === untouchedSubstring) return instance.substring(...args);
return safeApply(untouchedSubstring, instance, args);
}
function safeToLowerCase(instance) {
if (extractToLowerCase(instance) === untouchedToLowerCase) return instance.toLowerCase();
return safeApply(untouchedToLowerCase, instance, []);
}
function safeToUpperCase(instance) {
if (extractToUpperCase(instance) === untouchedToUpperCase) return instance.toUpperCase();
return safeApply(untouchedToUpperCase, instance, []);
}
function safePadStart(instance, ...args) {
if (extractPadStart(instance) === untouchedPadStart) return instance.padStart(...args);
return safeApply(untouchedPadStart, instance, args);
}
function safeCharCodeAt(instance, index) {
if (extractCharCodeAt(instance) === untouchedCharCodeAt) return instance.charCodeAt(index);
return safeApply(untouchedCharCodeAt, instance, [index]);
}
function safeNormalize(instance, form) {
if (extractNormalize(instance) === untouchedNormalize) return instance.normalize(form);
return safeApply(untouchedNormalize, instance, [form]);
}
function safeReplace(instance, pattern, replacement) {
if (extractReplace(instance) === untouchedReplace) return instance.replace(pattern, replacement);
return safeApply(untouchedReplace, instance, [pattern, replacement]);
}
const untouchedNumberToString = Number.prototype.toString;
function extractNumberToString(instance) {
try {
return instance.toString;
} catch {
return;
}
}
function safeNumberToString(instance, ...args) {
if (extractNumberToString(instance) === untouchedNumberToString) return instance.toString(...args);
return safeApply(untouchedNumberToString, instance, args);
}
const untouchedHasOwnProperty = Object.prototype.hasOwnProperty;
const untouchedToString = Object.prototype.toString;
function safeHasOwnProperty(instance, v) {
return safeApply(untouchedHasOwnProperty, instance, [v]);
}
function safeToString(instance) {
return safeApply(untouchedToString, instance, []);
}
const untouchedErrorToString = Error.prototype.toString;
function safeErrorToString(instance) {
return safeApply(untouchedErrorToString, instance, []);
}
//#endregion
//#region src/stream/LazyIterableIterator.ts
/** @internal */
var LazyIterableIterator = class {
constructor(producer) {
this.producer = producer;
}
[Symbol.iterator]() {
if (this.it === void 0) this.it = this.producer();
return this.it;
}
next() {
if (this.it === void 0) this.it = this.producer();
return this.it.next();
}
};
/**
* Create an IterableIterator based on a function that will only be called once if needed
*
* @param producer - Function to instanciate the underlying IterableIterator
*
* @internal
*/
function makeLazy(producer) {
return new LazyIterableIterator(producer);
}
//#endregion
//#region src/arbitrary/_internals/TupleArbitrary.ts
const safeArrayIsArray$4 = Array.isArray;
const safeObjectDefineProperty$3 = Object.defineProperty;
/** @internal */
function tupleMakeItCloneable(vs, values) {
return safeObjectDefineProperty$3(vs, cloneMethod, { value: () => {
const cloned = [];
for (let idx = 0; idx !== values.length; ++idx) safePush(cloned, values[idx].value);
tupleMakeItCloneable(cloned, values);
return cloned;
} });
}
/** @internal */
function tupleWrapper(values) {
let cloneable = false;
const vs = [];
const ctxs = [];
for (let idx = 0; idx !== values.length; ++idx) {
const v = values[idx];
cloneable = cloneable || v.hasToBeCloned;
safePush(vs, v.value);
safePush(ctxs, v.context);
}
if (cloneable) tupleMakeItCloneable(vs, values);
return new Value(vs, ctxs);
}
/** @internal */
function tupleShrink(arbs, value, context) {
const shrinks = [];
const safeContext = safeArrayIsArray$4(context) ? context : [];
for (let idx = 0; idx !== arbs.length; ++idx) safePush(shrinks, makeLazy(() => arbs[idx].shrink(value[idx], safeContext[idx]).map((v) => {
const nextValues = safeMap(value, (v, idx) => new Value(cloneIfNeeded(v), safeContext[idx]));
return [
...safeSlice(nextValues, 0, idx),
v,
...safeSlice(nextValues, idx + 1)
];
}).map(tupleWrapper)));
return Stream.nil().join(...shrinks);
}
/** @internal */
var TupleArbitrary = class extends Arbitrary {
constructor(arbs) {
super();
this.arbs = arbs;
for (let idx = 0; idx !== arbs.length; ++idx) {
const arb = arbs[idx];
if (arb === null || arb === void 0 || arb.generate === null || arb.generate === void 0) throw new Error(`Invalid parameter encountered at index ${idx}: expecting an Arbitrary`);
}
}
generate(mrng, biasFactor) {
const mapped = [];
for (let idx = 0; idx !== this.arbs.length; ++idx) safePush(mapped, this.arbs[idx].generate(mrng, biasFactor));
return tupleWrapper(mapped);
}
canShrinkWithoutContext(value) {
if (!safeArrayIsArray$4(value) || value.length !== this.arbs.length) return false;
for (let index = 0; index !== this.arbs.length; ++index) if (!this.arbs[index].canShrinkWithoutContext(value[index])) return false;
return true;
}
shrink(value, context) {
return tupleShrink(this.arbs, value, context);
}
};
//#endregion
//#region src/arbitrary/tuple.ts
/**
* For tuples produced using the provided `arbs`
*
* @param arbs - Ordered list of arbitraries
*
* @remarks Since 0.0.1
* @public
*/
function tuple(...arbs) {
return new TupleArbitrary(arbs);
}
//#endregion
//#region src/check/property/IRawProperty.ts
const safeMathLog$3 = Math.log;
/**
* Convert runId (IProperty) into a frequency (Arbitrary)
*
* @param runId - Id of the run starting at 0
* @returns Frequency of bias starting at 2
*
* @internal
*/
function runIdToFrequency(runId) {
return 2 + ~~(safeMathLog$3(runId + 1) * .4342944819032518);
}
//#endregion
//#region src/check/runner/configuration/GlobalParameters.ts
/** @internal */
let globalParameters = {};
/**
* Define global parameters that will be used by all the runners
*
* @example
* ```typescript
* fc.configureGlobal({ numRuns: 10 });
* //...
* fc.assert(
* fc.property(
* fc.nat(), fc.nat(),
* (a, b) => a + b === b + a
* ), { seed: 42 }
* ) // equivalent to { numRuns: 10, seed: 42 }
* ```
*
* @param parameters - Global parameters
*
* @remarks Since 1.18.0
* @public
*/
function configureGlobal(parameters) {
globalParameters = parameters;
}
/**
* Read global parameters that will be used by runners
* @remarks Since 1.18.0
* @public
*/
function readConfigureGlobal() {
return globalParameters;
}
/**
* Reset global parameters
* @remarks Since 1.18.0
* @public
*/
function resetConfigureGlobal() {
globalParameters = {};
}
//#endregion
//#region src/arbitrary/_internals/helpers/NoUndefinedAsContext.ts
/** @internal */
const UndefinedContextPlaceholder = Symbol("UndefinedContextPlaceholder");
/** @internal */
function noUndefinedAsContext(value) {
if (value.context !== void 0) return value;
if (value.hasToBeCloned) return new Value(value.value_, UndefinedContextPlaceholder, () => value.value);
return new Value(value.value_, UndefinedContextPlaceholder);
}
//#endregion
//#region src/check/property/AsyncProperty.generic.ts
const dummyHook$1 = () => {};
/**
* Asynchronous property, see {@link IAsyncProperty}
*
* Prefer using {@link asyncProperty} instead
*
* @internal
*/
var AsyncProperty = class {
constructor(arb, predicate) {
this.arb = arb;
this.predicate = predicate;
const { asyncBeforeEach, asyncAfterEach, beforeEach, afterEach } = readConfigureGlobal() || {};
if (asyncBeforeEach !== void 0 && beforeEach !== void 0) throw SError("Global \"asyncBeforeEach\" and \"beforeEach\" parameters can't be set at the same time when running async properties");
if (asyncAfterEach !== void 0 && afterEach !== void 0) throw SError("Global \"asyncAfterEach\" and \"afterEach\" parameters can't be set at the same time when running async properties");
this.beforeEachHook = asyncBeforeEach || beforeEach || dummyHook$1;
this.afterEachHook = asyncAfterEach || afterEach || dummyHook$1;
}
isAsync() {
return true;
}
generate(mrng, runId) {
return noUndefinedAsContext(this.arb.generate(mrng, runId !== void 0 ? runIdToFrequency(runId) : void 0));
}
shrink(value) {
if (value.context === void 0 && !this.arb.canShrinkWithoutContext(value.value_)) return Stream.nil();
const safeContext = value.context !== UndefinedContextPlaceholder ? value.context : void 0;
return this.arb.shrink(value.value_, safeContext).map(noUndefinedAsContext);
}
async runBeforeEach() {
await this.beforeEachHook();
}
async runAfterEach() {
await this.afterEachHook();
}
async run(v) {
try {
const output = await this.predicate(v);
return output === void 0 || output === true ? null : { error: new SError("Property failed by returning false") };
} catch (err) {
if (PreconditionFailure.isFailure(err)) return err;
return { error: err };
}
}
/**
* Define a function that should be called before all calls to the predicate
* @param hookFunction - Function to be called
*/
beforeEach(hookFunction) {
const previousBeforeEachHook = this.beforeEachHook;
this.beforeEachHook = () => hookFunction(previousBeforeEachHook);
return this;
}
/**
* Define a function that should be called after all calls to the predicate
* @param hookFunction - Function to be called
*/
afterEach(hookFunction) {
const previousAfterEachHook = this.afterEachHook;
this.afterEachHook = () => hookFunction(previousAfterEachHook);
return this;
}
};
//#endregion
//#region src/arbitrary/_internals/AlwaysShrinkableArbitrary.ts
/**
* Arbitrary considering any value as shrinkable whatever the received context.
* In case the context corresponds to nil, it will be checked when calling shrink:
* valid would mean stream coming from shrink, otherwise empty stream
* @internal
*/
var AlwaysShrinkableArbitrary = class extends Arbitrary {
constructor(arb) {
super();
this.arb = arb;
}
generate(mrng, biasFactor) {
return noUndefinedAsContext(this.arb.generate(mrng, biasFactor));
}
canShrinkWithoutContext(value) {
return true;
}
shrink(value, context) {
if (context === void 0 && !this.arb.canShrinkWithoutContext(value)) return Stream.nil();
const safeContext = context !== UndefinedContextPlaceholder ? context : void 0;
return this.arb.shrink(value, safeContext).map(noUndefinedAsContext);
}
};
//#endregion
//#region src/check/property/AsyncProperty.ts
/**
* Instantiate a new {@link fast-check#IAsyncProperty}
* @param predicate - Assess the success of the property. Would be considered falsy if it throws or if its output evaluates to false
* @remarks Since 0.0.7
* @public
*/
function asyncProperty(...args) {
if (args.length < 2) throw new Error("asyncProperty expects at least two parameters");
const arbs = safeSlice(args, 0, args.length - 1);
const p = args[args.length - 1];
safeForEach(arbs, assertIsArbitrary);
return new AsyncProperty(tuple(...safeMap(arbs, (arb) => new AlwaysShrinkableArbitrary(arb))), (t) => p(...t));
}
//#endregion
//#region src/check/property/Property.generic.ts
const dummyHook = () => {};
/**
* Property, see {@link IProperty}
*
* Prefer using {@link property} instead
*
* @internal
*/
var Property = class {
constructor(arb, predicate) {
this.arb = arb;
this.predicate = predicate;
const { beforeEach = dummyHook, afterEach = dummyHook, asyncBeforeEach, asyncAfterEach } = readConfigureGlobal() || {};
if (asyncBeforeEach !== void 0) throw SError("\"asyncBeforeEach\" can't be set when running synchronous properties");
if (asyncAfterEach !== void 0) throw SError("\"asyncAfterEach\" can't be set when running synchronous properties");
this.beforeEachHook = beforeEach;
this.afterEachHook = afterEach;
}
isAsync() {
return false;
}
generate(mrng, runId) {
return noUndefinedAsContext(this.arb.generate(mrng, runId !== void 0 ? runIdToFrequency(runId) : void 0));
}
shrink(value) {
if (value.context === void 0 && !this.arb.canShrinkWithoutContext(value.value_)) return Stream.nil();
const safeContext = value.context !== UndefinedContextPlaceholder ? value.context : void 0;
return this.arb.shrink(value.value_, safeContext).map(noUndefinedAsContext);
}
runBeforeEach() {
this.beforeEachHook();
}
runAfterEach() {
this.afterEachHook();
}
run(v) {
try {
const output = this.predicate(v);
return output === void 0 || output === true ? null : { error: new SError("Property failed by returning false") };
} catch (err) {
if (PreconditionFailure.isFailure(err)) return err;
return { error: err };
}
}
beforeEach(hookFunction) {
const previousBeforeEachHook = this.beforeEachHook;
this.beforeEachHook = () => hookFunction(previousBeforeEachHook);
return this;
}
afterEach(hookFunction) {
const previousAfterEachHook = this.afterEachHook;
this.afterEachHook = () => hookFunction(previousAfterEachHook);
return this;
}
};
//#endregion
//#region src/check/property/Property.ts
/**
* Instantiate a new {@link fast-check#IProperty}
* @param predicate - Assess the success of the property. Would be considered falsy if it throws or if its output evaluates to false
* @remarks Since 0.0.1
* @public
*/
function property(...args) {
if (args.length < 2) throw new Error("property expects at least two parameters");
const arbs = safeSlice(args, 0, args.length - 1);
const p = args[args.length - 1];
safeForEach(arbs, assertIsArbitrary);
return new Property(tuple(...safeMap(arbs, (arb) => new AlwaysShrinkableArbitrary(arb))), (t) => p(...t));
}
//#endregion
//#region src/check/runner/configuration/VerbosityLevel.ts
/**
* Verbosity level
* @remarks Since 1.9.1
* @public
*/
let VerbosityLevel = /* @__PURE__ */ function(VerbosityLevel) {
/**
* Level 0 (default)
*
* Minimal reporting:
* - minimal failing case
* - error log corresponding to the minimal failing case
*
* @remarks Since 1.9.1
*/
VerbosityLevel[VerbosityLevel["None"] = 0] = "None";
/**
* Level 1
*
* Failures reporting:
* - same as `VerbosityLevel.None`
* - list all the failures encountered during the shrinking process
*
* @remarks Since 1.9.1
*/
VerbosityLevel[VerbosityLevel["Verbose"] = 1] = "Verbose";
/**
* Level 2
*
* Execution flow reporting:
* - same as `VerbosityLevel.None`
* - all runs with their associated status displayed as a tree
*
* @remarks Since 1.9.1
*/
VerbosityLevel[VerbosityLevel["VeryVerbose"] = 2] = "VeryVerbose";
return VerbosityLevel;
}({});
//#endregion
//#region src/random/generator/RandomGenerator.ts
/** @internal */
function adaptRandomGeneratorTo8x(rng) {
if ("unsafeNext" in rng) {
if (rng.unsafeJump === void 0) return {
clone: () => adaptRandomGeneratorTo8x(rng),
next: () => rng.unsafeNext(),
getState: () => rng.getState()
};
return {
clone: () => adaptRandomGeneratorTo8x(rng),
next: () => rng.unsafeNext(),
jump: () => rng.unsafeJump(),
getState: () => rng.getState()
};
}
return rng;
}
/** @internal */
function adaptRandomGeneratorToInternal(rng) {
if ("jump" in rng && typeof rng.jump === "function") return rng;
return {
clone: () => adaptRandomGeneratorToInternal(rng),
next: () => rng.next(),
jump: () => skipN(rng, 42),
getState: () => rng.getState()
};
}
/** @internal */
function adaptRandomGenerator(rng) {
return adaptRandomGeneratorToInternal(adaptRandomGeneratorTo8x(rng));
}
//#endregion
//#region src/check/runner/configuration/QualifiedParameters.ts
const safeDateNow$1 = Date.now;
const safeMathMin$6 = Math.min;
const safeMathRandom = Math.random;
/**
* Configuration extracted from incoming Parameters
*
* It handles and set the default settings that will be used by runners.
*
* @internal
*/
var QualifiedParameters = class {
constructor(op) {
const p = op || {};
this.seed = readSeed(p);
this.randomType = readRandomType(p);
this.numRuns = readNumRuns(p);
this.verbose = readVerbose(p);
this.maxSkipsPerRun = p.maxSkipsPerRun !== void 0 ? p.maxSkipsPerRun : 100;
this.timeout = safeTimeout(p.timeout);
this.skipAllAfterTimeLimit = safeTimeout(p.skipAllAfterTimeLimit);
this.interruptAfterTimeLimit = safeTimeout(p.interruptAfterTimeLimit);
this.markInterruptAsFailure = p.markInterruptAsFailure === true;
this.skipEqualValues = p.skipEqualValues === true;
this.ignoreEqualValues = p.ignoreEqualValues === true;
this.logger = p.logger !== void 0 ? p.logger : (v) => {
console.log(v);
};
this.path = p.path !== void 0 ? p.path : "";
this.unbiased = p.unbiased === true;
this.examples = p.examples !== void 0 ? p.examples : [];
this.endOnFailure = p.endOnFailure === true;
this.reporter = p.reporter;
this.asyncReporter = p.asyncReporter;
this.includeErrorInReport = p.includeErrorInReport === true;
}
toParameters() {
return {
seed: this.seed,
randomType: this.randomType,
numRuns: this.numRuns,
maxSkipsPerRun: this.maxSkipsPerRun,
timeout: this.timeout,
skipAllAfterTimeLimit: this.skipAllAfterTimeLimit,
interruptAfterTimeLimit: this.interruptAfterTimeLimit,
markInterruptAsFailure: this.markInterruptAsFailure,
skipEqualValues: this.skipEqualValues,
ignoreEqualValues: this.ignoreEqualValues,
path: this.path,
logger: this.logger,
unbiased: this.unbiased,
verbose: this.verbose,
examples: this.examples,
endOnFailure: this.endOnFailure,
reporter: this.reporter,
asyncReporter: this.asyncReporter,
includeErrorInReport: this.includeErrorInReport
};
}
};
/** @internal */
function createQualifiedRandomGenerator(random) {
return (seed) => {
return adaptRandomGenerator(random(seed));
};
}
/** @internal */
function readSeed(p) {
if (p.seed === void 0) return safeDateNow$1() ^ safeMathRandom() * 4294967296;
const seed32 = p.seed | 0;
if (p.seed === seed32) return seed32;
return seed32 ^ (p.seed - seed32) * 4294967296;
}
/** @internal */
function readRandomType(p) {
if (p.randomType === void 0) return xorshift128plus;
if (typeof p.randomType === "string") switch (p.randomType) {
case "mersenne": return createQualifiedRandomGenerator(mersenne);
case "congruential":
case "congruential32": return createQualifiedRandomGenerator(congruential32);
case "xorshift128plus": return xorshift128plus;
case "xoroshiro128plus": return xoroshiro128plus;
default: throw new Error(`Invalid random specified: '${p.randomType}'`);
}
const mrng = p.randomType(0);
if ("min" in mrng && mrng.min !== -2147483648) throw new Error(`Invalid random number generator: min must equal -0x80000000, got ${String(mrng.min)}`);
if ("max" in mrng && mrng.max !== 2147483647) throw new Error(`Invalid random number generator: max must equal 0x7fffffff, got ${String(mrng.max)}`);
if (mrng === adaptRandomGenerator(mrng)) return p.randomType;
return createQualifiedRandomGenerator(p.randomType);
}
/** @internal */
function readNumRuns(p) {
const defaultValue = 100;
if (p.numRuns !== void 0) return p.numRuns;
if (p.num_runs !== void 0) return p.num_runs;
return defaultValue;
}
/** @internal */
function readVerbose(p) {
if (p.verbose === void 0) return VerbosityLevel.None;
if (typeof p.verbose === "boolean") return p.verbose === true ? VerbosityLevel.Verbose : VerbosityLevel.None;
if (p.verbose <= VerbosityLevel.None) return VerbosityLevel.None;
if (p.verbose >= VerbosityLevel.VeryVerbose) return VerbosityLevel.VeryVerbose;
return p.verbose | 0;
}
/** @internal */
function safeTimeout(value) {
if (value === void 0) return;
return safeMathMin$6(value, 2147483647);
}
/**
* Extract a runner configuration from Parameters
* @param p - Incoming Parameters
*/
function read(op) {
return new QualifiedParameters(op);
}
//#endregion
//#region src/check/property/SkipAfterProperty.ts
/** @internal */
function interruptAfter(timeMs, setTimeoutSafe, clearTimeoutSafe) {
let timeoutHandle = null;
return {
clear: () => clearTimeoutSafe(timeoutHandle),
promise: new Promise((resolve) => {
timeoutHandle = setTimeoutSafe(() => {
resolve(new PreconditionFailure(true));
}, timeMs);
})
};
}
/** @internal */
var SkipAfterProperty = class {
constructor(property, getTime, timeLimit, interruptExecution, setTimeoutSafe, clearTimeoutSafe) {
this.property = property;
this.getTime = getTime;
this.interruptExecution = interruptExecution;
this.setTimeoutSafe = setTimeoutSafe;
this.clearTimeoutSafe = clearTimeoutSafe;
this.skipAfterTime = this.getTime() + timeLimit;
}
isAsync() {
return this.property.isAsync();
}
generate(mrng, runId) {
return this.property.generate(mrng, runId);
}
shrink(value) {
return this.property.shrink(value);
}
run(v) {
const remainingTime = this.skipAfterTime - this.getTime();
if (remainingTime <= 0) {
const preconditionFailure = new PreconditionFailure(this.interruptExecution);
if (this.isAsync()) return Promise.resolve(preconditionFailure);
else return preconditionFailure;
}
if (this.interruptExecution && this.isAsync()) {
const t = interruptAfter(remainingTime, this.setTimeoutSafe, this.clearTimeoutSafe);
const propRun = Promise.race([this.property.run(v), t.promise]);
propRun.then(t.clear, t.clear);
return propRun;
}
return this.property.run(v);
}
runBeforeEach() {
return this.property.runBeforeEach();
}
runAfterEach() {
return this.property.runAfterEach();
}
};
//#endregion
//#region src/check/property/TimeoutProperty.ts
/** @internal */
const timeoutAfter = (timeMs, setTimeoutSafe, clearTimeoutSafe) => {
let timeoutHandle = null;
return {
clear: () => clearTimeoutSafe(timeoutHandle),
promise: new Promise((resolve) => {
timeoutHandle = setTimeoutSafe(() => {
resolve({ error: new SError(`Property timeout: exceeded limit of ${timeMs} milliseconds`) });
}, timeMs);
})
};
};
/** @internal */
var TimeoutProperty = class {
constructor(property, timeMs, setTimeoutSafe, clearTimeoutSafe) {
this.property = property;
this.timeMs = timeMs;
this.setTimeoutSafe = setTimeoutSafe;
this.clearTimeoutSafe = clearTimeoutSafe;
}
isAsync() {
return true;
}
generate(mrng, runId) {
return this.property.generate(mrng, runId);
}
shrink(value) {
return this.property.shrink(value);
}
async run(v) {
const t = timeoutAfter(this.timeMs, this.setTimeoutSafe, this.clearTimeoutSafe);
const propRun = Promise.race([this.property.run(v), t.promise]);
propRun.then(t.clear, t.clear);
return propRun;
}
runBeforeEach() {
return Promise.resolve(this.property.runBeforeEach());
}
runAfterEach() {
return Promise.resolve(this.property.runAfterEach());
}
};
//#endregion
//#region src/check/property/UnbiasedProperty.ts
/** @internal */
var UnbiasedProperty = class {
constructor(property) {
this.property = property;
}
isAsync() {
return this.property.isAsync();
}
generate(mrng, _runId) {
return this.property.generate(mrng, void 0);
}
shrink(value) {
return this.property.shrink(value);
}
run(v) {
return this.property.run(v);
}
runBeforeEach() {
return this.property.runBeforeEach();
}
runAfterEach() {
return this.property.runAfterEach();
}
};
//#endregion
//#region src/utils/stringify.ts
const safeArrayFrom = Array.from;
const safeBufferIsBuffer = typeof Buffer !== "undefined" ? Buffer.isBuffer : void 0;
const safeJsonStringify$1 = JSON.stringify;
const safeNumberIsNaN$5 = Number.isNaN;
const safeObjectKeys$5 = Object.keys;
const safeObjectGetOwnPropertySymbols$2 = Object.getOwnPropertySymbols;
const safeObjectGetOwnPropertyDescriptor$3 = Object.getOwnPropertyDescriptor;
const safeObjectGetPrototypeOf$2 = Object.getPrototypeOf;
const safeNegativeInfinity$7 = Number.NEGATIVE_INFINITY;
const safePositiveInfinity$8 = Number.POSITIVE_INFINITY;
/**
* Use this symbol to define a custom serializer for your instances.
* Serializer must be a function returning a string (see {@link WithToStringMethod}).
*
* @remarks Since 2.17.0
* @public
*/
const toStringMethod = Symbol.for("fast-check/toStringMethod");
/**
* Check if an instance implements {@link WithToStringMethod}
*
* @remarks Since 2.17.0
* @public
*/
function hasToStringMethod(instance) {
return instance !== null && (typeof instance === "object" || typeof instance === "function") && toStringMethod in instance && typeof instance[toStringMethod] === "function";
}
/**
* Use this symbol to define a custom serializer for your instances.
* Serializer must be a function returning a promise of string (see {@link WithAsyncToStringMethod}).
*
* Please note that:
* 1. It will only be useful for asynchronous properties.
* 2. It has to return barely instantly.
*
* @remarks Since 2.17.0
* @public
*/
const asyncToStringMethod = Symbol.for("fast-check/asyncToStringMethod");
/**
* Check if an instance implements {@link WithAsyncToStringMethod}
*
* @remarks Since 2.17.0
* @public
*/
function hasAsyncToStringMethod(instance) {
return instance !== null && (typeof instance === "object" || typeof instance === "function") && asyncToStringMethod in instance && typeof instance[asyncToStringMethod] === "function";
}
/** @internal */
const findSymbolNameRegex =