From 658e1d76d3ce76815dd0e01fe4e2e96981f604db Mon Sep 17 00:00:00 2001 From: Nicolas DUBIEN Date: Thu, 17 Sep 2026 23:11:20 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=A5=20Return=20instances=20of=20`Itera?= =?UTF-8?q?tor`=20from=20`shrink`=20(#7320)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description When we started with fast-check, mapping or filtering on an Iterable was not a thing. Actually we ahd to wait until ES2025 to get it spec-ed. Now that the feature is spec-ed and implemented we can drop our ad-hoc APIs. Actually we came up with our own set of mapping, filtering and other functions and packaged them all into what we called the `Stream` class. `Stream` class does not really make now that it is native so worth dropping it. Impacts: - `shrink` return type changed to built-in iterators - `Stream` class drop _Previously merged in experimental versions under #7164._ ## Checklist — _Don't delete this checklist and make sure you do the following before opening the PR_ - [ ] I have a full understanding of every line in this PR — whether the code was hand-written, AI-generated, copied from external sources or produced by any other tool - [ ] I flagged the impact of my change (minor / patch / major) either by running `pnpm run bump` or by following the instructions from the changeset bot - [ ] I kept this PR focused on a single concern and did not bundle unrelated changes - [ ] I followed the [gitmoji](https://gitmoji.dev/) specification for the name of the PR, including the package scope (e.g. `🐛(vitest) Something...`) when the change targets a package other than `fast-check` - [ ] I added relevant tests and they would have failed without my PR (when applicable) --- .changeset/late-hotels-trade.md | 6 + examples/005-race/todolist/main.spec.tsx | 2 +- packages/fast-check/README.md | 1 + packages/fast-check/api-extractor.json | 2 +- packages/fast-check/package.json | 2 +- .../arbitrary/_internals/AdapterArbitrary.ts | 6 +- .../_internals/AlwaysShrinkableArbitrary.ts | 6 +- .../arbitrary/_internals/ArrayArbitrary.ts | 78 ++-- .../arbitrary/_internals/BigIntArbitrary.ts | 5 +- .../arbitrary/_internals/CloneArbitrary.ts | 15 +- .../arbitrary/_internals/CommandsArbitrary.ts | 19 +- .../arbitrary/_internals/ConstantArbitrary.ts | 8 +- .../_internals/FrequencyArbitrary.ts | 19 +- .../_internals/GeneratorArbitrary.ts | 6 +- .../arbitrary/_internals/IntegerArbitrary.ts | 5 +- .../src/arbitrary/_internals/LazyArbitrary.ts | 3 +- .../_internals/LimitedShrinkArbitrary.ts | 10 +- .../_internals/MixedCaseArbitrary.ts | 43 +-- .../_internals/SchedulerArbitrary.ts | 6 +- .../arbitrary/_internals/StreamArbitrary.ts | 16 +- .../arbitrary/_internals/SubarrayArbitrary.ts | 31 +- .../arbitrary/_internals/TupleArbitrary.ts | 11 +- .../WithShrinkFromOtherArbitrary.ts | 3 +- .../_internals/helpers/ShrinkBigInt.ts | 12 +- .../_internals/helpers/ShrinkInteger.ts | 12 +- .../helpers/ZipIterableIterators.ts | 3 +- .../fast-check/src/arbitrary/chainUntil.ts | 11 +- .../src/arbitrary/infiniteStream.ts | 6 +- packages/fast-check/src/arbitrary/noBias.ts | 3 +- packages/fast-check/src/arbitrary/noShrink.ts | 6 +- .../check/arbitrary/definition/Arbitrary.ts | 21 +- .../property/_internals/PropertyImplem.ts | 6 +- .../plugins/IgnoreEqualValuesProperty.ts | 3 +- .../property/plugins/SkipAfterProperty.ts | 3 +- .../check/property/plugins/TimeoutProperty.ts | 3 +- .../property/plugins/UnbiasedProperty.ts | 3 +- .../src/check/property/types/Property.ts | 3 +- .../fast-check/src/check/runner/Runner.ts | 6 +- .../fast-check/src/check/runner/Sampler.ts | 9 +- .../fast-check/src/check/runner/Tosser.ts | 4 +- .../src/check/runner/utils/PathWalker.ts | 14 +- packages/fast-check/src/fast-check.ts | 1 - .../src/stream/LazyIterableIterator.ts | 29 -- packages/fast-check/src/stream/Stream.ts | 248 ------------- .../fast-check/src/stream/StreamHelpers.ts | 77 ---- packages/fast-check/src/utils/iterator.ts | 49 +++ .../test/e2e/NoStackOverflowOnShrink.spec.ts | 6 +- .../test/e2e/StateFullArbitraries.spec.ts | 4 +- .../__test-helpers__/ArbitraryAssertions.ts | 7 +- .../__test-helpers__/ArbitraryHelpers.ts | 7 +- .../_internals/AdapterArbitrary.spec.ts | 9 +- .../_internals/ArrayArbitrary.spec.ts | 8 +- .../_internals/BigIntArbitrary.spec.ts | 4 +- .../_internals/CloneArbitrary.spec.ts | 22 +- .../_internals/FrequencyArbitrary.spec.ts | 13 +- .../_internals/GeneratorArbitrary.spec.ts | 12 +- .../_internals/IntegerArbitrary.spec.ts | 4 +- .../_internals/LazyArbitrary.spec.ts | 3 +- .../_internals/LimitedShrinkArbitrary.spec.ts | 9 +- .../_internals/StreamArbitrary.spec.ts | 49 +-- .../_internals/TupleArbitrary.spec.ts | 46 ++- .../WithShrinkFromOtherArbitrary.spec.ts | 13 +- .../_internals/helpers/ShrinkBigInt.spec.ts | 3 +- .../_internals/helpers/ShrinkInteger.spec.ts | 3 +- .../implementations/SchedulerImplem.spec.ts | 2 +- .../test/unit/arbitrary/chainUntil.spec.ts | 58 +-- .../test/unit/arbitrary/commands.spec.ts | 26 +- .../test/unit/arbitrary/dictionary.spec.ts | 10 +- .../test/unit/arbitrary/func.spec.ts | 8 +- .../test/unit/arbitrary/letrec.spec.ts | 3 +- .../test/unit/arbitrary/map.spec.ts | 10 +- .../test/unit/arbitrary/noBias.spec.ts | 7 +- .../test/unit/arbitrary/noShrink.spec.ts | 5 +- .../test/unit/arbitrary/string.spec.ts | 10 +- .../definition/Arbitrary.itest.spec.ts | 40 +- .../definition/Arbitrary.utest.spec.ts | 40 +- .../unit/check/property/AsyncProperty.spec.ts | 3 +- .../__test-helpers__/PropertyHelpers.ts | 4 +- .../check/runner/DecorateProperty.spec.ts | 4 +- .../test/unit/check/runner/Runner.spec.ts | 60 ++- .../check/runner/SourceValuesIterator.spec.ts | 4 +- .../test/unit/check/runner/Tosser.spec.ts | 24 +- .../test/unit/stream/Stream.spec.ts | 341 ------------------ .../fast-check/test/unit/stubs/arbitraries.ts | 18 +- .../iterator.spec.ts} | 2 +- packages/fast-check/tsconfig.json | 4 +- packages/fast-check/tsconfig.publish.json | 4 +- .../tsconfig.publish.types.api-extractor.json | 9 + .../fast-check/tsconfig.publish.types.json | 4 +- packages/fast-check/tsconfig.typedoc.json | 4 +- .../worker-property/NoopWorkerProperty.ts | 4 +- .../WorkerPropertyFromWorker.ts | 6 +- .../WorkerPropertyFromWorker.spec.ts | 2 +- packages/worker/tsconfig.json | 2 + 94 files changed, 569 insertions(+), 1206 deletions(-) create mode 100644 .changeset/late-hotels-trade.md delete mode 100644 packages/fast-check/src/stream/LazyIterableIterator.ts delete mode 100644 packages/fast-check/src/stream/Stream.ts delete mode 100644 packages/fast-check/src/stream/StreamHelpers.ts create mode 100644 packages/fast-check/src/utils/iterator.ts delete mode 100644 packages/fast-check/test/unit/stream/Stream.spec.ts rename packages/fast-check/test/unit/{stream/LazyIterableIterator.spec.ts => utils/iterator.spec.ts} (92%) create mode 100644 packages/fast-check/tsconfig.publish.types.api-extractor.json diff --git a/.changeset/late-hotels-trade.md b/.changeset/late-hotels-trade.md new file mode 100644 index 00000000..0d823876 --- /dev/null +++ b/.changeset/late-hotels-trade.md @@ -0,0 +1,6 @@ +--- +"@fast-check/worker": patch +"fast-check": major +--- + +Move out stream diff --git a/examples/005-race/todolist/main.spec.tsx b/examples/005-race/todolist/main.spec.tsx index 81885b60..493ce111 100644 --- a/examples/005-race/todolist/main.spec.tsx +++ b/examples/005-race/todolist/main.spec.tsx @@ -54,7 +54,7 @@ const TodoListCommands = fc.commands([ type ApiTodoItem = { id: string; label: string; checked: boolean }; -const mockApi = (s: fc.Scheduler, initialTodos: ApiTodoItem[], allFailures: fc.Stream) => { +const mockApi = (s: fc.Scheduler, initialTodos: ApiTodoItem[], allFailures: IteratorObject) => { let lastIdx = 0; let allTodos = [...initialTodos]; diff --git a/packages/fast-check/README.md b/packages/fast-check/README.md index 82319116..c77bcfaa 100644 --- a/packages/fast-check/README.md +++ b/packages/fast-check/README.md @@ -117,6 +117,7 @@ Here are the minimal requirements to use fast-check properly without any polyfil | fast-check | node | ECMAScript version | _TypeScript (optional)_ | | ---------- | ---------------------- | ------------------ | ----------------------- | +| **5.x** | ≥22.11.0 | ES2025 | ≥5.0 | | **4.x** | ≥12.17.0(1) | ES2020 | ≥5.0 | | **3.x** | ≥8(2) | ES2017 | ≥4.1(3) | | **2.x** | ≥8(2) | ES2017 | ≥3.2(4) | diff --git a/packages/fast-check/api-extractor.json b/packages/fast-check/api-extractor.json index d35ba4aa..3eda2baa 100644 --- a/packages/fast-check/api-extractor.json +++ b/packages/fast-check/api-extractor.json @@ -1,7 +1,7 @@ { "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", "compiler": { - "tsconfigFilePath": "/tsconfig.publish.types.json" + "tsconfigFilePath": "/tsconfig.publish.types.api-extractor.json" }, "tsdocMetadata": { "enabled": false diff --git a/packages/fast-check/package.json b/packages/fast-check/package.json index bbd2fbee..a9a03281 100644 --- a/packages/fast-check/package.json +++ b/packages/fast-check/package.json @@ -38,7 +38,7 @@ "build-ci": "rolldown -c && pnpm run build:post-build", "typecheck": "tsc --noEmit", "test-bundle": "for f in test-bundle/*.mjs test-bundle/*.cjs; do [ -f \"$f\" ] && echo \"Running ${f##*/}\" && node \"$f\" || exit 1; done", - "test-legacy-bundle": "nvs add 12.17.0 && for f in test-bundle/*.cjs; do [ -f \"$f\" ] && echo \"Running ${f##*/}\" && $(nvs which 12.17.0) \"$f\" || exit 1; done", + "test-legacy-bundle": "nvs add 22.11.0 && for f in test-bundle/*.cjs; do [ -f \"$f\" ] && echo \"Running ${f##*/}\" && $(nvs which 22.11.0) \"$f\" || exit 1; done", "api-extractor": "api-extractor run --local" }, "repository": { diff --git a/packages/fast-check/src/arbitrary/_internals/AdapterArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/AdapterArbitrary.ts index 959fb613..f9344294 100644 --- a/packages/fast-check/src/arbitrary/_internals/AdapterArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/AdapterArbitrary.ts @@ -1,7 +1,7 @@ import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../check/arbitrary/definition/Value.js'; import type { Random } from '../../random/generator/Random.js'; -import { Stream } from '../../stream/Stream.js'; +import { nil } from '../../utils/iterator.js'; /** @internal */ export type AdapterOutput = { adapted: boolean; value: T }; @@ -39,10 +39,10 @@ class AdapterArbitrary extends Arbitrary { canShrinkWithoutContext(value: unknown): value is T { return this.sourceArb.canShrinkWithoutContext(value) && !this.adapter(value).adapted; } - shrink(value: T, context: unknown): Stream> { + shrink(value: T, context: unknown): IteratorObject> { if (context === AdaptedValue) { if (!this.sourceArb.canShrinkWithoutContext(value)) { - return Stream.nil(); + return nil; } return this.sourceArb.shrink(value, undefined).map(this.adaptValue); } diff --git a/packages/fast-check/src/arbitrary/_internals/AlwaysShrinkableArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/AlwaysShrinkableArbitrary.ts index 16a07d96..d53c7a91 100644 --- a/packages/fast-check/src/arbitrary/_internals/AlwaysShrinkableArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/AlwaysShrinkableArbitrary.ts @@ -1,7 +1,7 @@ import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import type { Value } from '../../check/arbitrary/definition/Value.js'; import type { Random } from '../../random/generator/Random.js'; -import { Stream } from '../../stream/Stream.js'; +import { nil } from '../../utils/iterator.js'; import { noUndefinedAsContext, UndefinedContextPlaceholder } from './helpers/NoUndefinedAsContext.js'; /** @@ -24,11 +24,11 @@ export class AlwaysShrinkableArbitrary extends Arbitrary { return true; } - shrink(value: Ts, context: unknown): Stream> { + shrink(value: Ts, context: unknown): IteratorObject> { if (context === undefined && !this.arb.canShrinkWithoutContext(value)) { // This arbitrary will never produce any context being `undefined` // neither during `generate` nor during `shrink` - return Stream.nil(); + return nil; } const safeContext = context !== UndefinedContextPlaceholder ? context : undefined; return this.arb.shrink(value, safeContext).map(noUndefinedAsContext); diff --git a/packages/fast-check/src/arbitrary/_internals/ArrayArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/ArrayArbitrary.ts index 183dd66d..cac6c39a 100644 --- a/packages/fast-check/src/arbitrary/_internals/ArrayArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/ArrayArbitrary.ts @@ -1,14 +1,14 @@ import type { Random } from '../../random/generator/Random.js'; -import { Stream } from '../../stream/Stream.js'; import { cloneIfNeeded, cloneMethod } from '../../check/symbols.js'; import { integer } from '../integer.js'; -import { makeLazy } from '../../stream/LazyIterableIterator.js'; +import { makeLazy } from '../../utils/iterator.js'; import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../check/arbitrary/definition/Value.js'; import type { CustomSetBuilder } from './interfaces/CustomSet.js'; import type { DepthContext, DepthIdentifier } from './helpers/DepthContext.js'; import { getDepthContextFor } from './helpers/DepthContext.js'; import { buildSlicedGenerator } from './helpers/BuildSlicedGenerator.js'; +import { joinAll, nil } from '../../utils/iterator.js'; /** @internal */ type ArrayArbitraryContext = { @@ -234,12 +234,12 @@ export class ArrayArbitrary extends Arbitrary { value: T[], safeContext: ArrayArbitraryContext, endIndex: number, - ): IterableIterator<[Value[], unknown, number]> { - const shrinks: IterableIterator<[Value[], unknown, number]>[] = []; + ): IteratorObject<[Value[], unknown, number]> { + const shrinks: IteratorObject<[Value[], unknown, number]>[] = []; for (let index = safeContext.startIndex; index < endIndex; ++index) { shrinks.push( makeLazy(() => - this.arb.shrink(value[index], safeContext.itemsContexts[index]).map((v): [Value[], unknown, number] => { + this.arb.shrink(value[index], safeContext.itemsContexts[index]).map((v): [Value[], undefined, number] => { const beforeCurrent = value .slice(0, index) .map((v, i) => new Value(cloneIfNeeded(v), safeContext.itemsContexts[i])); @@ -255,12 +255,12 @@ export class ArrayArbitrary extends Arbitrary { ), ); } - return Stream.nil<[Value[], unknown, number]>().join(...shrinks); + return joinAll(shrinks); } - private shrinkImpl(value: T[], context?: unknown): Stream<[Value[], unknown, number]> { + private shrinkImpl(value: T[], context?: unknown): IteratorObject<[Value[], unknown, number]> { if (value.length === 0) { - return Stream.nil(); + return nil; } const safeContext: ArrayArbitraryContext = @@ -268,7 +268,7 @@ export class ArrayArbitrary extends Arbitrary { ? (context as ArrayArbitraryContext) : { shrunkOnce: false, lengthContext: undefined, itemsContexts: [], startIndex: 0 }; - return ( + return joinAll([ this.lengthArb .shrink( value.length, @@ -292,40 +292,36 @@ export class ArrayArbitrary extends Arbitrary { lengthValue.context, // integer context for value lengthValue.value (the length) 0, ]; - }) - // Length context value will be set to undefined for remaining shrinking values - // as they are outside of our shrinking process focused on items.length. - // None of our computed contexts will apply for them. - .join( - makeLazy(() => - value.length > this.minLength - ? this.shrinkItemByItem(value, safeContext, 1) - : this.shrinkItemByItem(value, safeContext, value.length), - ), - ) - .join( - value.length > this.minLength - ? makeLazy(() => { - // We pass itemsLengthContext=undefined to next shrinker to start shrinking - // without any assumptions on the current state (we never explored that one) - const subContext: ArrayArbitraryContext = { - shrunkOnce: false, - lengthContext: undefined, - itemsContexts: safeContext.itemsContexts.slice(1), - startIndex: 0, - }; - return this.shrinkImpl(value.slice(1), subContext) - .filter((v) => this.minLength <= v[0].length + 1) - .map((v): [Value[], unknown, number] => { - return [[new Value(cloneIfNeeded(value[0]), safeContext.itemsContexts[0]), ...v[0]], undefined, 0]; - }); - }) - : Stream.nil(), - ) - ); + }), + // Length context value will be set to undefined for remaining shrinking values + // as they are outside of our shrinking process focused on items.length. + // None of our computed contexts will apply for them. + makeLazy(() => + value.length > this.minLength + ? this.shrinkItemByItem(value, safeContext, 1) + : this.shrinkItemByItem(value, safeContext, value.length), + ), + value.length > this.minLength + ? makeLazy(() => { + // We pass itemsLengthContext=undefined to next shrinker to start shrinking + // without any assumptions on the current state (we never explored that one) + const subContext: ArrayArbitraryContext = { + shrunkOnce: false, + lengthContext: undefined, + itemsContexts: safeContext.itemsContexts.slice(1), + startIndex: 0, + }; + return this.shrinkImpl(value.slice(1), subContext) + .filter((v) => this.minLength <= v[0].length + 1) + .map((v): [Value[], unknown, number] => { + return [[new Value(cloneIfNeeded(value[0]), safeContext.itemsContexts[0]), ...v[0]], undefined, 0]; + }); + }) + : nil, + ]); } - shrink(value: T[], context?: unknown): Stream> { + shrink(value: T[], context?: unknown): IteratorObject> { return this.shrinkImpl(value, context).map((contextualValue) => this.wrapper(contextualValue[0], true, contextualValue[1], contextualValue[2]), ); diff --git a/packages/fast-check/src/arbitrary/_internals/BigIntArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/BigIntArbitrary.ts index 008e9ee6..19999ba1 100644 --- a/packages/fast-check/src/arbitrary/_internals/BigIntArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/BigIntArbitrary.ts @@ -1,5 +1,4 @@ import type { Random } from '../../random/generator/Random.js'; -import { Stream } from '../../stream/Stream.js'; import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../check/arbitrary/definition/Value.js'; import { biasNumericRange, bigIntLogLike } from './helpers/BiasNumericRange.js'; @@ -34,7 +33,7 @@ export class BigIntArbitrary extends Arbitrary { return typeof value === 'bigint' && this.min <= value && value <= this.max; } - shrink(current: bigint, context?: unknown): Stream> { + shrink(current: bigint, context?: unknown): IteratorObject> { if (!BigIntArbitrary.isValidContext(current, context)) { // No context: // Take default target and shrink towards it @@ -46,7 +45,7 @@ export class BigIntArbitrary extends Arbitrary { // Last chance try... // context is set to undefined, so that shrink will restart // without any assumptions in case our try find yet another bug - return Stream.of(new Value(context, undefined)); + return Iterator.from([new Value(context, undefined)]); } // Normal shrink process return shrinkBigInt(current, context, false); diff --git a/packages/fast-check/src/arbitrary/_internals/CloneArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/CloneArbitrary.ts index d533e75a..4ff0c8b4 100644 --- a/packages/fast-check/src/arbitrary/_internals/CloneArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/CloneArbitrary.ts @@ -2,7 +2,7 @@ import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../check/arbitrary/definition/Value.js'; import { cloneMethod } from '../../check/symbols.js'; import type { Random } from '../../random/generator/Random.js'; -import { Stream } from '../../stream/Stream.js'; +import { nil } from '../../utils/iterator.js'; /** @internal */ export class CloneArbitrary extends Arbitrary { @@ -44,22 +44,21 @@ export class CloneArbitrary extends Arbitrary { return this.arb.canShrinkWithoutContext(value[0]); } - shrink(value: T[], context?: unknown): Stream> { + shrink(value: T[], context?: unknown): IteratorObject> { if (value.length === 0) { - return Stream.nil(); + return nil; } - return new Stream(this.shrinkImpl(value, context !== undefined ? (context as unknown[]) : [])).map((v) => - this.wrapper(v), - ); + return this.shrinkImpl(value, context !== undefined ? (context as unknown[]) : []).map((v) => this.wrapper(v)); } - private *shrinkImpl(value: T[], contexts: unknown[]): IterableIterator[]> { + private *shrinkImpl(value: T[], contexts: unknown[]): IteratorObject[]> { const its = value.map((v, idx) => this.arb.shrink(v, contexts[idx])[Symbol.iterator]()); let cur = its.map((it) => it.next()); while (!cur[0].done) { - yield cur.map((c) => c.value); + yield cur.map((c: IteratorResult>) => c.value); cur = its.map((it) => it.next()); } + return undefined; } private static makeItCloneable(vs: T[], shrinkables: Value[]) { diff --git a/packages/fast-check/src/arbitrary/_internals/CommandsArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/CommandsArbitrary.ts index d4207619..d1971cde 100644 --- a/packages/fast-check/src/arbitrary/_internals/CommandsArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/CommandsArbitrary.ts @@ -5,8 +5,7 @@ import { CommandsIterable } from '../../check/model/commands/CommandsIterable.js import { CommandWrapper } from '../../check/model/commands/CommandWrapper.js'; import { ReplayPath } from '../../check/model/ReplayPath.js'; import type { Random } from '../../random/generator/Random.js'; -import { makeLazy } from '../../stream/LazyIterableIterator.js'; -import { Stream } from '../../stream/Stream.js'; +import { makeLazy, joinAll, nil } from '../../utils/iterator.js'; import { oneof } from '../oneof.js'; import { restrictedIntegerArbitraryBuilder } from './builders/RestrictedIntegerArbitraryBuilder.js'; @@ -104,9 +103,9 @@ export class CommandsArbitrary, context: unknown, - ): Stream>> { + ): IteratorObject>> { if (context === undefined) { - return Stream.nil>>(); + return nil; } const safeContext = context as CommandsArbitraryContext; @@ -115,14 +114,14 @@ export class CommandsArbitrary>>(); + return nil; } // The shrinker of commands have to keep the last item // because it is the one causing the failure - const rootShrink: Stream>[]> = shrunkOnce - ? Stream.nil() - : new Stream([[]][Symbol.iterator]()); + const rootShrink: IteratorObject>[]> = shrunkOnce + ? nil + : Iterator.from([[]]); // If the resulting shrinkable was simply built by joining the streams one by one, // > stream[n] = stream[n-1].join(nextFor[n]) -- with nextFor[-1] = rootShrink @@ -130,7 +129,7 @@ export class CommandsArbitrary>[]>[] = []; + const nextShrinks: IteratorObject>[]>[] = []; // keep fixed number commands at the beginning // remove items in remaining part except the last one @@ -156,7 +155,7 @@ export class CommandsArbitrary { + return joinAll([rootShrink, ...nextShrinks]).map((shrinkables) => { return this.buildValueFor( shrinkables.map((c) => new Value(c.value_.clone(), c.context)), true, diff --git a/packages/fast-check/src/arbitrary/_internals/ConstantArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/ConstantArbitrary.ts index 2e93a7d0..c4f158a9 100644 --- a/packages/fast-check/src/arbitrary/_internals/ConstantArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/ConstantArbitrary.ts @@ -1,5 +1,5 @@ import type { Random } from '../../random/generator/Random.js'; -import { Stream } from '../../stream/Stream.js'; +import { nil } from '../../utils/iterator.js'; import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../check/arbitrary/definition/Value.js'; import { cloneMethod, hasCloneMethod } from '../../check/symbols.js'; @@ -61,10 +61,10 @@ export class ConstantArbitrary extends Arbitrary { } return this.fastValues.has(value); } - shrink(value: T, context?: unknown): Stream> { + shrink(value: T, context?: unknown): IteratorObject> { if (context === 0 || Object.is(value, this.values[0])) { - return Stream.nil(); + return nil; } - return Stream.of(new Value(this.values[0], 0)); + return Iterator.from([new Value(this.values[0], 0)]); } } diff --git a/packages/fast-check/src/arbitrary/_internals/FrequencyArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/FrequencyArbitrary.ts index 47157198..479737c5 100644 --- a/packages/fast-check/src/arbitrary/_internals/FrequencyArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/FrequencyArbitrary.ts @@ -1,5 +1,5 @@ import type { Random } from '../../random/generator/Random.js'; -import { Stream } from '../../stream/Stream.js'; +import { joinAll, nil } from '../../utils/iterator.js'; import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../check/arbitrary/definition/Value.js'; import type { DepthContext, DepthIdentifier } from './helpers/DepthContext.js'; @@ -71,7 +71,7 @@ export class FrequencyArbitrary extends Arbitrary { return this.canShrinkWithoutContextIndex(value) !== -1; } - shrink(value: T, context?: unknown): Stream> { + shrink(value: T, context?: unknown): IteratorObject> { if (context !== undefined) { const safeContext = context as _FrequencyArbitraryContext; const selectedIndex = safeContext.selectedIndex; @@ -89,35 +89,36 @@ export class FrequencyArbitrary extends Arbitrary { ); } const valueFromFirst = safeContext.cachedGeneratedForFirst; - return Stream.of(valueFromFirst).join(originalShrinks); + return joinAll([Iterator.from([valueFromFirst]), originalShrinks]); } return originalShrinks; } const potentialSelectedIndex = this.canShrinkWithoutContextIndex(value); if (potentialSelectedIndex === -1) { - return Stream.nil(); // No arbitrary found to accept this value + return nil; // No arbitrary found to accept this value } - return this.defaultShrinkForFirst(potentialSelectedIndex).join( + return joinAll([ + this.defaultShrinkForFirst(potentialSelectedIndex), this.warbs[potentialSelectedIndex].arbitrary .shrink(value, undefined) // re-checked by canShrinkWithoutContextIndex .map((v) => this.mapIntoValue(potentialSelectedIndex, v, null, undefined)), - ); + ]); } /** Generate shrink values for first arbitrary when no context and no value was provided */ - private defaultShrinkForFirst(selectedIndex: number): Stream> { + private defaultShrinkForFirst(selectedIndex: number): IteratorObject> { ++this.context.depth; // increase depth try { if (!this.mustFallbackToFirstInShrink(selectedIndex) || this.warbs[0].fallbackValue === undefined) { // Not applicable: no fallback to first arbitrary on shrink OR no hint to shrink without an initial value and context - return Stream.nil(); + return nil; } } finally { --this.context.depth; // decrease depth (reset depth) } // The arbitrary at [0] accepts to shrink fallbackValue.default without any context (context=undefined) const rawShrinkValue = new Value(this.warbs[0].fallbackValue.default, undefined); - return Stream.of(this.mapIntoValue(0, rawShrinkValue, null, undefined)); + return Iterator.from([this.mapIntoValue(0, rawShrinkValue, null, undefined)]); } /** Extract the index of the generator that would have been able to gennrate the value */ diff --git a/packages/fast-check/src/arbitrary/_internals/GeneratorArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/GeneratorArbitrary.ts index 471153b3..8c40470c 100644 --- a/packages/fast-check/src/arbitrary/_internals/GeneratorArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/GeneratorArbitrary.ts @@ -1,7 +1,7 @@ import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import type { Value } from '../../check/arbitrary/definition/Value.js'; import type { Random } from '../../random/generator/Random.js'; -import { Stream } from '../../stream/Stream.js'; +import { nil } from '../../utils/iterator.js'; import type { GeneratorContext, GeneratorValue, PreBuiltValue } from './builders/GeneratorValueBuilder.js'; import { buildGeneratorValue } from './builders/GeneratorValueBuilder.js'; import { buildStableArbitraryGeneratorCache, naiveIsEqual } from './builders/StableArbitraryGeneratorCache.js'; @@ -24,10 +24,10 @@ export class GeneratorArbitrary extends Arbitrary { return false; } - shrink(_value: GeneratorValue, context: unknown): Stream> { + shrink(_value: GeneratorValue, context: unknown): IteratorObject> { if (context === undefined) { // Auto can NEVER shrink without any context as there is no way to find back what to call to apply the shrink - return Stream.nil(); + return nil; } const safeContext = context as GeneratorContext; const mrng = safeContext.mrng; diff --git a/packages/fast-check/src/arbitrary/_internals/IntegerArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/IntegerArbitrary.ts index 4f1cdbfd..d280edb0 100644 --- a/packages/fast-check/src/arbitrary/_internals/IntegerArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/IntegerArbitrary.ts @@ -1,7 +1,6 @@ import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../check/arbitrary/definition/Value.js'; import type { Random } from '../../random/generator/Random.js'; -import { Stream } from '../../stream/Stream.js'; import { integerLogLike, biasNumericRange } from './helpers/BiasNumericRange.js'; import { shrinkInteger } from './helpers/ShrinkInteger.js'; @@ -41,7 +40,7 @@ export class IntegerArbitrary extends Arbitrary { ); } - shrink(current: number, context?: unknown): Stream> { + shrink(current: number, context?: unknown): IteratorObject> { if (!IntegerArbitrary.isValidContext(current, context)) { // No context: // Take default target and shrink towards it @@ -56,7 +55,7 @@ export class IntegerArbitrary extends Arbitrary { // Last chance try... // context is set to undefined, so that shrink will restart // without any assumptions in case our try find yet another bug - return Stream.of(new Value(context, undefined)); + return Iterator.from([new Value(context, undefined)]); } // Normal shrink process return shrinkInteger(current, context, false); diff --git a/packages/fast-check/src/arbitrary/_internals/LazyArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/LazyArbitrary.ts index b0e03577..dcc364af 100644 --- a/packages/fast-check/src/arbitrary/_internals/LazyArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/LazyArbitrary.ts @@ -1,7 +1,6 @@ import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import type { Value } from '../../check/arbitrary/definition/Value.js'; import type { Random } from '../../random/generator/Random.js'; -import type { Stream } from '../../stream/Stream.js'; /** @internal */ export class LazyArbitrary extends Arbitrary { @@ -21,7 +20,7 @@ export class LazyArbitrary extends Arbitrary { } return this.underlying.canShrinkWithoutContext(value); } - shrink(value: T, context?: unknown): Stream> { + shrink(value: T, context?: unknown): IteratorObject> { if (this.underlying === null) { throw new Error(`Lazy arbitrary ${JSON.stringify(this.name)} not correctly initialized`); } diff --git a/packages/fast-check/src/arbitrary/_internals/LimitedShrinkArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/LimitedShrinkArbitrary.ts index a838bdea..838c0b7f 100644 --- a/packages/fast-check/src/arbitrary/_internals/LimitedShrinkArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/LimitedShrinkArbitrary.ts @@ -1,7 +1,7 @@ import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../check/arbitrary/definition/Value.js'; import type { Random } from '../../random/generator/Random.js'; -import { Stream } from '../../stream/Stream.js'; +import { nil } from '../../utils/iterator.js'; import { zipIterableIterators } from './helpers/ZipIterableIterators.js'; /** @internal */ @@ -28,18 +28,18 @@ export class LimitedShrinkArbitrary extends Arbitrary { canShrinkWithoutContext(value: unknown): value is T { return this.arb.canShrinkWithoutContext(value); } - shrink(value: T, context?: unknown): Stream> { + shrink(value: T, context?: unknown): IteratorObject> { if (this.isSafeContext(context)) { return this.safeShrink(value, context.originalContext, context.length); } return this.safeShrink(value, undefined, 0); } - private safeShrink(value: T, originalContext: unknown, currentLength: number): Stream> { + private safeShrink(value: T, originalContext: unknown, currentLength: number): IteratorObject> { const remaining = this.maxShrinks - currentLength; if (remaining <= 0) { - return Stream.nil(); // early-exit to avoid potentially expensive computations in .shrink + return nil; // early-exit to avoid potentially expensive computations in .shrink } - return new Stream(zipIterableIterators(this.arb.shrink(value, originalContext), iotaFrom(currentLength + 1))) + return zipIterableIterators(this.arb.shrink(value, originalContext), iotaFrom(currentLength + 1)) .take(remaining) .map((valueAndLength) => this.valueMapper(valueAndLength[0], valueAndLength[1])); } diff --git a/packages/fast-check/src/arbitrary/_internals/MixedCaseArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/MixedCaseArbitrary.ts index 90fbc76e..afb83133 100644 --- a/packages/fast-check/src/arbitrary/_internals/MixedCaseArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/MixedCaseArbitrary.ts @@ -1,9 +1,8 @@ import type { Random } from '../../random/generator/Random.js'; -import type { Stream } from '../../stream/Stream.js'; import { bigInt } from '../bigInt.js'; import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../check/arbitrary/definition/Value.js'; -import { makeLazy } from '../../stream/LazyIterableIterator.js'; +import { makeLazy, joinAll } from '../../utils/iterator.js'; import { applyFlagsOnChars, computeFlagsFromChars, @@ -66,7 +65,7 @@ export class MixedCaseArbitrary extends Arbitrary { this.stringArb.canShrinkWithoutContext(value); } - shrink(value: string, context?: unknown): Stream> { + shrink(value: string, context?: unknown): IteratorObject> { let contextSafe: MixedCaseArbitraryContext; if (context !== undefined) { contextSafe = context as MixedCaseArbitraryContext; @@ -95,9 +94,8 @@ export class MixedCaseArbitrary extends Arbitrary { } const rawString = contextSafe.rawString; const flags = contextSafe.flags; - return this.stringArb - .shrink(rawString, contextSafe.rawStringContext) - .map((nRawStringValue) => { + return joinAll([ + this.stringArb.shrink(rawString, contextSafe.rawStringContext).map((nRawStringValue) => { const nChars = [...nRawStringValue.value]; const nTogglePositions = computeTogglePositions(nChars, this.toggleCase); const nFlags = computeNextFlags(flags, nTogglePositions.length); @@ -107,22 +105,21 @@ export class MixedCaseArbitrary extends Arbitrary { // Remark: Value nFlags can be attached to a context equal to undefined // as `canShrinkWithoutContext(nFlags) === true` for the bigint arbitrary return new Value(nChars.join(''), this.buildContextFor(nRawStringValue, new Value(nFlags, undefined))); - }) - .join( - makeLazy(() => { - const chars = [...rawString]; - const togglePositions = computeTogglePositions(chars, this.toggleCase); - return bigInt(0n, (1n << BigInt(togglePositions.length)) - 1n) - .shrink(flags, contextSafe.flagsContext) - .map((nFlagsValue) => { - const nChars = chars.slice(); // cloning chars - applyFlagsOnChars(nChars, nFlagsValue.value, togglePositions, this.toggleCase); - return new Value( - nChars.join(''), - this.buildContextFor(new Value(rawString, contextSafe.rawStringContext), nFlagsValue), - ); - }); - }), - ); + }), + makeLazy(() => { + const chars = [...rawString]; + const togglePositions = computeTogglePositions(chars, this.toggleCase); + return bigInt(0n, (1n << BigInt(togglePositions.length)) - 1n) + .shrink(flags, contextSafe.flagsContext) + .map((nFlagsValue) => { + const nChars = chars.slice(); // cloning chars + applyFlagsOnChars(nChars, nFlagsValue.value, togglePositions, this.toggleCase); + return new Value( + nChars.join(''), + this.buildContextFor(new Value(rawString, contextSafe.rawStringContext), nFlagsValue), + ); + }); + }), + ]); } } diff --git a/packages/fast-check/src/arbitrary/_internals/SchedulerArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/SchedulerArbitrary.ts index 580f9152..ac36cede 100644 --- a/packages/fast-check/src/arbitrary/_internals/SchedulerArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/SchedulerArbitrary.ts @@ -1,7 +1,7 @@ import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../check/arbitrary/definition/Value.js'; import type { Random } from '../../random/generator/Random.js'; -import { Stream } from '../../stream/Stream.js'; +import { nil } from '../../utils/iterator.js'; import type { Scheduler } from './interfaces/Scheduler.js'; import type { ScheduledTask, TaskSelector } from './implementations/SchedulerImplem.js'; import { SchedulerImplem } from './implementations/SchedulerImplem.js'; @@ -36,8 +36,8 @@ export class SchedulerArbitrary extends Arbitrary, _context?: unknown): Stream>> { + shrink(_value: Scheduler, _context?: unknown): IteratorObject>> { // Not supported yet - return Stream.nil(); + return nil; } } diff --git a/packages/fast-check/src/arbitrary/_internals/StreamArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/StreamArbitrary.ts index 2675c902..d4577841 100644 --- a/packages/fast-check/src/arbitrary/_internals/StreamArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/StreamArbitrary.ts @@ -2,7 +2,7 @@ import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../check/arbitrary/definition/Value.js'; import { cloneMethod } from '../../check/symbols.js'; import type { Random } from '../../random/generator/Random.js'; -import { Stream } from '../../stream/Stream.js'; +import { nil } from '../../utils/iterator.js'; import { asyncStringify, asyncToStringMethod, stringify, toStringMethod } from '../../utils/stringify.js'; /** @internal */ @@ -12,7 +12,7 @@ function prettyPrint(numSeen: number, seenValuesStrings?: string[]): string { } /** @internal */ -export class StreamArbitrary extends Arbitrary> { +export class StreamArbitrary extends Arbitrary> { constructor( readonly arb: Arbitrary, readonly history: boolean, @@ -20,12 +20,12 @@ export class StreamArbitrary extends Arbitrary> { super(); } - generate(mrng: Random, biasFactor: number | undefined): Value> { + generate(mrng: Random, biasFactor: number | undefined): Value> { const appliedBiasFactor = biasFactor !== undefined && mrng.nextInt(1, biasFactor) === 1 ? biasFactor : undefined; const enrichedProducer = () => { const seenValues: T[] | null = this.history ? [] : null; let numSeenValues = 0; - const g = function* (arb: Arbitrary, clonedMrng: Random) { + const g = function* (arb: Arbitrary, clonedMrng: Random): IteratorObject { while (true) { const value = arb.generate(clonedMrng, appliedBiasFactor).value; numSeenValues++; @@ -35,7 +35,7 @@ export class StreamArbitrary extends Arbitrary> { yield value; } }; - const s = new Stream(g(this.arb, mrng.clone())); + const s = g(this.arb, mrng.clone()); return Object.defineProperties(s, { toString: { value: () => prettyPrint(numSeenValues, seenValues !== null ? seenValues.map(stringify) : undefined), @@ -57,14 +57,14 @@ export class StreamArbitrary extends Arbitrary> { return new Value(enrichedProducer(), undefined); } - canShrinkWithoutContext(_value: unknown): _value is Stream { + canShrinkWithoutContext(_value: unknown): _value is IteratorObject { // Knowing if we can generate or not an infinite stream would require to iterate over it // (until its "end") return false; } - shrink(_value: Stream, _context?: unknown): Stream>> { + shrink(_value: IteratorObject, _context?: unknown): IteratorObject>> { // Not supported yet, even if context was provided - return Stream.nil(); + return nil; } } diff --git a/packages/fast-check/src/arbitrary/_internals/SubarrayArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/SubarrayArbitrary.ts index 57e22277..98562001 100644 --- a/packages/fast-check/src/arbitrary/_internals/SubarrayArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/SubarrayArbitrary.ts @@ -1,8 +1,7 @@ import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../check/arbitrary/definition/Value.js'; import type { Random } from '../../random/generator/Random.js'; -import { makeLazy } from '../../stream/LazyIterableIterator.js'; -import { Stream } from '../../stream/Stream.js'; +import { makeLazy, joinAll, nil } from '../../utils/iterator.js'; import { isSubarrayOf } from './helpers/IsSubarrayOf.js'; import { IntegerArbitrary } from './IntegerArbitrary.js'; @@ -68,28 +67,26 @@ export class SubarrayArbitrary extends Arbitrary { return isSubarrayOf(this.originalArray, value); } - shrink(value: T[], context: unknown): Stream> { + shrink(value: T[], context: unknown): IteratorObject> { // shrinking one by one is not the most comprehensive // but allows a reasonable number of entries in the shrink if (value.length === 0) { - return Stream.nil>(); + return nil; } - return this.lengthArb - .shrink(value.length, context) - .map((newSize) => { + return joinAll([ + this.lengthArb.shrink(value.length, context).map((newSize) => { return new Value( value.slice(value.length - newSize.value), // array of length newSize.value newSize.context, // integer context for value newSize.value (the length) ); - }) - .join( - value.length > this.minLength - ? makeLazy(() => - this.shrink(value.slice(1), undefined) - .filter((newValue) => this.minLength <= newValue.value.length + 1) - .map((newValue) => new Value([value[0], ...newValue.value], undefined)), - ) - : Stream.nil>(), - ); + }), + value.length > this.minLength + ? makeLazy(() => + this.shrink(value.slice(1), undefined) + .filter((newValue) => this.minLength <= newValue.value.length + 1) + .map((newValue) => new Value([value[0], ...newValue.value], undefined)), + ) + : nil, + ]); } } diff --git a/packages/fast-check/src/arbitrary/_internals/TupleArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/TupleArbitrary.ts index ee28257e..fbb36646 100644 --- a/packages/fast-check/src/arbitrary/_internals/TupleArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/TupleArbitrary.ts @@ -1,10 +1,9 @@ import type { Random } from '../../random/generator/Random.js'; -import { Stream } from '../../stream/Stream.js'; import type { WithCloneMethod } from '../../check/symbols.js'; import { cloneIfNeeded, cloneMethod } from '../../check/symbols.js'; import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../check/arbitrary/definition/Value.js'; -import { makeLazy } from '../../stream/LazyIterableIterator.js'; +import { makeLazy, joinAll } from '../../utils/iterator.js'; /** @internal */ type TupleContext = unknown[]; @@ -38,10 +37,10 @@ export function tupleShrink( arbs: ArbsArray, value: Ts, context?: TupleContext, -): Stream> { +): IteratorObject> { // shrinking one by one is the not the most comprehensive // but allows a reasonable number of entries in the shrink - const shrinks: IterableIterator>[] = []; + const shrinks: IteratorObject>[] = []; const safeContext: TupleContext = Array.isArray(context) ? context : []; for (let idx = 0; idx !== arbs.length; ++idx) { shrinks.push( @@ -68,7 +67,7 @@ export function tupleShrink( ), ); } - return Stream.nil>().join(...shrinks); + return joinAll(shrinks); } /** @internal */ @@ -111,7 +110,7 @@ export class TupleArbitrary extends Arbitrary { } return true; } - shrink(value: Ts, context?: unknown): Stream> { + shrink(value: Ts, context?: unknown): IteratorObject> { return tupleShrink(this.arbs, value, context as TupleContext | undefined); } } diff --git a/packages/fast-check/src/arbitrary/_internals/WithShrinkFromOtherArbitrary.ts b/packages/fast-check/src/arbitrary/_internals/WithShrinkFromOtherArbitrary.ts index 95e2cc35..3319093a 100644 --- a/packages/fast-check/src/arbitrary/_internals/WithShrinkFromOtherArbitrary.ts +++ b/packages/fast-check/src/arbitrary/_internals/WithShrinkFromOtherArbitrary.ts @@ -1,7 +1,6 @@ import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../check/arbitrary/definition/Value.js'; import type { Random } from '../../random/generator/Random.js'; -import type { Stream } from '../../stream/Stream.js'; /** @internal */ function isSafeContext(context: unknown): context is { generatorContext: unknown } | { shrinkerContext: unknown } { @@ -41,7 +40,7 @@ export class WithShrinkFromOtherArbitrary extends Arbitrary { return this.shrinkerArbitrary.canShrinkWithoutContext(value); } - shrink(value: T, context: unknown): Stream> { + shrink(value: T, context: unknown): IteratorObject> { if (!isSafeContext(context)) { return this.shrinkerArbitrary.shrink(value, undefined).map(toShrinkerValue); } diff --git a/packages/fast-check/src/arbitrary/_internals/helpers/ShrinkBigInt.ts b/packages/fast-check/src/arbitrary/_internals/helpers/ShrinkBigInt.ts index 5ef350f0..b51ffb72 100644 --- a/packages/fast-check/src/arbitrary/_internals/helpers/ShrinkBigInt.ts +++ b/packages/fast-check/src/arbitrary/_internals/helpers/ShrinkBigInt.ts @@ -1,5 +1,3 @@ -import type { Stream } from '../../../stream/Stream.js'; -import { stream } from '../../../stream/Stream.js'; import { Value } from '../../../check/arbitrary/definition/Value.js'; /** @@ -14,9 +12,9 @@ function halveBigInt(n: bigint): bigint { * Compute shrunk values to move from current to target * @internal */ -export function shrinkBigInt(current: bigint, target: bigint, tryTargetAsap: boolean): Stream> { +export function shrinkBigInt(current: bigint, target: bigint, tryTargetAsap: boolean): IteratorObject> { const realGap = current - target; - function* shrinkDecr(): IterableIterator> { + function* shrinkDecr(): IteratorObject> { let previous: bigint | undefined = tryTargetAsap ? undefined : target; const gap = tryTargetAsap ? realGap : halveBigInt(realGap); for (let toremove = gap; toremove > 0; toremove = halveBigInt(toremove)) { @@ -24,8 +22,9 @@ export function shrinkBigInt(current: bigint, target: bigint, tryTargetAsap: boo yield new Value(next, previous); // previous indicates the last passing value previous = next; } + return undefined; } - function* shrinkIncr(): IterableIterator> { + function* shrinkIncr(): IteratorObject> { let previous: bigint | undefined = tryTargetAsap ? undefined : target; const gap = tryTargetAsap ? realGap : halveBigInt(realGap); for (let toremove = gap; toremove < 0; toremove = halveBigInt(toremove)) { @@ -33,6 +32,7 @@ export function shrinkBigInt(current: bigint, target: bigint, tryTargetAsap: boo yield new Value(next, previous); // previous indicates the last passing value previous = next; } + return undefined; } - return realGap > 0 ? stream(shrinkDecr()) : stream(shrinkIncr()); + return realGap > 0 ? shrinkDecr() : shrinkIncr(); } diff --git a/packages/fast-check/src/arbitrary/_internals/helpers/ShrinkInteger.ts b/packages/fast-check/src/arbitrary/_internals/helpers/ShrinkInteger.ts index e1e79d35..04d781e0 100644 --- a/packages/fast-check/src/arbitrary/_internals/helpers/ShrinkInteger.ts +++ b/packages/fast-check/src/arbitrary/_internals/helpers/ShrinkInteger.ts @@ -1,6 +1,4 @@ import { Value } from '../../../check/arbitrary/definition/Value.js'; -import type { Stream } from '../../../stream/Stream.js'; -import { stream } from '../../../stream/Stream.js'; /** @internal */ function halvePosInteger(n: number): number { @@ -15,9 +13,9 @@ function halveNegInteger(n: number): number { * Compute shrunk values to move from current to target * @internal */ -export function shrinkInteger(current: number, target: number, tryTargetAsap: boolean): Stream> { +export function shrinkInteger(current: number, target: number, tryTargetAsap: boolean): IteratorObject> { const realGap = current - target; - function* shrinkDecr(): IterableIterator> { + function* shrinkDecr(): IteratorObject> { let previous: number | undefined = tryTargetAsap ? undefined : target; const gap = tryTargetAsap ? realGap : halvePosInteger(realGap); for (let toremove = gap; toremove > 0; toremove = halvePosInteger(toremove)) { @@ -27,8 +25,9 @@ export function shrinkInteger(current: number, target: number, tryTargetAsap: bo yield new Value(next, previous); // previous indicates the last passing value previous = next; } + return undefined; } - function* shrinkIncr(): IterableIterator> { + function* shrinkIncr(): IteratorObject> { let previous: number | undefined = tryTargetAsap ? undefined : target; const gap = tryTargetAsap ? realGap : halveNegInteger(realGap); for (let toremove = gap; toremove < 0; toremove = halveNegInteger(toremove)) { @@ -36,6 +35,7 @@ export function shrinkInteger(current: number, target: number, tryTargetAsap: bo yield new Value(next, previous); // previous indicates the last passing value previous = next; } + return undefined; } - return realGap > 0 ? stream(shrinkDecr()) : stream(shrinkIncr()); + return realGap > 0 ? shrinkDecr() : shrinkIncr(); } diff --git a/packages/fast-check/src/arbitrary/_internals/helpers/ZipIterableIterators.ts b/packages/fast-check/src/arbitrary/_internals/helpers/ZipIterableIterators.ts index 43344ebe..69690581 100644 --- a/packages/fast-check/src/arbitrary/_internals/helpers/ZipIterableIterators.ts +++ b/packages/fast-check/src/arbitrary/_internals/helpers/ZipIterableIterators.ts @@ -32,6 +32,7 @@ export function* zipIterableIterators[]>( yield vs.map((v) => v.value) as unknown as ZippedIterableIteratorValues; nextZippedValues(its, vs); } + return undefined; } /** @internal */ @@ -40,6 +41,6 @@ type ZippedIterableIteratorValues[]> = { }; /** @internal */ -type ZippedIterableIterator[]> = IterableIterator< +type ZippedIterableIterator[]> = IteratorObject< ZippedIterableIteratorValues >; diff --git a/packages/fast-check/src/arbitrary/chainUntil.ts b/packages/fast-check/src/arbitrary/chainUntil.ts index cbe90eb6..a245cdc3 100644 --- a/packages/fast-check/src/arbitrary/chainUntil.ts +++ b/packages/fast-check/src/arbitrary/chainUntil.ts @@ -1,7 +1,7 @@ import type { Random } from '../random/generator/Random.js'; import { Arbitrary } from '../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../check/arbitrary/definition/Value.js'; -import { Stream } from '../stream/Stream.js'; +import { nil } from '../utils/iterator.js'; /** @internal */ type ChainUntilEntry = { @@ -68,14 +68,14 @@ class ChainUntilArbitrary extends Arbitrary { return false; } - shrink(value: T, context?: unknown): Stream> { + shrink(value: T, context?: unknown): IteratorObject> { if (!this.isSafeContext(context)) { - return Stream.nil(); + return nil; } - return new Stream(this.shrinkIterator(context)); + return this.shrinkIterator(context); } - private *shrinkIterator(context: ChainUntilArbitraryContext): IterableIterator> { + private *shrinkIterator(context: ChainUntilArbitraryContext): IteratorObject> { const { entries, currentShrinkLevel, biasFactor } = context; for (let level = currentShrinkLevel; level < entries.length; ++level) { @@ -122,6 +122,7 @@ class ChainUntilArbitrary extends Arbitrary { yield new Value(lastEntry.value, newContext); } } + return undefined; } private isSafeContext(context: unknown): context is ChainUntilArbitraryContext { diff --git a/packages/fast-check/src/arbitrary/infiniteStream.ts b/packages/fast-check/src/arbitrary/infiniteStream.ts index 258c6303..86e097d9 100644 --- a/packages/fast-check/src/arbitrary/infiniteStream.ts +++ b/packages/fast-check/src/arbitrary/infiniteStream.ts @@ -1,4 +1,3 @@ -import type { Stream } from '../stream/Stream.js'; import type { Arbitrary } from '../check/arbitrary/definition/Arbitrary.js'; import { StreamArbitrary } from './_internals/StreamArbitrary.js'; @@ -32,7 +31,10 @@ interface InfiniteStreamConstraints { * @remarks Since 1.8.0 * @public */ -function infiniteStream(arb: Arbitrary, constraints?: InfiniteStreamConstraints): Arbitrary> { +function infiniteStream( + arb: Arbitrary, + constraints?: InfiniteStreamConstraints, +): Arbitrary> { const history = constraints !== undefined && typeof constraints === 'object' && 'noHistory' in constraints ? !constraints.noHistory diff --git a/packages/fast-check/src/arbitrary/noBias.ts b/packages/fast-check/src/arbitrary/noBias.ts index 6a6209e9..96993472 100644 --- a/packages/fast-check/src/arbitrary/noBias.ts +++ b/packages/fast-check/src/arbitrary/noBias.ts @@ -1,7 +1,6 @@ import { Arbitrary } from '../check/arbitrary/definition/Arbitrary.js'; import type { Value } from '../check/arbitrary/definition/Value.js'; import type { Random } from '../random/generator/Random.js'; -import type { Stream } from '../stream/Stream.js'; /** @internal */ class NoBiasArbitrary extends Arbitrary { @@ -14,7 +13,7 @@ class NoBiasArbitrary extends Arbitrary { canShrinkWithoutContext(value: unknown): value is T { return this.arb.canShrinkWithoutContext(value); } - shrink(value: T, context?: unknown): Stream> { + shrink(value: T, context?: unknown): IteratorObject> { return this.arb.shrink(value, context); } } diff --git a/packages/fast-check/src/arbitrary/noShrink.ts b/packages/fast-check/src/arbitrary/noShrink.ts index ac8e892b..eb1f3e61 100644 --- a/packages/fast-check/src/arbitrary/noShrink.ts +++ b/packages/fast-check/src/arbitrary/noShrink.ts @@ -1,7 +1,7 @@ import type { Value } from '../check/arbitrary/definition/Value.js'; import type { Random } from '../random/generator/Random.js'; import { Arbitrary } from '../check/arbitrary/definition/Arbitrary.js'; -import { Stream } from '../stream/Stream.js'; +import { nil } from '../utils/iterator.js'; /** @internal */ class NoShrinkArbitrary extends Arbitrary { @@ -14,8 +14,8 @@ class NoShrinkArbitrary extends Arbitrary { canShrinkWithoutContext(value: unknown): value is T { return this.arb.canShrinkWithoutContext(value); } - shrink(_value: T, _context?: unknown): Stream> { - return Stream.nil(); + shrink(_value: T, _context?: unknown): IteratorObject> { + return nil; } } diff --git a/packages/fast-check/src/check/arbitrary/definition/Arbitrary.ts b/packages/fast-check/src/check/arbitrary/definition/Arbitrary.ts index b5482f2f..99ec4bb3 100644 --- a/packages/fast-check/src/check/arbitrary/definition/Arbitrary.ts +++ b/packages/fast-check/src/check/arbitrary/definition/Arbitrary.ts @@ -1,6 +1,6 @@ import type { Random } from '../../../random/generator/Random.js'; -import { Stream } from '../../../stream/Stream.js'; import { cloneMethod, hasCloneMethod } from '../../symbols.js'; +import { joinAll, nil } from '../../../utils/iterator.js'; import { Value } from './Value.js'; /** @@ -53,7 +53,7 @@ export abstract class Arbitrary { * * @remarks Since 3.0.0 */ - abstract shrink(value: T, context: unknown | undefined): Stream>; + abstract shrink(value: T, context: unknown | undefined): IteratorObject>; /** * Create another arbitrary by filtering values against `predicate` @@ -171,15 +171,14 @@ class ChainArbitrary extends Arbitrary { // TODO Need unchainer return false; } - shrink(value: U, context?: unknown): Stream> { + shrink(value: U, context?: unknown): IteratorObject> { if (this.isSafeContext(context)) { - return ( + return joinAll([ !context.stoppedForOriginal ? this.arb .shrink(context.originalValue, context.originalContext) .map((v) => this.valueChainer(v, context.clonedMrng.clone(), context.clonedMrng, context.originalBias)) - : Stream.nil>() - ).join( + : nil, context.chainedArbitrary.shrink(value, context.chainedContext).map((dst) => { const newContext: ChainArbitraryContext = { ...context, @@ -188,10 +187,10 @@ class ChainArbitrary extends Arbitrary { }; return new Value(dst.value_, newContext); }), - ); + ]); } // TODO Need unchainer - return Stream.nil(); + return nil; } private valueChainer( v: Value, @@ -290,7 +289,7 @@ class MapArbitrary extends Arbitrary { } return false; } - shrink(value: U, context?: unknown): Stream> { + shrink(value: U, context?: unknown): IteratorObject> { if (this.isSafeContext(context)) { return this.arb.shrink(context.originalValue, context.originalContext).map(this.bindValueMapper); } @@ -301,7 +300,7 @@ class MapArbitrary extends Arbitrary { // we can safely consider `this.arb.canShrinkWithoutContext(unmapped)` to be true at that point. return this.arb.shrink(unmapped, undefined).map(this.bindValueMapper); } - return Stream.nil(); + return nil; } private isSafeContext(context: unknown): context is MapArbitraryContext { return ( @@ -335,7 +334,7 @@ class FilterArbitrary extends Arbitrary { canShrinkWithoutContext(value: unknown): value is U { return this.arb.canShrinkWithoutContext(value) && this.refinement(value); } - shrink(value: U, context?: unknown): Stream> { + shrink(value: U, context?: unknown): IteratorObject> { return this.arb.shrink(value, context).filter(this.bindRefinementOnValue); } private refinementOnValue(v: Value): v is Value { diff --git a/packages/fast-check/src/check/property/_internals/PropertyImplem.ts b/packages/fast-check/src/check/property/_internals/PropertyImplem.ts index 273a5beb..23e1a36b 100644 --- a/packages/fast-check/src/check/property/_internals/PropertyImplem.ts +++ b/packages/fast-check/src/check/property/_internals/PropertyImplem.ts @@ -5,7 +5,7 @@ import { runIdToFrequency } from './ToFrequency.js'; import type { GlobalPropertyHookFunction } from '../../runner/configuration/GlobalParameters.js'; import { readConfigureGlobal } from '../../runner/configuration/GlobalParameters.js'; import type { Value } from '../../arbitrary/definition/Value.js'; -import { Stream } from '../../../stream/Stream.js'; +import { nil } from '../../../utils/iterator.js'; import { noUndefinedAsContext, UndefinedContextPlaceholder, @@ -55,11 +55,11 @@ export class PropertyImplem implements PropertyWithHooks { return noUndefinedAsContext(value); } - shrink(value: Value): Stream> { + shrink(value: Value): IteratorObject> { if (value.context === undefined && !this.arb.canShrinkWithoutContext(value.value_)) { // `undefined` can only be coming from values derived from examples provided by the user // context set to `undefined` are automatically replaced by `UndefinedContextPlaceholder` in generate - return Stream.nil(); + return nil; } const safeContext = value.context !== UndefinedContextPlaceholder ? value.context : undefined; return this.arb.shrink(value.value_, safeContext).map(noUndefinedAsContext); diff --git a/packages/fast-check/src/check/property/plugins/IgnoreEqualValuesProperty.ts b/packages/fast-check/src/check/property/plugins/IgnoreEqualValuesProperty.ts index ee5c5584..aa73cd43 100644 --- a/packages/fast-check/src/check/property/plugins/IgnoreEqualValuesProperty.ts +++ b/packages/fast-check/src/check/property/plugins/IgnoreEqualValuesProperty.ts @@ -3,7 +3,6 @@ import type { Random } from '../../../random/generator/Random.js'; import { stringify } from '../../../utils/stringify.js'; import { PreconditionFailure } from '../../precondition/PreconditionFailure.js'; import type { Value } from '../../arbitrary/definition/Value.js'; -import type { Stream } from '../../../stream/Stream.js'; /** @internal */ function fromSyncCached( @@ -34,7 +33,7 @@ export class IgnoreEqualValuesProperty implements Property { return this.property.generate(mrng, runId); } - shrink(value: Value): Stream> { + shrink(value: Value): IteratorObject> { return this.property.shrink(value); } diff --git a/packages/fast-check/src/check/property/plugins/SkipAfterProperty.ts b/packages/fast-check/src/check/property/plugins/SkipAfterProperty.ts index 0dda5572..88fa8c10 100644 --- a/packages/fast-check/src/check/property/plugins/SkipAfterProperty.ts +++ b/packages/fast-check/src/check/property/plugins/SkipAfterProperty.ts @@ -1,5 +1,4 @@ import type { Random } from '../../../random/generator/Random.js'; -import type { Stream } from '../../../stream/Stream.js'; import type { Value } from '../../arbitrary/definition/Value.js'; import { PreconditionFailure } from '../../precondition/PreconditionFailure.js'; import type { Property } from '../types/Property.js'; @@ -40,7 +39,7 @@ export class SkipAfterProperty implements Property { return this.property.generate(mrng, runId); } - shrink(value: Value): Stream> { + shrink(value: Value): IteratorObject> { return this.property.shrink(value); } diff --git a/packages/fast-check/src/check/property/plugins/TimeoutProperty.ts b/packages/fast-check/src/check/property/plugins/TimeoutProperty.ts index 3776c024..77ed0120 100644 --- a/packages/fast-check/src/check/property/plugins/TimeoutProperty.ts +++ b/packages/fast-check/src/check/property/plugins/TimeoutProperty.ts @@ -1,5 +1,4 @@ import type { Random } from '../../../random/generator/Random.js'; -import type { Stream } from '../../../stream/Stream.js'; import type { Value } from '../../arbitrary/definition/Value.js'; import type { PreconditionFailure } from '../../precondition/PreconditionFailure.js'; import type { PropertyFailure } from '../types/PropertyFailure.js'; @@ -34,7 +33,7 @@ export class TimeoutProperty implements Property { return this.property.generate(mrng, runId); } - shrink(value: Value): Stream> { + shrink(value: Value): IteratorObject> { return this.property.shrink(value); } diff --git a/packages/fast-check/src/check/property/plugins/UnbiasedProperty.ts b/packages/fast-check/src/check/property/plugins/UnbiasedProperty.ts index 976fd063..ecdeb6fc 100644 --- a/packages/fast-check/src/check/property/plugins/UnbiasedProperty.ts +++ b/packages/fast-check/src/check/property/plugins/UnbiasedProperty.ts @@ -1,5 +1,4 @@ import type { Random } from '../../../random/generator/Random.js'; -import type { Stream } from '../../../stream/Stream.js'; import type { Value } from '../../arbitrary/definition/Value.js'; import type { Property } from '../types/Property.js'; @@ -11,7 +10,7 @@ export class UnbiasedProperty implements Property { return this.property.generate(mrng, undefined); } - shrink(value: Value): Stream> { + shrink(value: Value): IteratorObject> { return this.property.shrink(value); } diff --git a/packages/fast-check/src/check/property/types/Property.ts b/packages/fast-check/src/check/property/types/Property.ts index 8da43f7f..296418eb 100644 --- a/packages/fast-check/src/check/property/types/Property.ts +++ b/packages/fast-check/src/check/property/types/Property.ts @@ -1,5 +1,4 @@ import type { Random } from '../../../random/generator/Random.js'; -import type { Stream } from '../../../stream/Stream.js'; import type { Value } from '../../arbitrary/definition/Value.js'; import type { PreconditionFailure } from '../../precondition/PreconditionFailure.js'; import type { PropertyFailure } from './PropertyFailure.js'; @@ -32,7 +31,7 @@ export interface Property { * * @remarks Since 5.0.0 */ - shrink(value: Value): Stream>; + shrink(value: Value): IteratorObject>; /** * Check the predicate for v diff --git a/packages/fast-check/src/check/runner/Runner.ts b/packages/fast-check/src/check/runner/Runner.ts index 1f267532..bd9d3d55 100644 --- a/packages/fast-check/src/check/runner/Runner.ts +++ b/packages/fast-check/src/check/runner/Runner.ts @@ -1,4 +1,4 @@ -import { Stream, stream } from '../../stream/Stream.js'; +import { nil } from '../../utils/iterator.js'; import type { Property } from '../property/types/Property.js'; import { readConfigureGlobal } from './configuration/GlobalParameters.js'; import type { Parameters } from './configuration/Parameters.js'; @@ -154,9 +154,9 @@ function check(property: Property, params?: Parameters): Promise nil; const out = runIt(run, finalShrink, sourceValues, qParams.verbose, qParams.markInterruptAsFailure).then((e) => e.toRunDetails(qParams.seed, qParams.path, maxSkips, qParams), ); diff --git a/packages/fast-check/src/check/runner/Sampler.ts b/packages/fast-check/src/check/runner/Sampler.ts index 26f5e871..da857efc 100644 --- a/packages/fast-check/src/check/runner/Sampler.ts +++ b/packages/fast-check/src/check/runner/Sampler.ts @@ -1,4 +1,3 @@ -import { stream } from '../../stream/Stream.js'; import type { Arbitrary } from '../arbitrary/definition/Arbitrary.js'; import { PropertyImplem } from '../property/_internals/PropertyImplem.js'; import type { Property } from '../property/types/Property.js'; @@ -32,12 +31,8 @@ function streamSample( const shrink = nextProperty.shrink.bind(nextProperty); const tossedValues = qParams.path.length === 0 - ? stream(toss(nextProperty, qParams.seed, qParams.randomType, qParams.examples)) - : pathWalk( - qParams.path, - stream(lazyToss(nextProperty, qParams.seed, qParams.randomType, qParams.examples)), - shrink, - ); + ? toss(nextProperty, qParams.seed, qParams.randomType, qParams.examples) + : pathWalk(qParams.path, lazyToss(nextProperty, qParams.seed, qParams.randomType, qParams.examples), shrink); return tossedValues.take(qParams.numRuns).map((s) => s.value_); } diff --git a/packages/fast-check/src/check/runner/Tosser.ts b/packages/fast-check/src/check/runner/Tosser.ts index f7ff67fb..7be37dc4 100644 --- a/packages/fast-check/src/check/runner/Tosser.ts +++ b/packages/fast-check/src/check/runner/Tosser.ts @@ -25,7 +25,7 @@ export function* toss( seed: number, random: (seed: number) => QualifiedRandomGenerator, examples: Ts[], -): IterableIterator> { +): IteratorObject> { for (let idx = 0; idx !== examples.length; ++idx) { yield new Value(examples[idx], undefined); } @@ -49,7 +49,7 @@ export function* lazyToss( seed: number, random: (seed: number) => RandomGenerator, examples: Ts[], -): IterableIterator<() => Value> { +): IteratorObject<() => Value> { yield* examples.map((e) => () => new Value(e, undefined)); let idx = 0; const rng = adaptRandomGenerator(random(seed)); diff --git a/packages/fast-check/src/check/runner/utils/PathWalker.ts b/packages/fast-check/src/check/runner/utils/PathWalker.ts index 65632fa0..104fbfd2 100644 --- a/packages/fast-check/src/check/runner/utils/PathWalker.ts +++ b/packages/fast-check/src/check/runner/utils/PathWalker.ts @@ -1,5 +1,5 @@ import type { Value } from '../../arbitrary/definition/Value.js'; -import type { Stream } from '../../../stream/Stream.js'; +import { getNthOrLast } from '../../../utils/iterator.js'; /** @internal */ function produce(producer: () => Value): Value { @@ -9,10 +9,10 @@ function produce(producer: () => Value): Value { /** @internal */ export function pathWalk( path: string, - initialProducers: Stream<() => Value>, - shrink: (value: Value) => Stream>, -): Stream> { - const producers: Stream<() => Value> = initialProducers; + initialProducers: IteratorObject<() => Value>, + shrink: (value: Value) => IteratorObject>, +): IteratorObject> { + const producers: IteratorObject<() => Value> = initialProducers; const segments: number[] = path.split(':').map((text: string) => +text); if (segments.length === 0) { return producers.map(produce); @@ -20,9 +20,9 @@ export function pathWalk( if (!segments.every((v) => !Number.isNaN(v))) { throw new Error(`Unable to replay, got invalid path=${path}`); } - let values: Stream> = producers.drop(segments[0]).map(produce); + let values: IteratorObject> = producers.drop(segments[0]).map(produce); for (const s of segments.slice(1)) { - const valueToShrink = values.getNthOrLast(0); + const valueToShrink = getNthOrLast(values, 0); if (valueToShrink === null) { throw new Error(`Unable to replay, got wrong path=${path}`); } diff --git a/packages/fast-check/src/fast-check.ts b/packages/fast-check/src/fast-check.ts index 945c520c..55920c3c 100644 --- a/packages/fast-check/src/fast-check.ts +++ b/packages/fast-check/src/fast-check.ts @@ -148,7 +148,6 @@ export { ExecutionStatus } from './check/runner/reporter/ExecutionStatus.js'; export type { ExecutionTree } from './check/runner/reporter/ExecutionTree.js'; export type { WithCloneMethod } from './check/symbols.js'; export { cloneMethod, cloneIfNeeded, hasCloneMethod } from './check/symbols.js'; -export { Stream, stream } from './stream/Stream.js'; export { hash } from './utils/hash.js'; export type { WithToStringMethod, WithAsyncToStringMethod } from './utils/stringify.js'; export { diff --git a/packages/fast-check/src/stream/LazyIterableIterator.ts b/packages/fast-check/src/stream/LazyIterableIterator.ts deleted file mode 100644 index ce5fc174..00000000 --- a/packages/fast-check/src/stream/LazyIterableIterator.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** @internal */ -class LazyIterableIterator implements IterableIterator { - private it?: IterableIterator; - constructor(private readonly producer: () => IterableIterator) {} - - [Symbol.iterator]() { - if (this.it === undefined) { - this.it = this.producer(); - } - return this.it; - } - next() { - if (this.it === undefined) { - 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 - */ -export function makeLazy(producer: () => IterableIterator): IterableIterator { - return new LazyIterableIterator(producer); -} diff --git a/packages/fast-check/src/stream/Stream.ts b/packages/fast-check/src/stream/Stream.ts deleted file mode 100644 index 7bb83408..00000000 --- a/packages/fast-check/src/stream/Stream.ts +++ /dev/null @@ -1,248 +0,0 @@ -import { - filterHelper, - flatMapHelper, - joinHelper, - mapHelper, - nilHelper, - takeNHelper, - takeWhileHelper, -} from './StreamHelpers.js'; - -/** - * Wrapper around `IterableIterator` interface - * offering a set of helpers to deal with iterations in a simple way - * - * @remarks Since 0.0.7 - * @public - */ -export class Stream implements IterableIterator { - /** - * Create an empty stream of T - * @remarks Since 0.0.1 - */ - static nil(): Stream { - 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: T[]): Stream { - return new Stream(elements[Symbol.iterator]()); - } - - // /*DEBUG*/ // no double iteration - // /*DEBUG*/ private isLive: boolean; - - /** - * Create a Stream based on `g` - * @param g - Underlying data of the Stream - */ - constructor(/** @internal */ private readonly g: IterableIterator) { - // /*DEBUG*/ this.isLive = true; - } - - // /*DEBUG*/ private closeCurrentStream() { - // /*DEBUG*/ if (! this.isLive) throw new Error('Stream has already been closed'); - // /*DEBUG*/ this.isLive = false; - // /*DEBUG*/ } - - next(): IteratorResult { - return this.g.next(); - } - [Symbol.iterator](): IterableIterator { - // /*DEBUG*/ this.closeCurrentStream(); - 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: (v: T) => U): Stream { - // /*DEBUG*/ this.closeCurrentStream(); - 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: (v: T) => IterableIterator): Stream { - // /*DEBUG*/ this.closeCurrentStream(); - 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: (v: T) => boolean): Stream { - let foundEligible = false; - function* helper(v: T): IterableIterator { - 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: number): Stream { - if (n <= 0) { - return this; - } - let idx = 0; - function helper(): boolean { - 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: (v: T) => boolean): Stream { - // /*DEBUG*/ this.closeCurrentStream(); - 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: number): Stream { - // /*DEBUG*/ this.closeCurrentStream(); - return new Stream(takeNHelper(this.g, n)); - } - - /** - * Filter elements of the Stream - * - * WARNING: It closes the current stream - * - * @param f - Elements to keep - * @remarks Since 1.23.0 - */ - filter(f: (v: T) => v is U): Stream; - /** - * Filter elements of the Stream - * - * WARNING: It closes the current stream - * - * @param f - Elements to keep - * @remarks Since 0.0.1 - */ - filter(f: (v: T) => boolean): Stream; - filter(f: (v: T) => v is U): Stream { - // /*DEBUG*/ this.closeCurrentStream(); - 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: (v: T) => boolean): boolean { - // /*DEBUG*/ this.closeCurrentStream(); - 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: (v: T) => boolean): [boolean, T | null] { - // /*DEBUG*/ this.closeCurrentStream(); - 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: IterableIterator[]): Stream { - // /*DEBUG*/ this.closeCurrentStream(); - 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: number): T | null { - // /*DEBUG*/ this.closeCurrentStream(); - let remaining = nth; - let last: T | null = 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 - */ -export function stream(g: IterableIterator): Stream { - return new Stream(g); -} diff --git a/packages/fast-check/src/stream/StreamHelpers.ts b/packages/fast-check/src/stream/StreamHelpers.ts deleted file mode 100644 index 75e3b912..00000000 --- a/packages/fast-check/src/stream/StreamHelpers.ts +++ /dev/null @@ -1,77 +0,0 @@ -// The functions in this file have been extracted from Stream.ts -// for performance reasons -// -// They were originally defined as anonymous functions -// Most of the methods of Stream were calling Stream.prototype.flatMap (eg.: map, filter...) - -class Nil implements IterableIterator { - [Symbol.iterator](): IterableIterator { - return this; - } - next(value?: any): IteratorResult { - return { value, done: true }; - } -} - -/** @internal */ -const nil = new Nil(); - -/** @internal */ -export function nilHelper(): IterableIterator { - return nil; -} - -/** @internal */ -export function* mapHelper(g: IterableIterator, f: (v: T) => U): IterableIterator { - for (const v of g) { - yield f(v); - } -} - -/** @internal */ -export function* flatMapHelper(g: IterableIterator, f: (v: T) => IterableIterator): IterableIterator { - for (const v of g) { - yield* f(v); - } -} - -/** @internal */ -export function* filterHelper(g: IterableIterator, f: (v: T) => v is U): IterableIterator { - for (const v of g) { - if (f(v)) { - yield v; - } - } -} - -/** @internal */ -export function* takeNHelper(g: IterableIterator, n: number): IterableIterator { - for (let i = 0; i < n; ++i) { - const cur = g.next(); - if (cur.done) { - break; - } - yield cur.value; - } -} - -/** @internal */ -export function* takeWhileHelper(g: IterableIterator, f: (v: T) => boolean): IterableIterator { - let cur = g.next(); - while (!cur.done && f(cur.value)) { - yield cur.value; - cur = g.next(); - } -} - -/** @internal */ -export function* joinHelper(g: IterableIterator, others: IterableIterator[]): IterableIterator { - 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; - } - } -} diff --git a/packages/fast-check/src/utils/iterator.ts b/packages/fast-check/src/utils/iterator.ts new file mode 100644 index 00000000..fac7e17e --- /dev/null +++ b/packages/fast-check/src/utils/iterator.ts @@ -0,0 +1,49 @@ +class Nil implements IterableIterator { + [Symbol.iterator](): IterableIterator { + return this; + } + next(value?: any): IteratorResult { + return { value, done: true }; + } +} + +export const nil: IteratorObject = Iterator.from(new Nil()); + +export function getNthOrLast(it: IterableIterator, nth: number): T | null { + let remaining = nth; + let last: T | null = null; + for (const v of it) { + if (remaining-- === 0) return v; + last = v; + } + return last; +} + +export function* joinAll(its: IteratorObject[]): IteratorObject { + let last!: U; + for (const s of its) { + let cur = s.next(); + for (; !cur.done; cur = s.next()) { + yield cur.value; + } + last = cur.value; + } + return last; +} + +class LazyIterator extends Iterator { + private it?: IteratorObject; + constructor(private readonly producer: () => IteratorObject) { + super(); + } + next(...[value]: [] | [any]): IteratorResult { + if (this.it === undefined) { + this.it = this.producer(); + } + return this.it.next(value); + } +} + +export function makeLazy(producer: () => IteratorObject): IteratorObject { + return new LazyIterator(producer); +} diff --git a/packages/fast-check/test/e2e/NoStackOverflowOnShrink.spec.ts b/packages/fast-check/test/e2e/NoStackOverflowOnShrink.spec.ts index 7aa6c647..0491dc3d 100644 --- a/packages/fast-check/test/e2e/NoStackOverflowOnShrink.spec.ts +++ b/packages/fast-check/test/e2e/NoStackOverflowOnShrink.spec.ts @@ -50,11 +50,11 @@ describe(`NoStackOverflowOnShrink (seed: ${seed})`, () => { canShrinkWithoutContext(_value: unknown): _value is number { return false; } - shrink(value: number): fc.Stream> { + shrink(value: number): IteratorObject> { if (value <= -maxDepthForArrays) { - return fc.Stream.nil(); + return Iterator.from([]); } - return fc.Stream.of(new fc.Value(value - 1, undefined)); + return Iterator.from([new fc.Value(value - 1, undefined)]); } } diff --git a/packages/fast-check/test/e2e/StateFullArbitraries.spec.ts b/packages/fast-check/test/e2e/StateFullArbitraries.spec.ts index 980261fd..6f8aad55 100644 --- a/packages/fast-check/test/e2e/StateFullArbitraries.spec.ts +++ b/packages/fast-check/test/e2e/StateFullArbitraries.spec.ts @@ -18,8 +18,8 @@ describe(`StateFullArbitraries (seed: ${seed})`, () => { canShrinkWithoutContext(_value: unknown): _value is any { return false; } - shrink(): fc.Stream> { - return fc.Stream.nil(); + shrink(): IteratorObject> { + return Iterator.from([]); } })(); it('normal property', async () => { diff --git a/packages/fast-check/test/unit/arbitrary/__test-helpers__/ArbitraryAssertions.ts b/packages/fast-check/test/unit/arbitrary/__test-helpers__/ArbitraryAssertions.ts index 0ad8109c..1c869498 100644 --- a/packages/fast-check/test/unit/arbitrary/__test-helpers__/ArbitraryAssertions.ts +++ b/packages/fast-check/test/unit/arbitrary/__test-helpers__/ArbitraryAssertions.ts @@ -1,4 +1,5 @@ import { expect } from 'vitest'; +import { getNthOrLast } from '../../../../src/utils/iterator.js'; import { xorshift128plus } from 'pure-rand/generator/xorshift128plus'; import * as fc from 'fast-check'; import { assertNoPoisoning, restoreGlobals } from '@fast-check/poisoning'; @@ -65,8 +66,8 @@ export function assertProduceSameValueGivenSameSeed( while (g1 !== null && g2 !== null) { assertEquality(isEqual, g1.value, g2.value, extraParameters); const pos = shrinkPath.next().value; - g1 = arb.shrink(g1.value_, g1.context).getNthOrLast(pos); - g2 = arb.shrink(g2.value_, g2.context).getNthOrLast(pos); + g1 = getNthOrLast(arb.shrink(g1.value_, g1.context), pos); + g2 = getNthOrLast(arb.shrink(g2.value_, g2.context), pos); } expect(g1).toBe(null); expect(g2).toBe(null); @@ -107,7 +108,7 @@ export function assertProduceCorrectValues( while (g !== null) { assertCorrectness(isCorrect, g.value, extraParameters, arb); const pos = shrinkPath.next().value; - g = arb.shrink(g.value, g.context).getNthOrLast(pos); + g = getNthOrLast(arb.shrink(g.value, g.context), pos); } expect(g).toBe(null); }, diff --git a/packages/fast-check/test/unit/arbitrary/__test-helpers__/ArbitraryHelpers.ts b/packages/fast-check/test/unit/arbitrary/__test-helpers__/ArbitraryHelpers.ts index cd87bbec..7d292436 100644 --- a/packages/fast-check/test/unit/arbitrary/__test-helpers__/ArbitraryHelpers.ts +++ b/packages/fast-check/test/unit/arbitrary/__test-helpers__/ArbitraryHelpers.ts @@ -3,7 +3,6 @@ import type { MaybeMocked, MockWithArgs } from '../../__test-helpers__/Mocked.js import { Arbitrary } from '../../../../src/check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../../../src/check/arbitrary/definition/Value.js'; import type { Random } from '../../../../src/random/generator/Random.js'; -import { Stream } from '../../../../src/stream/Stream.js'; /** * Generate a fake Class inheriting from Arbitrary with all methods being mocked @@ -81,12 +80,12 @@ export class FakeIntegerArbitrary extends Arbitrary { Number.isInteger(value) ); } - shrink(value: number, context?: unknown): Stream> { + shrink(value: number, context?: unknown): IteratorObject> { const currentStep = context !== undefined ? (context as { step: number }).step : 2; const nextStep = currentStep + 1; - return Stream.of( + return Iterator.from([ ...(value - currentStep >= this.offset ? [new Value(value - currentStep, { step: nextStep })] : []), ...(value - currentStep + 1 >= this.offset ? [new Value(value - currentStep + 1, { step: nextStep })] : []), - ); + ]); } } diff --git a/packages/fast-check/test/unit/arbitrary/_internals/AdapterArbitrary.spec.ts b/packages/fast-check/test/unit/arbitrary/_internals/AdapterArbitrary.spec.ts index 0b43f717..98be81b7 100644 --- a/packages/fast-check/test/unit/arbitrary/_internals/AdapterArbitrary.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/_internals/AdapterArbitrary.spec.ts @@ -4,7 +4,6 @@ import { adapter } from '../../../../src/arbitrary/_internals/AdapterArbitrary.j import { Value } from '../../../../src/check/arbitrary/definition/Value.js'; import { fakeArbitrary } from '../__test-helpers__/ArbitraryHelpers.js'; import { fakeRandom } from '../__test-helpers__/RandomHelpers.js'; -import { Stream } from '../../../../src/stream/Stream.js'; import * as fc from 'fast-check'; describe('AdapterArbitrary', () => { @@ -125,7 +124,7 @@ describe('AdapterArbitrary', () => { const valueAB = new Value(vAB, cAB); const { instance, generate, shrink, canShrinkWithoutContext } = fakeArbitrary(); generate.mockReturnValueOnce(valueA); - shrink.mockReturnValueOnce(Stream.of(valueAA, valueAB)); + shrink.mockReturnValueOnce(Iterator.from([valueAA, valueAB])); canShrinkWithoutContext.mockReturnValue(canShrinkIfAdapted); const { instance: mrng } = fakeRandom(); const adapterFunction = vi @@ -216,7 +215,9 @@ describe('AdapterArbitrary', () => { const valueABC = new Value(vABC, cABC); const { instance, generate, shrink, canShrinkWithoutContext } = fakeArbitrary(); generate.mockReturnValueOnce(valueA); - shrink.mockReturnValueOnce(Stream.of(valueAA, valueAB, valueAC)).mockReturnValueOnce(Stream.of(valueABC)); + shrink + .mockReturnValueOnce(Iterator.from([valueAA, valueAB, valueAC])) + .mockReturnValueOnce(Iterator.from([valueABC])); if (adaptedA.adapted) canShrinkWithoutContext.mockReturnValueOnce(true); canShrinkWithoutContext.mockReturnValueOnce(canShrinkIfAdapted); const { instance: mrng } = fakeRandom(); @@ -285,7 +286,7 @@ describe('AdapterArbitrary', () => { const valueAA = new Value(vAA, cAA); const valueAB = new Value(vAB, cAB); const { instance, generate, shrink, canShrinkWithoutContext } = fakeArbitrary(); - shrink.mockReturnValueOnce(Stream.of(valueAA, valueAB)); + shrink.mockReturnValueOnce(Iterator.from([valueAA, valueAB])); const adapterFunction = vi .fn<(arg0: any) => AdapterOutput>() .mockImplementation((v) => (Object.is(v, vAA) ? adaptedAA : adaptedAB)); diff --git a/packages/fast-check/test/unit/arbitrary/_internals/ArrayArbitrary.spec.ts b/packages/fast-check/test/unit/arbitrary/_internals/ArrayArbitrary.spec.ts index 6375bbd9..f0ef8610 100644 --- a/packages/fast-check/test/unit/arbitrary/_internals/ArrayArbitrary.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/_internals/ArrayArbitrary.spec.ts @@ -1,4 +1,5 @@ import { describe, it, expect, vi } from 'vitest'; +import { nil } from '../../../../src/utils/iterator.js'; import * as fc from 'fast-check'; import { mersenne } from 'pure-rand/generator/mersenne'; @@ -6,7 +7,6 @@ import { ArrayArbitrary } from '../../../../src/arbitrary/_internals/ArrayArbitr import { Value } from '../../../../src/check/arbitrary/definition/Value.js'; import { MaxLengthUpperBound } from '../../../../src/arbitrary/_internals/helpers/MaxLengthFromMinLength.js'; import type { CustomSet } from '../../../../src/arbitrary/_internals/interfaces/CustomSet.js'; -import { Stream } from '../../../../src/stream/Stream.js'; import { cloneMethod, hasCloneMethod } from '../../../../src/check/symbols.js'; import { Arbitrary } from '../../../../src/check/arbitrary/definition/Arbitrary.js'; import { Random } from '../../../../src/random/generator/Random.js'; @@ -633,14 +633,14 @@ class CloneableArbitrary extends Arbitrary { canShrinkWithoutContext(_value: unknown): _value is number[] { throw new Error('No call expected in that scenario'); } - shrink(value: number[], context?: unknown): Stream> { + shrink(value: number[], context?: unknown): IteratorObject> { if (typeof context !== 'object' || context === null || !('shrunkOnce' in context)) { throw new Error('Invalid context for CloneableArbitrary'); } const safeContext = context as { shrunkOnce: boolean }; if (safeContext.shrunkOnce) { - return Stream.nil(); + return nil; } - return Stream.of(new Value(this.instance(), { shrunkOnce: true })); + return Iterator.from([new Value(this.instance(), { shrunkOnce: true })]); } } diff --git a/packages/fast-check/test/unit/arbitrary/_internals/BigIntArbitrary.spec.ts b/packages/fast-check/test/unit/arbitrary/_internals/BigIntArbitrary.spec.ts index 4fffebf9..d5ad2b4b 100644 --- a/packages/fast-check/test/unit/arbitrary/_internals/BigIntArbitrary.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/_internals/BigIntArbitrary.spec.ts @@ -1,4 +1,5 @@ import { describe, it, expect, vi } from 'vitest'; +import { nil } from '../../../../src/utils/iterator.js'; import * as fc from 'fast-check'; import { BigIntArbitrary } from '../../../../src/arbitrary/_internals/BigIntArbitrary.js'; import { Value } from '../../../../src/check/arbitrary/definition/Value.js'; @@ -11,7 +12,6 @@ import { assertProduceSameValueGivenSameSeed, } from '../__test-helpers__/ArbitraryAssertions.js'; import { buildShrinkTree, renderTree, walkTree } from '../__test-helpers__/ShrinkTree.js'; -import { Stream } from '../../../../src/stream/Stream.js'; import * as BiasNumericRangeMock from '../../../../src/arbitrary/_internals/helpers/BiasNumericRange.js'; import * as ShrinkBigIntMock from '../../../../src/arbitrary/_internals/helpers/ShrinkBigInt.js'; @@ -187,7 +187,7 @@ describe('BigIntArbitrary', () => { fc.asyncProperty(fc.bigInt(), fc.bigInt(), fc.bigInt(), (a, b, c) => { // Arrange const [min, mid, max] = [a, b, c].sort((v1, v2) => Number(v1 - v2)); - const expectedShrinks = Stream.nil>(); + const expectedShrinks = nil; const shrinkBigInt = vi.spyOn(ShrinkBigIntMock, 'shrinkBigInt'); shrinkBigInt.mockReturnValueOnce(expectedShrinks); diff --git a/packages/fast-check/test/unit/arbitrary/_internals/CloneArbitrary.spec.ts b/packages/fast-check/test/unit/arbitrary/_internals/CloneArbitrary.spec.ts index a97d34ff..46eda3a1 100644 --- a/packages/fast-check/test/unit/arbitrary/_internals/CloneArbitrary.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/_internals/CloneArbitrary.spec.ts @@ -1,11 +1,11 @@ import { describe, it, expect, vi } from 'vitest'; +import { nil } from '../../../../src/utils/iterator.js'; import * as fc from 'fast-check'; import { CloneArbitrary } from '../../../../src/arbitrary/_internals/CloneArbitrary.js'; import { Arbitrary } from '../../../../src/check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../../../src/check/arbitrary/definition/Value.js'; import { cloneMethod, hasCloneMethod } from '../../../../src/check/symbols.js'; import type { Random } from '../../../../src/random/generator/Random.js'; -import { Stream } from '../../../../src/stream/Stream.js'; import { assertProduceValuesShrinkableWithoutContext, assertProduceCorrectValues, @@ -129,9 +129,9 @@ describe('CloneArbitrary', () => { const numValues = 3; const { instance: sourceArb, shrink } = fakeArbitrary(); shrink - .mockReturnValueOnce(Stream.of>(new Value(s1, undefined), new Value(s2, undefined))) - .mockReturnValueOnce(Stream.of>(new Value(s1, undefined), new Value(s2, undefined))) - .mockReturnValueOnce(Stream.of>(new Value(s1, undefined), new Value(s2, undefined))); + .mockReturnValueOnce(Iterator.from>([new Value(s1, undefined), new Value(s2, undefined)])) + .mockReturnValueOnce(Iterator.from>([new Value(s1, undefined), new Value(s2, undefined)])) + .mockReturnValueOnce(Iterator.from>([new Value(s1, undefined), new Value(s2, undefined)])); // Act const arb = new CloneArbitrary(sourceArb, numValues); @@ -235,19 +235,19 @@ class FirstArbitrary extends Arbitrary { canShrinkWithoutContext(_value: unknown): _value is number { throw new Error('No call expected in that scenario'); } - shrink(value: number, context?: unknown): Stream> { + shrink(value: number, context?: unknown): IteratorObject> { if (typeof context !== 'object' || context === null || !('step' in context)) { throw new Error('Invalid context for FirstArbitrary'); } if (value <= 0) { - return Stream.nil(); + return nil; } const currentStep = (context as { step: number }).step; const nextStep = currentStep + 1; - return Stream.of( + return Iterator.from([ ...(value - currentStep >= 0 ? [new Value(value - currentStep, { step: nextStep })] : []), ...(value - currentStep + 1 >= 0 ? [new Value(value - currentStep + 1, { step: nextStep })] : []), - ); + ]); } } @@ -261,14 +261,14 @@ class CloneableArbitrary extends Arbitrary { canShrinkWithoutContext(_value: unknown): _value is number[] { throw new Error('No call expected in that scenario'); } - shrink(value: number[], context?: unknown): Stream> { + shrink(value: number[], context?: unknown): IteratorObject> { if (typeof context !== 'object' || context === null || !('shrunkOnce' in context)) { throw new Error('Invalid context for CloneableArbitrary'); } const safeContext = context as { shrunkOnce: boolean }; if (safeContext.shrunkOnce) { - return Stream.nil(); + return nil; } - return Stream.of(new Value(this.instance(), { shrunkOnce: true })); + return Iterator.from([new Value(this.instance(), { shrunkOnce: true })]); } } diff --git a/packages/fast-check/test/unit/arbitrary/_internals/FrequencyArbitrary.spec.ts b/packages/fast-check/test/unit/arbitrary/_internals/FrequencyArbitrary.spec.ts index 4369191e..0156f61f 100644 --- a/packages/fast-check/test/unit/arbitrary/_internals/FrequencyArbitrary.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/_internals/FrequencyArbitrary.spec.ts @@ -12,7 +12,6 @@ import { assertShrinkProducesStrictlySmallerValue, } from '../__test-helpers__/ArbitraryAssertions.js'; import * as DepthContextMock from '../../../../src/arbitrary/_internals/helpers/DepthContext.js'; -import { Stream } from '../../../../src/stream/Stream.js'; import { sizeArb } from '../__test-helpers__/SizeHelpers.js'; function beforeEachHook() { @@ -402,7 +401,7 @@ describe('FrequencyArbitrary', () => { const { instance: mrng, nextInt } = fakeRandom(); nextInt.mockImplementation(() => totalWeightBefore + (generateSeed % selectedArbitrary.weight)); selectedArbitrary.arbitraryMeta.shrink.mockReturnValue( - Stream.of(new Value(1, undefined), new Value(42, undefined)), + Iterator.from([new Value(1, undefined), new Value(42, undefined)]), ); // Act @@ -445,7 +444,7 @@ describe('FrequencyArbitrary', () => { clone.mockReturnValue(anotherMrng); nextInt.mockImplementation(() => totalWeightBefore + (generateSeed % selectedArbitrary.weight)); selectedArbitrary.arbitraryMeta.shrink.mockReturnValue( - Stream.of(new Value(1, undefined), new Value(42, undefined)), + Iterator.from([new Value(1, undefined), new Value(42, undefined)]), ); // Act @@ -479,7 +478,9 @@ describe('FrequencyArbitrary', () => { const { instance: mrng, nextInt } = fakeRandom(); nextInt.mockReturnValue(0); - warbs[0].arbitraryMeta.shrink.mockReturnValue(Stream.of(new Value(1, undefined), new Value(42, undefined))); + warbs[0].arbitraryMeta.shrink.mockReturnValue( + Iterator.from([new Value(1, undefined), new Value(42, undefined)]), + ); // Act const arb = FrequencyArbitrary.from(warbs, { ...constraints, withCrossShrink: true }, 'test'); @@ -515,7 +516,7 @@ describe('FrequencyArbitrary', () => { const can = index === selectedIndex; input.arbitraryMeta.canShrinkWithoutContext.mockReturnValue(can); input.arbitraryMeta.shrink.mockReturnValue( - Stream.of(new Value(42, undefined), new Value(index, undefined)), + Iterator.from([new Value(42, undefined), new Value(index, undefined)]), ); } @@ -552,7 +553,7 @@ describe('FrequencyArbitrary', () => { const can = index === selectedIndex; input.arbitraryMeta.canShrinkWithoutContext.mockReturnValue(can); input.arbitraryMeta.shrink.mockReturnValue( - Stream.of(new Value(42, undefined), new Value(index, undefined)), + Iterator.from([new Value(42, undefined), new Value(index, undefined)]), ); } warbs[0].fallbackValue = { default: 48 }; diff --git a/packages/fast-check/test/unit/arbitrary/_internals/GeneratorArbitrary.spec.ts b/packages/fast-check/test/unit/arbitrary/_internals/GeneratorArbitrary.spec.ts index 50144450..dcc9b077 100644 --- a/packages/fast-check/test/unit/arbitrary/_internals/GeneratorArbitrary.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/_internals/GeneratorArbitrary.spec.ts @@ -1,8 +1,8 @@ import { describe, it, expect } from 'vitest'; +import { getNthOrLast } from '../../../../src/utils/iterator.js'; import { GeneratorArbitrary } from '../../../../src/arbitrary/_internals/GeneratorArbitrary.js'; import { Value } from '../../../../src/check/arbitrary/definition/Value.js'; import type { Random } from '../../../../src/random/generator/Random.js'; -import { Stream } from '../../../../src/stream/Stream.js'; import type { MockWithArgs } from '../../__test-helpers__/Mocked.js'; import { fakeArbitrary } from '../__test-helpers__/ArbitraryHelpers.js'; import { fakeRandom } from '../__test-helpers__/RandomHelpers.js'; @@ -183,7 +183,7 @@ describe('GeneratorArbitrary', () => { // > d, a, 1 // > a, b, 1 // > a, c, 1 - const genValueB = g.shrink(genA, genValueA.context).getNthOrLast(4); // a, c, 1 + const genValueB = getNthOrLast(g.shrink(genA, genValueA.context), 4); // a, c, 1 const genB = genValueB!.value; seenValues.push([genB(() => first.instance), genB(() => first.instance), genB(() => third.instance)]); expect(third.offsetOnLastCall()).toBe(2); @@ -192,7 +192,7 @@ describe('GeneratorArbitrary', () => { // > b, c, A // > c, c, A // > d, c, A - const genValueC = g.shrink(genB, genValueB!.context).getNthOrLast(2); // d, c, A + const genValueC = getNthOrLast(g.shrink(genB, genValueB!.context), 2); // d, c, A const genC = genValueC!.value; seenValues.push([genC(() => first.instance), genC(() => first.instance), genC(() => third.instance)]); // Shrink third level @@ -201,14 +201,14 @@ describe('GeneratorArbitrary', () => { // > h, c, A // > d, e, A // > d, f, A - const genValueD = g.shrink(genC, genValueC!.context).getNthOrLast(3); // d, f, A + const genValueD = getNthOrLast(g.shrink(genC, genValueC!.context), 3); // d, f, A const genD = genValueD!.value; seenValues.push([genD(() => first.instance), genD(() => first.instance)]); // Shrink fourth level // d, f // > g, f // > h, f - const genValueE = g.shrink(genD, genValueD!.context).getNthOrLast(1); // h, f + const genValueE = getNthOrLast(g.shrink(genD, genValueD!.context), 1); // h, f const genE = genValueE!.value; seenValues.push([ genE(() => first.instance), @@ -266,7 +266,7 @@ function buildArbitraryForGen(value: string, shrinks: Map) { }); shrink.mockImplementation((value) => { const subValues = shrinks.get(value) ?? []; - return new Stream(subValues.map((v) => new Value(v, `c${v}`))[Symbol.iterator]()); + return Iterator.from(subValues.map((v) => new Value(v, `c${v}`))); }); return { instance, generate, shrink, offsetOnLastCall: () => offset }; diff --git a/packages/fast-check/test/unit/arbitrary/_internals/IntegerArbitrary.spec.ts b/packages/fast-check/test/unit/arbitrary/_internals/IntegerArbitrary.spec.ts index 6c43ae0c..7d9075dd 100644 --- a/packages/fast-check/test/unit/arbitrary/_internals/IntegerArbitrary.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/_internals/IntegerArbitrary.spec.ts @@ -1,4 +1,5 @@ import { describe, it, expect, vi } from 'vitest'; +import { nil } from '../../../../src/utils/iterator.js'; import type { MockInstance } from 'vitest'; import * as fc from 'fast-check'; import { IntegerArbitrary } from '../../../../src/arbitrary/_internals/IntegerArbitrary.js'; @@ -15,7 +16,6 @@ import { buildShrinkTree, renderTree, walkTree } from '../__test-helpers__/Shrin import * as BiasNumericRangeMock from '../../../../src/arbitrary/_internals/helpers/BiasNumericRange.js'; import * as ShrinkIntegerMock from '../../../../src/arbitrary/_internals/helpers/ShrinkInteger.js'; -import { Stream } from '../../../../src/stream/Stream.js'; import { declareCleaningHooksForSpies } from '../__test-helpers__/SpyCleaner.js'; describe('IntegerArbitrary', () => { @@ -194,7 +194,7 @@ describe('IntegerArbitrary', () => { fc.asyncProperty(fc.maxSafeNat(), fc.maxSafeNat(), fc.maxSafeNat(), (a, b, c) => { // Arrange const [min, mid, max] = [a, b, c].sort((v1, v2) => v1 - v2); - const expectedShrinks = Stream.nil>(); + const expectedShrinks = nil; const shrinkInteger = vi.spyOn(ShrinkIntegerMock, 'shrinkInteger'); shrinkInteger.mockReturnValueOnce(expectedShrinks); diff --git a/packages/fast-check/test/unit/arbitrary/_internals/LazyArbitrary.spec.ts b/packages/fast-check/test/unit/arbitrary/_internals/LazyArbitrary.spec.ts index 8e6941db..19295b5a 100644 --- a/packages/fast-check/test/unit/arbitrary/_internals/LazyArbitrary.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/_internals/LazyArbitrary.spec.ts @@ -1,7 +1,6 @@ import { describe, it, expect } from 'vitest'; import { LazyArbitrary } from '../../../../src/arbitrary/_internals/LazyArbitrary.js'; import { Value } from '../../../../src/check/arbitrary/definition/Value.js'; -import { Stream } from '../../../../src/stream/Stream.js'; import { fakeArbitrary } from '../__test-helpers__/ArbitraryHelpers.js'; import { fakeRandom } from '../__test-helpers__/RandomHelpers.js'; @@ -73,7 +72,7 @@ describe('LazyArbitrary', () => { // Arrange const value = Symbol(); const context = Symbol(); - const streamOutput = Stream.of(new Value(1, undefined)); + const streamOutput = Iterator.from([new Value(1, undefined)]); const { instance: underlying, shrink } = fakeArbitrary(); shrink.mockReturnValue(streamOutput); const lazy = new LazyArbitrary('id007'); diff --git a/packages/fast-check/test/unit/arbitrary/_internals/LimitedShrinkArbitrary.spec.ts b/packages/fast-check/test/unit/arbitrary/_internals/LimitedShrinkArbitrary.spec.ts index b20486a9..d9ac2dee 100644 --- a/packages/fast-check/test/unit/arbitrary/_internals/LimitedShrinkArbitrary.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/_internals/LimitedShrinkArbitrary.spec.ts @@ -1,7 +1,6 @@ import { describe, it, expect } from 'vitest'; import * as fc from 'fast-check'; import { Value } from '../../../../src/check/arbitrary/definition/Value.js'; -import { Stream } from '../../../../src/stream/Stream.js'; import { fakeRandom } from '../__test-helpers__/RandomHelpers.js'; import { declareCleaningHooksForSpies } from '../__test-helpers__/SpyCleaner.js'; @@ -82,7 +81,9 @@ describe('LimitedShrinkArbitrary', () => { const { instance: mrng } = fakeRandom(); const { instance: arbitrary, generate, shrink } = fakeArbitrary(); generate.mockReturnValueOnce(value); - shrink.mockReturnValueOnce(Stream.of(...shrunkValues.map(([value, context]) => new Value(value, context)))); + shrink.mockReturnValueOnce( + Iterator.from(shrunkValues.map(([value, context]) => new Value(value, context))), + ); // Act const arb = new LimitedShrinkArbitrary(arbitrary, maxShrinks); @@ -139,12 +140,12 @@ describe('LimitedShrinkArbitrary', () => { const { instance: mrng } = fakeRandom(); const { instance: arbitrary, generate, shrink } = fakeArbitrary(); generate.mockReturnValueOnce(value); - shrink.mockImplementation((): Stream> => { + shrink.mockImplementation((): IteratorObject> => { const itShrinks = shrunkValuesLevels.next(); if (itShrinks.done) { throw new Error('Not possible, only added for typings'); } - return new Stream(itShrinks.value.map(([value, context]) => new Value(value, context))); + return itShrinks.value.map(([value, context]) => new Value(value, context)); }); // Act / Assert diff --git a/packages/fast-check/test/unit/arbitrary/_internals/StreamArbitrary.spec.ts b/packages/fast-check/test/unit/arbitrary/_internals/StreamArbitrary.spec.ts index e39199d4..8ebacd83 100644 --- a/packages/fast-check/test/unit/arbitrary/_internals/StreamArbitrary.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/_internals/StreamArbitrary.spec.ts @@ -1,9 +1,9 @@ import { describe, it, expect, vi } from 'vitest'; +import { nil } from '../../../../src/utils/iterator.js'; import * as fc from 'fast-check'; import { StreamArbitrary } from '../../../../src/arbitrary/_internals/StreamArbitrary.js'; import { Value } from '../../../../src/check/arbitrary/definition/Value.js'; import { cloneIfNeeded, cloneMethod, hasCloneMethod } from '../../../../src/check/symbols.js'; -import { Stream } from '../../../../src/stream/Stream.js'; import { assertProduceCorrectValues, assertProduceSameValueGivenSameSeed, @@ -31,7 +31,7 @@ describe('StreamArbitrary', () => { const out = arb.generate(mrng, biasFactor); // Assert - expect(out.value).toBeInstanceOf(Stream); + expect(out.value).toBeInstanceOf(Iterator); expect(out.hasToBeCloned).toBe(true); expect(hasCloneMethod(out.value)).toBe(true); }), @@ -217,7 +217,7 @@ describe('StreamArbitrary', () => { }), )); - it('should create independent Stream even in terms of toString', async () => + it('should create independent Stream', async () => await fc.assert( fc.asyncProperty(fc.boolean(), (history) => { // Arrange @@ -239,34 +239,41 @@ describe('StreamArbitrary', () => { const stream2 = out.value; const values1 = [...stream1.take(2)]; const values2 = [...stream2.take(3)]; - const values1Bis = [...stream1.take(2)]; // Assert - expect(values1).toEqual([0, 1]); + const expectedFromStream1 = [0, 1]; + expect(values1).toEqual(expectedFromStream1); + const expectedFromStream2 = [2, 3, 4]; expect(values2).toEqual([2, 3, 4]); - expect(values1Bis).toEqual([5, 6]); const stream1String = String(stream1); const stream2String = String(stream2); - [0, 1, 5, 6].forEach((v) => { - expect(stream2String).not.toMatch(`\\<${v}\\>`); - }); - [2, 3, 4].forEach((v) => { - expect(stream1String).not.toMatch(`\\<${v}\\>`); - }); - expect(generate).toHaveBeenCalledTimes(7); + for (const v of expectedFromStream1) { + expect(stream2String).not.toMatch(`<${v}>`); + if (history) { + expect(stream1String).toMatch(`<${v}>`); + } + } + for (const v of expectedFromStream2) { + expect(stream1String).not.toMatch(`<${v}>`); + if (history) { + expect(stream2String).toMatch(`<${v}>`); + } + } + expect(generate).toHaveBeenCalledTimes(expectedFromStream1.length + expectedFromStream2.length); }), )); }); describe('canShrinkWithoutContext', () => { - function* infiniteG() { + function* infiniteG(): IteratorObject { yield 1; + return undefined; } it.each` - data | description - ${Stream.nil()} | ${'empty stream'} - ${Stream.of(1, 5, 6, 74, 4)} | ${'finite stream'} - ${new Stream(infiniteG())} | ${'infinite stream'} + data | description + ${nil} | ${'empty stream'} + ${Iterator.from([1, 5, 6, 74, 4])} | ${'finite stream'} + ${infiniteG()} | ${'infinite stream'} `('should return false for any Stream whatever the size ($description)', ({ data }) => { // Arrange const { instance: sourceArb, canShrinkWithoutContext } = fakeArbitrary(); @@ -326,12 +333,12 @@ describe('StreamArbitrary', () => { describe('StreamArbitrary (integration)', () => { const sourceArb = new FakeIntegerArbitrary(); - const isEqual = (s1: Stream, s2: Stream) => { + const isEqual = (s1: IteratorObject, s2: IteratorObject) => { expect([...cloneIfNeeded(s1).take(10)]).toEqual([...cloneIfNeeded(s2).take(10)]); }; - const isCorrect = (value: Stream) => - value instanceof Stream && [...value.take(10)].every((v) => sourceArb.canShrinkWithoutContext(v)); + const isCorrect = (value: IteratorObject) => + value instanceof Iterator && [...value.take(10)].every((v) => sourceArb.canShrinkWithoutContext(v)); const streamBuilder = () => new StreamArbitrary(sourceArb, true); diff --git a/packages/fast-check/test/unit/arbitrary/_internals/TupleArbitrary.spec.ts b/packages/fast-check/test/unit/arbitrary/_internals/TupleArbitrary.spec.ts index a7c0fdf2..05ad7701 100644 --- a/packages/fast-check/test/unit/arbitrary/_internals/TupleArbitrary.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/_internals/TupleArbitrary.spec.ts @@ -1,10 +1,10 @@ import { describe, it, expect, vi } from 'vitest'; +import { nil } from '../../../../src/utils/iterator.js'; import { TupleArbitrary } from '../../../../src/arbitrary/_internals/TupleArbitrary.js'; import { Value } from '../../../../src/check/arbitrary/definition/Value.js'; import { FakeIntegerArbitrary, fakeArbitrary } from '../__test-helpers__/ArbitraryHelpers.js'; import { fakeRandom } from '../__test-helpers__/RandomHelpers.js'; import { cloneMethod, hasCloneMethod } from '../../../../src/check/symbols.js'; -import { Stream } from '../../../../src/stream/Stream.js'; import { assertProduceValuesShrinkableWithoutContext, assertProduceCorrectValues, @@ -173,14 +173,16 @@ describe('TupleArbitrary', () => { const shrinkC1 = Symbol(); const shrinkC2 = Symbol(); const shrinkC3 = Symbol(); - shrinkA.mockReturnValueOnce(Stream.of(new Value(shrinkA1 as symbol, undefined), new Value(shrinkA2, undefined))); - shrinkB.mockReturnValueOnce(Stream.of(new Value(shrinkB1 as symbol, undefined))); + shrinkA.mockReturnValueOnce( + Iterator.from([new Value(shrinkA1 as symbol, undefined), new Value(shrinkA2, undefined)]), + ); + shrinkB.mockReturnValueOnce(Iterator.from([new Value(shrinkB1 as symbol, undefined)])); shrinkC.mockReturnValueOnce( - Stream.of( + Iterator.from([ new Value(shrinkC1 as symbol, undefined), new Value(shrinkC2, undefined), new Value(shrinkC3, undefined), - ), + ]), ); const { instance: mrng } = fakeRandom(); @@ -226,13 +228,19 @@ describe('TupleArbitrary', () => { .fn() .mockImplementation(() => Object.defineProperty([], cloneMethod, { value: cloneMethodImpl })); generateA.mockReturnValue(new Value([], undefined)); - shrinkA.mockReturnValue(Stream.of(...Array.from({ length: numShrinksA }).map(() => new Value([], undefined)))); + shrinkA.mockReturnValue( + Iterator.from([...Array.from({ length: numShrinksA }).map(() => new Value([], undefined))]), + ); generateB.mockReturnValue( new Value(Object.defineProperty([], cloneMethod, { value: cloneMethodImpl }), undefined), ); - shrinkB.mockReturnValue(Stream.of(...Array.from({ length: numShrinksB }).map(() => new Value([], undefined)))); + shrinkB.mockReturnValue( + Iterator.from([...Array.from({ length: numShrinksB }).map(() => new Value([], undefined))]), + ); generateC.mockReturnValue(new Value([], undefined)); - shrinkC.mockReturnValue(Stream.of(...Array.from({ length: numShrinksC }).map(() => new Value([], undefined)))); + shrinkC.mockReturnValue( + Iterator.from([...Array.from({ length: numShrinksC }).map(() => new Value([], undefined))]), + ); const { instance: mrng } = fakeRandom(); // Act @@ -404,19 +412,19 @@ class FirstArbitrary extends Arbitrary { canShrinkWithoutContext(_value: unknown): _value is number { throw new Error('No call expected in that scenario'); } - shrink(value: number, context?: unknown): Stream> { + shrink(value: number, context?: unknown): IteratorObject> { if (typeof context !== 'object' || context === null || !('step' in context)) { throw new Error('Invalid context for FirstArbitrary'); } if (value <= 0) { - return Stream.nil(); + return nil; } const currentStep = (context as { step: number }).step; const nextStep = currentStep + 1; - return Stream.of( + return Iterator.from([ ...(value - currentStep >= 0 ? [new Value(value - currentStep, { step: nextStep })] : []), ...(value - currentStep + 1 >= 0 ? [new Value(value - currentStep + 1, { step: nextStep })] : []), - ); + ]); } } class SecondArbitrary extends Arbitrary { @@ -426,19 +434,19 @@ class SecondArbitrary extends Arbitrary { canShrinkWithoutContext(_value: unknown): _value is number { throw new Error('No call expected in that scenario'); } - shrink(value: number, context?: unknown): Stream> { + shrink(value: number, context?: unknown): IteratorObject> { if (typeof context !== 'object' || context === null || !('step' in context)) { throw new Error('Invalid context for SecondArbitrary'); } if (value >= 100) { - return Stream.nil(); + return nil; } const currentStep = (context as { step: number }).step; const nextStep = currentStep + 1; - return Stream.of( + return Iterator.from([ ...(value + currentStep <= 100 ? [new Value(value + currentStep, { step: nextStep })] : []), ...(value + currentStep - 1 <= 100 ? [new Value(value + currentStep - 1, { step: nextStep })] : []), - ); + ]); } } @@ -452,14 +460,14 @@ class CloneableArbitrary extends Arbitrary { canShrinkWithoutContext(_value: unknown): _value is number[] { throw new Error('No call expected in that scenario'); } - shrink(value: number[], context?: unknown): Stream> { + shrink(value: number[], context?: unknown): IteratorObject> { if (typeof context !== 'object' || context === null || !('shrunkOnce' in context)) { throw new Error('Invalid context for CloneableArbitrary'); } const safeContext = context as { shrunkOnce: boolean }; if (safeContext.shrunkOnce) { - return Stream.nil(); + return nil; } - return Stream.of(new Value(this.instance(), { shrunkOnce: true })); + return Iterator.from([new Value(this.instance(), { shrunkOnce: true })]); } } diff --git a/packages/fast-check/test/unit/arbitrary/_internals/WithShrinkFromOtherArbitrary.spec.ts b/packages/fast-check/test/unit/arbitrary/_internals/WithShrinkFromOtherArbitrary.spec.ts index 32b4c1d2..b9c2141d 100644 --- a/packages/fast-check/test/unit/arbitrary/_internals/WithShrinkFromOtherArbitrary.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/_internals/WithShrinkFromOtherArbitrary.spec.ts @@ -3,7 +3,6 @@ import { WithShrinkFromOtherArbitrary } from '../../../../src/arbitrary/_interna import { Value } from '../../../../src/check/arbitrary/definition/Value.js'; import { fakeArbitrary } from '../__test-helpers__/ArbitraryHelpers.js'; import { fakeRandom } from '../__test-helpers__/RandomHelpers.js'; -import { Stream } from '../../../../src/stream/Stream.js'; import * as fc from 'fast-check'; describe('WithShrinkFromOtherArbitrary', () => { @@ -115,7 +114,7 @@ describe('WithShrinkFromOtherArbitrary', () => { canShrinkWithoutContext: canShrinkWithoutContextB, } = fakeArbitrary(); generateA.mockReturnValueOnce(new Value(vA, cA)); - shrinkA.mockReturnValueOnce(Stream.of(new Value(vAA, cAA), new Value(vAB, cAB))); + shrinkA.mockReturnValueOnce(Iterator.from([new Value(vAA, cAA), new Value(vAB, cAB)])); const { instance: mrng } = fakeRandom(); // Act @@ -167,8 +166,8 @@ describe('WithShrinkFromOtherArbitrary', () => { canShrinkWithoutContext: canShrinkWithoutContextB, } = fakeArbitrary(); generateA.mockReturnValueOnce(new Value(vA, cA)); - shrinkA.mockReturnValueOnce(Stream.of(new Value(vAA, cAA), new Value(vAB, cAB), new Value(vAC, cAC))); - shrinkA.mockReturnValueOnce(Stream.of(new Value(vABA, cABA))); + shrinkA.mockReturnValueOnce(Iterator.from([new Value(vAA, cAA), new Value(vAB, cAB), new Value(vAC, cAC)])); + shrinkA.mockReturnValueOnce(Iterator.from([new Value(vABA, cABA)])); const { instance: mrng } = fakeRandom(); // Act @@ -214,7 +213,7 @@ describe('WithShrinkFromOtherArbitrary', () => { shrink: shrinkB, canShrinkWithoutContext: canShrinkWithoutContextB, } = fakeArbitrary(); - shrinkB.mockReturnValueOnce(Stream.of(new Value(vAA, cAA), new Value(vAB, cAB))); + shrinkB.mockReturnValueOnce(Iterator.from([new Value(vAA, cAA), new Value(vAB, cAB)])); // Act const arb = new WithShrinkFromOtherArbitrary(generatorArbitrary, shrinkerArbitrary); @@ -262,8 +261,8 @@ describe('WithShrinkFromOtherArbitrary', () => { shrink: shrinkB, canShrinkWithoutContext: canShrinkWithoutContextB, } = fakeArbitrary(); - shrinkB.mockReturnValueOnce(Stream.of(new Value(vAA, cAA), new Value(vAB, cAB), new Value(vAC, cAC))); - shrinkB.mockReturnValueOnce(Stream.of(new Value(vABA, cABA))); + shrinkB.mockReturnValueOnce(Iterator.from([new Value(vAA, cAA), new Value(vAB, cAB), new Value(vAC, cAC)])); + shrinkB.mockReturnValueOnce(Iterator.from([new Value(vABA, cABA)])); // Act const arb = new WithShrinkFromOtherArbitrary(generatorArbitrary, shrinkerArbitrary); diff --git a/packages/fast-check/test/unit/arbitrary/_internals/helpers/ShrinkBigInt.spec.ts b/packages/fast-check/test/unit/arbitrary/_internals/helpers/ShrinkBigInt.spec.ts index 8d754f8a..e1191196 100644 --- a/packages/fast-check/test/unit/arbitrary/_internals/helpers/ShrinkBigInt.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/_internals/helpers/ShrinkBigInt.spec.ts @@ -1,4 +1,5 @@ import { describe, it, expect } from 'vitest'; +import { getNthOrLast } from '../../../../../src/utils/iterator.js'; import * as fc from 'fast-check'; import { shrinkBigInt } from '../../../../../src/arbitrary/_internals/helpers/ShrinkBigInt.js'; @@ -91,7 +92,7 @@ describe('shrinkBigInt', () => { const expectedFirstContext = tryAsap ? undefined : target; // Act - const first = shrinkBigInt(current, target, tryAsap).getNthOrLast(0); + const first = getNthOrLast(shrinkBigInt(current, target, tryAsap), 0); // Assert if (first !== null) { diff --git a/packages/fast-check/test/unit/arbitrary/_internals/helpers/ShrinkInteger.spec.ts b/packages/fast-check/test/unit/arbitrary/_internals/helpers/ShrinkInteger.spec.ts index dda0166a..970af22e 100644 --- a/packages/fast-check/test/unit/arbitrary/_internals/helpers/ShrinkInteger.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/_internals/helpers/ShrinkInteger.spec.ts @@ -1,4 +1,5 @@ import { describe, it, expect } from 'vitest'; +import { getNthOrLast } from '../../../../../src/utils/iterator.js'; import * as fc from 'fast-check'; import { shrinkInteger } from '../../../../../src/arbitrary/_internals/helpers/ShrinkInteger.js'; @@ -89,7 +90,7 @@ describe('shrinkInteger', () => { const expectedFirstContext = tryAsap ? undefined : target; // Act - const first = shrinkInteger(current, target, tryAsap).getNthOrLast(0); + const first = getNthOrLast(shrinkInteger(current, target, tryAsap), 0); // Assert if (first !== null) { diff --git a/packages/fast-check/test/unit/arbitrary/_internals/implementations/SchedulerImplem.spec.ts b/packages/fast-check/test/unit/arbitrary/_internals/implementations/SchedulerImplem.spec.ts index 51700432..4525443e 100644 --- a/packages/fast-check/test/unit/arbitrary/_internals/implementations/SchedulerImplem.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/_internals/implementations/SchedulerImplem.spec.ts @@ -2381,7 +2381,7 @@ describe('SchedulerImplem', () => { // Helpers -function buildSeededNextTaskIndex(seeds: fc.Stream, nextTaskIndexLengths: number[] = []) { +function buildSeededNextTaskIndex(seeds: IteratorObject, nextTaskIndexLengths: number[] = []) { const nextTaskIndex = vi.fn().mockImplementation((scheduledTasks: ScheduledTask[]) => { const seed = seeds.next(); if (seed.done) { diff --git a/packages/fast-check/test/unit/arbitrary/chainUntil.spec.ts b/packages/fast-check/test/unit/arbitrary/chainUntil.spec.ts index e6801bf5..4b08314b 100644 --- a/packages/fast-check/test/unit/arbitrary/chainUntil.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/chainUntil.spec.ts @@ -1,8 +1,8 @@ import { describe, expect, it, vi } from 'vitest'; import { Value } from '../../../src/check/arbitrary/definition/Value.js'; import { Arbitrary } from '../../../src/check/arbitrary/definition/Arbitrary.js'; -import { Stream } from '../../../src/stream/Stream.js'; import { chainUntil } from '../../../src/arbitrary/chainUntil.js'; +import { nil } from '../../../src/utils/iterator.js'; import * as stubRng from '../stubs/generators.js'; import { buildShrinkTree, renderTree } from './__test-helpers__/ShrinkTree.js'; import type { Random } from '../../../src/random/generator/Random.js'; @@ -33,7 +33,7 @@ describe('chainUntil', () => { canShrinkWithoutContext(_value: unknown): _value is number { return false; } - shrink = vi.fn().mockReturnValue(Stream.nil()); + shrink = vi.fn().mockReturnValue(nil); } // Act @@ -57,8 +57,8 @@ describe('chainUntil', () => { canShrinkWithoutContext(_value: unknown): _value is number { return false; } - shrink(): Stream> { - return Stream.nil(); + shrink(): IteratorObject> { + return nil; } } const startArb = new NumArb(1); @@ -91,8 +91,8 @@ describe('chainUntil', () => { canShrinkWithoutContext(_value: unknown): _value is number { return false; } - shrink(): Stream> { - return Stream.nil(); + shrink(): IteratorObject> { + return nil; } } const chainer = (prev: number): Arbitrary | undefined => { @@ -119,8 +119,8 @@ describe('chainUntil', () => { canShrinkWithoutContext(_value: unknown): _value is number { return false; } - shrink(): Stream> { - return Stream.of(new Value(42, undefined)); + shrink(): IteratorObject> { + return Iterator.from([new Value(42, undefined)]); } } @@ -141,10 +141,10 @@ describe('chainUntil', () => { canShrinkWithoutContext(_value: unknown): _value is number { return false; } - shrink(value: number, context?: unknown): Stream> { + shrink(value: number, context?: unknown): IteratorObject> { const ctx = context as { step: number }; - if (value - ctx.step < 0) return Stream.nil(); - return Stream.of(new Value(value - ctx.step, { step: ctx.step + 1 })); + if (value - ctx.step < 0) return nil; + return Iterator.from([new Value(value - ctx.step, { step: ctx.step + 1 })]); } } @@ -176,10 +176,10 @@ describe('chainUntil', () => { canShrinkWithoutContext(_value: unknown): _value is number { return false; } - shrink(_value: number, context?: unknown): Stream> { - if (context !== 'ctx') return Stream.nil(); - if (this.shrinkVal === undefined) return Stream.nil(); - return Stream.of(new Value(this.shrinkVal, 'ctx-shrunk')); + shrink(_value: number, context?: unknown): IteratorObject> { + if (context !== 'ctx') return nil; + if (this.shrinkVal === undefined) return nil; + return Iterator.from([new Value(this.shrinkVal, 'ctx-shrunk')]); } } const chainer = vi.fn((prev: number): Arbitrary | undefined => { @@ -219,13 +219,13 @@ describe('chainUntil', () => { canShrinkWithoutContext(_value: unknown): _value is string { return false; } - shrink(value: string, context?: unknown): Stream> { - if (context === undefined) return Stream.nil(); + shrink(value: string, context?: unknown): IteratorObject> { + if (context === undefined) return nil; const parts = value.split('-'); const last = parts[parts.length - 1]; - if (last === last.toLowerCase()) return Stream.nil(); + if (last === last.toLowerCase()) return nil; parts[parts.length - 1] = last.toLowerCase(); - return Stream.of(new Value(parts.join('-'), 'ctx')); + return Iterator.from([new Value(parts.join('-'), 'ctx')]); } } @@ -275,8 +275,8 @@ describe('chainUntil', () => { canShrinkWithoutContext(_value: unknown): _value is number { return false; } - shrink(): Stream> { - return Stream.nil(); + shrink(): IteratorObject> { + return nil; } } @@ -318,11 +318,11 @@ describe('chainUntil', () => { canShrinkWithoutContext(_value: unknown): _value is number { return false; } - shrink(value: number, context?: unknown): Stream> { - if (context !== 'has-context') return Stream.nil(); - if (value <= 0) return Stream.nil(); + shrink(value: number, context?: unknown): IteratorObject> { + if (context !== 'has-context') return nil; + if (value <= 0) return nil; // Shrink to value - 1 - return Stream.of(new Value(value - 1, 'has-context')); + return Iterator.from([new Value(value - 1, 'has-context')]); } } @@ -367,13 +367,13 @@ describe('chainUntil', () => { canShrinkWithoutContext(_value: unknown): _value is string { return false; } - shrink(value: string, context?: unknown): Stream> { - if (context !== 'ctx') return Stream.nil(); + shrink(value: string, context?: unknown): IteratorObject> { + if (context !== 'ctx') return nil; const parts = value.split('-'); const last = parts[parts.length - 1]; - if (last === last.toLowerCase()) return Stream.nil(); + if (last === last.toLowerCase()) return nil; parts[parts.length - 1] = last.toLowerCase(); - return Stream.of(new Value(parts.join('-'), 'ctx')); + return Iterator.from([new Value(parts.join('-'), 'ctx')]); } } diff --git a/packages/fast-check/test/unit/arbitrary/commands.spec.ts b/packages/fast-check/test/unit/arbitrary/commands.spec.ts index 0b0bc145..01812a87 100644 --- a/packages/fast-check/test/unit/arbitrary/commands.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/commands.spec.ts @@ -1,4 +1,5 @@ import { describe, it, expect } from 'vitest'; +import { getNthOrLast, nil } from '../../../src/utils/iterator.js'; import * as fc from 'fast-check'; import { commands } from '../../../src/arbitrary/commands.js'; @@ -7,7 +8,6 @@ import type { Command } from '../../../src/check/model/command/Command.js'; import { Random } from '../../../src/random/generator/Random.js'; import { Arbitrary } from '../../../src/check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../../src/check/arbitrary/definition/Value.js'; -import { Stream } from '../../../src/stream/Stream.js'; import { tuple } from '../../../src/arbitrary/tuple.js'; import { nat } from '../../../src/arbitrary/nat.js'; import { isStrictlySmallerArray } from './__test-helpers__/ArrayHelpers.js'; @@ -180,16 +180,16 @@ describe('commands (integration)', () => { // Traverse the shrink tree in order to detect already seen ids while (currentValue !== null) { - currentValue = manyArbsIncludingCommandsOne - .shrink(currentValue.value_, currentValue.context) - .map((nextValue) => { + currentValue = getNthOrLast( + manyArbsIncludingCommandsOne.shrink(currentValue.value_, currentValue.context).map((nextValue) => { // Check nothing starting for the next one assertCommandsNotStarted(nextValue); // Start everything: not supposed to impact any other shrinkable startCommands(nextValue); return nextValue; - }) - .getNthOrLast(it.next().value); + }), + it.next().value, + ); } }, ), @@ -216,9 +216,8 @@ describe('commands (integration)', () => { const extractIdRegex = /^custom\((\d+)\)$/; while (currentValue !== null) { const currentItems = [...currentValue.value_].map((c) => +extractIdRegex.exec(c.toString())![1]); - currentValue = commandsArb - .shrink(currentValue.value_, currentValue.context) - .map((nextValue) => { + currentValue = getNthOrLast( + commandsArb.shrink(currentValue.value_, currentValue.context).map((nextValue) => { // Run all commands of nextShrinkable simulateCommands(nextValue.value_); // Check nextShrinkable is strictly smaller than current one @@ -226,8 +225,9 @@ describe('commands (integration)', () => { expect(isStrictlySmallerArray(nextItems, currentItems)).toBe(true); // Next is eligible for shrinking return nextValue; - }) - .getNthOrLast(it.next().value); + }), + it.next().value, + ); } }, ), @@ -305,8 +305,8 @@ class FakeConstant extends Arbitrary { canShrinkWithoutContext(_value: unknown): _value is Cmd { return false; } - shrink(): Stream> { - return Stream.nil(); + shrink(): IteratorObject> { + return nil; } } diff --git a/packages/fast-check/test/unit/arbitrary/dictionary.spec.ts b/packages/fast-check/test/unit/arbitrary/dictionary.spec.ts index 76d0f075..4efa1b24 100644 --- a/packages/fast-check/test/unit/arbitrary/dictionary.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/dictionary.spec.ts @@ -1,4 +1,5 @@ import { describe, it, expect } from 'vitest'; +import { nil } from '../../../src/utils/iterator.js'; import * as fc from 'fast-check'; import type { DictionaryConstraints } from '../../../src/arbitrary/dictionary.js'; import { dictionary } from '../../../src/arbitrary/dictionary.js'; @@ -6,7 +7,6 @@ import { dictionary } from '../../../src/arbitrary/dictionary.js'; import { Arbitrary } from '../../../src/check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../../src/check/arbitrary/definition/Value.js'; import type { Random } from '../../../src/random/generator/Random.js'; -import { Stream } from '../../../src/stream/Stream.js'; import { assertProduceSameValueGivenSameSeed, assertProduceCorrectValues, @@ -104,8 +104,8 @@ class FromKeysArbitrary extends Arbitrary { canShrinkWithoutContext(value: unknown): value is K { return this.keys.includes(value as any); } - shrink(_value: K, _context?: unknown): Stream> { - return Stream.nil(); + shrink(_value: K, _context?: unknown): IteratorObject> { + return nil; } } @@ -121,7 +121,7 @@ class FromValuesArbitrary extends Arbitrary { // includes might mix 0 and -0 return this.source.includes(value as any); } - shrink(_value: V, _context?: unknown): Stream> { - return Stream.nil(); + shrink(_value: V, _context?: unknown): IteratorObject> { + return nil; } } diff --git a/packages/fast-check/test/unit/arbitrary/func.spec.ts b/packages/fast-check/test/unit/arbitrary/func.spec.ts index 8f545306..6354ff6b 100644 --- a/packages/fast-check/test/unit/arbitrary/func.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/func.spec.ts @@ -1,4 +1,5 @@ import { describe, it, expect } from 'vitest'; +import { nil } from '../../../src/utils/iterator.js'; import * as fc from 'fast-check'; import { func } from '../../../src/arbitrary/func.js'; @@ -6,7 +7,6 @@ import { Arbitrary } from '../../../src/check/arbitrary/definition/Arbitrary.js' import { Value } from '../../../src/check/arbitrary/definition/Value.js'; import { hasCloneMethod, cloneIfNeeded, cloneMethod } from '../../../src/check/symbols.js'; import type { Random } from '../../../src/random/generator/Random.js'; -import { Stream } from '../../../src/stream/Stream.js'; import { assertProduceCorrectValues, assertProduceSameValueGivenSameSeed, @@ -110,12 +110,12 @@ describe('func (integration)', () => { canShrinkWithoutContext(_value: unknown): _value is number[] { throw new Error('No call expected in that scenario'); } - shrink(value: number[], context?: unknown): Stream> { + shrink(value: number[], context?: unknown): IteratorObject> { const safeContext = context as { shrunkOnce: boolean }; if (safeContext.shrunkOnce) { - return Stream.nil(); + return nil; } - return Stream.of(new Value(this.instance(0, value[1] === 1), { shrunkOnce: true })); + return Iterator.from([new Value(this.instance(0, value[1] === 1), { shrunkOnce: true })]); } } await assertProduceCorrectValues( diff --git a/packages/fast-check/test/unit/arbitrary/letrec.spec.ts b/packages/fast-check/test/unit/arbitrary/letrec.spec.ts index 0b02f347..ce1bee14 100644 --- a/packages/fast-check/test/unit/arbitrary/letrec.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/letrec.spec.ts @@ -2,7 +2,6 @@ import { describe, it, expect } from 'vitest'; import { letrec } from '../../../src/arbitrary/letrec.js'; import { LazyArbitrary } from '../../../src/arbitrary/_internals/LazyArbitrary.js'; import { Value } from '../../../src/check/arbitrary/definition/Value.js'; -import { Stream } from '../../../src/stream/Stream.js'; import { FakeIntegerArbitrary, fakeArbitrary } from './__test-helpers__/ArbitraryHelpers.js'; import { fakeRandom } from './__test-helpers__/RandomHelpers.js'; import { @@ -282,7 +281,7 @@ describe('letrec', () => { // Arrange const expectedValue = Symbol(); const expectedContext = Symbol(); - const expectedStream = Stream.of(new Value(Symbol(), undefined)); + const expectedStream = Iterator.from([new Value(Symbol(), undefined)]); const { instance: simpleArb, shrink } = fakeArbitrary(); shrink.mockReturnValueOnce(expectedStream); const { arb1 } = letrec((tie) => { diff --git a/packages/fast-check/test/unit/arbitrary/map.spec.ts b/packages/fast-check/test/unit/arbitrary/map.spec.ts index 8326781a..6ac31d1d 100644 --- a/packages/fast-check/test/unit/arbitrary/map.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/map.spec.ts @@ -1,4 +1,5 @@ import { describe, it, expect } from 'vitest'; +import { nil } from '../../../src/utils/iterator.js'; import * as fc from 'fast-check'; import type { MapConstraints } from '../../../src/arbitrary/map.js'; import { map } from '../../../src/arbitrary/map.js'; @@ -6,7 +7,6 @@ import { map } from '../../../src/arbitrary/map.js'; import { Arbitrary } from '../../../src/check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../../src/check/arbitrary/definition/Value.js'; import type { Random } from '../../../src/random/generator/Random.js'; -import { Stream } from '../../../src/stream/Stream.js'; import { assertProduceSameValueGivenSameSeed, assertProduceCorrectValues, @@ -90,8 +90,8 @@ class FromKeysArbitrary extends Arbitrary { canShrinkWithoutContext(value: unknown): value is K { return this.sourceAsSet.has(value as K); } - shrink(_value: K, _context?: unknown): Stream> { - return Stream.nil(); + shrink(_value: K, _context?: unknown): IteratorObject> { + return nil; } } @@ -106,7 +106,7 @@ class FromValuesArbitrary extends Arbitrary { canShrinkWithoutContext(value: unknown): value is V { return this.source.some((v) => Object.is(v, value)); } - shrink(_value: V, _context?: unknown): Stream> { - return Stream.nil(); + shrink(_value: V, _context?: unknown): IteratorObject> { + return nil; } } diff --git a/packages/fast-check/test/unit/arbitrary/noBias.spec.ts b/packages/fast-check/test/unit/arbitrary/noBias.spec.ts index 3848834a..e36c60e6 100644 --- a/packages/fast-check/test/unit/arbitrary/noBias.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/noBias.spec.ts @@ -1,7 +1,6 @@ import { describe, it, vi, expect } from 'vitest'; import { Arbitrary } from '../../../src/check/arbitrary/definition/Arbitrary.js'; import type { Value } from '../../../src/check/arbitrary/definition/Value.js'; -import type { Stream } from '../../../src/stream/Stream.js'; import { noBias } from '../../../src/arbitrary/noBias.js'; import * as stubRng from '../stubs/generators.js'; @@ -16,7 +15,7 @@ describe('noBias', () => { canShrinkWithoutContext(_value: unknown): _value is any { throw new Error('Not implemented.'); } - shrink(): Stream> { + shrink(): IteratorObject> { throw new Error('Not implemented.'); } } @@ -40,7 +39,7 @@ describe('noBias', () => { canShrinkWithoutContext(_value: unknown): _value is any { throw new Error('Not implemented.'); } - shrink(): Stream> { + shrink(): IteratorObject> { throw new Error('Not implemented.'); } } @@ -65,7 +64,7 @@ describe('noBias', () => { canShrinkWithoutContext(_value: unknown): _value is any { throw new Error('Not implemented.'); } - shrink(): Stream> { + shrink(): IteratorObject> { throw new Error('Not implemented.'); } } diff --git a/packages/fast-check/test/unit/arbitrary/noShrink.spec.ts b/packages/fast-check/test/unit/arbitrary/noShrink.spec.ts index 05d0bdcd..f4a143de 100644 --- a/packages/fast-check/test/unit/arbitrary/noShrink.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/noShrink.spec.ts @@ -3,7 +3,6 @@ import { Value } from '../../../src/check/arbitrary/definition/Value.js'; import { Arbitrary } from '../../../src/check/arbitrary/definition/Arbitrary.js'; import { noShrink } from '../../../src/arbitrary/noShrink.js'; import * as stubRng from '../stubs/generators.js'; -import type { Stream } from '../../../src/stream/Stream.js'; const mrngNoCall = stubRng.mutable.nocall(); @@ -63,7 +62,7 @@ describe('noShrink', () => { canShrinkWithoutContext(_value: unknown): _value is any { throw new Error('Not implemented.'); } - shrink(): Stream> { + shrink(): IteratorObject> { throw new Error('Not implemented.'); } } @@ -88,7 +87,7 @@ describe('noShrink', () => { canShrinkWithoutContext(_value: unknown): _value is any { throw new Error('Not implemented.'); } - shrink(): Stream> { + shrink(): IteratorObject> { throw new Error('Not implemented.'); } } diff --git a/packages/fast-check/test/unit/arbitrary/string.spec.ts b/packages/fast-check/test/unit/arbitrary/string.spec.ts index f66fbb6b..96c23a9d 100644 --- a/packages/fast-check/test/unit/arbitrary/string.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/string.spec.ts @@ -1,4 +1,5 @@ import { describe, it, expect } from 'vitest'; +import { nil } from '../../../src/utils/iterator.js'; import * as fc from 'fast-check'; import { string } from '../../../src/arbitrary/string.js'; import type { StringConstraints } from '../../../src/arbitrary/string.js'; @@ -13,7 +14,6 @@ import { import { buildShrinkTree, renderTree } from './__test-helpers__/ShrinkTree.js'; import { Arbitrary } from '../../../src/check/arbitrary/definition/Arbitrary.js'; import type { Random } from '../../../src/random/generator/Random.js'; -import { Stream } from '../../../src/stream/Stream.js'; describe('string (integration)', () => { type Extra = StringConstraints; @@ -48,7 +48,6 @@ describe('string (integration)', () => { case 'grapheme-composite': case 'grapheme-ascii': case undefined: { - // @ts-expect-error Not available with our current preset for TypeScript const segmenter = new Intl.Segmenter(); return [...segmenter.segment(value)].length; } @@ -67,7 +66,6 @@ describe('string (integration)', () => { case 'grapheme': return; case 'grapheme-composite': { - // @ts-expect-error Not available with our current preset for TypeScript const segmenter = new Intl.Segmenter(); expect([...segmenter.segment(value)].map((s) => s.segment)).toEqual([...value]); // assert: grapheme equivalent to code-point return; @@ -228,11 +226,11 @@ class PatternsArbitrary extends Arbitrary { if (typeof value !== 'string') return false; return this.patterns.includes(value); } - shrink(value: string): Stream> { + shrink(value: string): IteratorObject> { const patternIndex = this.patterns.indexOf(value); if (patternIndex <= 0) { - return Stream.nil(); + return nil; } - return Stream.of(new Value(this.patterns[0], undefined)); + return Iterator.from([new Value(this.patterns[0], undefined)]); } } diff --git a/packages/fast-check/test/unit/check/arbitrary/definition/Arbitrary.itest.spec.ts b/packages/fast-check/test/unit/check/arbitrary/definition/Arbitrary.itest.spec.ts index 2ec2a966..9406fd90 100644 --- a/packages/fast-check/test/unit/check/arbitrary/definition/Arbitrary.itest.spec.ts +++ b/packages/fast-check/test/unit/check/arbitrary/definition/Arbitrary.itest.spec.ts @@ -1,10 +1,10 @@ import { describe, it, expect } from 'vitest'; +import { nil } from '../../../../../src/utils/iterator.js'; import { Arbitrary } from '../../../../../src/check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../../../../src/check/arbitrary/definition/Value.js'; import { cloneMethod, hasCloneMethod } from '../../../../../src/check/symbols.js'; import type { Random } from '../../../../../src/random/generator/Random.js'; -import { Stream } from '../../../../../src/stream/Stream.js'; import * as stubRng from '../../../stubs/generators.js'; import { buildShrinkTree, renderTree, walkTree } from '../../../arbitrary/__test-helpers__/ShrinkTree.js'; @@ -22,16 +22,16 @@ describe('Arbitrary', () => { canShrinkWithoutContext(_value: unknown): _value is number { throw new Error('No call expected in current scenario'); } - shrink(value: number, context?: unknown): Stream> { + shrink(value: number, context?: unknown): IteratorObject> { if (typeof context !== 'object' || context === null || !('step' in context)) { throw new Error('Invalid context for MyArbitrary'); } const currentStep = (context as { step: number }).step; const nextStep = currentStep + 1; - return Stream.of( + return Iterator.from([ ...(value - currentStep >= 0 ? [new Value(value - currentStep, { step: nextStep })] : []), ...(value - 1 >= 0 ? [new Value(value - 1, { step: nextStep })] : []), - ); + ]); } } const arb = new MyArbitrary().map((n) => String(n)); @@ -113,12 +113,12 @@ describe('Arbitrary', () => { canShrinkWithoutContext(_value: unknown): _value is MyArbitraryOutput { throw new Error('No call expected in current scenario'); } - shrink(v: MyArbitraryOutput, _context?: unknown): Stream> { + shrink(v: MyArbitraryOutput, _context?: unknown): IteratorObject> { const value = v.value; - return Stream.of( + return Iterator.from([ ...(value - 2 >= 0 ? [new Value(this.create(value - 2), undefined)] : []), ...(value - 1 >= 0 ? [new Value(this.create(value - 1), undefined)] : []), - ); + ]); } } const seenInstances = new Set(); @@ -155,12 +155,12 @@ describe('Arbitrary', () => { canShrinkWithoutContext(_value: unknown): _value is MyArbitraryOutput { throw new Error('No call expected in current scenario'); } - shrink(v: MyArbitraryOutput, _context?: unknown): Stream> { + shrink(v: MyArbitraryOutput, _context?: unknown): IteratorObject> { const value = v.value; - return Stream.of( + return Iterator.from([ ...(value - 2 >= 0 ? [new Value(this.create(value - 2), undefined)] : []), ...(value - 1 >= 0 ? [new Value(this.create(value - 1), undefined)] : []), - ); + ]); } } const seenInstances = new Set(); @@ -194,16 +194,16 @@ describe('Arbitrary', () => { canShrinkWithoutContext(_value: unknown): _value is number { throw new Error('No call expected in current scenario'); } - shrink(value: number, context?: unknown): Stream> { + shrink(value: number, context?: unknown): IteratorObject> { if (typeof context !== 'object' || context === null || !('step' in context)) { throw new Error('Invalid context for MyArbitrary'); } const currentStep = (context as { step: number }).step; if (value - currentStep < 0) { - return Stream.nil(); + return nil; } const nextStep = currentStep + 1; - return Stream.of(new Value(value - currentStep, { step: nextStep })); + return Iterator.from([new Value(value - currentStep, { step: nextStep })]); } } class MyChainedArbitrary extends Arbitrary { @@ -222,20 +222,20 @@ describe('Arbitrary', () => { canShrinkWithoutContext(_value: unknown): _value is number[] { throw new Error('No call expected in current scenario'); } - shrink(value: number[], context?: unknown): Stream> { + shrink(value: number[], context?: unknown): IteratorObject> { if (typeof context !== 'object' || context === null || !('size' in context) || !('value' in context)) { throw new Error('Invalid context for MyChainedArbitrary'); } const currentContext = context as { size: number; value: number }; if (currentContext.size === 0) { - return Stream.nil(); + return nil; } - return Stream.of( + return Iterator.from([ ...(currentContext.value === value[0] ? [new Value(Array(currentContext.size).fill(0), currentContext)] : []), ...(value.length > 1 ? [new Value([value[0]], currentContext)] : []), - ); + ]); } } const arb = new MyArbitrary().chain((n) => new MyChainedArbitrary(n, n)); @@ -273,17 +273,17 @@ describe('Arbitrary', () => { canShrinkWithoutContext(_value: unknown): _value is number { throw new Error('No call expected in current scenario'); } - shrink(value: number, context?: unknown): Stream> { + shrink(value: number, context?: unknown): IteratorObject> { if (typeof context !== 'object' || context === null || !('step' in context)) { throw new Error('Invalid context for MyArbitrary'); } const currentStep = (context as { step: number }).step; const nextStep = currentStep + 1; - return Stream.of( + return Iterator.from([ ...(value - currentStep >= 0 ? [new Value(value - currentStep, { step: nextStep })] : []), ...(value - 2 >= 0 ? [new Value(value - 2, { step: nextStep })] : []), ...(value - 1 >= 0 ? [new Value(value - 1, { step: nextStep })] : []), - ); + ]); } } const arb = new MyArbitrary().filter((n) => n % 2 === 0); diff --git a/packages/fast-check/test/unit/check/arbitrary/definition/Arbitrary.utest.spec.ts b/packages/fast-check/test/unit/check/arbitrary/definition/Arbitrary.utest.spec.ts index 6dd49000..867cfc84 100644 --- a/packages/fast-check/test/unit/check/arbitrary/definition/Arbitrary.utest.spec.ts +++ b/packages/fast-check/test/unit/check/arbitrary/definition/Arbitrary.utest.spec.ts @@ -1,7 +1,7 @@ import { describe, it, expect, vi } from 'vitest'; +import { getNthOrLast } from '../../../../../src/utils/iterator.js'; import { Arbitrary } from '../../../../../src/check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../../../../src/check/arbitrary/definition/Value.js'; -import { Stream } from '../../../../../src/stream/Stream.js'; import * as stubRng from '../../../stubs/generators.js'; import { cloneMethod, hasCloneMethod } from '../../../../../src/check/symbols.js'; import { Random } from '../../../../../src/random/generator/Random.js'; @@ -52,7 +52,7 @@ describe('NextArbitrary', () => { const choice3 = new Value(3, Symbol()); const choice4 = new Value(4, Symbol()); const choice5 = new Value(6, Symbol()); - shrink.mockReturnValueOnce(Stream.of(choice1, choice2, choice3, choice4, choice5)); + shrink.mockReturnValueOnce(Iterator.from([choice1, choice2, choice3, choice4, choice5])); class MyNextArbitrary extends Arbitrary { generate = generate; canShrinkWithoutContext = canShrinkWithoutContext; @@ -197,7 +197,7 @@ describe('NextArbitrary', () => { const choice1 = new Value(1, Symbol()); const choice2 = new Value(2, Symbol()); const choice3 = new Value(3, Symbol()); - shrink.mockReturnValueOnce(Stream.of(choice1, choice2, choice3)); + shrink.mockReturnValueOnce(Iterator.from([choice1, choice2, choice3])); class MyNextArbitrary extends Arbitrary { generate = generate; canShrinkWithoutContext = canShrinkWithoutContext; @@ -225,10 +225,10 @@ describe('NextArbitrary', () => { const choice1 = new Value(1, Symbol()); const choice2 = new Value(2, Symbol()); const choice3 = new Value(3, Symbol()); - shrink.mockReturnValueOnce(Stream.of(choice1, choice2, choice3)); + shrink.mockReturnValueOnce(Iterator.from([choice1, choice2, choice3])); const choice21 = new Value(21, Symbol()); const choice22 = new Value(22, Symbol()); - shrink.mockReturnValueOnce(Stream.of(choice21, choice22)); + shrink.mockReturnValueOnce(Iterator.from([choice21, choice22])); class MyNextArbitrary extends Arbitrary { generate = generate; canShrinkWithoutContext = canShrinkWithoutContext; @@ -239,7 +239,7 @@ describe('NextArbitrary', () => { const arb = new MyNextArbitrary().map((v) => String(v)); const g = arb.generate(mrngNoCall, expectedBiasFactor); const shrinksGen1 = arb.shrink(g.value, g.context); - const mappedChoice2 = shrinksGen1.getNthOrLast(1)!; + const mappedChoice2 = getNthOrLast(shrinksGen1, 1)!; const shrinksGen2 = arb.shrink(mappedChoice2.value, mappedChoice2.context); // Assert @@ -258,7 +258,7 @@ describe('NextArbitrary', () => { generate.mockReturnValueOnce(source); const choice1 = new Value({ source: 2, [cloneMethod]: () => choice1.value_ }, Symbol()); const choice2 = new Value({ source: 2, [cloneMethod]: () => choice2.value_ }, Symbol()); - shrink.mockReturnValueOnce(Stream.of(choice1, choice2)); + shrink.mockReturnValueOnce(Iterator.from([choice1, choice2])); class MyNextArbitrary extends Arbitrary { generate = generate; canShrinkWithoutContext = canShrinkWithoutContext; @@ -381,11 +381,11 @@ describe('NextArbitrary', () => { it('should return a mapped version of the stream produced by the source arbitrary for the unmapped value when provided an unmapper function', () => { // Arrange - const expectedStreamValuesFromSource = Stream.of( + const expectedStreamValuesFromSource = Iterator.from([ new Value('titi', undefined), new Value('toto', undefined), new Value('tutu', undefined), - ); + ]); const generate = vi.fn(); const canShrinkWithoutContext = vi.fn(); const shrink = vi.fn().mockReturnValueOnce(expectedStreamValuesFromSource); @@ -460,7 +460,7 @@ describe('NextArbitrary', () => { const shrinkRoot1 = new Value(10, Symbol()); const shrinkRoot2 = new Value(11, Symbol()); const shrinkRoot3 = new Value(15, Symbol()); - shrink.mockReturnValueOnce(Stream.of(shrinkRoot1, shrinkRoot2, shrinkRoot3)); + shrink.mockReturnValueOnce(Iterator.from([shrinkRoot1, shrinkRoot2, shrinkRoot3])); const generateChained = vi.fn(); const canShrinkWithoutContextChained = vi.fn() as any as (value: unknown) => value is any; const shrinkChained = vi.fn(); @@ -475,7 +475,7 @@ describe('NextArbitrary', () => { .mockReturnValueOnce(choiceShrink3Chained); const shrinkChained1 = new Value(25, Symbol()); const shrinkChained2 = new Value(51, Symbol()); - shrinkChained.mockReturnValueOnce(Stream.of(shrinkChained1, shrinkChained2)); + shrinkChained.mockReturnValueOnce(Iterator.from([shrinkChained1, shrinkChained2])); class MyNextArbitrary extends Arbitrary { generate = generate; canShrinkWithoutContext = canShrinkWithoutContext; @@ -520,9 +520,9 @@ describe('NextArbitrary', () => { const shrinkRoot1 = new Value(10, Symbol()); const shrinkRoot2 = new Value(11, Symbol()); // will not be iterated (getNthOrLast(0)) const shrinkRoot3 = new Value(15, Symbol()); // will not be iterated (getNthOrLast(0)) - shrink.mockReturnValueOnce(Stream.of(shrinkRoot1, shrinkRoot2, shrinkRoot3)); + shrink.mockReturnValueOnce(Iterator.from([shrinkRoot1, shrinkRoot2, shrinkRoot3])); const shrinkRoot11 = new Value(310, Symbol()); - shrink.mockReturnValueOnce(Stream.of(shrinkRoot11)); + shrink.mockReturnValueOnce(Iterator.from([shrinkRoot11])); const generateChained = vi.fn(); const canShrinkWithoutContextChained = vi.fn() as any as (value: unknown) => value is any; const shrinkChained = vi.fn(); @@ -535,10 +535,10 @@ describe('NextArbitrary', () => { .mockReturnValueOnce(choiceShrink2Chained); const shrinkChained1 = new Value(25, Symbol()); const shrinkChained2 = new Value(51, Symbol()); - shrinkChained.mockReturnValueOnce(Stream.of(shrinkChained1, shrinkChained2)); + shrinkChained.mockReturnValueOnce(Iterator.from([shrinkChained1, shrinkChained2])); const shrinkChained11 = new Value(125, Symbol()); const shrinkChained12 = new Value(151, Symbol()); - shrinkChained.mockReturnValueOnce(Stream.of(shrinkChained11, shrinkChained12)); + shrinkChained.mockReturnValueOnce(Iterator.from([shrinkChained11, shrinkChained12])); class MyNextArbitrary extends Arbitrary { generate = generate; canShrinkWithoutContext = canShrinkWithoutContext; @@ -555,7 +555,7 @@ describe('NextArbitrary', () => { // Act const arb = new MyNextArbitrary().chain(chainer); const g = arb.generate(mrngNoCall, expectedBiasFactor); - const firstShrunkValue = arb.shrink(g.value, g.context).getNthOrLast(0)!; + const firstShrunkValue = getNthOrLast(arb.shrink(g.value, g.context), 0)!; const shrinks = arb.shrink(firstShrunkValue.value, firstShrunkValue.context); // Assert @@ -582,7 +582,7 @@ describe('NextArbitrary', () => { generate.mockReturnValueOnce(choiceRoot); const shrinkRoot1 = new Value(10, Symbol()); const shrinkRoot2 = new Value(11, Symbol()); - shrink.mockReturnValueOnce(Stream.of(shrinkRoot1, shrinkRoot2)); + shrink.mockReturnValueOnce(Iterator.from([shrinkRoot1, shrinkRoot2])); const generateChained = vi.fn(); const canShrinkWithoutContextChained = vi.fn() as any as (value: unknown) => value is any; const shrinkChained = vi.fn(); @@ -595,10 +595,10 @@ describe('NextArbitrary', () => { .mockReturnValueOnce(choiceShrink2Chained); const shrinkChained1 = new Value(25, Symbol()); const shrinkChained2 = new Value(51, Symbol()); - shrinkChained.mockReturnValueOnce(Stream.of(shrinkChained1, shrinkChained2)); + shrinkChained.mockReturnValueOnce(Iterator.from([shrinkChained1, shrinkChained2])); const shrinkChained11 = new Value(125, Symbol()); const shrinkChained12 = new Value(151, Symbol()); - shrinkChained.mockReturnValueOnce(Stream.of(shrinkChained11, shrinkChained12)); + shrinkChained.mockReturnValueOnce(Iterator.from([shrinkChained11, shrinkChained12])); class MyNextArbitrary extends Arbitrary { generate = generate; canShrinkWithoutContext = canShrinkWithoutContext; @@ -615,7 +615,7 @@ describe('NextArbitrary', () => { // Act const arb = new MyNextArbitrary().chain(chainer); const g = arb.generate(mrngNoCall, expectedBiasFactor); - const shrunkValue = arb.shrink(g.value, g.context).getNthOrLast(2)!; // source will be exhausted it only declares two shrunk values + const shrunkValue = getNthOrLast(arb.shrink(g.value, g.context), 2)!; // source will be exhausted it only declares two shrunk values const shrinks = arb.shrink(shrunkValue.value, shrunkValue.context); // Assert diff --git a/packages/fast-check/test/unit/check/property/AsyncProperty.spec.ts b/packages/fast-check/test/unit/check/property/AsyncProperty.spec.ts index 12538e59..286e1d46 100644 --- a/packages/fast-check/test/unit/check/property/AsyncProperty.spec.ts +++ b/packages/fast-check/test/unit/check/property/AsyncProperty.spec.ts @@ -8,7 +8,6 @@ import * as stubArb from '../../stubs/arbitraries.js'; import * as stubRng from '../../stubs/generators.js'; import { Value } from '../../../../src/check/arbitrary/definition/Value.js'; import { fakeArbitrary } from '../../arbitrary/__test-helpers__/ArbitraryHelpers.js'; -import { Stream } from '../../../../src/stream/Stream.js'; import type { PropertyFailure } from '../../../../src/check/property/types/PropertyFailure.js'; import * as fc from 'fast-check'; @@ -328,7 +327,7 @@ describe('AsyncProperty', () => { canShrinkWithoutContext.mockReturnValue(true); const s1 = Symbol(); const s2 = Symbol(); - shrink.mockReturnValue(Stream.of(new Value(s1, undefined), new Value(s2, undefined))); + shrink.mockReturnValue(Iterator.from([new Value(s1, undefined), new Value(s2, undefined)])); const value = Symbol(); // Act diff --git a/packages/fast-check/test/unit/check/property/__test-helpers__/PropertyHelpers.ts b/packages/fast-check/test/unit/check/property/__test-helpers__/PropertyHelpers.ts index 623c8f4c..63267ef8 100644 --- a/packages/fast-check/test/unit/check/property/__test-helpers__/PropertyHelpers.ts +++ b/packages/fast-check/test/unit/check/property/__test-helpers__/PropertyHelpers.ts @@ -1,7 +1,7 @@ import { vi } from 'vitest'; +import { nil } from '../../../../../src/utils/iterator.js'; import type { MockInstance } from 'vitest'; import type { Property } from '../../../../../src/check/property/types/Property.js'; -import { Stream } from '../../../../../src/stream/Stream.js'; import { Value } from '../../../../../src/check/arbitrary/definition/Value.js'; /** @@ -11,7 +11,7 @@ export function fakeProperty(): { instance: Property } & { [K in keyof Property]: MockInstance[K]>; } { const generate = vi.fn['generate']>(() => new Value(Symbol() as unknown as T, undefined)); - const shrink = vi.fn['shrink']>(() => Stream.nil()); + const shrink = vi.fn['shrink']>(() => nil); const runBeforeEach = vi.fn['runBeforeEach']>(() => undefined); const runAfterEach = vi.fn['runAfterEach']>(() => undefined); const run = vi.fn['run']>(() => null); diff --git a/packages/fast-check/test/unit/check/runner/DecorateProperty.spec.ts b/packages/fast-check/test/unit/check/runner/DecorateProperty.spec.ts index ef2399e6..02cb02ad 100644 --- a/packages/fast-check/test/unit/check/runner/DecorateProperty.spec.ts +++ b/packages/fast-check/test/unit/check/runner/DecorateProperty.spec.ts @@ -1,8 +1,8 @@ import { beforeEach, describe, it, expect, vi } from 'vitest'; +import { nil } from '../../../../src/utils/iterator.js'; import { decorateProperty } from '../../../../src/check/runner/DecorateProperty.js'; import type { Property } from '../../../../src/check/property/types/Property.js'; import { Value } from '../../../../src/check/arbitrary/definition/Value.js'; -import { Stream } from '../../../../src/stream/Stream.js'; // Mocks import { SkipAfterProperty } from '../../../../src/check/property/plugins/SkipAfterProperty.js'; @@ -17,7 +17,7 @@ vi.mock('../../../../src/check/property/plugins/IgnoreEqualValuesProperty'); function buildProperty() { return { generate: () => new Value({}, undefined), - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: () => null, runAfterEach: () => {}, diff --git a/packages/fast-check/test/unit/check/runner/Runner.spec.ts b/packages/fast-check/test/unit/check/runner/Runner.spec.ts index 378da3d4..72ad0c29 100644 --- a/packages/fast-check/test/unit/check/runner/Runner.spec.ts +++ b/packages/fast-check/test/unit/check/runner/Runner.spec.ts @@ -1,4 +1,5 @@ import { describe, it, expect } from 'vitest'; +import { nil } from '../../../../src/utils/iterator.js'; import * as fc from 'fast-check'; import { Value } from '../../../../src/check/arbitrary/definition/Value.js'; @@ -6,7 +7,6 @@ import { check, assert as rAssert } from '../../../../src/check/runner/Runner.js import type { Random } from '../../../../src/random/generator/Random.js'; import type { RunDetails } from '../../../../src/check/runner/reporter/RunDetails.js'; import { PreconditionFailure } from '../../../../src/check/precondition/PreconditionFailure.js'; -import { Stream } from '../../../../src/stream/Stream.js'; import { VerbosityLevel } from '../../../../src/check/runner/configuration/VerbosityLevel.js'; import type { Property } from '../../../../src/check/property/types/Property.js'; @@ -16,7 +16,7 @@ describe('Runner', () => { it('Should throw if both reporter and asyncReporter are defined', () => { const p: Property<[number]> = { generate: () => new Value([0], undefined), - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: () => null, runAfterEach: () => {}, @@ -26,7 +26,7 @@ describe('Runner', () => { it('Should not throw if reporter is specified on asynchronous properties', () => { const p: Property<[number]> = { generate: () => new Value([0], undefined), - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: () => null, runAfterEach: () => {}, @@ -36,7 +36,7 @@ describe('Runner', () => { it('Should not throw if asyncReporter is specified on asynchronous properties', () => { const p: Property<[number]> = { generate: () => new Value([0], undefined), - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: () => null, runAfterEach: () => {}, @@ -52,7 +52,7 @@ describe('Runner', () => { ++numCallsGenerate; return new Value([numCallsGenerate] as [number], undefined); }, - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: (value: [number]) => { expect(value[0]).toEqual(numCallsGenerate); // called with previously generated value @@ -75,7 +75,7 @@ describe('Runner', () => { ++numCallsGenerate; return new Value([numCallsGenerate] as [number], undefined); }, - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: (value: [number]) => { expect(value[0]).toEqual(numCallsGenerate); // called with previously generated value @@ -106,7 +106,7 @@ describe('Runner', () => { yield new Value<[number]>([0], undefined); } } - return new Stream(g()); + return g(); }, runBeforeEach: () => {}, run: () => { @@ -134,7 +134,7 @@ describe('Runner', () => { let numCallsRun = 0; const p: Property<[number]> = { generate: () => new Value([numCallsGenerate++] as [number], undefined), - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: (value: [number]) => { ++numCallsRun; @@ -174,7 +174,7 @@ describe('Runner', () => { let numPreconditionFailures = 0; const p: Property<[number]> = { generate: () => new Value([numCallsGenerate++] as [number], undefined), - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: (value: [number]) => { if (value[0] === settings.onlySuccessId) return null; @@ -227,7 +227,7 @@ describe('Runner', () => { ++numCallsGenerate; return new Value([0], undefined); }, - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: (_value: [number]) => { return ++numCallsRun < num ? null : { error: new Error('error') }; @@ -253,7 +253,7 @@ describe('Runner', () => { ++numCallsGenerate; return new Value([0], undefined); }, - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: (_value: [number]) => { ++numCallsRun; @@ -276,7 +276,7 @@ describe('Runner', () => { generate: (rng: Random) => { return new Value([rng.nextInt(-0x80000000, 0x7fffffff)], undefined); }, - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: (value: [number]) => { runOn.push(value[0]); @@ -321,7 +321,7 @@ describe('Runner', () => { if (value.value[0] !== 0) { throw 'Not implemented'; } - return Stream.of(new Value([42], undefined)); + return Iterator.from([new Value([42], undefined)]); }, runBeforeEach: () => {}, run: (value: [number]) => { @@ -336,7 +336,7 @@ describe('Runner', () => { it('Should not provide list of failures by default (no verbose)', async () => { const p: Property<[number]> = { generate: () => new Value([42], undefined), - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: () => ({ error: new Error('failure') }), runAfterEach: () => {}, @@ -348,9 +348,7 @@ describe('Runner', () => { const p: Property<[number]> = { generate: () => new Value([42], undefined), shrink: (value) => { - return value.value[0] === 42 - ? Stream.of(new Value([48], undefined), new Value([12], undefined)) - : Stream.nil(); + return value.value[0] === 42 ? Iterator.from([new Value([48], undefined), new Value([12], undefined)]) : nil; }, runBeforeEach: () => {}, run: () => ({ error: new Error('failure') }), @@ -378,12 +376,12 @@ describe('Runner', () => { shrink: (value) => { const depth = value.context as number; if (depth <= 0) { - return Stream.nil(); + return nil; } - function* g(): IterableIterator> { + function* g(): IteratorObject> { while (true) yield new Value([0], depth - 1); } - return new Stream(g()); + return g(); }, runBeforeEach: () => {}, run: (_value: [number]) => { @@ -418,7 +416,7 @@ describe('Runner', () => { return new Value([1], undefined); }, shrink: (value) => { - return value.value[0] === 1 ? Stream.of(new Value([42], undefined)) : Stream.nil(); + return value.value[0] === 1 ? Iterator.from([new Value([42], undefined)]) : nil; }, runBeforeEach: async () => {}, run: async (_value: [number]) => { @@ -456,7 +454,7 @@ describe('Runner', () => { it('Should not timeout if no timeout defined', async () => { const p: Property<[number]> = { generate: () => new Value([1], undefined), - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: async () => {}, run: async (_value: [number]) => null, runAfterEach: async () => {}, @@ -468,7 +466,7 @@ describe('Runner', () => { const wait = (timeMs: number) => new Promise((resolve) => setTimeout(() => resolve(null), timeMs)); const p: Property<[number]> = { generate: () => new Value([1], undefined), - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: async () => {}, run: async (_value: [number]) => await wait(0), runAfterEach: async () => {}, @@ -480,7 +478,7 @@ describe('Runner', () => { const wait = (timeMs: number) => new Promise((resolve) => setTimeout(() => resolve(null), timeMs)); const p: Property<[number]> = { generate: () => new Value([1], undefined), - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: async () => {}, run: async (_value: [number]) => await wait(100), runAfterEach: async () => {}, @@ -492,7 +490,7 @@ describe('Runner', () => { const neverEnds = () => new Promise(() => {}); const p: Property<[number]> = { generate: () => new Value([1], undefined), - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: async () => {}, run: async (_value: [number]) => await neverEnds(), runAfterEach: async () => {}, @@ -506,21 +504,21 @@ describe('Runner', () => { const v2 = { a: 'Hello', b: 21 }; const failingProperty: Property<[any, any]> = { generate: () => new Value([v1, v2], undefined), - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: (_v: [any, any]) => ({ error: new Error('error in failingProperty') }), runAfterEach: () => {}, }; const failingComplexProperty: Property<[any, any, any]> = { generate: () => new Value([[v1, v2], v2, v1], undefined), - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: (_v: [any, any, any]) => ({ error: new Error('error in failingComplexProperty') }), runAfterEach: () => {}, }; const successProperty: Property<[any, any]> = { generate: () => new Value([v1, v2], undefined), - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: (_v: [any, any]) => null, runAfterEach: () => {}, @@ -571,9 +569,7 @@ describe('Runner', () => { return new Value([42], undefined); }, shrink: (value) => { - return value.value[0] === 42 - ? Stream.of(new Value([48], undefined), new Value([12], undefined)) - : Stream.nil(); + return value.value[0] === 42 ? Iterator.from([new Value([48], undefined), new Value([12], undefined)]) : nil; }, runBeforeEach: () => {}, run: () => ({ error: new Error('failure') }), @@ -615,7 +611,7 @@ describe('Runner', () => { const baseErrorMessage = 'Failed to run property, too many pre-condition failures encountered'; const p: Property<[number]> = { generate: () => new Value([42], undefined), - shrink: () => Stream.nil(), + shrink: () => nil, runBeforeEach: () => {}, run: () => new PreconditionFailure(), runAfterEach: () => {}, diff --git a/packages/fast-check/test/unit/check/runner/SourceValuesIterator.spec.ts b/packages/fast-check/test/unit/check/runner/SourceValuesIterator.spec.ts index 14689e1b..2405869e 100644 --- a/packages/fast-check/test/unit/check/runner/SourceValuesIterator.spec.ts +++ b/packages/fast-check/test/unit/check/runner/SourceValuesIterator.spec.ts @@ -3,12 +3,12 @@ import * as fc from 'fast-check'; import { SourceValuesIterator } from '../../../../src/check/runner/SourceValuesIterator.js'; -function iota() { +function iota(): IteratorObject { function* g() { let idx = 0; while (true) yield idx++; } - return new fc.Stream(g()); + return g(); } function iotaN(n: number) { return iota().take(n); diff --git a/packages/fast-check/test/unit/check/runner/Tosser.spec.ts b/packages/fast-check/test/unit/check/runner/Tosser.spec.ts index 30f8982b..333d318a 100644 --- a/packages/fast-check/test/unit/check/runner/Tosser.spec.ts +++ b/packages/fast-check/test/unit/check/runner/Tosser.spec.ts @@ -1,8 +1,8 @@ import { describe, it, expect } from 'vitest'; +import { nil } from '../../../../src/utils/iterator.js'; import * as fc from 'fast-check'; import { toss } from '../../../../src/check/runner/Tosser.js'; -import { Stream, stream } from '../../../../src/stream/Stream.js'; import type { Arbitrary } from '../../../../src/check/arbitrary/definition/Arbitrary.js'; import type { Property } from '../../../../src/check/property/types/Property.js'; import type { Random } from '../../../../src/random/generator/Random.js'; @@ -18,7 +18,7 @@ const wrap = (arb: Arbitrary): Property => new (class implements Property { constructor(readonly arb: Arbitrary) {} generate = (rng: Random) => new Value(this.arb.generate(rng, undefined).value_, undefined); - shrink = () => Stream.nil>(); + shrink = () => nil; runBeforeEach = () => {}; run = () => ({ error: new Error('failure') }); runAfterEach = () => {}; @@ -29,7 +29,7 @@ describe('Tosser', () => { it('Should offset the random number generator between calls', async () => await fc.assert( fc.asyncProperty(fc.integer(), fc.nat(100), (seed, start) => { - const s = stream(toss(wrap(stubArb.forwardArray(4)), seed, rngProducer, [])); + const s = toss(wrap(stubArb.forwardArray(4)), seed, rngProducer, []); const [g1, g2] = [ ...s .drop(start) @@ -44,11 +44,11 @@ describe('Tosser', () => { await fc.assert( fc.asyncProperty(fc.integer(), fc.nat(20), (seed, num) => { expect([ - ...stream(toss(wrap(stubArb.forward()), seed, rngProducer, [])) + ...toss(wrap(stubArb.forward()), seed, rngProducer, []) .take(num) .map((f) => f.value), ]).toStrictEqual([ - ...stream(toss(wrap(stubArb.forward()), seed, rngProducer, [])) + ...toss(wrap(stubArb.forward()), seed, rngProducer, []) .take(num) .map((f) => f.value), ]); @@ -57,8 +57,8 @@ describe('Tosser', () => { it('Should not depend on the order of iteration', async () => await fc.assert( fc.asyncProperty(fc.integer(), fc.nat(20), (seed, num) => { - const onGoingItems1 = [...stream(toss(wrap(stubArb.forward()), seed, rngProducer, [])).take(num)]; - const onGoingItems2 = [...stream(toss(wrap(stubArb.forward()), seed, rngProducer, [])).take(num)]; + const onGoingItems1 = [...toss(wrap(stubArb.forward()), seed, rngProducer, []).take(num)]; + const onGoingItems2 = [...toss(wrap(stubArb.forward()), seed, rngProducer, []).take(num)]; expect( onGoingItems2 .reverse() @@ -70,13 +70,13 @@ describe('Tosser', () => { it('Should offset toss with the provided examples', async () => await fc.assert( fc.asyncProperty(fc.integer(), fc.nat(20), fc.array(fc.integer()), (seed, num, examples) => { - const noExamplesProvided = [ - ...stream(toss(wrap(stubArb.forward()), seed, rngProducer, [])).take(num - examples.length), - ].map((f) => f.value); + const noExamplesProvided = [...toss(wrap(stubArb.forward()), seed, rngProducer, []).take(num)].map( + (f) => f.value, + ); const examplesProvided = [ - ...stream(toss(wrap(stubArb.forward()), seed, rngProducer, examples)).take(num), + ...toss(wrap(stubArb.forward()), seed, rngProducer, examples).take(num + examples.length), ].map((f) => f.value); - expect([...examples, ...noExamplesProvided].slice(0, num)).toStrictEqual(examplesProvided); + expect([...examples, ...noExamplesProvided]).toStrictEqual(examplesProvided); }), )); }); diff --git a/packages/fast-check/test/unit/stream/Stream.spec.ts b/packages/fast-check/test/unit/stream/Stream.spec.ts deleted file mode 100644 index 39ced407..00000000 --- a/packages/fast-check/test/unit/stream/Stream.spec.ts +++ /dev/null @@ -1,341 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { Stream, stream } from '../../../src/stream/Stream.js'; - -describe('Stream', () => { - describe('constructor', () => { - it('Should have the same values as its underlying', () => { - function* g() { - yield* [1, 42, 350, 0]; - } - const s = stream(g()); - expect([...s]).toEqual([1, 42, 350, 0]); - }); - it('Should not be able to iterate twice', () => { - function* g() { - yield* [1, 42, 350, 0]; - } - const s = stream(g()); - expect([...s]).toEqual([1, 42, 350, 0]); - expect([...s]).toEqual([]); - }); - it('Should handle infinite generators', () => { - function* g() { - let idx = 0; - while (true) { - yield ++idx; - } - } - const s = stream(g()); - const data = []; - for (let idx = 0; idx !== 5; ++idx) { - data.push(s.next().value); - } - expect(data).toEqual([1, 2, 3, 4, 5]); - }); - }); - describe('nil', () => { - it('Should instantiate an empty stream', () => { - const s: Stream = Stream.nil(); - expect([...s]).toEqual([]); - }); - }); - describe('of', () => { - it('Should instantiate an empty stream given no elements', () => { - const s: Stream = Stream.of(); - expect([...s]).toEqual([]); - }); - it('Should instantiate a stream containing a single entry given a single element', () => { - const s: Stream = Stream.of(1); - expect([...s]).toEqual([1]); - }); - it('Should instantiate a stream containing the same entries as passed elements with same ordering', () => { - const s: Stream = Stream.of(1, 42, 69); - expect([...s]).toEqual([1, 42, 69]); - }); - it('Should not consider elements of type Array differently from other ones', () => { - const s: Stream = Stream.of([1, 42, 69]); - expect([...s]).toEqual([[1, 42, 69]]); - }); - }); - describe('map', () => { - it('Should apply on each element', () => { - function* g() { - yield* [1, 2, 3, 5]; - } - const s = stream(g()).map((v) => v * v); - expect([...s]).toEqual([1, 4, 9, 25]); - }); - it('Should be able to perform conversions', () => { - function* g() { - yield* [1, 2, 3, 5]; - } - const s: Stream = stream(g()).map((v) => String(v)); - expect([...s]).toEqual(['1', '2', '3', '5']); - }); - }); - describe('flatMap', () => { - it('Should apply on each element', () => { - function* g() { - yield* [1, 2, 3, 5]; - } - function* expand(n: number) { - for (let idx = 0; idx !== n; ++idx) { - yield n; - } - } - const s = stream(g()).flatMap(expand); - expect([...s]).toEqual([1, 2, 2, 3, 3, 3, 5, 5, 5, 5, 5]); - }); - it('Should handle correctly empty iterables', () => { - function* g() { - yield* [1, 2, 3, 0, 5]; - } - function* noexpand(n: number) { - if (n >= 3) { - yield n; - } - } - const s = stream(g()).flatMap(noexpand); - expect([...s]).toEqual([3, 5]); - }); - }); - describe('drop', () => { - it('Should drop the right number of elements', () => { - function* g() { - yield* [1, 2, 3, 4, 5, 6]; - } - const s = stream(g()).drop(2); - expect([...s]).toEqual([3, 4, 5, 6]); - }); - }); - describe('dropWhile', () => { - it('Should drop while predicate stays valid', () => { - function* g() { - yield* [-4, -2, -3, 1, -8, 7]; - } - const s = stream(g()).dropWhile((v) => v < 0); - expect([...s]).toEqual([1, -8, 7]); - }); - it('Should drop everything', () => { - function* g() { - yield* [-4, -2, -3, 1, -8, 7]; - } - const s = stream(g()).dropWhile((_) => true); - expect([...s]).toEqual([]); - }); - it('Should drop nothing', () => { - function* g() { - yield* [-4, -2, -3, 1, -8, 7]; - } - const s = stream(g()).dropWhile((_) => false); - expect([...s]).toEqual([-4, -2, -3, 1, -8, 7]); - }); - }); - describe('take', () => { - it('Should take the right number of elements', () => { - function* g() { - yield* [1, 2, 3, 4, 5, 6]; - } - const s = stream(g()).take(4); - expect([...s]).toEqual([1, 2, 3, 4]); - }); - it('Should accept stream containing less values than the requested number', () => { - function* g() { - yield* [1, 2]; - } - const s = stream(g()).take(4); - expect([...s]).toEqual([1, 2]); - }); - it('Should only pull the requested number of items not more', () => { - let numValues = 0; - function* g() { - while (true) { - ++numValues; - yield 0; - } - } - const s = stream(g()).take(4); - expect([...s]).toEqual([0, 0, 0, 0]); - expect(numValues).toBe(4); - }); - }); - describe('takeWhile', () => { - it('Should take while predicate stays valid', () => { - function* g() { - yield* [-4, -2, -3, 1, -8, 7]; - } - const s = stream(g()).takeWhile((v) => v < 0); - expect([...s]).toEqual([-4, -2, -3]); - }); - it('Should take everything', () => { - function* g() { - yield* [-4, -2, -3, 1, -8, 7]; - } - const s = stream(g()).takeWhile((_) => true); - expect([...s]).toEqual([-4, -2, -3, 1, -8, 7]); - }); - it('Should take nothing', () => { - function* g() { - yield* [-4, -2, -3, 1, -8, 7]; - } - const s = stream(g()).takeWhile((_) => false); - expect([...s]).toEqual([]); - }); - }); - describe('filter', () => { - it('Should remove undesirable values', () => { - function* g() { - yield* [1, 3, 4, 7, 8, 10, 1, 1, 3, 4, 4]; - } - const s = stream(g()).filter((v) => v % 2 === 0); - expect([...s]).toEqual([4, 8, 10, 4, 4]); - }); - }); - describe('every', () => { - it('Should be true if all values are ok', () => { - function* g() { - yield* [1, 3, 4, 7, 8, 10, 1, 1, 3, 4, 4]; - } - expect(stream(g()).every((v) => v > 0)).toBe(true); - }); - it('Should be true for empty streams', () => { - function* g() { - yield* []; - } - expect(stream(g()).every((v) => v > 0)).toBe(true); - }); - it('Should be false if it starts by a failing value', () => { - function* g() { - yield* [0, 1, 3, 4, 7, 8, 10, 1, 1, 3, 4, 4]; - } - expect(stream(g()).every((v) => v > 0)).toBe(false); - }); - it('Should be false if it ends by a failing value', () => { - function* g() { - yield* [1, 3, 4, 7, 8, 10, 1, 1, 3, 4, 4, 0]; - } - expect(stream(g()).every((v) => v > 0)).toBe(false); - }); - it('Should be false if it contains a failing value', () => { - function* g() { - yield* [1, 3, 4, 7, 8, 10, 0, 1, 1, 3, 4, 4]; - } - expect(stream(g()).every((v) => v > 0)).toBe(false); - }); - }); - describe('has', () => { - it('Should be true if one of the values is ok', () => { - function* g() { - yield* [1, 3, 4, 7, 8, 10, 1, 1, 3, 4, 4]; - } - expect(stream(g()).has((v) => v > 9)).toEqual([true, 10]); - }); - it('Should be true if multiple values are ok', () => { - function* g() { - yield* [1, 3, 4, 7, 8, 10, 1, 1, 3, 4, 4]; - } - expect(stream(g()).has((v) => v > 4)).toEqual([true, 7]); - }); - it('Should be false for empty streams', () => { - function* g() { - yield* []; - } - expect(stream(g()).has((v) => v > 0)).toEqual([false, null]); - }); - it('Should be false if no value is ok', () => { - function* g() { - yield* [-2, -4, 0]; - } - expect(stream(g()).has((v) => v > 0)).toEqual([false, null]); - }); - }); - describe('join', () => { - it('Should be able to join nothing', () => { - function* g() { - yield* [1, 2, 3, 4, 5]; - } - const s = stream(g()).join(); - expect([...s]).toEqual([1, 2, 3, 4, 5]); - }); - it('Should be able to join another iterable', () => { - function* g1() { - yield* [1, 2, 3, 4, 5]; - } - function* g2() { - yield* [8, 9]; - } - const s = stream(g1()).join(g2()); - expect([...s]).toEqual([1, 2, 3, 4, 5, 8, 9]); - }); - it('Should be able to join multiple other streams', () => { - function* g1() { - yield* [1, 2, 3, 4, 5]; - } - function* g2() { - yield* [8, 9]; - } - const s = stream(g1()).join(g2(), g1()); - expect([...s]).toEqual([1, 2, 3, 4, 5, 8, 9, 1, 2, 3, 4, 5]); - }); - it('Should be able to join multiple other streams while mapping the initial stream', () => { - function* g1() { - yield* [1, 2, 3, 4, 5]; - } - function* g2() { - yield* [8, 9]; - } - const s = stream(g1()) - .map((v) => 10 * v) - .join(g2(), g1()); - expect([...s]).toEqual([10, 20, 30, 40, 50, 8, 9, 1, 2, 3, 4, 5]); - }); - it('Should be able to join infinite streams', () => { - function* g1() { - while (true) yield 1; - } - function* g2() { - while (true) yield 2; - } - const s = stream(g1()) - .map((v) => 10 * v) - .join(g2()) - .take(5); - expect([...s]).toEqual([10, 10, 10, 10, 10]); - }); - it('Should be able to join on nil', () => { - function* g1() { - yield* [1, 2, 3, 4, 5]; - } - const s = Stream.nil().join(g1()); - expect([...s]).toEqual([1, 2, 3, 4, 5]); - }); - }); - describe('getNthOrLast', () => { - it('Should return the nth value of the stream', () => { - function* g() { - yield* [42, 5, 43, 8, 19]; - } - const v = stream(g()).getNthOrLast(2); - expect(v).toEqual(43); - }); - it('Should return the last value if the stream is too small', () => { - function* g() { - yield* [42, 5, 43, 8, 19]; - } - const v = stream(g()).getNthOrLast(20); - expect(v).toEqual(19); - }); - it('Should be null for empty streams', () => { - const v = Stream.nil().getNthOrLast(10); - expect(v).toBe(null); - }); - it('Should be able to run on infinite streams', () => { - function* g() { - let idx = 0; - while (true) yield idx++; - } - const v = stream(g()).getNthOrLast(10); - expect(v).toEqual(10); - }); - }); -}); diff --git a/packages/fast-check/test/unit/stubs/arbitraries.ts b/packages/fast-check/test/unit/stubs/arbitraries.ts index 8d6fa3de..3007f284 100644 --- a/packages/fast-check/test/unit/stubs/arbitraries.ts +++ b/packages/fast-check/test/unit/stubs/arbitraries.ts @@ -1,7 +1,7 @@ import { Arbitrary } from '../../../src/check/arbitrary/definition/Arbitrary.js'; +import { nil } from '../../../src/utils/iterator.js'; import { Value } from '../../../src/check/arbitrary/definition/Value.js'; import type { Random } from '../../../src/random/generator/Random.js'; -import { Stream } from '../../../src/stream/Stream.js'; /** * CounterArbitrary @@ -22,8 +22,8 @@ class CounterArbitrary extends Arbitrary { canShrinkWithoutContext(_value: unknown): _value is number { return false; } - shrink(_value: number, _context: unknown): Stream> { - return Stream.nil(); + shrink(_value: number, _context: unknown): IteratorObject> { + return nil; } } @@ -42,8 +42,8 @@ class ForwardArbitrary extends Arbitrary { canShrinkWithoutContext(_value: unknown): _value is number { return false; } - shrink(_value: number, _context: unknown): Stream> { - return Stream.nil(); + shrink(_value: number, _context: unknown): IteratorObject> { + return nil; } } @@ -66,8 +66,8 @@ class ForwardArrayArbitrary extends Arbitrary { canShrinkWithoutContext(_value: unknown): _value is number[] { return false; } - shrink(_value: number[], _context: unknown): Stream> { - return Stream.nil(); + shrink(_value: number[], _context: unknown): IteratorObject> { + return nil; } } @@ -95,8 +95,8 @@ class SingleUseArbitrary extends Arbitrary { canShrinkWithoutContext(_value: unknown): _value is T { return false; } - shrink(_value: T, _context: unknown): Stream> { - return Stream.nil(); + shrink(_value: T, _context: unknown): IteratorObject> { + return nil; } } diff --git a/packages/fast-check/test/unit/stream/LazyIterableIterator.spec.ts b/packages/fast-check/test/unit/utils/iterator.spec.ts similarity index 92% rename from packages/fast-check/test/unit/stream/LazyIterableIterator.spec.ts rename to packages/fast-check/test/unit/utils/iterator.spec.ts index e682b2b3..951d1b95 100644 --- a/packages/fast-check/test/unit/stream/LazyIterableIterator.spec.ts +++ b/packages/fast-check/test/unit/utils/iterator.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, vi } from 'vitest'; -import { makeLazy } from '../../../src/stream/LazyIterableIterator.js'; +import { makeLazy } from '../../../src/utils/iterator.js'; describe('makeLazy', () => { it('Should not call producer on create', () => { diff --git a/packages/fast-check/tsconfig.json b/packages/fast-check/tsconfig.json index d06b3f7f..7ccf9b8a 100644 --- a/packages/fast-check/tsconfig.json +++ b/packages/fast-check/tsconfig.json @@ -1,6 +1,8 @@ { "extends": "../../tsconfig.common.json", "compilerOptions": { - "types": ["node"] + "types": ["node"], + "target": "es2025", + "lib": ["es2025"] } } diff --git a/packages/fast-check/tsconfig.publish.json b/packages/fast-check/tsconfig.publish.json index ed67654f..7fc6fd33 100644 --- a/packages/fast-check/tsconfig.publish.json +++ b/packages/fast-check/tsconfig.publish.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.publish.json", "compilerOptions": { - "outDir": "lib/" + "outDir": "lib/", + "target": "es2025", + "lib": ["es2025"] }, "include": ["src/"] } diff --git a/packages/fast-check/tsconfig.publish.types.api-extractor.json b/packages/fast-check/tsconfig.publish.types.api-extractor.json new file mode 100644 index 00000000..569d99f4 --- /dev/null +++ b/packages/fast-check/tsconfig.publish.types.api-extractor.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.publish.types.json", + "compilerOptions": { + "outDir": "lib/types/", + "target": "esnext", + "lib": ["esnext"] + }, + "include": ["src/"] +} diff --git a/packages/fast-check/tsconfig.publish.types.json b/packages/fast-check/tsconfig.publish.types.json index db9f4fc2..2181f123 100644 --- a/packages/fast-check/tsconfig.publish.types.json +++ b/packages/fast-check/tsconfig.publish.types.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.publish.types.json", "compilerOptions": { - "outDir": "lib/types/" + "outDir": "lib/types/", + "target": "es2025", + "lib": ["es2025"] }, "include": ["src/"] } diff --git a/packages/fast-check/tsconfig.typedoc.json b/packages/fast-check/tsconfig.typedoc.json index 84d13246..618b79a7 100644 --- a/packages/fast-check/tsconfig.typedoc.json +++ b/packages/fast-check/tsconfig.typedoc.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.common.json", "compilerOptions": { - "types": ["node"] + "types": ["node"], + "target": "es2025", + "lib": ["es2025"] }, "include": ["src/"] } diff --git a/packages/worker/src/internals/worker-property/NoopWorkerProperty.ts b/packages/worker/src/internals/worker-property/NoopWorkerProperty.ts index 5235fe89..b02432f0 100644 --- a/packages/worker/src/internals/worker-property/NoopWorkerProperty.ts +++ b/packages/worker/src/internals/worker-property/NoopWorkerProperty.ts @@ -1,4 +1,4 @@ -import type { PropertyWithHooks, Value, Stream, PreconditionFailure, PropertyFailure } from 'fast-check'; +import type { PropertyWithHooks, Value, PreconditionFailure, PropertyFailure } from 'fast-check'; import type { WorkerProperty } from '../SharedTypes.js'; /** @@ -16,7 +16,7 @@ export class NoopWorkerProperty implements WorkerProperty { generate(): Value { throw new Error('Method not implemented.'); } - shrink(): Stream> { + shrink(): IteratorObject> { throw new Error('Method not implemented.'); } run(): Promise { diff --git a/packages/worker/src/internals/worker-property/WorkerPropertyFromWorker.ts b/packages/worker/src/internals/worker-property/WorkerPropertyFromWorker.ts index 6565fd29..7da21ca1 100644 --- a/packages/worker/src/internals/worker-property/WorkerPropertyFromWorker.ts +++ b/packages/worker/src/internals/worker-property/WorkerPropertyFromWorker.ts @@ -1,4 +1,4 @@ -import type { PropertyHookFunction, PropertyWithHooks, Property, Random, Stream, Value } from 'fast-check'; +import type { PropertyHookFunction, PropertyWithHooks, Property, Random, Value } from 'fast-check'; import type { PropertyArbitraries } from '../SharedTypes.js'; import type { ValueState } from '../ValueFromState.js'; import type { Payload } from '../worker-pool/IWorkerPool.js'; @@ -70,9 +70,9 @@ export class WorkerPropertyFromWorker implem return new fc.Value(inputs, undefined); } - shrink(_value: Value): Stream> { + shrink(_value: Value): IteratorObject> { // No shrink on worker-based generations - return fc.Stream.nil(); + return Iterator.from([]); } run(v: Ts): ReturnType['run']> { diff --git a/packages/worker/test/internals/worker-property/WorkerPropertyFromWorker.spec.ts b/packages/worker/test/internals/worker-property/WorkerPropertyFromWorker.spec.ts index 14c3f854..a8d66364 100644 --- a/packages/worker/test/internals/worker-property/WorkerPropertyFromWorker.spec.ts +++ b/packages/worker/test/internals/worker-property/WorkerPropertyFromWorker.spec.ts @@ -113,7 +113,7 @@ class TrackedArbitrary extends fc.Arbitrary { canShrinkWithoutContext(_value: unknown): _value is unknown { throw new Error('Method not implemented.'); } - shrink(_value: unknown, _context: unknown): fc.Stream> { + shrink(_value: unknown, _context: unknown): IteratorObject> { throw new Error('Method not implemented.'); } } diff --git a/packages/worker/tsconfig.json b/packages/worker/tsconfig.json index d06b3f7f..94e93bdf 100644 --- a/packages/worker/tsconfig.json +++ b/packages/worker/tsconfig.json @@ -1,6 +1,8 @@ { "extends": "../../tsconfig.common.json", "compilerOptions": { + "target": "es2025", + "lib": ["es2025"], "types": ["node"] } } -- 2.51.2