view release on metacpan or search on metacpan
lib/PAX/CodeUnitCompiler.pm view on Meta::CPAN
return $body =~ /^\s*require\s+(?:[A-Za-z_][A-Za-z0-9_]*::)*\Q$class_tail\E\s*;/m ? 1 : 0;
}
sub _sibling_class {
my ($package, $class) = @_;
return $package if !defined $class || $class eq '';
return $package if !defined $package || $package eq '';
my ($root) = $package =~ m{^(.*)::([^:]+)$};
$root //= '';
my @class_parts = split m{::}, $class;
return join('::', grep { defined && $_ ne '' } $root, @class_parts);
}
sub _related_class_from_source {
my ($source, $package, $body, $class, %args) = @_;
return _sibling_class($package, $class) if !defined $class || $class eq '';
my @methods = @{ $args{methods} || [] };
for my $scope (grep { defined && $_ ne '' } $body, $source) {
my $qualified = _qualified_class_in_scope($scope, $class, \@methods);
lib/PAX/StandaloneDispatch.pm view on Meta::CPAN
region_id => $region->{region_id},
region_name => $region->{region_name},
guards => $region->{guards} // [],
deopt => $region->{deopt} // {},
},
args => [ $left + 0, $right + 0 ],
context => 'scalar',
);
if ($guard->{status} eq 'native_allowed' && $region->{executable_logical_path}) {
my $path = File::Spec->catfile($extract_dir, split m{/}, $region->{executable_logical_path});
my $result = $self->{native_runner}->run_i64_binary(
path => $path,
left => $left,
right => $right,
);
if (($result->{status} // '') eq 'ok') {
return {
status => 'native',
execution_model => 'standalone_packaged_native',
region_id => $region->{region_id},
lib/PAX/StandaloneDispatch.pm view on Meta::CPAN
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{
lib/PAX/StandaloneImage.pm view on Meta::CPAN
open STDERR, '>', File::Spec->devnull or die "cannot open devnull: $!";
exec {$entrypoint} $entrypoint, '--pax-standalone-extract', $extract_root;
exit 127;
}
waitpid($pid, 0);
return ($? >> 8) == 0 ? 1 : 0;
}
sub _extract_payload_path {
my ($root, $prefix, $logical_path) = @_;
my @parts = grep { defined && $_ ne '' } split m{/+}, ($logical_path // '');
return File::Spec->catfile($root, $prefix, @parts);
}
sub _extracted_manifest_path {
my ($root, $prefix, $logical_path) = @_;
my $path = _extract_payload_path($root, $prefix, $logical_path);
return '' if !defined $path || $path eq '' || !-f $path;
return $path;
}
lib/PAX/StandaloneImage.pm view on Meta::CPAN
make_path($rebuild_root) if !-d $rebuild_root;
my %written;
my $materialized_entrypoint = '';
for my $item (@source_items) {
my $source_path = $item->{source_path} // next;
my $bytes = $item->{source_bytes} // '';
next if $bytes eq '';
my $rel = File::Spec->abs2rel($source_path, $root);
next if !defined $rel || $rel eq '' || $rel =~ /^\.\.(?:\/|\\|$)/;
my $dest = File::Spec->catfile($rebuild_root, split m{/+|\\+}, $rel);
next if $written{$dest}++;
my ($vol, $dirs) = File::Spec->splitpath($dest);
make_path($dirs) if $dirs ne '' && !-d $dirs;
open my $fh, '>:raw', $dest or return {};
print {$fh} $bytes;
close $fh or return {};
if (($item->{unit_kind} // '') eq 'entrypoint') {
$materialized_entrypoint = $dest;
}
}
lib/PAX/StandaloneImage.pm view on Meta::CPAN
sub _materialized_manifest_roots {
my ($manifest, $field, $unit_kind, $source_root, $rebuild_root) = @_;
my @roots;
my %seen;
for my $logical_root (@{ $manifest->{$field} // [] }) {
next if !defined $logical_root || $logical_root eq '';
my $original_root = _manifest_source_root_for_logical($manifest, $logical_root, $unit_kind);
next if !defined $original_root || $original_root eq '';
my $rel = File::Spec->abs2rel($original_root, $source_root);
next if !defined $rel || $rel eq '' || $rel =~ /^\.\.(?:\/|\\|$)/;
my $materialized = File::Spec->catdir($rebuild_root, split m{/+|\\+}, $rel);
next if !-d $materialized || $seen{$materialized}++;
push @roots, $materialized;
}
return \@roots;
}
sub _common_source_parent {
my @paths = grep { defined && $_ ne '' } @_;
return '' if !@paths;
my @common = File::Spec->splitdir(dirname(shift @paths));
lib/PAX/StandaloneImage.pm view on Meta::CPAN
}
return File::Spec->catdir(@common);
}
sub _extracted_manifest_roots {
my ($root, $prefix, $logical_roots) = @_;
my @roots;
my %seen;
for my $logical_root (@{ $logical_roots // [] }) {
next if !defined $logical_root || $logical_root eq '';
my @parts = grep { defined && $_ ne '' } split m{/+}, $logical_root;
my $path = File::Spec->catdir($root, $prefix, @parts);
next if !-d $path || $seen{$path}++;
push @roots, $path;
}
return \@roots;
}
sub _original_manifest_roots {
my ($manifest, $field, $unit_kind) = @_;
my @roots;
lib/PAX/StandaloneImage.pm view on Meta::CPAN
my ($manifest, $logical_root, $unit_kind) = @_;
for my $unit (@{ $manifest->{code_units} // [] }) {
my $logical_path = $unit->{logical_path} // '';
my $source_path = $unit->{source_path} // '';
my $kind = $unit->{unit_kind} // '';
next if $logical_path eq '' || $source_path eq '';
next if defined $unit_kind && $unit_kind ne '' && $kind ne $unit_kind;
next if index($logical_path, $logical_root . '/') != 0;
my $rel = substr($logical_path, length($logical_root) + 1);
next if $rel eq '';
my @rel_parts = split m{/+}, $rel;
my @source_parts = File::Spec->splitdir(dirname($source_path));
splice @source_parts, -(@rel_parts - 1) if @rel_parts > 1;
my $root = File::Spec->catdir(@source_parts);
return $root if $root ne '';
}
return;
}
sub load {
my ($self, %args) = @_;
lib/PAX/StandaloneImage.pm view on Meta::CPAN
push @files, $path if !$seen{$path}++;
}
return @files;
}
sub _helper_module_path {
my ($rel, $roots) = @_;
return if !$rel;
for my $root (@{ $roots // [] }) {
next if !defined $root || $root eq '';
my $path = File::Spec->catfile($root, split m{/}, $rel);
return $path if -f $path;
}
return;
}
sub _probe_loaded_runtime_files {
my (%args) = @_;
my @modules = @{ $args{modules} // [] };
return () if !@modules;
lib/PAX/StandaloneRuntime.pm view on Meta::CPAN
return 0 if $entrypoint =~ /\A-/;
return 0 if $entrypoint =~ /\A\s*\z/;
return 1;
}
sub _resolve_entrypoint_from_manifest {
my ($entrypoint) = @_;
my $state = _state();
my $manifest_entrypoint = $state->{manifest}{entrypoint}{logical_path} // '';
if ($manifest_entrypoint ne '') {
my $candidate = File::Spec->catfile($state->{root}, 'code', split m{/}, $manifest_entrypoint);
return $candidate if -f $candidate;
}
my @unit_candidates = grep {
my $unit = $_;
my $unit_kind = $unit->{unit_kind} // '';
my $packaging = $unit->{packaging} // '';
($unit_kind // '') eq 'entrypoint' || ($packaging // '') =~ /\A(compiled|hybrid|residual)_(?:dispatch|cli_router|script)_pcu_v1\z/;
} @{ $state->{manifest}{code_units} // [] };
for my $unit (@unit_candidates) {
my $logical = $unit->{logical_path} // '';
next if $logical eq '';
my $candidate = File::Spec->catfile($state->{root}, 'code', split m{/}, $logical);
return $candidate if -f $candidate;
}
return;
}
sub _state {
return $STATE if $STATE;
my $manifest_path = $ENV{PAX_STANDALONE_MANIFEST_PATH} or die 'PAX_STANDALONE_MANIFEST_PATH not set';
open my $fh, '<', $manifest_path or die "cannot read $manifest_path: $!";
local $/;
lib/PAX/StandaloneRuntime.pm view on Meta::CPAN
sub _standalone_embedded_asset_path {
my ($name) = @_;
return if !defined $name || $name eq '';
my $state = _state();
for my $asset (@{ $state->{manifest}{assets} // [] }) {
next if ref($asset) ne 'HASH';
my $logical = $asset->{logical_path} // '';
next if $logical eq '';
next if $logical ne $name && $logical !~ m{(?:^|/)\Q$name\E\z};
my $path = File::Spec->catfile($state->{root}, 'assets', split m{/}, $logical);
return $path if -f $path;
}
return;
}
sub _share_dist_private_cli_dir {
my ($dist_name) = @_;
return if !defined $dist_name || $dist_name eq '';
my $ok = eval {
require File::ShareDir;
lib/PAX/StandaloneRuntime.pm view on Meta::CPAN
my $guard = PAX::GuardManager->new(
epochs => $state->{manifest}{runtime_epochs} // {},
)->validate_or_deopt({
region_id => $meta->{region_id},
region_name => $meta->{region_name},
guards => $meta->{guards} // [],
deopt => $meta->{deopt} // {},
}, args => [ @args[0, 1] ], context => 'scalar');
if (($guard->{status} // '') eq 'native_allowed') {
my $probe = File::Spec->catfile($state->{root}, split m{/}, $meta->{executable_logical_path});
chmod 0700, $probe if -f $probe;
my $result = $state->{native_runner}->run_i64_binary(
path => $probe,
left => $args[0],
right => $args[1],
);
if (($result->{status} // '') eq 'ok' && defined $result->{value}) {
_log_native_hit($full);
return $result->{value};
}
lib/PAX/StandaloneRuntime.pm view on Meta::CPAN
my ($args) = @_;
return 0 if @$args != 2;
return 0 if !defined $args->[0] || !defined $args->[1];
return ($args->[0] =~ /\A-?\d+\z/ && $args->[1] =~ /\A-?\d+\z/) ? 1 : 0;
}
sub _load_compiled_unit {
my ($unit) = @_;
my $state = _state();
_trace("load unit " . (($unit->{require_path} // $unit->{logical_path} // 'unknown')));
my $path = File::Spec->catfile($state->{root}, 'code', split m{/}, $unit->{logical_path});
open my $fh, '<', $path or die "cannot read compiled unit $path: $!";
local $/;
my $record = _runtime_json_decode(<$fh>);
if (($record->{residual_mode} // '') eq 'module') {
_load_residual_module($unit, $record);
return;
}
for my $init (@{ $record->{initializers} // [] }) {
lib/PAX/StandaloneRuntime.pm view on Meta::CPAN
}
if (@{ $record->{unsupported_subs} // [] }) {
_install_residual_stubs($unit, $record);
}
}
sub _ensure_virtual_source_file {
my ($unit) = @_;
my $state = _state();
my $logical = _virtual_source_logical_path($unit);
my $path = File::Spec->catfile($state->{root}, 'code', split m{/}, $logical);
return $path if -f $path;
my $dir = dirname($path);
make_path($dir) if !-d $dir;
open my $fh, '>', $path or die "cannot write virtual source file $path: $!";
print {$fh} "# PAX compiled unit placeholder for ", ($unit->{require_path} // $unit->{logical_path} // 'unknown'), "\n1;\n";
close $fh;
return $path;
}
sub _virtual_source_logical_path {
my ($unit) = @_;
my $logical = $unit->{logical_path} // '';
if (($unit->{require_path} // '') ne '') {
if ($logical =~ /\.pcu\.json\z/) {
$logical =~ s/\.pcu\.json\z/.pm/;
return $logical;
}
return File::Spec->catfile('virtual', split m{/}, ($unit->{require_path} // 'module.pm'));
}
if ($logical =~ /\.dashboard\.json\z/) {
$logical =~ s/\.dashboard\.json\z/.pl/;
return $logical;
}
if ($logical =~ /\.dispatch\.json\z/) {
$logical =~ s/\.dispatch\.json\z/.pl/;
return $logical;
}
if ($logical =~ /\.script\.json\z/) {
lib/PAX/StandaloneRuntime.pm view on Meta::CPAN
_load_package_by_module_name($module);
no strict 'refs';
my $value = ${ $action->{symbol} };
print $value;
print "\n" if $action->{newline};
exit($action->{exit_code} // 0);
}
if ($op eq 'print_embedded_asset') {
my $root = $ENV{PAX_EMBEDDED_ASSET_ROOT} // '';
my $logical = $action->{logical_path} // die 'dispatch asset logical path missing';
my $path = $root ? File::Spec->catfile($root, split m{/}, $logical) : '';
if (!$path || !-f $path) {
print STDERR "missing asset\n";
exit 3;
}
open my $fh, '<', $path or die $!;
local $/;
my $content = <$fh>;
close $fh;
print $content;
exit 0;
lib/PAX/StandaloneRuntime.pm view on Meta::CPAN
return $payload;
}
sub _find_code_unit_for_entrypoint {
my ($entrypoint) = @_;
my $state = _state();
my $entrypoint_name = $entrypoint;
for my $unit (@{ $state->{manifest}{code_units} // [] }) {
next unless $unit && ref($unit) eq 'HASH';
my $logical = $unit->{logical_path} // '';
my $packed = File::Spec->catfile($state->{root}, 'code', split m{/}, $logical);
return $unit if $unit->{logical_path} eq $entrypoint || $packed eq $entrypoint_name;
my $source_path = $unit->{source_path} // '';
next if $source_path eq '';
return $unit if File::Spec->rel2abs($source_path) eq File::Spec->rel2abs($entrypoint_name);
}
return;
}
sub _apply_initializer {
my ($init) = @_;
lib/PAX/StandaloneRuntime.pm view on Meta::CPAN
$impl = sub {
my ($self, $collector_name, $entry) = @_;
my ($timestamp) = $entry =~ /\A=== collector [^\n]* \| \@ ([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:Z|[+-][0-9]{4}|[+-][0-9]{2}:[0-9]{2}))(?: \| [^\n]*)* ===\n/;
die "Unable to parse collector log timestamp for $collector_name\n" if !defined $timestamp;
return _code_for($to_epoch_method)->($self, $timestamp);
};
return _install_sub_impl($package, $name, $sub->{prototype}, $impl);
}
if (($sub->{op} // '') eq 'collector_trim_log_by_age') {
my $split_method = $sub->{split_method} // die 'compiled sub split method missing';
my $entry_epoch_method = $sub->{entry_epoch_method} // die 'compiled sub entry-epoch method missing';
$impl = sub {
my ($self, $collector_name, $text, $retention_seconds, %args) = @_;
return $text if !defined $retention_seconds;
return $text if $text eq '';
my $now_epoch = defined $args{now_epoch} ? $args{now_epoch} : time;
my $cutoff = $now_epoch - $retention_seconds;
my @kept;
for my $entry (_code_for($split_method)->($self, $text)) {
my $entry_epoch = _code_for($entry_epoch_method)->($self, $collector_name, $entry);
lib/PAX/StandaloneRuntime.pm view on Meta::CPAN
};
return _install_sub_impl($package, $name, $sub->{prototype}, $impl);
}
if (($sub->{op} // '') eq 'skill_dispatcher_page_location') {
my $skill_lookup_roots_method = $sub->{skill_lookup_roots_method} // die 'compiled sub skill-lookup-roots method missing';
$impl = sub {
my ($self, $skill_name, $route_id) = @_;
return if !$skill_name || !$route_id;
for my $skill_path (_code_for($skill_lookup_roots_method)->($self, $skill_name)) {
my $file = File::Spec->catfile($skill_path, 'dashboards', split m{/+}, $route_id);
return ($file, $skill_path) if -f $file;
}
return;
};
return _install_sub_impl($package, $name, $sub->{prototype}, $impl);
}
if (($sub->{op} // '') eq 'skill_dispatcher_skill_bookmark_entries') {
my $skill_lookup_roots_method = $sub->{skill_lookup_roots_method} // die 'compiled sub skill-lookup-roots method missing';
$impl = sub {
lib/PAX/StandaloneRuntime.pm view on Meta::CPAN
if (($sub->{op} // '') eq 'skill_dispatcher_route_response') {
my $skill_layers_method = $sub->{skill_layers_method} // die 'compiled sub skill-layers method missing';
my $bookmark_entries_method = $sub->{bookmark_entries_method} // die 'compiled sub bookmark entries method missing';
my $page_response_method = $sub->{page_response_method} // die 'compiled sub page response method missing';
$impl = sub {
my ($self, %args) = @_;
my $skill_name = $args{skill_name} || '';
my $route = defined $args{route} ? $args{route} : '';
my @skill_layers = _code_for($skill_layers_method)->($self, $skill_name);
return [404, 'text/plain; charset=utf-8', "Skill '$skill_name' not found\n"] if !@skill_layers;
my @parts = grep { defined && $_ ne '' } split m{/+}, $route;
my @dashboards_roots = map { File::Spec->catdir($_, 'dashboards') } @skill_layers;
return [404, 'text/plain; charset=utf-8', "Skill '$skill_name' does not provide dashboards\n"]
if !grep { -d $_ } @dashboards_roots;
if (@parts && $parts[0] eq 'bookmarks') {
if (@parts == 1) {
my @items = _code_for($bookmark_entries_method)->($self, $skill_name);
return [404, 'text/plain; charset=utf-8', "Skill '$skill_name' does not provide dashboards\n"] if !@items;
return [200, 'application/json; charset=utf-8', JSON::XS::encode_json({ skill => $skill_name, bookmarks => \@items })];
}
my $legacy_id = join '/', @parts[1 .. $#parts];
lib/PAX/StandaloneRuntime.pm view on Meta::CPAN
my @patterns = @{ $args{patterns} || [] };
my ($basename) = $match_path =~ m{([^/\\]+)$};
$basename ||= $match_path;
my $stem = $basename;
$stem =~ s{\.[^.]+$}{};
my $rank = 0;
for my $pattern (@patterns) {
next if !defined $pattern || $pattern eq '';
my $regex = _code_for($compile_regex_method)->($pattern);
my $score = 50;
my @components = grep { defined && $_ ne '' } split m{[\\/]+}, $match_path;
if ($basename =~ /\A(?:$pattern)\z/i) {
$score = 0;
} elsif ($stem =~ /\A(?:$pattern)\z/i) {
$score = 1;
} elsif ($basename =~ /\A(?:$pattern)/i) {
$score = 2;
} elsif ($basename =~ $regex) {
$score = 3;
} elsif (grep { $_ =~ /\A(?:$pattern)\z/i } @components) {
$score = 4;
lib/PAX/StandaloneRuntime.pm view on Meta::CPAN
return _install_sub_impl($package, $name, $sub->{prototype}, $impl);
}
if (($sub->{op} // '') eq 'open_file_cached_archive_source_path') {
$impl = sub {
my (%args) = @_;
my $paths = $args{paths} || die 'Missing path registry';
my $archive = $args{archive} || die 'Missing archive path';
my $entry = $args{entry} || die 'Missing archive entry';
my $digest = Digest::MD5::md5_hex(join "\0", $archive, $entry);
my @parts = grep { defined && $_ ne '' } split m{/+}, $entry;
return File::Spec->catfile(
$paths->cache_root,
'open-file',
'java-sources',
$digest,
@parts,
);
};
return _install_sub_impl($package, $name, $sub->{prototype}, $impl);
}
lib/PAX/StandaloneRuntime.pm view on Meta::CPAN
return _interpret_native_shape($shape, \@args);
}
# Dispatch supported native-shape script subs through the runtime dispatcher and
# fall back to interpretation when no packaged artifact is available.
sub _invoke_native_shape_runtime {
my ($full, $shape, $args) = @_;
my $state = _state();
my $meta = $state->{by_region}{$full} || {};
return { status => 'fallback', reason => 'native region missing' } if !($meta->{executable_logical_path} // '');
my $probe = File::Spec->catfile($state->{root}, split m{/}, $meta->{executable_logical_path});
chmod 0700, $probe if -f $probe;
my $left = $args->[0];
my $right = @$args > 1 ? $args->[1] : 0;
return $state->{native_runner}->run_i64_binary(
path => $probe,
left => $left,
right => $right,
);
}