++ed by:
Salvador Ortiz

NAME

PerlSub - Encapsulate a perl CODE reference in JavaScript

DESCRIPTION

Perl subroutines that you pass to javascript will be wrapped into instances of PerlSub.

More generally, any perl CODE reference that enters javascript land will become a PerlSub instance.

    ...
    $ctx->bind_function(perl_rand => sub { rand });
    $ctx->bind_function(add => sub {
        my($a, $b) = @_;
        return $a + $b;
    });
    ...
    $ctx->eval(q{
        val = add(10, 20);         // val now 30
        say("10 + 20 = " + val);   // 'say' itself is defined in the
                                   //  stock context
        v1 = perl_rand();
        v2 = perl_rand();
        say(v1 + " + " + v2 + " = " + add(v1, v2));
    });

JAVASCRIPT INTERFACE

When you send a subroutine from perl to javascript, you'll get an instance of PerlSub. PerlSubs behave pretty much like native javascript Functions.

Like Function instances, instances of PerlSub are invoked with a parenthesized list of arguments.

    var foo = perl_rand();  // invoke perl_rand, foo now random number
    var bar = perl_rand;    // now 'bar' is another reference to perl_rand
    var baz = bar();        // invoke it, baz now a random number

And as with any other object, you can manipulate properties and call methods of instances of PerlSub.

    perl_rand.attr = 'This is a function imported from perl';
    add.toString();          // Please try this ;-)
    add.toSource();         // Or this!

Instance methods

PerlSub.prototype implements methods analogous to Function.prototype's.

call(thisArg, ARGLIST)

Analogous to Function.prototype.call.

apply(thisArg, somerray)

Analogous to Function.prototype.apply.

toSource( )

Analogous to Function.protype.toSource. Tries to uncompile and returns the perl code associated, depends on B::Deparse.

toString( )

Returns the literal string "sub {\n\t[perl code]\n}"

Instance properties

name string

Store the name on the original perl subroutine if named or the string "(anonymous)".

prototype object

Remember that any Function instance has a property prototype, and PerlSub instances have one also. Please read your javascript documentation for details.

$wantarray boolean

Determines the perl's context, false -> 'scalar', true -> 'list', to use when the subrotine is called. Defaults to true !!. See "Perl contexts".

Constructor

You can construct new perl functions from inside javascript.

new PerlSub(PERLCODE)
    var padd = new PerlSub("\
        my($a, $b) = @_;\
        return $a +$b\
    ");

Returns a new instance of PerlSub, that can be called in the normal way:

    padd(5, 6); // 11

PERLCODE, a string, is the body of your new perl subroutine, it's passed verbatim to perl for compilation. Syntax errors will throw exceptions at construction time.

If you ever pass to perl instances constructed by PerlSub you'll see normal CODE references indistinguishable from anonymous subs.

Calling semantics

When you invoke a PerlSub from javascript, in most cases JSPL does the right thing. But there are differences in the way than javascript and perl behave respect to function calling that you should be aware of. Mainly when you export to javascript arbitrary perl functions or expose perl namespaces to javascript.

Read this section for the gory details.

Perl contexts

In perl you call a subroutine in either scalar or list context. Perl determines this context automatically using the form of the expression in which the function is called. And perl lets your subroutine know which context is being used (via "wantarray" in perlfunc). Some subroutines behave differently depending on which context they where called. In javascript this concept doesn't exists.

To make the problem of calling perl subroutines from javascript even more interesting, perl subroutines can return list of values where javascript functions always return a single value.

To solve the first problem, the context in which the perl subroutine call will be made is taken from the $wantarray property of the instances of PerlSub. $wantarray defaults to true, which is the correct value to use in the vast majority of the cases. We explain why and when to use a false value below.

For the return value of a PerlSub call you will get either a single value or a PerlArray. You'll get a single value when $wantarray is false or when the list returned has a single element, otherwise you'll get a PerlArray.

You'll never receive arrays with a single element in them. This behaviour may be unfortunate but it makes the rest of the cases much more simpler. Besides, you can check trivially for that condition as follows:

    res = perl_sub_that_returns_a_list();
    if(res instanceof PerlArray) {
         ...
    } else {
        ...
    }

Having $wantarray default to true is the best thing to do because, on one side, perl subroutines returning single values are not affected, and on the other side it's the correct value to use for subroutines returning lists.

You'll need to set $wantarray to false when: you need to call a perl subroutine that uses wantarray and/or you need to force 'scalar' context for the call.

$wantarray usage example:

    // Asuming that 'perlfunc' is a PerlSub
    
    perlfunc.$wantarray = true;  // this is the default
    listres = perlfunc(); // Called in 'list' context

    perlfunc.$wantarray = false;
    scalres = perlfunc(); // Called in 'scalar' context

this

In javascript every call to a function is a method call and a reference to the caller is visible inside the function as this. The function author decides if behave as a method, using this or as a simple function ignoring this.

In perl method calls use a syntax different from regular calls. A subroutine called as a method sees its caller in front of the other arguments.

When the caller to a PerlSub is either a PerlObject or a Stash, JSPL's engine will push it in the arguments. The call will use perl's method call semantics.

In every other case, JSPL's engine assumes that you are creating or extending regular JavaScript objects with PerlSub-based methods and you need a way to get the value of this in a transparent way. Thats the purpose of the magical variable "$This" in JSPL.

Perl code not aware of being called from JavaScript will see its arguments unmodified. Perl code that needs JavaScript's this gets it in $JSPL::This. And everyone is happy.




Hosting generously
sponsored by Bytemark