File Coverage

blib/lib/Mojo/Promise/Role/Repeat.pm
Criterion Covered Total %
statement 39 39 100.0
branch 4 4 100.0
condition 3 4 75.0
subroutine 9 9 100.0
pod 2 2 100.0
total 57 58 98.2


line stmt bran cond sub pod time code
1             package Mojo::Promise::Role::Repeat 0.006;
2              
3             # ABSTRACT: Promise looping construct with break
4              
5 1     1   523003 use Mojo::Base -role;
  1         8  
  1         5  
6              
7             sub repeat {
8 26     26 1 17884 my ($self, $body) = (shift, pop);
9 26 100 100     84 unless (ref $self) {
10 5         21 $self = $self->resolve(@_);
11             }
12             elsif (@_) {
13             my @values = @_;
14 5     5   1095 $self = $self->then( sub { (@values, @_) });
15             }
16 26         760 my $done_p = $self->clone;
17             my $break = sub {
18 19     19   283 $done_p->resolve(@_);
19 19         797 die $self->clone;
20             # kills whatever handler we are in,
21             # but because the reason is a promise,
22             # does not actually reject anything,
23             # any promises dependent on that handler remain unsettled,
24             # and, because the passed promise is not referenced by anyone else,
25             # it will NEVER be settled; that whole line of execution just stops;
26             # which is not a problem here because we're skipping ahead and
27             # resolving the promise at the "end" of the chain
28 26         700 };
29 26         41 my $again_w;
30             $again_w = sub {
31 95     95   136 my $again = $again_w;
32             $self = $self->then(
33             sub {
34 69         10072 $again->();
35 69         2680 return $body->(@_) for ($break);
36             },
37             sub {
38 4         666 $done_p->reject(@_);
39             }
40 95         352 );
41 26         69 };
42 26         55 $again_w->();
43 26         1100 Scalar::Util::weaken($again_w);
44 26         104 return $done_p;
45             };
46              
47             sub repeat_catch {
48 10     10 1 10136 my ($self, $body) = (shift, pop);
49 10 100 50     34 unless (ref $self) {
50 5         12 $self = $self->reject(@_);
51             }
52             elsif (@_) {
53             my @values = @_;
54             $self = $self->catch(
55 5     5   1106 sub { $self->clone->reject(@values, @_) }
56             );
57             }
58 10         593 my $done_p = $self->clone;
59             my $break = sub {
60 6     6   46 $done_p->reject(@_);
61 6         311 die $self->clone;
62             # kill/abandon whatever handler we are in.
63             # Same as for repeat()
64 10         261 };
65 10         14 my $again_w;
66             $again_w = sub {
67 52     52   65 my $again = $again_w;
68             $self = $self->then(
69             sub {
70 4         1080 $done_p->resolve(@_);
71             },
72             sub {
73 42         5470 $again->();
74 42         1628 return $body->(@_) for ($break);
75             }
76 52         172 );
77 10         24 };
78 10         23 $again_w->();
79 10         487 Scalar::Util::weaken($again_w);
80 10         32 return $done_p;
81             };
82              
83             1;
84              
85             __END__