#define PERL_NO_GET_CONTEXT #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "duktape.h" #include "duk_config.h" #include "javascript_builtins.h" MODULE = Peertube::DL::Javascript PACKAGE = Peertube::DL::Javascript PROTOTYPES: ENABLE SV * _duk_create_heap_default() CODE: duk_context *context = duk_create_heap_default(); if (context) { duk_push_c_function(context, js_builtin_print, 1); duk_put_global_string(context, "print"); RETVAL = newSVuv((size_t)context); } else { RETVAL = &PL_sv_undef; } OUTPUT: RETVAL 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 null on function call."); } 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, 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%s\n", duk_safe_to_string(context, -1), duk_to_stacktrace(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 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 null on function call."); } 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); const char * return_value = duk_get_lstring(context, -1, lstring_len); if ( (top_index = duk_get_top_index(context)) != DUK_INVALID_INDEX ) { duk_pop_n(context, top_index+1); } RETVAL = newSVpv(return_value, (size_t) lstring_len); OUTPUT: RETVAL void _duk_destroy_heap(SV *) CODE: duk_context *context = (duk_context *) SvUV(ST(0)); if (!context) { croak("Cannot destroy something that is not a context."); } duk_destroy_heap(context);