File Coverage

blib/lib/Mojo/Phantom/Process.pm
Criterion Covered Total %
statement 15 37 40.5
branch 1 4 25.0
condition 0 3 0.0
subroutine 5 9 55.5
pod 2 2 100.0
total 23 55 41.8


line stmt bran cond sub pod time code
1             package Mojo::Phantom::Process;
2              
3 7     7   24 use Mojo::Base 'Mojo::EventEmitter';
  7         9  
  7         38  
4              
5 7     7   890 use constant DEBUG => $ENV{MOJO_PHANTOM_DEBUG};
  7         10  
  7         585  
6              
7 7     7   31 use Mojo::IOLoop;
  7         9  
  7         59  
8 7     7   125 use Mojo::IOLoop::Stream;
  7         8  
  7         55  
9              
10             has [qw/error exit_status pid stream/];
11              
12             has exe => 'phantomjs';
13              
14             sub kill {
15 0     0 1 0 my ($self) = @_;
16 0 0       0 return unless my $pid = $self->pid;
17 0         0 warn "Killing $pid\n" if DEBUG;
18 0         0 kill KILL => $pid;
19 0         0 waitpid $pid, 0;
20 0         0 $self->exit_status($?);
21 0         0 $self->stream->close;
22             };
23              
24             sub start {
25 11     11 1 15 my ($self, $file) = @_;
26              
27 11         84 my $pid = open my $pipe, '-|', $self->exe, "$file";
28 11 50       31555 die 'Could not spawn' unless defined $pid;
29 0           $self->pid($pid);
30 0           $self->emit(spawn => $pid);
31              
32 0           my $stream = Mojo::IOLoop::Stream->new($pipe);
33 0           my $id = Mojo::IOLoop->stream($stream);
34 0           $self->stream($stream);
35 0     0     $stream->on(error => sub { $self->error($_[1])->kill });
  0            
36 0     0     $stream->on(read => sub { $self->emit(read => $_[1]) });
  0            
37             $stream->on(close => sub {
38 0     0     my $pid = delete $self->{pid};
39 0           warn "Stream for $pid closed\n" if DEBUG;
40 0   0       $self->{exit_status} ||= $?;
41 0           $self->emit('close');
42 0           });
43              
44 0           return $self;
45             }
46              
47             1;
48              
49             =head1 NAME
50              
51             Mojo::Phantom::Process - Represents the running phantom process and its stream
52              
53             =head1 SYNOPSIS
54              
55             my $proc = Mojo::Phantom::Process->new;
56             $proc->start($file);
57              
58             =head1 DESCRIPTION
59              
60             A very utilitarian class representing a single execution of the PhantomJS executable.
61             It forks the new process and attaches a stream watcher to its STDOUT and attaches to various stream events.
62             This class is just process management and transport.
63             All real behavior is defined by the executed javascript file and the listeners to the events defined by this class.
64              
65             =head1 EVENTS
66              
67             L inherits all the events from L and emits the following new ones
68              
69             =head2 close
70              
71             $proc->on(close => sub { ($proc) = @_; ... });
72              
73             Emitted when the process has exitted (possibly with errors) and the stream has closed.
74             The user will want to check L and L.
75              
76             =head2 read
77              
78             $proc->on(read => sub { ($proc, $bytes) = @_; ... });
79              
80             Re-emitted after bytes have been read from the L.
81              
82             =head2 spawn
83              
84             $proc->on(spawn => sub { my ($proc, $pid) = @_; ... });
85              
86             Emitted just after the child process is spawned.
87             Passed the new child pid.
88              
89             =head1 ATTRIBUTES
90              
91             =head2 error
92              
93             Holds errors caught from the L's error event.
94             Note that when such an error event is caught, the process is then killed by the L method immediately afterwards.
95              
96             =head2 exit_status
97              
98             The exit status C<$?> from the closed pid.
99              
100             =head2 pid
101              
102             The pid of the spawned process.
103             The stream's close event will clear this value once the process has ended.
104              
105             =head2 stream
106              
107             The instance of L used to monitor the STDOUT of the external process.
108             It is created automatically attacted to the L by running L.
109              
110             =head2 exe
111              
112             The executable name or path to call PhantomJS. You may substitute a compatible platform, for example using C to use
113             CasperJS.
114              
115             =head1 METHODS
116              
117             =head2 kill
118              
119             $proc->kill
120              
121             Kills the child process (KILL) and closes the stream.
122             Note that since the process might exit before the kill signal is sent, it is not guaranteed that the L will reflect the signal.
123              
124             =head2 start
125              
126             $proc->start($file);
127              
128             Starts a PhantomJS in a child process running a given file, creates a stream listener and attaches to its events.
129             Returns itself.
130