George S. Baugh 4 år sedan
förälder
incheckning
724e30f4cb
6 ändrade filer med 34 tillägg och 13 borttagningar
  1. 1 0
      Changes
  2. 4 6
      lib/Playwright.pm
  3. 1 1
      lib/Playwright/Base.pm
  4. 22 0
      lib/Playwright/Util.pm
  5. 2 0
      t/Playwright-Util.t
  6. 4 6
      t/Playwright.t

+ 1 - 0
Changes

@@ -2,6 +2,7 @@ Revision history for Playwright
 
 0.008 2021-07-19 TEODESIAN
     - Add parent attribute to grab element parents when needed
+    - Remove dependency on AsyncData in favor of File::Temp, Sereal and fork().
 
 0.007 2021-06-17 TEODESIAN
     - Adjust module for changing Download returns, and api.json no longer being shipped with Playwright

+ 4 - 6
lib/Playwright.pm

@@ -15,7 +15,6 @@ use LWP::UserAgent();
 use Sub::Install();
 use Net::EmptyPort();
 use JSON::MaybeXS();
-use File::Slurper();
 use File::Which();
 use Capture::Tiny qw{capture_merged capture_stderr};
 use Carp qw{confess};
@@ -147,8 +146,8 @@ L<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/ar
 
 =head2 Asynchronous operations
 
-The waitFor* methods defined on various classes will return an instance of AsyncData, a part of the L<Async> module.
-You will then need to wait on the result of the backgrounded action with the await() method documented below.
+The waitFor* methods defined on various classes are essentially a light wrapper around Mojo::IOLoop::Subprocess.
+You will need to wait on the result of the backgrounded action with the await() method documented below.
 
     # Assuming $handle is a Playwright object
     my $async = $page->waitForEvent('console');
@@ -412,15 +411,14 @@ sub launch ( $self, %args ) {
     return $msg;
 }
 
-=head2 await (AsyncData) = Object
+=head2 await (HASH) = Object
 
 Waits for an asynchronous operation returned by the waitFor* methods to complete and returns the value.
 
 =cut
 
 sub await ( $self, $promise ) {
-    confess("Input must be an AsyncData") unless $promise->isa('AsyncData');
-    my $obj = $promise->result(1);
+    my $obj = Playwright::Util::await($promise);
 
     return $obj unless $obj->{_type};
     my $class = "Playwright::$obj->{_type}";

+ 1 - 1
lib/Playwright/Base.pm

@@ -91,7 +91,7 @@ sub _request ( $self, %args ) {
 
     %args = Playwright::Base::_coerce( $self->{spec}, %args );
 
-    return AsyncData->new( sub { &Playwright::Base::_do( $self, %args ) } )
+    return Playwright::Util::async( sub { &Playwright::Base::_do( $self, %args ) } )
       if $args{command} =~ m/^waitFor/;
 
     my $msg = Playwright::Base::_do->( $self, %args );

+ 22 - 0
lib/Playwright/Util.pm

@@ -7,6 +7,9 @@ use v5.28;
 
 use JSON::MaybeXS();
 use Carp qw{confess};
+use Sereal::Encoder;
+use Sereal::Decoder;
+use File::Temp;
 
 #ABSTRACT: Common utility functions for the Playwright module
 
@@ -41,4 +44,23 @@ sub arr2hash ($array,$primary_key) {
     return $inside_out;
 }
 
+# Serialize a subprocess because NOTHING ON CPAN DOES THIS GRRRRR
+sub async ($subroutine) {
+    # The fork would result in the tmpdir getting whacked when it terminates.
+    my (undef, $filename) = File::Temp::tempfile();
+    my $pid = fork() // die "Could not fork";
+    _child($filename, $subroutine) unless $pid;
+    return { pid => $pid, file => $filename };
+}
+
+sub _child ($filename,$subroutine) {
+    Sereal::Encoder->encode_to_file($filename,$subroutine->());
+    exit 0;
+}
+
+sub await ($to_wait) {
+    waitpid($to_wait->{pid},0);
+    return Sereal::Decoder->decode_from_file($to_wait->{file});
+}
+
 1;

+ 2 - 0
t/Playwright-Util.t

@@ -21,4 +21,6 @@ $json = '{ "error":false, "message": { "_type":"Bogus", "_guid":"abc123" } }';
 
 is(Playwright::Util::request('tickle','chase',666, LWP::UserAgent->new(), a => 'b' ), { _type => 'Bogus', _guid => 'abc123' }, "Good response from server decoded and returned");
 
+#Not testing async/await, mocking forks is bogus
+
 done_testing();

+ 4 - 6
t/Playwright.t

@@ -4,7 +4,6 @@ use JSON::MaybeXS;
 use Test::MockModule qw{strict};
 use Test::MockFile;
 use Test::Fatal qw{exception};
-use Async;
 
 my ($qxret,$qxcode) = ('',255);
 use Test::Mock::Cmd qx => sub { $? = $qxcode; return $qxret }, system => sub { print $qxret };
@@ -158,18 +157,17 @@ subtest "await" => sub {
 
     my $res = {};
 
-    no warnings qw{redefine once};
-    local *AsyncData::result = sub { $res };
-    use warnings;
+    my $utilmock = Test::MockModule->new('Playwright::Util');
+    $utilmock->redefine('await', sub { $res } );
 
-    my $promise = bless({},'AsyncData');
+    my $promise = { file => 'foo.out', pid => 666 };
 
     my $obj = bless({ ua => 'eee', 'port' => 1 }, 'Playwright');
     no warnings qw{redefine once};
     local *Playwright::Bogus::new = sub { my ($class, %input) = @_; return bless({ spec => 'whee', ua => $input{handle}{ua}, port => $input{handle}{port}, type => $input{type}, guid => $input{id} }, 'Playwright::Bogus') };
     use warnings;
 
-    is($obj->await($promise),{},"await passthru works");
+    is($obj->await($promise), {},"await passthru works");
 
     $res = { _guid => 'abc123', _type => 'Bogus' };
     my $expected = bless({ spec => 'whee', ua => 'eee', port => 1, guid => 'abc123', type => 'Bogus' }, 'Bogus');