NAME
JSPL::Controller - Control which Perl namespaces can be used from JavaScript.
SYNOPSIS
use JSPL;
use Gtk2 -init; # Load your perl modules as usual
my $ctx = JSPL->stock_context;
my $ctl = $ctx->get_controller;
$ctl->install(
'Gtk2' => 'Gtk2',
'Gtk2.Window' => 'Gtk2::Window',
'Gtk2.Button' => 'Gtk2::Button',
# Any more needed
);
$ctx->eval(q|
var window = new Gtk2.Window('toplevel');
var button = new Gtk2.Button('Quit');
button.signal_connect('clicked', function() { Gtk2.main_quit() });
window.add(button);
window.show_all();
Gtk2.main();
say('Thats all folks!');
|);
DESCRIPTION
Every context has a controller object. Context's controller object allows you to reflect entire perl namespaces to JavaScript side and control how they can be used.
In the following discussion, we use the words "perl package" or simply "package" to refer to a perl namespace, declared in perl with the keyword "package" in perlfunc.
The controller object holds a list of every perl package exposed in some form to JavaScript land. When JavaScript is made aware of a perl package an instance of the special Stash
native class is created in the context. How you can use that particular namespace from JavaScript depends on how the Stash
instance or its properties are bound in JavaScript.
See JSPL::Stash for details on Stash
instances.
This perl class allows you to make JavaScript land aware of perl packages and provides some utilities methods.
INTERFACE
You obtain the instance of a context's controller calling "get_controller" in JSPL::Context.
my $ctl = $context->get_controller;
With this you can use any of the following:
Instance methods
- add( $package_name )
-
my $stash = $ctl->add('Foo::Bar');
Adds the package named $package_name to the list of namespaces visible in JavaScript, if not in there already. Returns the JSPL::Stash object that encapsulates the associated
Stash
. - added ( $package_name )
-
$ctl->added('Foo::Bar');
Check if the package with the given $package_name is in the list of perl namespaces visible from JavaScript land. Returns a TRUE value (the JSPL::Stash object) if $package_name is in the list, otherwise returns a FALSE value.
Normal operation is to automatically add namespaces as needed. Packages are added when a perl object enters javacript or you use "bind_class" in JSPL::Context and the package isn't already known.
- list ( )
-
@exported = $ctl->list();
Returns a list with the names of packages available in JavaScript land.
- install ( BIND_OPERATION, ... )
-
Performs a series of BIND_OPERATIONs in JavaScript land.
Every BIND_OPERATION is an expression of the form:
bind => [ $package, $mode ]
Where bind is the property name to attach the package named $package and $mode is the form to perform the binding.
There are three ways to bind a package: binding as a constructor, as a static class or in indirect form. You choose which way to use depending on the value you give to the $mode argument:
STRING
When a STRING is used as $mode, you want to bind a constructor. The property bind in JavaScript will be bound to a
PerlSub
that references the function named STRING in the perl class associated with $package. bind will then be used as a constructor.For example
$ctl->install(Img => [ 'GD::Simple', 'new' ]);
Binds to
Img
a JavaScript constructor for objects of the perl classGD::Simple
, so in JavaScript you can write:myimg = new Img(400, 250);
In perl the most common name for a constructor is
new
, as long as you known that your perl class has a constructor namednew
, you can use a simplified form of the BIND_OPERATION:$ctl->install(Img => 'GD::Simple');
undef
When $mode is undef, you want to bind the perl package as a static class. The property bind in JavaScript will be bound to the
Stash
itself associated with the $package. See JSPL::Stash for all the implications.You should bind in this form any perl package for which you need to make static calls to multiple functions (class methods).
For example:
$ctl->install(DBI => [ 'DBI', undef ]);
Binds to
DBI
theStash
instance associated to theDBI
perl package, allowing you to write in JavaScript:drivers = DBI->available_drivers(); handle = DBI->connect(...);
In perl many packages work this way and/or provide constructors for other packages as static functions, but don't have a constructor for themselves.
If you know the perl class doesn't has a constructor named
new
you can use the same simplified form of the BIND_OPERATION above, andinstall
will do the right thing.$ctl->install(DBI => 'DBI');
-1
When $mode is -1, you want to bind the perl package in indirect mode. This mode allows JavaScript to resolve method calls on bind to subroutines defined in $package.
Using the indirect form will make plain function calls to those subroutines instead of static method calls.
For example:
$ctl->install(Tests => [ 'Test::More', -1 ]);
Bind to
Tests
an object allowing JavaScript to find all subroutines defined inTest::More
. In JavaScript you'll write:Test.ok(...); Test.is(...);
A simple way to export to JavaScript a lot of new functions is to bind this way a carefully crafted namespace.
#!/usr/bin/perl # We are in 'main' use JSPL; package forjsuse; sub foo {...}; sub bar {...}; sub baz {...}; my $ctx = JSPL->stock_context; $ctx->get_controller->install(Utils => ['forjsuse', -1]); $ctx->eval(q| Utils.bar(...); |);
An advantage of this method over using "bind_function" in JSPL::Context is that the
PerlSub
objects associated to your perl subroutines won't get created in JavaScript until needed.
Every BIND_OPERATION, search for a "Tweaks file" associated to the $package added and if found loads it, see JSPL::Tweaks for details.
To create a hierarchy of related properties you can pass to
install
many BIND_OPERATIONs as follows:$ctl->install( 'Gtk2' => 'Gtk2', # Gtk lacks a 'new'. Binds a static class 'Gtk2.Window' => 'Gtk2::Window', # Bind Gtk2::Window constructor 'Gtk2.Button' => 'Gtk2::Button', # Bind Grk2::Button constructor );
- secure ( )
-
$ctl->secure();
Prevent further modifications to the controller's list. As a result no more perl namespaces can be installed nor exported to the context.