MozRepl-RemoteObject
view release on metacpan or search on metacpan
lib/MozRepl/RemoteObject.pm view on Meta::CPAN
# It's required on Firefox 3.0 only
my $capabilities = $options{ repl }->execute(
join "",
# Extract version
'Components.classes["@mozilla.org/xre/app-info;1"].',
'getService(Components.interfaces.nsIXULAppInfo).version+"!"',
# Native JSON object available?
q{+eval("var r;try{r=JSON.stringify('\u30BD');}catch(e){r=''};r")},
# UTF-8 transport detection
'+"!\u30BD"',
";\n"
);
$capabilities =~ s/^"(.*)"\s*$/$1/;
$capabilities =~ s/^"//;
$capabilities =~ s/"$//;
#warn "Capabilities: [$capabilities]";
my ($version, $have_native, $unicode) = split /!/, $capabilities;
#warn $unicode;
#warn sprintf "%02x",$_ for map{ord} split //, $unicode;
if ($have_native eq '') {
$options{ js_JSON } ||= "json2; No native JSON object found ($version)";
};
if( lc $have_native eq lc q{"\u30bd"} # values get escaped
or $have_native eq qq{"\x{E3}\x{82}\x{BD}"} # values get encoded as UTF-8
) {
# so we can transport unicode properly
$options{ js_JSON } ||= 'native';
} else {
$options{ js_JSON } ||= "json2; Transport not UTF-8-safe";
};
};
if ($options{ js_JSON } ne 'native') {
# send our own JSON encoder
#warn "Installing custom JSON encoder ($options{ native_JSON })";
require MozRepl::Plugin::JSON2;
my $json2 = MozRepl::Plugin::JSON2->new()->process('setup');
$options{ repl }->execute($json2);
# Now, immediately check whether our transport is UTF-8 safe:
my $utf8 = $options{ repl }->execute(
q{JSON.stringify('\u30BD')}.";\n"
);
$utf8 =~ s/\s*$//;
lc $utf8 eq lc q{""\u30bd""}
or warn "Transport still not UTF-8 safe: [$utf8].\nDo you have mozrepl 1.1.0 or later installed?";
};
my $rn = $options{repl}->repl;
$options{ json } ||= JSON->new->allow_nonref->ascii; # We talk ASCII
# Is this still true? It seems to be even when we find an UTF-8 safe
# transport above. This needs some investigation.
# Switch the Perl-repl to multiline input mode
# Well, better use a custom interactor and pass JSON messages that
# are self-delimited and contain no newlines. Newline for a new message.
# Switch the JS-repl to multiline input mode
$options{repl}->execute("$rn.setenv('inputMode','multiline');undefined;\n");
# Load the JS side of the JS <-> Perl bridge
my $c = $objBridge; # make a copy
$c =~ s/\[%\s+rn\s+%\]/$rn/g; # cheap templating
#warn $c;
$package->execute_command($c, %options);
$options{ functions } = {}; # cache
$options{ constants } = {}; # cache
$options{ callbacks } = {}; # active callbacks
bless \%options, $package;
};
sub execute_command {
my ($self, $command, %options) = @_;
$options{ repl } ||= $self->repl;
$options{ command_sep } ||= $self->command_sep
unless exists $options{ command_sep };
$command =~ s/\s+$//;
$command .= $options{ command_sep };
$options{repl}->execute($command);
};
=head2 C<< $bridge->expr( $js, $context ) >>
Runs the Javascript passed in through C< $js > and links
the returned result to a Perl object or a plain
value, depending on the type of the Javascript result.
This is how you get at the initial Javascript object
in the object forest.
my $window = $bridge->expr('window');
print $window->{title};
You can also create Javascript functions and use them from Perl:
my $add = $bridge->expr(<<JS);
function (a,b) { return a+b }
JS
print $add->(2,3);
# prints 5
The C<context> parameter allows you to specify that you
expect a Javascript array and want it to be returned
as list. To do that, specify C<'list'> as the C<$context> parameter:
for ($bridge->expr(<<JS,'list')) { print $_ };
[1,2,3,4]
JS
This is slightly more efficient than passing back an array reference
and then fetching all elements.
=cut
# This is used by ->declare() so can't use it itself
sub expr {
( run in 1.379 second using v1.01-cache-2.11-cpan-140bd7fdf52 )