DUK_EXTERNAL int sjs_vm_eval_code(const sjs_vm_t* vm, const char* filename, const char* code, size_t len, FILE* foutput, FILE* ferror) { int r; assert(vm); duk_context* ctx = vm->ctx; duk_push_pointer(ctx, (void *) code); duk_push_uint(ctx, len); duk_push_string(ctx, filename); r = duk_safe_call(ctx, sjs__compile_execute, 3 /*nargs*/, 1 /*nret*/); if (r != DUK_EXEC_SUCCESS) { if (ferror) { duk_safe_call(ctx, sjs__get_error_stack, 1 /*nargs*/, 1 /*nrets*/); fprintf(ferror, "%s\n", duk_safe_to_string(ctx, -1)); fflush(ferror); } } else { if (foutput) { fprintf(foutput, "= %s\n", duk_safe_to_string(ctx, -1)); fflush(foutput); } } duk_pop(ctx); return r; }
void test(duk_context *ctx) { int rc; rc = duk_safe_call(ctx, test_1, 0, 1); printf("rc=%d, result=%s\n", rc, duk_to_string(ctx, -1)); duk_pop(ctx); rc = duk_safe_call(ctx, test_2, 0, 1); printf("rc=%d, result=%s\n", rc, duk_to_string(ctx, -1)); duk_pop(ctx); }
void test(duk_context *ctx) { int rc; rc = duk_safe_call(ctx, test_1, 0, 1, DUK_INVALID_INDEX); printf("rc=%d, result='%s'\n", rc, duk_to_string(ctx, -1)); duk_pop(ctx); rc = duk_safe_call(ctx, test_2, 0, 1, DUK_INVALID_INDEX); printf("rc=%d, result='%s'\n", rc, duk_to_string(ctx, -1)); duk_pop(ctx); }
static duk_ret_t test_2a(duk_context *ctx, void *udata) { (void) udata; /* Test first with nothing on stack index -3. */ duk_safe_call(ctx, test__null, NULL, 0, 1); printf("%s\n", duk_safe_to_string(ctx, 0)); duk_pop(ctx); duk_set_top(ctx, 0); duk_push_undefined(ctx); test__require_calls(ctx); duk_set_top(ctx, 0); duk_push_null(ctx); test__require_calls(ctx); duk_set_top(ctx, 0); duk_push_true(ctx); test__require_calls(ctx); duk_set_top(ctx, 0); duk_push_false(ctx); test__require_calls(ctx); duk_set_top(ctx, 0); duk_push_number(ctx, 123.0); test__require_calls(ctx); duk_set_top(ctx, 0); duk_push_string(ctx, "foo\x00" "bar"); test__require_calls(ctx); duk_set_top(ctx, 0); duk_push_fixed_buffer(ctx, 16); test__require_calls(ctx); duk_set_top(ctx, 0); duk_push_pointer(ctx, NULL); test__require_calls(ctx); duk_set_top(ctx, 0); duk_push_pointer(ctx, (void *) 0xdeadbeefUL); test__require_calls(ctx); duk_set_top(ctx, 0); duk_push_object(ctx); test__require_calls(ctx); duk_set_top(ctx, 0); duk_push_array(ctx); test__require_calls(ctx); duk_set_top(ctx, 0); duk_push_c_function(ctx, dummy_func, 0); test__require_calls(ctx); duk_set_top(ctx, 0); duk_push_c_lightfunc(ctx, dummy_func, 0, 0, 0); test__require_calls(ctx); duk_set_top(ctx, 0); duk_eval_string(ctx, "(function dummy(){})"); test__require_calls(ctx); duk_set_top(ctx, 0); duk_push_thread(ctx); test__require_calls(ctx); printf("done\n"); return 0; }
static duk_ret_t test_error_augment(duk_context *ctx, void *udata) { duk_int_t ret; (void) udata; prep(ctx); /* This case is a bit tricky. There used to be a problem where the * error augmentation process itself failed when checking whether or * not the throw value inherited from Error. This has now been fixed * and the error value no longer gets augmented and is thrown correctly. * * The TEST_SAFE_CALL() wrapper uses duk_safe_to_string() to coerce * the throw result. Since the object doesn't have a toString() * function, this coercion will fail and generate a prototype loop * error! * * So, use a separate duk_safe_call() wrapping here to ensure we treat * the final result value carefully. We print out 'foo' to be sure * the correct value was thrown. */ duk_dup(ctx, 0); ret = duk_safe_call(ctx, augment_raw, NULL, 0 /*nargs*/, 1 /*nrets*/); printf("ret=%d\n", (int) ret); duk_get_prop_string(ctx, -1, "foo"); printf("throw value .foo=%d\n", duk_get_int(ctx, -1)); duk_pop_2(ctx); return 0; }
static duk_ret_t test_basic(duk_context *ctx, void *udata) { duk_idx_t i, n; duk_int_t rc; (void) udata; duk_push_undefined(ctx); duk_push_null(ctx); duk_push_true(ctx); duk_push_false(ctx); duk_push_string(ctx, "foo"); duk_push_int(ctx, 123); duk_push_object(ctx); duk_push_pointer(ctx, (void *) NULL); duk_push_pointer(ctx, (void *) 0xdeadbeefUL); n = duk_get_top(ctx); printf("top: %ld\n", (long) n); for (i = 0; i <= n; i++) { rc = duk_safe_call(ctx, safe_helper, (void *) i, 0, 1); if (rc != DUK_EXEC_SUCCESS) { printf("index %ld: %s\n", (long) i, duk_safe_to_string(ctx, -1)); } duk_pop(ctx); } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
void test(duk_context *ctx) { duk_context *new_ctx; new_ctx = duk_create_heap(NULL, NULL, NULL, NULL, my_fatal_handler); duk_safe_call(new_ctx, my_func, NULL, 0, 1); printf("duk_safe_call() returned, should not happen\n"); }
static int handle_eval(duk_context *ctx, const char *code) { int rc; int retval = -1; duk_push_pointer(ctx, (void *) code); duk_push_uint(ctx, (duk_uint_t) strlen(code)); duk_push_string(ctx, "eval"); interactive_mode = 0; /* global */ rc = duk_safe_call(ctx, wrapped_compile_execute, 3 /*nargs*/, 1 /*nret*/); #if defined(DUK_CMDLINE_AJSHEAP) ajsheap_clear_exec_timeout(); #endif if (rc != DUK_EXEC_SUCCESS) { print_pop_error(ctx, stderr); } else { duk_pop(ctx); retval = 0; } return retval; }
/* in interactive mode, write to stdout */ print_pop_error(ctx, stdout); retval = -1; /* an error 'taints' the execution */ } else { duk_pop(ctx); } } done: if (buffer) { free(buffer); buffer = NULL; } return retval; } #else /* NO_READLINE */ static int handle_interactive(duk_context *ctx) { const char *prompt = "duk> "; char *buffer = NULL; int retval = 0; int rc; duk_eval_string(ctx, GREET_CODE("")); duk_pop(ctx); /* * Note: using readline leads to valgrind-reported leaks inside * readline itself. Execute code from an input file (and not * through stdin) for clean valgrind runs. */ rl_initialize(); for (;;) { if (buffer) { free(buffer); buffer = NULL; } buffer = readline(prompt); if (!buffer) { break; } if (buffer && buffer[0] != (char) 0) { add_history(buffer); } duk_push_lstring(ctx, buffer, strlen(buffer)); duk_push_string(ctx, "input"); if (buffer) { free(buffer); buffer = NULL; } interactive_mode = 1; /* global */ rc = duk_safe_call(ctx, wrapped_compile_execute, 2 /*nargs*/, 1 /*nret*/); if (rc != DUK_EXEC_SUCCESS) { /* in interactive mode, write to stdout */ print_pop_error(ctx, stdout); retval = -1; /* an error 'taints' the execution */ } else { duk_pop(ctx); } } if (buffer) { free(buffer); buffer = NULL; } return retval; }
/* Load a module as the 'main' module. */ duk_ret_t duk_module_node_peval_main(duk_context *ctx, const char *path) { /* * Stack: [ ... source ] */ duk__push_module_object(ctx, path, 1 /*main*/); /* [ ... source module ] */ duk_dup(ctx, 0); /* [ ... source module source ] */ #if DUK_VERSION >= 19999 return duk_safe_call(ctx, duk__eval_module_source, NULL, 2, 1); #else return duk_safe_call(ctx, duk__eval_module_source, 2, 1); #endif }
DUK_EXTERNAL int sjs_vm_eval_code(const sjs_vm_t* vm, const char* filename, const char* code, size_t len, FILE* foutput, FILE* ferror, bool use_strict) { int r; assert(vm); duk_context* ctx = vm->ctx; duk_push_boolean(ctx, use_strict); duk_push_pointer(ctx, (void *) code); duk_push_uint(ctx, len); duk_push_string(ctx, filename); r = duk_safe_call(ctx, sjs__compile_execute, 4 /*nargs*/, 1 /*nret*/); if (r != DUK_EXEC_SUCCESS) { if (ferror) { duk_safe_call(ctx, sjs__get_error_stack, 1 /*nargs*/, 1 /*nrets*/); fprintf(ferror, "%s\n", duk_safe_to_string(ctx, -1)); fflush(ferror); } } else { if (foutput) { /* TODO: make this optional with a parameter? */ /* beautify output */ duk_eval_string(ctx, "(function (v) {\n" " try {\n" " return Duktape.enc('jx', v, null, 4);\n" " } catch (e) {\n" " return String(v);\n" " }\n" "})"); duk_insert(ctx, -2); duk_call(ctx, 1); fprintf(foutput, "= %s\n", duk_safe_to_string(ctx, -1)); fflush(foutput); } } duk_pop(ctx); return r; }
static int handle_fh(duk_context *ctx, FILE *f, const char *filename, const char *bytecode_filename) { char *buf = NULL; int len; size_t got; int rc; int retval = -1; if (fseek(f, 0, SEEK_END) < 0) { goto error; } len = (int) ftell(f); if (fseek(f, 0, SEEK_SET) < 0) { goto error; } buf = (char *) malloc(len); if (!buf) { goto error; } got = fread((void *) buf, (size_t) 1, (size_t) len, f); duk_push_string(ctx, bytecode_filename); duk_push_pointer(ctx, (void *) buf); duk_push_uint(ctx, (duk_uint_t) got); duk_push_string(ctx, filename); interactive_mode = 0; /* global */ rc = duk_safe_call(ctx, wrapped_compile_execute, 4 /*nargs*/, 1 /*nret*/); #if defined(DUK_CMDLINE_AJSHEAP) ajsheap_clear_exec_timeout(); #endif free(buf); buf = NULL; if (rc != DUK_EXEC_SUCCESS) { print_pop_error(ctx, stderr); goto error; } else { duk_pop(ctx); retval = 0; } /* fall thru */ cleanup: if (buf) { free(buf); } return retval; error: fprintf(stderr, "error in executing file %s\n", filename); fflush(stderr); goto cleanup; }
static duk_ret_t test_basic(duk_context *ctx, void *udata) { duk_idx_t i, n; duk_int_t rc; (void) udata; duk_push_undefined(ctx); duk_push_null(ctx); duk_push_true(ctx); duk_push_false(ctx); duk_push_string(ctx, ""); duk_push_string(ctx, "foo"); duk_push_int(ctx, 123); duk_push_object(ctx); duk_push_fixed_buffer(ctx, 0); duk_push_fixed_buffer(ctx, 1024); duk_push_dynamic_buffer(ctx, 0); duk_push_dynamic_buffer(ctx, 2048); duk_eval_string(ctx, "(function () { return new ArrayBuffer(16); })()"); duk_eval_string(ctx, "(function () { return new Uint32Array(16); })()"); duk_eval_string(ctx, "(function () { return new DataView(new ArrayBuffer(16)); })()"); duk_eval_string(ctx, "(function () { return new Uint32Array(16).subarray(3, 6); })()"); duk_eval_string(ctx, "(function () { return new Buffer('ABCDEFGH'); })()"); duk_eval_string(ctx, "(function () { return new Buffer('ABCDEFGH').slice(3, 6); })()"); n = duk_get_top(ctx); printf("top: %ld\n", (long) n); for (i = 0; i <= n; i++) { rc = duk_safe_call(ctx, safe_helper1, (void *) i, 0, 1); if (rc != DUK_EXEC_SUCCESS) { printf("index %ld: %s\n", (long) i, duk_safe_to_string(ctx, -1)); } duk_pop(ctx); rc = duk_safe_call(ctx, safe_helper2, (void *) i, 0, 1); if (rc != DUK_EXEC_SUCCESS) { printf("index %ld: %s\n", (long) i, duk_safe_to_string(ctx, -1)); } duk_pop(ctx); } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
DUK_INTERNAL void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj) { duk_context *ctx = (duk_context *) thr; duk_ret_t rc; #if defined(DUK_USE_ASSERTIONS) duk_idx_t entry_top; #endif DUK_DDD(DUK_DDDPRINT("running object finalizer for object: %p", (void *) obj)); DUK_ASSERT(thr != NULL); DUK_ASSERT(ctx != NULL); DUK_ASSERT(obj != NULL); DUK_ASSERT_VALSTACK_SPACE(thr, 1); #if defined(DUK_USE_ASSERTIONS) entry_top = duk_get_top(ctx); #endif /* * Get and call the finalizer. All of this must be wrapped * in a protected call, because even getting the finalizer * may trigger an error (getter may throw one, for instance). */ DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)); if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj)) { DUK_D(DUK_DPRINT("object already finalized, avoid running finalizer twice: %!O", obj)); return; } DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj); /* ensure never re-entered until rescue cycle complete */ if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj)) { /* This shouldn't happen; call sites should avoid looking up * _Finalizer "through" a Proxy, but ignore if we come here * with a Proxy to avoid finalizer re-entry. */ DUK_D(DUK_DPRINT("object is a proxy, skip finalizer call")); return; } /* XXX: use a NULL error handler for the finalizer call? */ DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling wrapped finalize helper")); duk_push_hobject(ctx, obj); /* this also increases refcount by one */ rc = duk_safe_call(ctx, duk__finalize_helper, NULL /*udata*/, 0 /*nargs*/, 1 /*nrets*/); /* -> [... obj retval/error] */ DUK_ASSERT_TOP(ctx, entry_top + 2); /* duk_safe_call discipline */ if (rc != DUK_EXEC_SUCCESS) { /* Note: we ask for one return value from duk_safe_call to get this * error debugging here. */ DUK_D(DUK_DPRINT("wrapped finalizer call failed for object %p (ignored); error: %!T", (void *) obj, (duk_tval *) duk_get_tval(ctx, -1))); } duk_pop_2(ctx); /* -> [...] */ DUK_ASSERT_TOP(ctx, entry_top); }
/* Print error to stderr and pop error. */ static void print_error(duk_context *ctx, FILE *f) { /* Print error objects with a stack trace specially. * Note that getting the stack trace may throw an error * so this also needs to be safe call wrapped. */ (void) duk_safe_call(ctx, get_stack_raw, 1 /*nargs*/, 1 /*nrets*/); fprintf(f, "%s\n", duk_safe_to_string(ctx, -1)); fflush(f); duk_pop(ctx); }
int main(int argc, char *argv[]) { /**(uint32_t *)0x40023830 |= 0x8; *(uint32_t *)0x40020C00 |= 0x55000000; *(uint32_t *)0x40020C14 = 0x00000000; while(1) { *(uint32_t *)0x40020C14 = 0x00000000; delay(); *(uint32_t *)0x40020C14 = 0x00008000; delay(); } duk_context *ctx = duk_create_heap_default(); duk_eval_string(ctx, "'Hello world!'"); duk_destroy_heap(ctx); */ *(uint32_t *)0x40023830 |= 0x8; *(uint32_t *)0x40020C00 |= 0x55000000; *(uint32_t *)0x40020C14 = 0x00000000; ctx = duk_create_heap_default(); duk_push_global_object(ctx); duk_push_c_function(ctx, LED_Toggle, DUK_VARARGS); duk_put_prop_string(ctx, -2, "LED_Toggle"); duk_push_string(ctx, "blink = function() { LED_Toggle(); };"); duk_safe_call(ctx, safeEval, 1, 1); while (1) { duk_push_global_object(ctx); duk_get_prop_string(ctx, -1, "blink"); duk_push_string(ctx, "0"); duk_safe_call(ctx, safeCall, 1, 0); duk_pop_2(ctx); //for(volatile int i = 0; i < 100000; i++); //delay(); } return 0; }
int handle_fh(duk_context *ctx, FILE *f, const char *filename) { char *buf = NULL; int len; int got; int rc; int retval = -1; if (fseek(f, 0, SEEK_END) < 0) { goto error; } len = (int) ftell(f); if (fseek(f, 0, SEEK_SET) < 0) { goto error; } buf = (char *) malloc(len); if (!buf) { goto error; } got = fread((void *) buf, (size_t) 1, (size_t) len, f); duk_push_lstring(ctx, buf, got); duk_push_string(ctx, filename); free(buf); buf = NULL; interactive_mode = 0; /* global */ rc = duk_safe_call(ctx, wrapped_compile_execute, 2 /*nargs*/, 1 /*nret*/); if (rc != DUK_EXEC_SUCCESS) { print_error(ctx, stderr); goto error; } else { duk_pop(ctx); retval = 0; } /* fall thru */ cleanup: if (buf) { free(buf); } return retval; error: fprintf(stderr, "error in reading input from file %s\n", filename); fflush(stderr); goto cleanup; }
void test(duk_context *ctx) { int rc; rc = duk_safe_call(ctx, test_1, 0, 1, DUK_INVALID_INDEX); printf("rc=%d -> %s\n", rc, duk_to_string(ctx, -1)); duk_pop(ctx); /* FIXME: printing the specific error is currently fragile * because it includes a tag number. */ rc = duk_safe_call(ctx, test_2, 0, 1, DUK_INVALID_INDEX); printf("rc=%d -> %s\n", rc, duk_to_string(ctx, -1)); duk_pop(ctx); rc = duk_safe_call(ctx, test_3, 0, 1, DUK_INVALID_INDEX); printf("rc=%d -> %s\n", rc, duk_to_string(ctx, -1)); duk_pop(ctx); rc = duk_safe_call(ctx, test_4, 0, 1, DUK_INVALID_INDEX); printf("rc=%d -> %s\n", rc, duk_to_string(ctx, -1)); duk_pop(ctx); }
static duk_ret_t empty_helper(duk_context *ctx, duk_safe_call_function target_func) { duk_int_t rc; rc = duk_safe_call(ctx, target_func, NULL, 0, 1); (void) rc; duk_eval_string(ctx, "(function (e) { print(e.fileName, e.lineNumber); if (PRINT_STACK) { print(e.stack); } })"); duk_dup(ctx, -2); duk_call(ctx, 1); duk_pop(ctx); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start, duk_size_t *p_count_check, duk_size_t *p_count_compact, duk_size_t *p_count_bytes_saved) { #else DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start) { #endif duk_heaphdr *curr; #if defined(DUK_USE_DEBUG) duk_size_t old_size, new_size; #endif duk_hobject *obj; DUK_UNREF(heap); curr = start; while (curr) { DUK_DDD(DUK_DDDPRINT("mark-and-sweep compact: %p", (void *) curr)); if (DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_OBJECT) { goto next; } obj = (duk_hobject *) curr; #if defined(DUK_USE_DEBUG) old_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj), DUK_HOBJECT_GET_ASIZE(obj), DUK_HOBJECT_GET_HSIZE(obj)); #endif DUK_DD(DUK_DDPRINT("compact object: %p", (void *) obj)); duk_push_hobject((duk_context *) thr, obj); /* XXX: disable error handlers for duration of compaction? */ duk_safe_call((duk_context *) thr, duk__protected_compact_object, NULL, 1, 0); #if defined(DUK_USE_DEBUG) new_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj), DUK_HOBJECT_GET_ASIZE(obj), DUK_HOBJECT_GET_HSIZE(obj)); #endif #if defined(DUK_USE_DEBUG) (*p_count_compact)++; (*p_count_bytes_saved) += (duk_size_t) (old_size - new_size); #endif next: curr = DUK_HEAPHDR_GET_NEXT(heap, curr); #if defined(DUK_USE_DEBUG) (*p_count_check)++; #endif } }
void test(duk_context *ctx) { duk_ret_t rc; /* Custom test macro, prints top after call. */ SETUP(2); PRINTTOP(); rc = duk_safe_call(ctx, test_pop_a, NULL, 2, 1); printf("test_pop_1 -> top=%ld, rc=%d, ret='%s'\n", (long) duk_get_top(ctx), (int) rc, duk_to_string(ctx, -1)); SETUP(2); PRINTTOP(); rc = duk_safe_call(ctx, test_pop_b, NULL, 2, 1); printf("test_pop_b -> top=%ld, rc=%d, ret='%s'\n", (long) duk_get_top(ctx), (int) rc, duk_to_string(ctx, -1)); SETUP(5); PRINTTOP(); rc = duk_safe_call(ctx, test_pop_2a, NULL, 5, 1); printf("test_pop_2a -> top=%ld, rc=%d, ret='%s'\n", (long) duk_get_top(ctx), (int) rc, duk_to_string(ctx, -1)); SETUP(5); PRINTTOP(); rc = duk_safe_call(ctx, test_pop_2b, NULL, 5, 1); printf("test_pop_2b -> top=%ld, rc=%d, ret='%s'\n", (long) duk_get_top(ctx), (int) rc, duk_to_string(ctx, -1)); SETUP(7); PRINTTOP(); rc = duk_safe_call(ctx, test_pop_3a, NULL, 7, 1); printf("test_pop_3a -> top=%ld, rc=%d, ret='%s'\n", (long) duk_get_top(ctx), (int) rc, duk_to_string(ctx, -1)); SETUP(7); PRINTTOP(); rc = duk_safe_call(ctx, test_pop_3b, NULL, 7, 1); printf("test_pop_3b -> top=%ld, rc=%d, ret='%s'\n", (long) duk_get_top(ctx), (int) rc, duk_to_string(ctx, -1)); SETUP(11); PRINTTOP(); rc = duk_safe_call(ctx, test_pop_na, NULL, 11, 1); printf("test_pop_na -> top=%ld, rc=%d, ret='%s'\n", (long) duk_get_top(ctx), (int) rc, duk_to_string(ctx, -1)); SETUP(11); PRINTTOP(); rc = duk_safe_call(ctx, test_pop_nb, NULL, 11, 1); printf("test_pop_nb -> top=%ld, rc=%d, ret='%s'\n", (long) duk_get_top(ctx), (int) rc, duk_to_string(ctx, -1)); PRINTTOP(); }
void test(duk_context *ctx) { duk_ret_t rc; duk_set_top(ctx, 0); duk_push_string(ctx, "foo"); /* dummy */ /* success case */ duk_push_int(ctx, 10); duk_push_int(ctx, 11); duk_push_int(ctx, 12); rc = duk_safe_call(ctx, test_1, 3 /*nargs*/, 2 /*nrets*/); if (rc == DUK_EXEC_SUCCESS) { printf("1st return value: %s\n", duk_to_string(ctx, -2)); /* 21 */ printf("2nd return value: %s\n", duk_to_string(ctx, -1)); /* undefined */ } else { printf("error: %s\n", duk_to_string(ctx, -2)); } duk_pop_2(ctx); /* error case */ duk_push_int(ctx, 10); duk_push_int(ctx, 11); duk_push_int(ctx, 12); rc = duk_safe_call(ctx, test_2, 3 /*nargs*/, 2 /*nrets*/); if (rc == DUK_EXEC_SUCCESS) { printf("1st return value: %s\n", duk_to_string(ctx, -2)); /* 21 */ printf("2nd return value: %s\n", duk_to_string(ctx, -1)); /* undefined */ } else { printf("error: %s\n", duk_to_string(ctx, -2)); } duk_pop_2(ctx); /* XXX: also test invalid input stack shapes (like not enough args) */ printf("final top: %ld\n", (long) duk_get_top(ctx)); }
int main(int argc, char *argv[]) { int i, rc; prg.argc = argc; prg.argv = argv; prg.name = argv[1]; duk_context *ctx = duk_create_heap_default(); duk_push_global_object(ctx); duk_push_object(ctx); /* -> [ ... global obj ] */ sys1(ctx); for(i=1;i<argc;i++) { duk_push_string(ctx, argv[i]); duk_put_prop_index(ctx, -2, i-1); } duk_push_number(ctx, argc-1); duk_put_prop_string(ctx, -2, "argc"); duk_put_prop_string(ctx, -2, "Sys1"); /* -> [ ... global ] */ duk_push_object(ctx); /* -> [ ... global obj ] */ prg1(ctx); duk_put_prop_string(ctx, -2, "Prg1"); /* -> [ ... global ] */ prg_push_modsearch(ctx); duk_pop(ctx); prg_parse_appfile(&prg); // push file duk_push_lstring(ctx, prg.main->buf, prg.main->size); duk_push_string(ctx, argv[1]); // execute file (compile + call) prg_register(&prg); rc = duk_safe_call(ctx, prg_wrapped_compile_execute, 2 /*nargs*/, 1 /*nret*/); if (rc != DUK_EXEC_SUCCESS) { print_error(ctx, stderr); exit(2); } duk_pop(ctx); /* pop eval result */ duk_destroy_heap(ctx); return prg.status; }
int main(int argc, char *argv[]) { duk_context *ctx; int i; const char *res; if (argc < 2) { usage_exit(); } ctx = duk_create_heap_default(); for (i = 1; i < argc; i++) { printf("=== eval: '%s' ===\n", argv[i]); duk_push_string(ctx, argv[i]); duk_safe_call(ctx, eval_raw, 1 /*nargs*/, 1 /*nrets*/); duk_safe_call(ctx, tostring_raw, 1 /*nargs*/, 1 /*nrets*/); res = duk_get_string(ctx, -1); printf("%s\n", res ? res : "null"); duk_pop(ctx); } duk_destroy_heap(ctx); return 0; }
static duk_ret_t test_safe_call_error2(duk_context *ctx) { duk_idx_t i; duk_int_t rc; duk_require_stack(ctx, STACK_REQUIRE + 1); rc = duk_safe_call(ctx, my_safe_func_error2, 0 /*nargs*/, 1 /*nrets*/); printf("duk_safe_call: rc=%ld, value: %s\n", (long) rc, duk_safe_to_string(ctx, -1)); for (i = 0; i < STACK_REQUIRE; i++) { duk_push_int(ctx, 123); } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_nargs_minus1(duk_context *ctx, void *udata) { duk_int_t rc; (void) udata; duk_push_null(ctx); duk_push_null(ctx); duk_push_null(ctx); printf("top before: %ld\n", (long) duk_get_top(ctx)); rc = duk_safe_call(ctx, dummy, NULL, -1 /*nargs, negative*/, 0 /*nrets*/); printf("duk_safe_call rc: %ld\n", (long) rc); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
DUK_EXTERNAL duk_int_t duk_pnew(duk_context *ctx, duk_idx_t nargs) { duk_int_t rc; DUK_ASSERT_CTX_VALID(ctx); /* For now, just use duk_safe_call() to wrap duk_new(). We can't * simply use a protected duk_handle_call() because there's post * processing which might throw. It should be possible to ensure * the post processing never throws (except in internal errors and * out of memory etc which are always allowed) and then remove this * wrapper. */ rc = duk_safe_call(ctx, duk__pnew_helper, (void *) &nargs /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/); return rc; }
DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs) { /* * Must be careful to catch errors related to value stack manipulation * and property lookup, not just the call itself. */ DUK_ASSERT_CTX_VALID(ctx); duk_push_idx(ctx, obj_index); duk_push_idx(ctx, nargs); /* Inputs: explicit arguments (nargs), +1 for key, +2 for obj_index/nargs passing. * If the value stack does not contain enough args, an error is thrown; this matches * behavior of the other protected call API functions. */ return duk_safe_call(ctx, duk__pcall_prop_raw, nargs + 1 + 2 /*nargs*/, 1 /*nrets*/); }
static int lang_duktape_safe_eval(duk_context *ctx, const char *code) { #if UNSAFE duk_eval_string (ctx, code); #else int rc; duk_push_lstring (ctx, code, strlen (code)); duk_push_string (ctx, "input"); rc = duk_safe_call (ctx, wrapped_compile_execute, 2, 1); //, DUK_INVALID_INDEX); if (rc != DUK_EXEC_SUCCESS) { print_error(ctx, stderr); rc = R_FALSE; } else { duk_pop (ctx); rc = R_TRUE; } return rc; #endif }
static int lang_duktape_file(RLang *lang, const char *file) { int ret = -1; char *code = r_file_slurp (file, NULL); if (code) { register_helpers (lang); duk_push_lstring (ctx, code, strlen (code)); duk_push_string (ctx,file); free (code); ret = duk_safe_call (ctx, wrapped_compile_execute, 2, 1); if (ret != DUK_EXEC_SUCCESS) { print_error(ctx, stderr); eprintf ("duktape error"); } else { duk_pop (ctx); } } return ret; }