Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/RxSharp/Extras/AssumeNeverEmits.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
namespace RxSharp.Extras;

/// <summary>Extension methods widening an error-only <see cref="Observable{T}"/> to another element type.</summary>
public static partial class Extensions
public static partial class RxExtensions
{
/// <summary>
/// Widens an <see cref="Observable{Unit}"/> that only ever calls <see cref="IObserver{T}.OnError"/> (such as
/// <see cref="Extensions.FromCancellationToken"/> or <see cref="Extensions.Timeout"/>) so it
/// <see cref="RxExtensions.FromCancellationToken"/> or <see cref="RxExtensions.Timeout"/>) so it
/// type-checks anywhere an <see cref="Observable{T}"/> is expected - most commonly as one of the branches
/// passed to <see cref="RaceOperator.RaceWith{T}"/> alongside a source that actually produces
/// <typeparamref name="TResult"/> values. Mirrors how rxjs relies on TypeScript structurally accepting
Expand Down
2 changes: 1 addition & 1 deletion src/RxSharp/Extras/FilterAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace RxSharp.Extras;

/// <summary>Extension methods providing an async-predicate flavor of <c>Filter</c>.</summary>
public static partial class Extensions
public static partial class RxExtensions
{
/// <summary>
/// An operator supporting an async predicate, mirroring Puppeteer's own <c>filterAsync</c> helper (implemented,
Expand Down
2 changes: 1 addition & 1 deletion src/RxSharp/Extras/FromCancellationToken.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace RxSharp.Extras;

/// <summary>Puppeteer-flavored combinators built on top of the core primitives — the C# analogues of the helpers Puppeteer itself layers on top of rxjs (see CLAUDE.md's "Puppeteer-essential surface").</summary>
public static partial class Extensions
public static partial class RxExtensions
{
/// <summary>
/// An observable that never emits and errors as soon as <paramref name="cancellationToken"/> is cancelled.
Expand Down
22 changes: 18 additions & 4 deletions src/RxSharp/Extras/FromEventBuffered.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace RxSharp.Extras;

/// <summary>
/// A handle to an eagerly-attached, buffered .NET event source created by
/// <see cref="Extensions.FromEventBuffered{TDelegate, TEventArgs}"/>. Disposing detaches the underlying event handler.
/// <see cref="RxExtensions.FromEventBuffered{TDelegate, TEventArgs}"/>. Disposing detaches the underlying event handler.
/// </summary>
/// <typeparam name="TEventArgs">The type of the event's payload.</typeparam>
public sealed class BufferedEventSource<TEventArgs> : IDisposable
Expand Down Expand Up @@ -42,7 +42,7 @@ public void Dispose()
}

/// <summary>Extension methods providing an eagerly-attached, buffered variant of <see cref="Observable.FromEvent{TEventArgs}"/>.</summary>
public static partial class Extensions
public static partial class RxExtensions
{
/// <summary>
/// Like <see cref="Observable.FromEvent{TDelegate, TEventArgs}"/>, but attaches the underlying event handler
Expand All @@ -68,7 +68,14 @@ public static partial class Extensions
/// <param name="addHandler">Called immediately, with the handler to add to the event.</param>
/// <param name="removeHandler">Called on <see cref="BufferedEventSource{TEventArgs}.Dispose"/>, with the same handler, to remove it from the event.</param>
/// <param name="conversion">Converts an <see cref="Action{TEventArgs}"/> callback into the event's actual delegate shape.</param>
/// <param name="bufferSize">The maximum number of most-recent payloads kept for replay. Defaults to 1.</param>
/// <param name="bufferSize">
/// The maximum number of most-recent payloads kept for replay. Defaults to 1 - fine if the caller only
/// cares about the single most recent payload, but a real risk if the caller filters for a specific match
/// among possibly-several payloads that could arrive in the pre-subscribe gap this method exists to cover:
/// with the default of 1, a matching payload can be silently evicted from the buffer by a later
/// non-matching one before anyone subscribes to see it. Pass a larger value whenever more than one payload
/// could plausibly arrive before subscription and only some of them are what the caller is looking for.
/// </param>
/// <returns>A handle exposing the buffered payloads as an observable, and detaching the handler on disposal.</returns>
public static BufferedEventSource<TEventArgs> FromEventBuffered<TDelegate, TEventArgs>(
Action<TDelegate> addHandler,
Expand All @@ -86,7 +93,14 @@ public static BufferedEventSource<TEventArgs> FromEventBuffered<TDelegate, TEven
/// <typeparam name="TEventArgs">The type of the event's payload.</typeparam>
/// <param name="addHandler">Called immediately, with the handler to add to the event.</param>
/// <param name="removeHandler">Called on <see cref="BufferedEventSource{TEventArgs}.Dispose"/>, with the same handler, to remove it from the event.</param>
/// <param name="bufferSize">The maximum number of most-recent payloads kept for replay. Defaults to 1.</param>
/// <param name="bufferSize">
/// The maximum number of most-recent payloads kept for replay. Defaults to 1 - fine if the caller only
/// cares about the single most recent payload, but a real risk if the caller filters for a specific match
/// among possibly-several payloads that could arrive in the pre-subscribe gap this method exists to cover:
/// with the default of 1, a matching payload can be silently evicted from the buffer by a later
/// non-matching one before anyone subscribes to see it. Pass a larger value whenever more than one payload
/// could plausibly arrive before subscription and only some of them are what the caller is looking for.
/// </param>
/// <returns>A handle exposing the buffered payloads as an observable, and detaching the handler on disposal.</returns>
public static BufferedEventSource<TEventArgs> FromEventBuffered<TEventArgs>(
Action<EventHandler<TEventArgs>> addHandler,
Expand Down
10 changes: 5 additions & 5 deletions src/RxSharp/Extras/RaceWithSignalAndTimer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
namespace RxSharp.Extras;

/// <summary>Extension methods racing a single subscription against cancellation and a timeout.</summary>
public static partial class Extensions
public static partial class RxExtensions
{
/// <summary>
/// Races <paramref name="source"/> against cancellation and a timeout, whichever fires first. The
/// non-retrying half of <see cref="Extensions.RetryAndRaceWithSignalAndTimer{T}(Observable{T}, TimeSpan, Func{Exception}, TimeSpan?, CancellationToken)"/>
/// non-retrying half of <see cref="RxExtensions.RetryAndRaceWithSignalAndTimer{T}(Observable{T}, TimeSpan, Func{Exception}, TimeSpan?, CancellationToken)"/>
/// - use this directly for a single wait (e.g. "wait for the next matching event") that doesn't need
/// retrying, and reach for the retrying combinator when it does.
/// </summary>
Expand All @@ -17,7 +17,7 @@ public static partial class Extensions
/// <param name="causeFactory">
/// Produces the exception used for both the cancellation and timeout branches. Defaults to
/// <see cref="OperationCanceledException"/> for cancellation and <see cref="TimeoutException"/> for the timeout,
/// via the defaults of <see cref="Extensions.FromCancellationToken"/> and <see cref="Extensions.Timeout"/> respectively.
/// via the defaults of <see cref="RxExtensions.FromCancellationToken"/> and <see cref="RxExtensions.Timeout"/> respectively.
/// Since one factory covers both branches, a caller needing to tell the two apart by exception type should
/// pass <see langword="null"/> here (so each branch keeps its own distinct default type) and catch/rethrow
/// as needed at the call site.
Expand All @@ -30,8 +30,8 @@ public static Observable<T> RaceWithSignalAndTimer<T>(
Func<Exception>? causeFactory,
CancellationToken cancellationToken)
=> source.RaceWith(
Extensions.FromCancellationToken(cancellationToken, causeFactory).AssumeNeverEmits<T>(),
Extensions.Timeout(timeout, causeFactory).AssumeNeverEmits<T>());
RxExtensions.FromCancellationToken(cancellationToken, causeFactory).AssumeNeverEmits<T>(),
RxExtensions.Timeout(timeout, causeFactory).AssumeNeverEmits<T>());

/// <summary>
/// Overload of <see cref="RaceWithSignalAndTimer{T}(Observable{T}, TimeSpan, Func{Exception}, CancellationToken)"/>
Expand Down
6 changes: 3 additions & 3 deletions src/RxSharp/Extras/RetryAndRaceWithSignalAndTimer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace RxSharp.Extras;

/// <summary>Extension methods composing retry, cancellation, and timeout into the single combinator Puppeteer's <c>Locator</c> actions rely on.</summary>
public static partial class Extensions
public static partial class RxExtensions
{
/// <summary>
/// The combinator behind Puppeteer's <c>Locator</c> actions (click/fill/hover/wait): retry the source
Expand All @@ -13,7 +13,7 @@ public static partial class Extensions
/// that may not have rendered yet") while still giving up promptly, either because the caller cancelled it
/// or because it took longer than <paramref name="timeout"/> — whichever happens first. Since the cancellation
/// and timeout branches are <see cref="Observable{T}"/> sources that only ever error (see
/// <see cref="Extensions.FromCancellationToken"/> and <see cref="Extensions.Timeout"/>), the only way
/// <see cref="RxExtensions.FromCancellationToken"/> and <see cref="RxExtensions.Timeout"/>), the only way
/// this combinator produces a value is if the retried <paramref name="source"/> itself emits one before either
/// branch fires.
/// </summary>
Expand All @@ -23,7 +23,7 @@ public static partial class Extensions
/// <param name="causeFactory">
/// Produces the exception used for both the cancellation and timeout branches. Defaults to
/// <see cref="OperationCanceledException"/> for cancellation and <see cref="TimeoutException"/> for the timeout,
/// via the defaults of <see cref="Extensions.FromCancellationToken"/> and <see cref="Extensions.Timeout"/> respectively.
/// via the defaults of <see cref="RxExtensions.FromCancellationToken"/> and <see cref="RxExtensions.Timeout"/> respectively.
/// </param>
/// <param name="retryDelay">The delay between retry attempts. Defaults to 50 milliseconds.</param>
/// <param name="cancellationToken">A token that, when cancelled, aborts the whole operation immediately.</param>
Expand Down
2 changes: 1 addition & 1 deletion src/RxSharp/Extras/Timeout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace RxSharp.Extras;

/// <summary>Extension methods providing a standalone, <see cref="TimeoutException"/>-throwing timer observable.</summary>
public static partial class Extensions
public static partial class RxExtensions
{
/// <summary>
/// An observable that never emits and errors after <paramref name="delay"/> elapses, or never errors at all if
Expand Down
6 changes: 3 additions & 3 deletions src/RxSharp/RxSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
<PackageProjectUrl>https://github.com/hardkoded/ReactiveExtensions-Sharp</PackageProjectUrl>
<RepositoryUrl>https://github.com/hardkoded/ReactiveExtensions-Sharp</RepositoryUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageVersion>0.1.2</PackageVersion>
<AssemblyVersion>0.1.2.0</AssemblyVersion>
<FileVersion>0.1.2.0</FileVersion>
<PackageVersion>0.1.3</PackageVersion>
<AssemblyVersion>0.1.3.0</AssemblyVersion>
<FileVersion>0.1.3.0</FileVersion>
</PropertyGroup>

<PropertyGroup>
Expand Down
8 changes: 4 additions & 4 deletions test/RxSharp.Tests/Extras/CancellationExtrasTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public void ShouldErrorImmediatelyIfTokenIsAlreadyCancelled()
cts.Cancel();

Exception? received = null;
Extensions.FromCancellationToken(cts.Token).Subscribe(onError: err => received = err);
RxExtensions.FromCancellationToken(cts.Token).Subscribe(onError: err => received = err);

Assert.That(received, Is.InstanceOf<OperationCanceledException>());
}
Expand All @@ -22,7 +22,7 @@ public void ShouldErrorAsSoonAsTheTokenIsCancelled()
{
using var cts = new CancellationTokenSource();
Exception? received = null;
Extensions.FromCancellationToken(cts.Token).Subscribe(onError: err => received = err);
RxExtensions.FromCancellationToken(cts.Token).Subscribe(onError: err => received = err);

Assert.That(received, Is.Null);

Expand All @@ -36,7 +36,7 @@ public void ShouldNeverEmitAValue()
{
using var cts = new CancellationTokenSource();
var nextCalled = false;
var subscription = Extensions.FromCancellationToken(cts.Token).Subscribe(_ => nextCalled = true);
var subscription = RxExtensions.FromCancellationToken(cts.Token).Subscribe(_ => nextCalled = true);

subscription.Dispose();
cts.Cancel();
Expand All @@ -52,7 +52,7 @@ public void ShouldUseTheCustomCauseFactory()
var cause = new InvalidOperationException("custom cause");

Exception? received = null;
Extensions.FromCancellationToken(cts.Token, () => cause).Subscribe(onError: err => received = err);
RxExtensions.FromCancellationToken(cts.Token, () => cause).Subscribe(onError: err => received = err);

Assert.That(received, Is.SameAs(cause));
}
Expand Down
12 changes: 6 additions & 6 deletions test/RxSharp.Tests/Extras/FromEventBufferedExtrasTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public void ShouldAttachTheHandlerImmediatelyRatherThanAtSubscribeTime()
{
var manager = new FakeTargetManager();

using var source = Extensions.FromEventBuffered<string>(
using var source = RxExtensions.FromEventBuffered<string>(
h => manager.TargetCreated += h,
h => manager.TargetCreated -= h);

Expand All @@ -35,7 +35,7 @@ public void ShouldAttachTheHandlerImmediatelyRatherThanAtSubscribeTime()
public void ShouldReplayBufferedValuesToALateSubscriberThenDeliverLiveValues()
{
var manager = new FakeTargetManager();
using var source = Extensions.FromEventBuffered<string>(
using var source = RxExtensions.FromEventBuffered<string>(
h => manager.TargetCreated += h,
h => manager.TargetCreated -= h);

Expand All @@ -52,7 +52,7 @@ public void ShouldReplayBufferedValuesToALateSubscriberThenDeliverLiveValues()
public void ShouldDeliverToEveryIndependentSubscriber()
{
var manager = new FakeTargetManager();
using var source = Extensions.FromEventBuffered<string>(
using var source = RxExtensions.FromEventBuffered<string>(
h => manager.TargetCreated += h,
h => manager.TargetCreated -= h);

Expand All @@ -71,7 +71,7 @@ public void ShouldDeliverToEveryIndependentSubscriber()
public void ShouldOnlyReplayUpToTheRequestedBufferSize()
{
var manager = new FakeTargetManager();
using var source = Extensions.FromEventBuffered<string>(
using var source = RxExtensions.FromEventBuffered<string>(
h => manager.TargetCreated += h,
h => manager.TargetCreated -= h,
bufferSize: 2);
Expand All @@ -90,7 +90,7 @@ public void ShouldOnlyReplayUpToTheRequestedBufferSize()
public void ShouldDetachTheHandlerOnDispose()
{
var manager = new FakeTargetManager();
var source = Extensions.FromEventBuffered<string>(
var source = RxExtensions.FromEventBuffered<string>(
h => manager.TargetCreated += h,
h => manager.TargetCreated -= h);

Expand All @@ -106,7 +106,7 @@ public void ShouldDetachTheHandlerOnDispose()
public void ShouldBeSafeToDisposeMoreThanOnce()
{
var manager = new FakeTargetManager();
var source = Extensions.FromEventBuffered<string>(
var source = RxExtensions.FromEventBuffered<string>(
h => manager.TargetCreated += h,
h => manager.TargetCreated -= h);

Expand Down
6 changes: 3 additions & 3 deletions test/RxSharp.Tests/Extras/TimeoutExtrasTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public void ShouldErrorAfterTheDelay()
using var signal = new ManualResetEventSlim();
Exception? received = null;

Extensions.Timeout(TimeSpan.FromMilliseconds(20)).Subscribe(onError: err =>
RxExtensions.Timeout(TimeSpan.FromMilliseconds(20)).Subscribe(onError: err =>
{
received = err;
signal.Set();
Expand All @@ -25,7 +25,7 @@ public void ShouldErrorAfterTheDelay()
public void ShouldNeverErrorWhenDelayIsZero()
{
var errored = false;
Extensions.Timeout(TimeSpan.Zero).Subscribe(onError: _ => errored = true);
RxExtensions.Timeout(TimeSpan.Zero).Subscribe(onError: _ => errored = true);

Thread.Sleep(50);

Expand All @@ -39,7 +39,7 @@ public void ShouldUseTheCustomCauseFactory()
var cause = new InvalidOperationException("custom timeout cause");
Exception? received = null;

Extensions.Timeout(TimeSpan.FromMilliseconds(10), () => cause).Subscribe(onError: err =>
RxExtensions.Timeout(TimeSpan.FromMilliseconds(10), () => cause).Subscribe(onError: err =>
{
received = err;
signal.Set();
Expand Down