File Coverage

blib/lib/Moo/Role/RequestReplyHandler.pm
Criterion Covered Total %
statement 15 76 19.7
branch 0 8 0.0
condition 0 4 0.0
subroutine 5 11 45.4
pod 2 6 33.3
total 22 105 20.9


line stmt bran cond sub pod time code
1             package Moo::Role::RequestReplyHandler;
2 1     1   5296 use Moo::Role;
  1         3  
  1         6  
3 1     1   368 use feature 'signatures';
  1         2  
  1         61  
4 1     1   7 no warnings 'experimental::signatures';
  1         1  
  1         45  
5 1     1   7 use Scalar::Util 'weaken';
  1         7  
  1         60  
6 1     1   492 use Moo::Role::RequestReplyHandler::EventListener;
  1         3  
  1         910  
7              
8             our $VERSION = '0.01';
9              
10             requires 'get_reply_key';
11              
12             has outstanding_messages => (
13             is => 'ro',
14             default => sub { {} },
15             );
16              
17             has event_listeners => (
18             is => 'ro',
19             default => sub { {} },
20             );
21              
22             has message_id => (
23             is => 'rw',
24             default => '0',
25             );
26              
27 0     0 0   sub use_message_id( $self ) {
  0            
  0            
28 0           my $id = $self->message_id;
29 0           $self->message_id( $id++ );
30 0           return $id
31             };
32              
33 0     0 0   sub on_message( $self, $id, $callback ) {
  0            
  0            
  0            
  0            
34 0           $self->outstanding_messages->{$id} = $callback;
35             };
36              
37 0     0 0   sub message_received( $self, $msg ) {
  0            
  0            
  0            
38 0           my $id = $self->get_reply_key( $msg );
39 0 0         if( my $handler = delete $self->outstanding_messages->{$id} ) {
40 0           $handler->($msg);
41             } else {
42 0           warn "Unhandled message '$id' ignored";
43             };
44             }
45              
46 0     0 0   sub event_received( $self, $type, $ev ) {
  0            
  0            
  0            
  0            
47 0           my $handled;
48 0 0         if( my $listeners = $self->event_listeners->{ $type } ) {
49 0           @$listeners = grep { defined $_ } @$listeners;
  0            
50 0           for my $listener (@$listeners) {
51 0           eval {
52 0           $listener->notify( $ev );
53             };
54 0 0         warn $@ if $@;
55             };
56             # re-weaken our references
57 0           for (0..$#$listeners) {
58 0           weaken $listeners->[$_];
59             };
60              
61 0           $handled++;
62             };
63 0           $handled;
64             }
65              
66             =head2 C<< ->add_listener >>
67              
68             my $l = $driver->add_listener(
69             'Page.domContentEventFired',
70             sub {
71             warn "The DOMContent event was fired";
72             },
73             );
74              
75             # ...
76              
77             undef $l; # stop listening
78              
79             Adds a callback for the given event name. The callback will be removed once
80             the return value goes out of scope.
81              
82             =cut
83              
84 0     0 1   sub add_listener( $self, $event, $callback ) {
  0            
  0            
  0            
  0            
85 0           my $listener = Moo::Role::RequestReplyHandler::EventListener->new(
86             target => $self,
87             callback => $callback,
88             event => $event,
89             );
90 0   0       $self->event_listeners->{ $event } ||= [];
91 0           push @{ $self->event_listeners->{ $event }}, $listener;
  0            
92 0           weaken $self->event_listeners->{ $event }->[-1];
93 0           $listener
94             }
95              
96             =head2 C<< ->remove_listener >>
97              
98             $driver->remove_listener($l);
99              
100             Explicitly remove a listener.
101              
102             =cut
103              
104 0     0 1   sub remove_listener( $self, $listener ) {
  0            
  0            
  0            
105             # $listener->{event} can be undef during global destruction
106 0 0         if( my $event = $listener->event ) {
107 0   0       my $l = $self->event_listeners->{ $event } ||= [];
108 0           @{$l} = grep { $_ != $listener }
  0            
109 0           grep { defined $_ }
110 0           @{$self->event_listeners->{ $event }};
  0            
111             # re-weaken our references
112 0           for (0..$#$l) {
113 0           weaken $l->[$_];
114             };
115             };
116             }
117              
118             1;