Peertube-dl/javascript_interpreter_xs/javascript.xs

111 lines
3.6 KiB
Plaintext

#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);