PAX

 view release on metacpan or  search on metacpan

lib/PAX/StandaloneDispatch.pm  view on Meta::CPAN

    my ($image, $extract_dir) = @_;
    my $err = gensym;
    my $pid = open3(my $in, my $out, $err, $image->{output_path}, '--pax-standalone-extract', $extract_dir);
    close $in;
    local $/;
    <$out>;
    my $stderr = <$err> // '';
    waitpid($pid, 0);
    die "standalone extraction failed for $image->{output_path}: $stderr\n" if ($? >> 8) != 0;
}

sub _runtime_paths {
    my ($image, $extract_dir) = @_;
    my $code_root = File::Spec->catdir($extract_dir, 'code');
    my $runtime_root = File::Spec->catdir($extract_dir, 'runtime');
    my $assets_root = File::Spec->catdir($extract_dir, 'assets');
    my $entrypoint = File::Spec->catfile($code_root, split m{/}, $image->{entrypoint}{logical_path});
    my $perl_exec = ($image->{runtime}{mode} // '') eq 'bundled_perl'
        ? File::Spec->catfile($runtime_root, split m{/}, ($image->{runtime}{perl_binary_logical_path} // 'bin/perl'))
        : 'perl';

    my @lib_roots = map { File::Spec->catdir($code_root, split m{/}) } @{ $image->{lib_dirs} // [] };
    my @runtime_roots = map { File::Spec->catdir($runtime_root, split m{/}) } @{ $image->{runtime}{bundled_inc_roots} // [] };
    return {
        extract_dir => $extract_dir,
        code_root => $code_root,
        runtime_root => $runtime_root,
        assets_root => $assets_root,
        entrypoint => $entrypoint,
        manifest_path => File::Spec->catfile($image->{standalone_dir}, 'manifest.json'),
        perl_exec => $perl_exec,
        perl5lib => join(':', grep { defined && length } (@lib_roots, @runtime_roots)),
    };
}

sub _restore_executable_bits {
    my ($image, $paths) = @_;
    chmod 0700, $paths->{perl_exec} if ($image->{runtime}{mode} // '') eq 'bundled_perl' && -f $paths->{perl_exec};
    for my $region (@{ $image->{native_dispatch} // [] }) {
        next if !$region->{executable_logical_path};
        my $path = File::Spec->catfile($paths->{extract_dir}, split m{/}, $region->{executable_logical_path});
        chmod 0700, $path if -f $path;
    }
}

sub _run_perl_region {
    my (%args) = @_;
    my $paths = $args{paths};
    my $region = $args{region};
    my $perl = $paths->{perl_exec};
    my $script = q{
my ($entry, $region, $left, $right) = @ARGV;
require PAX::StandaloneRuntime;
my $rv = PAX::StandaloneRuntime->run(entrypoint => $entry, argv => []);
my $qualified = $region =~ /::/ ? $region : "main::$region";
no strict 'refs';
my $value = &{$qualified}(0 + $left, 0 + $right);
print defined $value ? $value : q{};
};
    local $ENV{PERL5LIB} = $paths->{perl5lib} if defined $paths->{perl5lib} && length $paths->{perl5lib};
    local $ENV{PAX_EMBEDDED_ASSET_ROOT} = $paths->{assets_root};
    local $ENV{PAX_STANDALONE_MANIFEST_PATH} = $paths->{manifest_path};
    local $ENV{PAX_STANDALONE_TMPDIR} = $paths->{extract_dir};

    my $err = gensym;
    my $pid = open3(my $in, my $out, $err, $perl, '-e', $script, $paths->{entrypoint}, $region->{region_name}, $args{left}, $args{right});
    close $in;
    local $/;
    my $stdout = <$out> // '';
    my $stderr = <$err> // '';
    waitpid($pid, 0);
    chomp $stdout;

    return {
        status => ($? >> 8) == 0 ? 'ok' : 'error',
        exit => $? >> 8,
        stdout => $stdout,
        stderr => $stderr,
        value => $stdout =~ /^-?\d+$/ ? 0 + $stdout : undef,
        reason => ($? >> 8) == 0 ? 'perl_region_fallback' : 'perl_region_execution_failed',
    };
}

1;

=pod

=head1 NAME

PAX::StandaloneDispatch - standalone command and region dispatch helper

=head1 SYNOPSIS

  use PAX::StandaloneDispatch;

  my $obj = PAX::StandaloneDispatch->new(...);
  my $result = $obj->run_i64(...);

=head1 DESCRIPTION

Holds the dispatch information that standalone binaries use to route built-in commands, helpers, and native regions.

=head1 METHODS

=head2 new, run_i64

These are the public entrypoints exposed by this module's current interface.

=head1 PURPOSE

This module exists to keep the standalone command and region dispatch helper logic in one place so the CLI, build
pipeline, and runtime can reuse the same behavior instead of duplicating it.

=head1 WHY IT EXISTS

PAX uses this module when it needs standalone command and region dispatch helper. Keeping that behavior isolated here
makes the surrounding compiler and packaging stages easier to reason about and
safer to evolve.

=head1 WHEN TO USE



( run in 1.516 second using v1.01-cache-2.11-cpan-71847e10f99 )