From 41d1dfaa6617df3b2caf88bd55ab17a6bb0aef00 Mon Sep 17 00:00:00 2001 From: sergiotarxz Date: Thu, 7 Jan 2021 16:02:34 +0100 Subject: [PATCH] Added support for calling javascript functions from perl. --- bin/js-pruebas | 20 +++-- javascript_interpreter_xs/javascript.xs | 115 +++++++++++++----------- 2 files changed, 75 insertions(+), 60 deletions(-) diff --git a/bin/js-pruebas b/bin/js-pruebas index 10d361d..ab65d63 100755 --- a/bin/js-pruebas +++ b/bin/js-pruebas @@ -8,13 +8,17 @@ use feature 'say'; use Peertube::DL::Javascript; my $a = Peertube::DL::Javascript::_duk_create_heap_default(); -eval { Peertube::DL::Javascript::_duk_push_lstring( $a, "\"hola mundo\"" ); }; -if ($@) { - warn $@; - $@ = ""; -} if ( defined $a ) { -Peertube::DL::Javascript::_duk_peval($a); -say Peertube::DL::Javascript::_duk_get_lstring($a, -1); -Peertube::DL::Javascript::_duk_destroy_heap($a); + eval { + my $return = Peertube::DL::Javascript::_duk_eval_wrapper( + $a, + "function a(nombre) { return 'Hello ' + nombre; }; a('sergio');" + ); + say $return; + }; + if ($@) { + warn $@; + } + say Peertube::DL::Javascript::_duk_call_function( $a, "a", "sergio" ); + Peertube::DL::Javascript::_duk_destroy_heap($a); } diff --git a/javascript_interpreter_xs/javascript.xs b/javascript_interpreter_xs/javascript.xs index b7c5595..9441baa 100644 --- a/javascript_interpreter_xs/javascript.xs +++ b/javascript_interpreter_xs/javascript.xs @@ -24,48 +24,80 @@ _duk_create_heap_default() RETVAL SV * -_duk_push_lstring(SV *, SV *) +_duk_eval_wrapper(SV *, SV *) CODE: + if (!ST(0)) { + croak("Javascript context undefined.", 0); + } duk_context *context = (duk_context *) SvUV(ST(0)); - if(!context) { - croak("Javascript context undef.", 0); + if (!context) { + croak("Javascript context null on function call."); } - STRLEN len; - char * lstring = SvPV(ST(1), len); - if(!len) { - croak("Empty string on lstring push."); + duk_idx_t top_index; + if ( (top_index = duk_get_top_index(context)) != DUK_INVALID_INDEX) { + duk_pop_n(context, top_index + 1); } - duk_push_lstring(context, lstring, strlen(lstring)); -// -// * Example subroutine call -// dSP; -// ENTER; -// SAVETMPS; -// PUSHMARK(SP); -// EXTEND(SP, 1); -// PUSHs(sv_2mortal(newSVpv("Javascript context invalid.", 0))); -// PUTBACK; -// -// call_sv(sv_2mortal(newSVpv("::die", 0)), G_DISCARD); -// -// FREETMPS; -// LEAVE; -// -// + duk_require_stack(context, 2); + if (!ST(1)) { + croak("Code to eval is undef."); + } + STRLEN code_len; + char *code = SvPV(ST(1), code_len); + duk_push_lstring(context, code, strlen(code)); + if ( duk_peval(context) != 0 ) { + croak("Eval failed:\n%s\n", duk_get_string(context, -1)); + } + duk_size_t *lstring_len; + const char * lstring = duk_get_lstring(context, -1, lstring_len); + RETVAL = newSVpv(lstring, (size_t) lstring_len); + top_index = duk_get_top_index(context); + duk_pop_n(context, top_index+1); OUTPUT: RETVAL -void -_duk_peval(SV *) +SV * +_duk_call_function(SV *, SV *, ...) CODE: + if (!ST(0)) { + croak("Context is undef."); + } duk_context *context = (duk_context *) SvUV(ST(0)); - if(!context) { - croak("Javascript context undef.", 0); + if (!context) { + croak("Javascript context null on function call."); } - - if(duk_peval(context) != 0) { - croak("Eval failed:\n%s\n", duk_safe_to_string(context, -1)); + STRLEN function_name_len; + if (!ST(1)) { + croak("Function name must be defined."); } + char * function_name = SvPV(ST(1), function_name_len); + if ( function_name_len == 0 ) { + croak("Function name cannot be empty."); + } + duk_idx_t top_index; + if ( (top_index = duk_get_top_index(context)) != DUK_INVALID_INDEX ) { + duk_pop_n(context, top_index+1); + } + duk_require_stack(context, items+1); + (void) duk_get_global_lstring(context, function_name, strlen(function_name)); + if (items > 2) { + for ( int i = 2; i < items; i++) { + SV *argument_SV = ST(i); + if (!argument_SV) { + croak("Argument %d undefined.", i); + } + STRLEN argument_len; + char *argument = SvPV(argument_SV, argument_len); + duk_push_lstring(context, argument, strlen(argument)); + } + } + duk_size_t *lstring_len; + duk_call(context, 1); + char * return_value = duk_get_lstring(context, -1, lstring_len); + top_index = duk_get_top_index(context); + duk_pop_n(context, top_index+1); + RETVAL = newSVpv(return_value, (size_t) lstring_len); + OUTPUT: + RETVAL void _duk_destroy_heap(SV *) @@ -75,24 +107,3 @@ _duk_destroy_heap(SV *) croak("Cannot destroy something that is not a context."); } duk_destroy_heap(context); - -SV * -_duk_get_lstring(SV *, SV *) - CODE: - duk_context *context = (duk_context *) SvUV(ST(0)); - if (!context) { - croak("Unable to get lstring from no existing context."); - } - duk_idx_t idx = SvIV(ST(1)); - if (!duk_is_string(context, idx)) { - croak("Idx is not a string."); - } - if (duk_is_symbol(context, idx)) { - croak("This is a symbol, not a string."); - } - duk_size_t *lstring_len; - const char * lstring = duk_get_lstring(context, idx, lstring_len); - RETVAL = newSVpv(lstring, (size_t) lstring_len); - OUTPUT: - RETVAL -