NAME
JavaScript::Shell - Run Spidermonkey shell from Perl
SYNOPSIS
use
JavaScript::Shell;
use
strict;
use
warnings;
my
$js
= JavaScript::Shell->new();
##create context
my
$ctx
=
$js
->createContext();
$ctx
->Set(
'str'
=>
'Hello'
);
$ctx
->Set(
'getName'
=>
sub
{
my
$context
=
shift
;
my
$args
=
shift
;
my
$firstname
=
$args
->[0];
my
$lastname
=
$args
->[1];
return
$firstname
.
' '
.
$lastname
;
});
$ctx
->
eval
(
qq!
function message (){
var name = getName.apply(this,arguments);
var welcome_message = str;
return welcome_message + ' ' + name;
}
!
);
my
$val
=
$ctx
->get(
'message'
=>
'Mamod'
,
'Mehyar'
)->value;
$val
.
"\n"
;
## prints 'Hello Mamod Mehyar'
$js
->destroy();
DESCRIPTION
JavaScript::Shell will turn Spidermonkey shell to an interactive environment by connecting it to perl
With JavaScript::Shell you can bind functions from perl and call them from javascript or create functions in javascript then call them from perl
WHY
While I was working on a project where I needed to connect perl with javascript I had a lot of problems with existing javascript modules, they were eaither hard to compile or out of date, so I thought of this approach as an alternative.
Even though this sounds crazy to do, to my surprise it worked as expected - at least in my usgae cases
SPEED
JavaScript::Shell connect spidermonkey with perl through IPC bridge using IPC::Open2 so execution speed will never be as fast as using C/C++ bindings ported to perl directly
There is another over head when translating data types to/from perl, since it converts perl data to JSON & javascript JSON to perl data back again.
Saying that, the over all speed is acceptable and you can take some steps to improve speed like
- Data Transfer
-
Try to transfer small data chunks between processes when possible, sending large data will be very slow
- Buffer Data
-
As of version 0.02 JavaScript::shell has a new method for dealing with large strings passed to/from javascript, use this feature when ever you want to send large data "strings" -- see
buffer
- Minimize calls
-
Minimize number of calls to both ends, let each part do it's processing. for eaxmple:
##instead of
$js
->
eval
(
qq!
function East (){}
function West (){}
function North (){}
function South (){}
!
);
$js
->call(
'East'
);
$js
->call(
'West'
);
$js
->call(
'North'
);
$js
->call(
'South'
);
##do this
$js
->
eval
(
qq!
function all () {
East();
West();
North();
South();
}
function East (){}
function west (){}
function North (){}
function South (){}
!
);
$js
->call(
'all'
);
CONTEXT
Once you intiate JavaScript::Shell you can create as many contexts as you want, each context will has it's own scope and will not overlap with other created contexts.
my
$js
= JavaScript::Shell->new();
my
$ctx
=
$js
->createContext();
You can pass a hash ref with simple data to createContext
method as a sandbox object and will be copied to the context immediately
my
$ctx
->createContext({
Foo
=>
'Bar'
,
Foo2
=>
'Bar2'
});
FUNCTIONS
new
Initiates SpiderMonkey Shell
createContext
creates a new context
run
This will run javascript code in a blocking loop until you call jshell.endLoop() from your javascript code
$js
->Set(
'Name'
=>
'XXX'
);
$js
->
eval
(
qq!
for (var i = 0; i < 100; i++){
}
jshell.endLoop();
!
);
$js
->run();
##will never reach this point unless we call
## jshell.endLoop(); in javascript code as above
Set
Sets/Defines javascript variables, objects and functions from perl
## set variable 'str' with Hello vales
$ctx
->Set(
'str'
=>
'Hello'
);
## set 'arr' Array Object [1,2,3,4]
$ctx
->Set(
'arr'
=> [1,2,3,4]);
## set Associated Array Object
$ctx
->Set(
'obj'
=> {
str1
=>
'something'
,
str2
=>
'something ..'
});
## set 'test' function
## caller will pass 2 arguments
## 1- context object
## 2- array ref of all passed arguments
$ctx
->Set(
'test'
=>
sub
{
my
$context
=
shift
;
my
$args
=
shift
;
return
$args
->[0] .
' '
.
$args
->[1];
});
## javascript object creation style
$ctx
->Set(
'obj'
=> {});
#then
$ctx
->Set(
'obj.name'
=>
'XXX'
);
$ctx
->Set(
'obj.get'
=>
sub
{ });
...
get
get values from javascript code, returns a JavaScript::Shell::Value
Object
my
$ret
=
$ctx
->get(
'str'
);
$ret
->value;
## Hello
## remember to call value to get the returned string/object
get method will search your context for a matched variable/object/function and return it's value, if the name was detected for a function it will run this function first and then returns it's return value
$ctx
->get(
'obj.name'
)->value;
## XXX
##you can pass variables when trying to get a function
$ctx
->get(
'test'
=>
'Hi'
,
'Bye'
)->value;
## Hi Bye
##get an evaled script values
$ctx
->get(
'eval'
=>
qq!
var n = 2;
var x = 3;
n+x;
!
)->value;
#--> 5
call
Calling javascript functions from perl, same as get
but doesn't return any value
$ctx
->call(
'test'
);
eval
eval javascript code
$ctx
->
eval
(
qq!
//javascript code
var n = 10;
for(var i = 0; i<100; i++){
n += 10;
}
...
!
);
buffer
This function should be used only when dealing with passing large strings
$js
->Set(
'largeStr'
=>
sub
{
my
$js
=
shift
;
my
$args
=
shift
;
##we have a very large string we need to pass to
##javascript
return
$js
->buffer(
'large string'
);
});
##javascript
var str = largeStr();
The same thing can be done when sending large strings from javascript to perl
//javascript
var str =
'very large string we need to pass to perl'
;
jshell.sendBuffer(str);
##perl
##to consume this string from perl just get it
my
$str
=
$js
->getBuffer();
onError
set error handler method, this method accepts a code ref only. When an error raised from javascript this code ref will be called with 2 arguments
JavaScript::Shell instance
error object - Hash ref
Error Hash has the folloing keys
message error message
type javascript error type: Error, TypeError, ReferenceError ..
file file name wich raised this error
line line number
stack string of the full stack trace
Setting error hnadler example
my
$js
= JavaScript::Shell->new();
$js
->onError(
sub
{
my
$self
=
shift
;
my
$error
=
shift
;
STDERR
$error
->{message} .
' at '
.
$error
->{line}
exit
(0);
});
destroy
Destroy javascript shell / clear context
my
$js
= JavaScript::Shell->new();
my
$ctx
->createContext();
##clear context;
$ctx
->destroy();
##close spidermonkey shell
$js
->destroy();
LICENSE
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.16.2 or, at your option, any later version of Perl 5 you may have available.
COPYRIGHTS
Copyright (C) 2013 by Mamod A. Mehyar <mamod.mehyar@gmail.com>