Jelajahi Sumber

Experimental support for running on windows.

Most of the code was lifted from selenium-client.

For some reason Net::EmptyPort::wait_port doesn't work anymore on windows?

Quite bizzare.

In any case I believe this *ought* to produce a working
module.
George Baugh 3 bulan lalu
induk
melakukan
c57fe631f4
3 mengubah file dengan 52 tambahan dan 6 penghapusan
  1. 2 0
      generate_api_json.sh
  2. 46 6
      lib/Playwright.pm
  3. 4 0
      lib/Playwright/Util.pm

+ 2 - 0
generate_api_json.sh

@@ -9,3 +9,5 @@ popd
 cp playwright_server bin/playwright_server
 API="$(<api.json)"
 sed -i -e '/%REPLACEME%/r api.json' -e 's/%REPLACEME%//g' bin/playwright_server
+# Make which work on windows
+cp bin/playwright_server bin/playwright_server.bat

+ 46 - 6
lib/Playwright.pm

@@ -7,6 +7,8 @@ use warnings;
 use 5.006;
 use v5.28.0;    # Before 5.006, v5.10.0 would not be understood.
 
+use constant IS_WIN => $^O eq 'MSWin32';
+
 use File::ShareDir();
 use File::Basename();
 use Cwd();
@@ -422,7 +424,12 @@ sub _check_node {
       unless $server_bin && -x $server_bin;
 
     # Attempt to start the server.  If we can't do this, we almost certainly have dependency issues.
-    my ($output) = capture_merged { system($node_bin, $server_bin, '--check') };
+    my $output = '';
+    if (IS_WIN) {
+        $output = 'OK';
+    } else {
+        ($output) = capture_merged { system($node_bin, $server_bin, '--check') };
+    }
     return if $output =~ m/OK/;
 
     warn $output if $output;
@@ -666,6 +673,8 @@ sub quit ($self) {
 
     Playwright::Util::request( 'GET', 'shutdown', $self->{host}, $self->{port}, $self->{ua} );
 
+    return $self->_kill_playwright_server_windows() if IS_WIN;
+
     # 0 is always WCONTINUED, 1 is always WNOHANG, and POSIX is an expensive import
     # When 0 is returned, the process is still active, so it needs more persuasion
     foreach (0..3) {
@@ -690,17 +699,32 @@ sub DESTROY ($self) {
     $self->quit();
 }
 
+sub _wait_port( $port ) {
+    # Check if the port is already live, and short-circuit if this is the case.
+    if (IS_WIN) {
+        sleep 5;
+        my $result = qx{netstat -na | findstr "$port"};
+        return !!$result;
+    }
+    return Net::EmptyPort::wait_port( $port, 1 )
+}
+
 sub _start_server ( $port, $cdp_uri, $timeout, $debug, $cleanup ) {
     $debug = $debug ? '--debug' : '';
 
     # Check if the port is already live, and short-circuit if this is the case.
-    if ( Net::EmptyPort::wait_port( $port, 1 ) ) {
+    if ( _wait_port( $port ) ) {
         print "Re-using playwright server on port $port...\n" if $debug;
         # Set the PID as something bogus, we don't really care as we won't kill it
         return "REUSE";
     }
 
+    my @args = ( qq{"$node_bin"}, qq{"$server_bin"}, "--port", $port );
+    push(@args, "--cdp", qq{"$cdp_uri"}) if $cdp_uri;
+    push(@args, $debug) if $debug;
+
     $ENV{DEBUG} = 'pw:api' if $debug;
+    return _start_server_windows( $port, $timeout, $debug, $cleanup, @args ) if IS_WIN;
     my $pid = fork // confess("Could not fork");
     if ($pid) {
         print "Waiting for playwright server on port $port to come up...\n" if $debug;
@@ -711,10 +735,6 @@ sub _start_server ( $port, $cdp_uri, $timeout, $debug, $cleanup ) {
         return $pid;
     }
 
-    my @args = ( $node_bin, $server_bin, "--port", $port );
-    push(@args, "--cdp", $cdp_uri) if $cdp_uri;
-    push(@args, $debug) if $debug;
-
     # Orphan the process in the event that cleanup => 0
     if (!$cleanup) {
         print "Detaching child process...\n";
@@ -728,4 +748,24 @@ sub _start_server ( $port, $cdp_uri, $timeout, $debug, $cleanup ) {
     exec( @args );
 }
 
+sub _start_server_windows ( $port, $timeout, $debug, $cleanup, @args) {
+        my $pid = qq/playwright-server:$port/;
+        my @cmdprefix = ("start /MIN", qq{"$pid"});
+
+        my $node_bin = File::Which::which('node');
+        my $server_bin = File::Which::which('playwright_server');
+        my $cmdstring = join(' ', @cmdprefix, @args );
+        print "$cmdstring\n" if $debug;
+        system($cmdstring);
+        _wait_port( $port );
+        return $pid;
+}
+
+sub _kill_playwright_server_windows ($self) {
+    my $killer = qq[taskkill /FI "WINDOWTITLE eq $self->{pid}"];
+    print "$killer\n" if $self->{debug};
+    system($killer);
+    return 1;
+}
+
 1;

+ 4 - 0
lib/Playwright/Util.pm

@@ -42,6 +42,10 @@ sub request ( $method,$url, $host, $port, $ua, %args ) {
     $request->content( JSON::MaybeXS::encode_json( \%args ) );
     my $response = $ua->request($request);
     my $content  = $response->decoded_content();
+
+    # If we get this kind of response the server failed to come up :(
+    die "playwright server failed to spawn!" if $content =~ m/^Can't connect to/;
+
     my $decoded  = JSON::MaybeXS::decode_json($content);
     my $msg      = $decoded->{message};