The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Safe::World::Scope - Enable access to a package scope not shared by a World.

DESCRIPTION

This enable the access to a not shared scopes. Soo, if you want to have an object created outside inside a World, but without share the packages of the object, you can design it to have access to sub-classes through scope access.

BEHAVIOR

The best way to understand what it does and why it exists, is to know the behavior of an object created outside of a World, but running it inside a World:

When an object created outside is used inside a World, for example, when you call a method, the object can see the scope of were the method/sub were created:

    $world->eval(q`
      $object->foo();
    `);

Soo, $object can call foo(), and foo() will see the scope of the package of $object, even if this package doesn't exists inside the World.

But let's say that foo() call some other package:

  #### THIS IS CODE OUTSIDE OF THE WORLD:
  
  package object ;
  
  use Data::Dumper qw() ;
  
  sub foo {
    my $this = shift ;
    my $dump = Data::Dumper::Dumper($this) ;
  }

Now foo() call Data::Dumper::Dumper(), but the package Data::Dumper exists only outside of the World and is not shared!

Here we will get an error, since foo can't have access to the scope of Data::Dumper::, since it will try to get the sub inside the World, at SAFEWORLD1::Data::Dumper::Dumper, and not at main::Data::Dumper::Dumper (where it really exists).

Soo, to make the object work, you can design it to access outside scopes through a Scope object:

  #### THIS IS CODE OUTSIDE OF THE WORLD:
  
  package object ;
  
  use Data::Dumper qw() ;

  my $SCOPE_Data_Dumper = new Safe::World::Scope('Data::Dumper') ;
  
  sub foo {
    my $this = shift ;
    my $dump = $SCOPE_Data_Dumper->call('Dumper',$this) ;
  }

Now with this design you can use $object inside the World without share any other package, what make it much more safer.

This is how the HPL object works inside the compartment, and this was created specially for it.

NEW

To call the method new() of a package you should use NEW() and not call() for 2 reasons. One beaceus NEW() paste the extra argument automatically (package name):

  ## Foo->new using call():
  $SCOPE_Foo->call('new','Foo',@args) ;

  ## Foo->new using NEW():
  $SCOPE_Foo->NEW(@args) ;

The 2nd reason is beacuse if you call Foo->new inside a World, bless() will create an object pointing to a package reference inside the World, and not to the rigth package where Foo::new() really exists.

Soo, using NEW() a call_hole() is made to ensure that bless() works fine.

USAGE

  package foo ;
    use vars qw($var);
    $var = 'foo var!' ;
    sub test { print "TEST!!! @_\n" ; }
  
  package main ;
  
    use Safe::World ;
    use Safe::World::Scope ;
  
    my $scope = new Safe::World::Scope('foo') ;
    
    my $world = new Safe::World(flush=>1) ;
    
    $world->set('$scope' , $scope , 1) ; ## Set the object inside the World.
    
    $world->eval(q`
      $scope->call('test','argmunet') ;
      
      my $v = $scope->get('$var') ;
      print "var: $v\n" ;
      
      $scope->set('$var', '123' ) ;
      
      $v = $scope->get('$var') ;
      print "var after set: $v\n" ;
    `);

METHODS

new (PACKAGE , NO_CACHE , ONLY_CALL)

Create a new Scope object.

Arguments:

PACKAGE

The package name to create the scope object.

NO_CACHE (bool) *optional

If TRUE tells to not use a cached scope object.

** By default all the scope objects are cached, soo if you try to create 2 scopes objects at the same package you are actually creating only one.

ONLY_CALL (bool) *optional

If TRUE tells to only enable the method call(). get() and set() will be denied, since they can be used to chage the variables of a package.

call (SUB , ARGS)

Call a sub inside the scope:

  ## calling the sub test():
  $scope->call('test','arg1','arg2') ;

call_hole (SUB , ARGS)

Same as call(), but ensure that the sub will be executed outside of the World, at the original main STASH.

get (VAR)

Get a variable value:

  my $val = $scope->get('$foo') ;

set (VAR , VALUEREF , KEEPREF)

Set the value of a variable. VALUEREF should be a reference to the new value:

  $scope->set('$var', '123' ) ;

If you need to set a reference, like an object, use the 3rd argument KEEPREF:

  $scope->set('$object', $outside_object , 1 ) ;

NEW

Make a new() call in the package of the scope:

  my $foo = new Foo(123) ;
  ## or:
  my $foo = Foo->new(123) ;
  
  ## Equal to:
  
  my $SCOPE_Foo = new Safe::World::Scope('Foo') ;
  my $foo = $SCOPE_Foo->NEW(123) ;

** Note that if the call is made inside the World, a call_hole() will be used to ensure that bless() is made to the rigth package. Or in other case, bless() will create an object pointing to a package reference inside the World, what create an object without reference to any method, since they are declared outside the World!

ACCESS REFERENCE

Note that you only can have access to the scope if it was already created. Soo, if new variables, subs, or any other symbols are added to the package table, created after create the Scope object, you won't have access to them!.

SEE ALSO

Safe::World, HPL, Safe::Hole, Safe.

AUTHOR

Graciliano M. P. <gm@virtuasites.com.br>

I will appreciate any type of feedback (include your opinions and/or suggestions). ;-P

COPYRIGHT

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.