Skip to content

Commit

Permalink
fix: remove the generic on _CapsuleManager to allow capsule upcasts (#39
Browse files Browse the repository at this point in the history
)

Fixes #36
  • Loading branch information
GregoryConrad authored Dec 25, 2023
1 parent d4a67c0 commit ef7fbb7
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 13 deletions.
14 changes: 7 additions & 7 deletions packages/rearch/lib/rearch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ abstract interface class SideEffectApi {
/// Contains the data of [Capsule]s.
/// See the documentation for more.
class CapsuleContainer implements Disposable {
final _capsules = <_UntypedCapsule, _UntypedCapsuleManager>{};
final _capsules = <_UntypedCapsule, _CapsuleManager>{};

/// Non-null indicates we are currently in a transaction,
/// with the changed nodes in the set.
/// When null, we are not in a transaction,
/// and we can rebuild capsules on the spot normally.
Set<_UntypedCapsuleManager>? _managersToRebuildFromTxn;
Set<_CapsuleManager>? _managersToRebuildFromTxn;

void _markNeedsBuild(_UntypedCapsuleManager manager) {
void _markNeedsBuild(_CapsuleManager manager) {
runTransaction(() => _managersToRebuildFromTxn!.add(manager));
}

Expand All @@ -126,16 +126,16 @@ class CapsuleContainer implements Disposable {
}
}

_CapsuleManager<T> _managerOf<T>(Capsule<T> capsule) {
_CapsuleManager _managerOf(_UntypedCapsule capsule) {
return _capsules.putIfAbsent(
capsule,
() => _CapsuleManager<T>(this, capsule),
) as _CapsuleManager<T>;
() => _CapsuleManager(this, capsule),
);
}

/// Reads the current data of the supplied [Capsule],
/// initializing it if needed.
T read<T>(Capsule<T> capsule) => _managerOf(capsule).data;
T read<T>(Capsule<T> capsule) => _managerOf(capsule).data as T;

/// *Temporarily* listens to changes in a given set of [Capsule]s.
///
Expand Down
11 changes: 5 additions & 6 deletions packages/rearch/lib/src/impl.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
part of '../rearch.dart';

typedef _UntypedCapsule = Capsule<Object?>;
typedef _UntypedCapsuleManager = _CapsuleManager<Object?>;

class _CapsuleManager<T> extends DataflowGraphNode
class _CapsuleManager extends DataflowGraphNode
implements SideEffectApi, Disposable {
_CapsuleManager(this.container, this.capsule) {
buildSelf();
}

final CapsuleContainer container;
final Capsule<T> capsule;
final _UntypedCapsule capsule;

late T data;
late Object? data;
bool hasBuilt = false;
bool debugIsBuilding = false;
final sideEffectData = <Object?>[];
Expand All @@ -34,7 +33,7 @@ class _CapsuleManager<T> extends DataflowGraphNode

final otherManager = container._managerOf(otherCapsule);
addDependency(otherManager);
return otherManager.data;
return otherManager.data as R;
}

@override
Expand Down Expand Up @@ -94,7 +93,7 @@ class _CapsuleManager<T> extends DataflowGraphNode
class _CapsuleHandleImpl implements CapsuleHandle {
_CapsuleHandleImpl(this.manager);

final _UntypedCapsuleManager manager;
final _CapsuleManager manager;

int sideEffectDataIndex = 0;

Expand Down
24 changes: 24 additions & 0 deletions packages/rearch/test/basic_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -434,4 +434,28 @@ void main() {
expect(container.read(useInCallbackCapsule), throwsA(anything));
expect(container.read(useAfterAwaitCapsule), throwsA(anything));
});

test('containers store capsules completely untyped (issue #36)', () {
// Re-reading the capsule under a different type should not throw.
() capsule(CapsuleHandle use) => ();
useContainer()
// ignore: unnecessary_cast
..read(capsule as Capsule<Object>)
..read(capsule);
});

test('use() in lists works correctly (spun off of issue #36)', () {
int intCapsule(CapsuleHandle use) => 0;
double doubleCapsule(CapsuleHandle use) => 0;
List<num> upcastedListCapsule1(CapsuleHandle use) =>
[use(intCapsule), use(doubleCapsule)];
List<num> upcastedListCapsule2(CapsuleHandle use) =>
[intCapsule, doubleCapsule].map(use.call).toList();

final container = useContainer();
expect(container.read(upcastedListCapsule1), equals([0, 0.0]));
expect(container.read(upcastedListCapsule2), equals([0, 0.0]));
expect(container.read(intCapsule), equals(0));
expect(container.read(doubleCapsule), equals(0.0));
});
}

0 comments on commit ef7fbb7

Please sign in to comment.