The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.


JavaScript::Duktape - Perl interface to Duktape embeddable javascript engine


    use JavaScript::Duktape;

    ## create new js context
    my $js = JavaScript::Duktape->new();

    # set function to be used from javascript land
    $js->set('write' => sub {
        print $_[0], "\n";

            for (var i = 0; i < 100; i++){


JavaScript::Duktape implements almost all duktape javascript engine api, the c code is just a thin layer that maps duktape api to perl, and all other functions implemented in perl it self, so maintaing and contributing to the base code should be easy.


initiate JavaScript::Duktape with options



Set maximum memory allowed for the excuted javascript code to consume, not setting this option is the default, which means no restricts on the maximum memory that can be consumed.

Minumum value to set for the max_memory option is 256 * 1024 = (256k) setting number below 256k will croak.

    max_memory => 256 * 1024 * 2

You can resize the memory allowed to consume on different executions by calling resize_memory method, see "Sandboxing" section below.


Set maximum time javascript code can run, this value represented in seconds and is not 100% guranteed that the javascript code will fail after the exact value passed, but it will eventually fail on first tick checking.

Not setting this option is the default, which means no timeout checking at all

    timeout => 5

You can override this value later on another code evaluation by calling set_timeout method


See "Sandboxing" section below


set('name', data);

Creates property 'name' and sets it's value to the given perl data

    $js->set('something', {}); #set something
    $js->set('', 'Joe');
    $js->set('number', 1234);

this method will die if you try to set a property on undfined base value

    $js->set('', 'Joe'); ## will die

    ## so first set "notHere"
    $js->set('notHere', {});
    $js->set('', 'Joe'); ## good

Gets property 'name' value from javascript and return it as perl data, this method will die if you try to get value of undefined base value

    my $print_sub = $js->get('print');

Evaluates javascript string and return the results or croak if error

    my $ret = $js->eval(q{
        var t = 1+2;
        t; // return value from eval

    print $ret, "\n"; # 3

Same as get method but instead of returning a raw value of the property name, it will return a JavaScript::Duktape::Object this method will die if you try to get a property that is not of type 'object'

        function Person (name){
   = name;

    my $personObject = $js->get('Person');

    # $personObject is a blessed 'JavaScript::Duktape::Object' object
    # so you can call internal

    my $person = $personObject->new('Joe');
    print $person->name, "\n"; # Joe

For more on how you can use JavaScript::Duktape::Object please see examples provided with this distribution


As of version 2.2.0 JavaScript::Duktape integrated some of Duktape Engine Sandboxing methods, this will allow developers to restrict the running javascript code by restricting memory consumption and running time

DUK_USE_EXEC_TIMEOUT_CHECK flag is set by default to enable Bytecode execution timeout

    # prevent javascript code to consume memory more
    # than max_memory option

    my $js = JavaScript::Duktape->new( max_memory => 256 * 1024 );

    # this will fail with "Error: alloc failed" message
    # when running, because it will consume more memory
    # than the allowed max_memory
        var str = '';
        while(1){ str += 'XXXX' }


Enable/Disable timeout checking, to disable set the value to 0 this value is in seconds

    my $js = JavaScript::Duktape->new();

    # throw 'time out' Error if executed
    # js code does not finish after 5 seconds

    eval {

    print $@, "\n"; #RangeError: execution timeout

    # disable timeout checking

    # now will run infinitely

This method can be used with duktape VM instance too

    my $js = JavaScript::Duktape->new();
    my $duk = $js->duk();

        while (1){}

    print $duk->safe_to_string(-1); # Error: execution 'time out'


This method will have effect only if you intiated with max_memory option

    my $js = JavaScript::Duktape->new( max_memory => 1024 * 256 );

    eval {
            var buf = Buffer(( 1024 * 256 ) + 1000 );
            print('does not reach');

    print $@, "\n"; # Error: 'alloc failed'

    $js->resize_memory( 1024 * 256 * 2 );

    # now it will not throw
        var buf = Buffer(( 1024 * 256 ) + 1000 );


vm api corresponds to Duktape Engine API see To access vm create new context then call vm

    my $js = JavaScript::Duktape->new();
    my $duk = $js->vm;

    #now you can call Duktape API from perl


Also you may find it useful to use dump function regularly to get a better idea where you're in the stack, the following code is the same example above but with using dump function to get a glance of stack top

    my $js = JavaScript::Duktape->new();
    my $duk = $js->duk;

    #push "print" string
    $duk->dump(); #-> [ Duktape (top=1): print ]

    #since print is a native function we need to evaluate it
    $duk->dump(); #-> [ Duktape (top=1): function print() {/* native */} ]

    #push one argument to print function
    $duk->dump(); #-> [ Duktape (top=2): function print() {/* native */} hi ]

    #now call print function and pass "hi" as one argument

    #since print function doesn't return any value, it will push undefined to the stack
    $duk->dump(); #-> [ Duktape (top=1): undefined ]

    #pop to remove undefined from stack top

    $duk->dump(); #-> [ Duktape (top=0): ]

VM methods

As a general rule all duktape api supported, but I haven't had the chance to test them all, so please report any missing or failure api call and I'll try to fix

For the list of duktape engine API please see, and here is how you can translate duktape api to perl

    my $js = JavaScript::Duktape->new();
    my $duk = $js->duk;

    # -- C example
    # duk_push_c_function(func, 2);
    # duk_push_int(ctx, 2);
    # duk_push_int(ctx, 3);
    # duk_call(ctx, 2);  /* [ ... func 2 3 ] -> [ 5 ] */
    # printf("2+3=%ld\n", (long) duk_get_int(ctx, -1));
    # duk_pop(ctx);

    #and here is how we can implement it in JavaScript::Duktape

    $duk->push_c_function(sub {
        my $num1 = $duk->get_int(0);
        my $num2 = $duk->get_int(1);

        my $total = $num1+$num2;
        return 1;
    }, 2);

    $duk->call(2);  # [ ... func 2 3 ] -> [ 5 ]
    printf("2+3=%ld\n", $duk->get_int(-1));

As you can see all you need to do is replacing duk_ with $duk-> and remove ctx from the function call, this may sounds crazy but api tests have been generated by copying duktape tests and using search and replace tool :)

Besides duktape api, JavaScript::Duktape::Vm implements the following methods

push_function ( code_ref );

push perl sub into duktape stack, this is the same as push_perl_function except it will handle both passed arguments and return data for you

    $duk->push_function(sub {
        my ($arg1, $arg2, ...) = @_;
        return $something;
push_perl_function ( code_ref, num_of_args );

an alias to push_c_function, same as push_perl_function except you will be responsible for extracting arguments and pushing returning data

    $duk->push_perl_function(sub {
        my $arg1 = $duk->get_int(-1);
        my $somthing_to_return = "..";
        return 1;
push_perl( ... );

Push given perl data into the duktape stack.


Get the value at index and return it as perl data


Get object at index and return it as 'JavaScript::Duktape::Object', this function will die if javascript data at index is not of type object


resets duktape stack top


JavaScript::Duktape exports the following by default

_ (underscore)

This can be used to indicate that we are calling an object function without arguments, see "CAVEATS"


This can be called from pushed perl sub

        my $this = this;

See examples/


JavaScript::Duktape has alert and print functions available as global functions to javascript, where alert prints to STDERR and print prints to STDOUT.


VM methods

JavaScript::Duktape vm methods is a direct low level calls to duktape c library, so stepping outside of the stack will result in a program termination without a useful error message, so you need to be careful when using these methods and always check your stack with $duk->dump() method


JavaScript::Duktape::Object use overload and AUTOLOAD internally, so there is no way to guess if you're trying to get a property type of function or executing it, this is the same as javascript behaviour

    # js
        function test () {
            return 'Hi';

        print(test); // function(){ ... }
        print(test()) // Hi

    ## same thing when we do it in perl
    my $test = $js->get_object('test');

    print $test, "\n"; #JavaScript::Duktape::Function=CODE(...)
    print $test->(), "\n"; #Hi

This may sound ok with simple function calls but gets ugly not perlish when you're trying to call deep object properties

So JavaScript::Duktape exports a special variable underscore '_' by default this to indicate that we are calling the function with no arguments

        function Person (name){
   = name;

        Person.prototype.getName = function(){

        var me = new Person('Joe');
        print(me.getName); // function(){ ... }
        print(me.getName()); // Joe

    # Now let's do it in perl
    my $Person = $js->get_object('Person');
    my $me = $Person->new('Joe');

    print $me->getName, "\n"; #JavaScript::Duktape::Function=CODE(...)
    print $me->getName(), "\n"; #JavaScript::Duktape::Function=CODE(...)
    print $me->getName->(), "\n"; # Joe

    #however if you pass any argument with the function it will work
    print $me->getName(0), "\n"; #Joe

    # or you can use special null argument _ which we export by default
    print $me->getName(_), "\n"; #Joe


Mamod Mehyar <>


Thanks for everyone who contributed to this module, either by code, bug reports, API design or suggestions


Credits should go to Duktape Javascript embeddable engine and it's creator Sami Vaarala


This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.