File Coverage

blib/lib/JE/Scope.pm
Criterion Covered Total %
statement 29 34 85.2
branch 13 16 81.2
condition 2 2 100.0
subroutine 6 7 85.7
pod 2 2 100.0
total 52 61 85.2


line stmt bran cond sub pod time code
1             package JE::Scope;
2              
3             our $VERSION = '0.064';
4              
5 101     101   34001 use strict;
  101         184  
  101         3678  
6 101     101   422 use warnings; no warnings 'utf8';
  101     101   153  
  101         2558  
  101         397  
  101         151  
  101         35122  
7              
8             require JE::LValue;
9              
10             our $AUTOLOAD;
11              
12             # ~~~ We need a C method.
13              
14             sub find_var {
15 105413     105413 1 263027 my ($self,$var) = @_;
16 105413         89589 my $lvalue;
17              
18 105413         157756 for(reverse @$self) {
19 107729         96732 my $p = $_;
20 107729   100     242906 defined($p=$p->prototype) or next while !$p->exists($var);
21 104835         268990 return new JE::LValue $_, $var;
22             }
23             # if we get this far, then we create an lvalue without a base obj
24 578         1897 new JE::LValue \$self->[0], $var;
25             }
26              
27             sub new_var {
28 773     773 1 1164 my ($self,$var) = (shift,shift);
29 773         759 my $var_obj;
30 773         1998 for(reverse @$self[1..$#$self]) { # Object 0 can't be a call
31             # object. Omitting it should the-
32             # oretically make things margin-
33             # ally faster.
34 352 100       1170 ref $_ eq 'JE::Object::Function::Call' and
35             $var_obj = $_,
36             last;
37             }
38 773 100       1693 defined $var_obj or $var_obj = $$self[0];
39              
40 773 100       1861 if (defined $var_obj->prop($var)) {
41 75 50       158 $var_obj->prop($var, shift) if @_;
42             }
43             else {
44 698 100       2367 $var_obj->prop($var, @_ ? shift :
45             $$self[0]->undefined);
46              
47             # This is very naughty code, but it works.
48 698 100       2864 $JE::Code::Expression::_eval or $var_obj->prop({
49             name => $var,
50             dontdel => 1,
51             });
52             }
53              
54 773 50       3398 return new JE::LValue $var_obj, $var
55             unless not defined wantarray;
56             }
57              
58             sub AUTOLOAD { # This delegates the method to the global object
59 1337     1337   8406 my($method) = $AUTOLOAD =~ /([^:]+)\z/;
60              
61             # deal with various ALLCAPS names
62 1337 50       4154 if($method =~ /^[A-Z]+\z/) {
63 0         0 substr($method,0,0) = 'SUPER::';
64 0         0 local *@;
65 0         0 return eval { shift->$method(@_) };
  0         0  
66             }
67              
68 1337         4717 shift->[0]->$method(@_); # ~~~ Maybe I should use goto
69             # to remove AUTOLOAD from
70             # the call stack.
71             }
72              
73 0     0     sub DESTROY {}
74              
75             1;
76              
77             =head1 NAME
78              
79             JE::Scope - JavaScript scope chain (what makes closures work)
80              
81             =head1 DESCRIPTION
82              
83             JavaScript code runs within an execution context which has a scope chain
84             associated with it. This class implements this scope chain. When a variable
85             is accessed the objects in the scope chain are searched till the variable
86             is found.
87              
88             A JE::Scope object can also be used as global (JE) object. Any methods it
89             does not understand will be delegated to the object at the bottom of the
90             stack (the far end of the chain), so that C<< $scope->null >> means the
91             same thing as C<< $scope->[0]->null >>.
92              
93             Objects of this class consist of a reference to an array, the elements of
94             which are the objects in the chain (the first element
95             being the global object). (Think
96             of it as a stack.)
97              
98             =head1 METHODS
99              
100             =over 4
101              
102             =item find_var($name, $value)
103              
104             =item find_var($name)
105              
106             This method searches through
107             the scope chain, starting at the end of the array, until it
108             finds the
109             variable named by the first argument. If the second argument is
110             present, it sets the variable. It then returns an lvalue (a
111             JE::LValue object) that references the variable.
112              
113             =item new_var($name, $value)
114              
115             =item new_var($name)
116              
117             This method creates (and optionally sets the value of) a new
118             variable in the variable object (the same thing that JavaScript's C
119             keyword does) and returns an lvalue.
120              
121             The variable object is the first object in the scope chain
122             (searching from the top of the
123             stack) that is a call object, or C<< $scope->[0] >> if no call object is
124             found.
125              
126             =back
127              
128             =head1 CONSTRUCTOR
129              
130             None. Just bless an array reference. You should not need to do
131             this because it is done for you by the C and C
132             classes.
133              
134             =head1 SEE ALSO
135              
136             =over
137              
138             =item L
139              
140             =item L
141              
142             =item L
143              
144             =back
145              
146             =cut
147              
148              
149              
150