Skip to content

eval '$foo' in package DB called from lexical sub can not see closure values or globals #19370

Open
@jimav

Description

@jimav

Perl v5.30.0

eval "string" in package DB is supposed to be evaluated in the nearest non-DB context, useful for debug tools. However when code in package DB is called from a nested lexical ("my") sub, only the lexicals in the innermost sub are visible; globals and lexicals in enclosing scopes can no longer be accessed.

(This may seem obscure, but it is important to me because I use some debugging tools which depend on eval in package DB being able to see user-defined lexicals).

The output from the following script is:

$w_from_outer = 41;
$x_from_outer = 42;
$y_from_outer = 43;
$w_from_inner = undef;
$x_from_inner = undef;
$y_from_inner = undef;
$z_from_inner = 44;

and here is the script:

!/usr/bin/perl
use strict; use warnings; use v5.18; use Data::Dumper;

our $w = 41;
my $x = 42;

my ($w_from_outer, $x_from_outer, $y_from_outer, 
    $w_from_inner, $x_from_inner, $y_from_inner, $z_from_inner);

sub outer {
  my $y = 43;

  $w_from_outer = &DB::doeval('$w');
  $x_from_outer = &DB::doeval('$x');
  $y_from_outer = &DB::doeval('$y');

  my sub inner {
    my $z = 44;

    $w_from_inner = &DB::doeval('$w'); # gets undef
    $x_from_inner = &DB::doeval('$x'); # gets undef
    $y_from_inner = &DB::doeval('$y'); # gets undef
    $z_from_inner = &DB::doeval('$z');
  }
  inner();
}
outer();

say Data::Dumper->Dump(
      [
        $w_from_outer, $x_from_outer, $y_from_outer,
        $w_from_inner, $x_from_inner, $y_from_inner, $z_from_inner
      ],
      [qw(
        w_from_outer x_from_outer y_from_outer
        w_from_inner x_from_inner y_from_inner z_from_inner
      )] );
      
package DB;

sub doeval($) {
  return eval $_[0];
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions