/* Arguments object still works after dump/load, relies on e.g. _Formals. */ static duk_ret_t test_arguments_object(duk_context *ctx) { duk_eval_string(ctx, "(function () {\n" " var f = function test(x,y) {\n" " print(typeof arguments, Object.prototype.toString.call(arguments));\n" " print(arguments[0], arguments[1]);\n" " arguments[0] = 123;\n" " print(x, y);\n" " };\n" " return f;\n" "})()"); duk_dup_top(ctx); duk_push_string(ctx, "foo"); duk_push_string(ctx, "bar"); duk_call(ctx, 2); duk_pop(ctx); duk_dump_function(ctx); duk_load_function(ctx); duk_push_string(ctx, "foo"); duk_push_string(ctx, "bar"); duk_call(ctx, 2); duk_pop(ctx); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* It's not an error for the underlying plain buffer to be too small to * cover the slice. This is allowed because it may happen for dynamic * and external buffers at run time anyway. In any case, no memory * unsafe behavior happens. */ static duk_ret_t test_uncovered(duk_context *ctx, void *udata) { (void) udata; duk_push_fixed_buffer(ctx, 256); duk_push_buffer_object(ctx, -1, 7, 512, DUK_BUFOBJ_UINT32ARRAY); duk_eval_string(ctx, "dumpBufferInfo"); duk_dup(ctx, -2); duk_call(ctx, 1); duk_pop(ctx); duk_eval_string(ctx, "(function (v) {\n" " for (var i = 0; i < v.length; i++) { v[i] = 123; }\n" " for (var i = 0; i < v.length; i++) { var ignore = v[i]; }\n" "})"); duk_dup(ctx, -2); duk_call(ctx, 1); duk_pop(ctx); duk_pop_n(ctx, 2); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* Strictness status is preserved. */ static duk_ret_t test_strict(duk_context *ctx) { duk_compile_string(ctx, DUK_COMPILE_FUNCTION, "function () {\n" " var strict = (function () { return !this; })();\n" " print('strict: ' + strict);\n" "}"); duk_dump_function(ctx); duk_load_function(ctx); duk_call(ctx, 0); duk_pop(ctx); duk_compile_string(ctx, DUK_COMPILE_FUNCTION, "function () {\n" " 'use strict';\n" " var strict = (function () { return !this; })();\n" " print('strict: ' + strict);\n" "}"); duk_dump_function(ctx); duk_load_function(ctx); duk_call(ctx, 0); duk_pop(ctx); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* Test serialization of Eval (instead of function) code: * * - Bindings established via Eval code are configurable; bindings * established from program and function code are not. (E5 Section * 10.5 step 2). * * Here we bytecode dump an eval function that is then loaded and executed * in the global scope. */ static duk_ret_t test_eval_code(duk_context *ctx) { /* Demonstrate behavior without dump/load. */ duk_compile_string(ctx, DUK_COMPILE_EVAL, "var testEval1 = 123;" ); duk_call(ctx, 0); duk_pop(ctx); duk_eval_string_noresult(ctx, "print(JSON.stringify(Object.getOwnPropertyDescriptor(this, 'testEval1')));" ); /* Same with dump/load. */ duk_compile_string(ctx, DUK_COMPILE_EVAL, "var testEval2 = 234;" ); duk_dump_function(ctx); duk_load_function(ctx); duk_call(ctx, 0); duk_pop(ctx); duk_eval_string_noresult(ctx, "print(JSON.stringify(Object.getOwnPropertyDescriptor(this, 'testEval2')));" ); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* _Varmap is preserved if function needs it. */ static duk_ret_t test_varmap(duk_context *ctx) { /* Get access to _Varmap by creating a function that provides * an 'eval service' in a function scope. */ duk_compile_string(ctx, DUK_COMPILE_FUNCTION, "function (code) {\n" " var foo = 123;\n" " eval(code);\n" "}"); duk_dump_function(ctx); duk_load_function(ctx); duk_dup(ctx, -1); duk_push_string(ctx, "print('hello world');"); duk_call(ctx, 1); duk_pop(ctx); /* Eval code will use GETVAR to read 'foo', and _Varmap is * needed for that. */ duk_dup(ctx, -1); duk_push_string(ctx, "print(foo);"); duk_call(ctx, 1); duk_pop(ctx); duk_pop(ctx); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* Name binding for function expressions is preserved, it is important * for recursive functions. */ static duk_ret_t test_name_binding_funcexpr(duk_context *ctx) { duk_eval_string(ctx, "(function () {\n" " var f = function test() { print('i am a ' + typeof test); };\n" " return f;\n" "})()"); duk_dup_top(ctx); duk_call(ctx, 0); /* undumped */ duk_pop(ctx); duk_dump_function(ctx); duk_load_function(ctx); duk_call(ctx, 0); /* dump/load */ duk_pop(ctx); duk_eval_string(ctx, "(function () {\n" " var f = function test(n) { print(n); if (n > 0) { test(n - 1); } };\n" " return f;\n" "})()"); duk_dup_top(ctx); duk_push_int(ctx, 5); duk_call(ctx, 1); /* undumped */ duk_pop(ctx); duk_dump_function(ctx); duk_load_function(ctx); duk_push_int(ctx, 7); duk_call(ctx, 1); /* dump/load */ duk_pop(ctx); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_int_t duk__eval_module_source(duk_context *ctx, void *udata) { #else static duk_int_t duk__eval_module_source(duk_context *ctx) { #endif /* * Stack: [ ... module source ] */ #if DUK_VERSION >= 19999 (void) udata; #endif /* Wrap the module code in a function expression. This is the simplest * way to implement CommonJS closure semantics and matches the behavior of * e.g. Node.js. */ duk_push_string(ctx, "(function(exports,require,module,__filename,__dirname){"); duk_dup(ctx, -2); /* source */ duk_push_string(ctx, "})"); duk_concat(ctx, 3); /* [ ... module source func_src ] */ (void) duk_get_prop_string(ctx, -3, "filename"); duk_compile(ctx, DUK_COMPILE_EVAL); duk_call(ctx, 0); /* [ ... module source func ] */ /* Set name for the wrapper function. */ duk_push_string(ctx, "name"); duk_push_string(ctx, "main"); duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_FORCE); /* call the function wrapper */ (void) duk_get_prop_string(ctx, -3, "exports"); /* exports */ (void) duk_get_prop_string(ctx, -4, "require"); /* require */ duk_dup(ctx, -5); /* module */ (void) duk_get_prop_string(ctx, -6, "filename"); /* __filename */ duk_push_undefined(ctx); /* __dirname */ duk_call(ctx, 5); /* [ ... module source result(ignore) ] */ /* module.loaded = true */ duk_push_true(ctx); duk_put_prop_string(ctx, -4, "loaded"); /* [ ... module source retval ] */ duk_pop_2(ctx); /* [ ... module ] */ return 1; }
static duk_ret_t havefile1_helper_2(duk_context *ctx) { duk_push_string(ctx, "(function () {\n" " var fn = function haveFileName(v) { v(); return 123; };\n" " return fn;\n" "})()"); duk_push_string(ctx, "dummy_filename.js"); duk_compile(ctx, DUK_COMPILE_EVAL); duk_call(ctx, 0); duk_push_c_function(ctx, target_func_hack, 0); duk_call(ctx, 1); return 0; }
void test(duk_context *ctx) { duk_idx_t i, funcidx, argcount; duk_ret_t rc; /* test C function arg count variants */ duk_push_c_function(ctx, my_int_adder, 0); /* [0] = c func with 0 args */ duk_push_c_function(ctx, my_int_adder, 1); /* [1] = c func with 1 arg */ duk_push_c_function(ctx, my_int_adder, 2); /* [2] = c func with 2 args */ duk_push_c_function(ctx, my_int_adder, DUK_VARARGS); /* [3] = c func with varargs */ for (funcidx = 0; funcidx < 4; funcidx++) { for (argcount = 0; argcount < 5; argcount++) { duk_dup(ctx, funcidx); for (i = 0; i < argcount; i++) { duk_push_int(ctx, i + 1); /* 1, 2, 3, ... */ } /* [ ... func <args> ] */ duk_call(ctx, argcount); printf("funcidx=%ld, argcount=%ld -> result=%ld\n", (long) funcidx, (long) argcount, (long) duk_to_int(ctx, -1)); duk_pop(ctx); } } /* test C function return value 0 and negative */ duk_set_top(ctx, 0); duk_push_c_function(ctx, my_zero_ret, 0); duk_call(ctx, 0); printf("top after calling my_zero_ret: %ld, retval='%s'\n", (long) duk_get_top(ctx), duk_to_string(ctx, -1)); duk_pop(ctx); duk_set_top(ctx, 0); duk_push_c_function(ctx, my_neg_ret, 0); rc = duk_pcall(ctx, 0); printf("top after calling my_neg_ret: %ld, rc=%d, retval='%s'\n", (long) duk_get_top(ctx), (int) rc, duk_to_string(ctx, -1)); duk_pop(ctx); duk_set_top(ctx, 0); duk_push_c_function(ctx, my_type_error_ret, 0); rc = duk_pcall(ctx, 0); printf("top after calling my_type_error_ret: %ld, rc=%d, retval='%s'\n", (long) duk_get_top(ctx), (int) rc, duk_to_string(ctx, -1)); duk_pop(ctx); }
/* Dump/load mandelbrot. No inner functions but a bit more code. */ static duk_ret_t test_mandel(duk_context *ctx) { unsigned char *p; duk_size_t i, sz; printf("Mandelbrot source length: %ld\n", (long) strlen(MANDELBROT)); /* Compiled as a function; force source filename. */ duk_push_string(ctx, MANDELBROT); duk_push_string(ctx, "mandel.js"); duk_compile(ctx, DUK_COMPILE_FUNCTION); duk_dump_function(ctx); p = (unsigned char *) duk_get_buffer(ctx, -1, &sz); for (i = 0; i < sz; i++) { printf("%02x", (int) p[i]); } printf("\n"); fflush(stdout); /* Load test function from dump and execute it. */ duk_load_function(ctx); duk_call(ctx, 0); printf("call result: %s\n", duk_safe_to_string(ctx, -1)); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t duk__console_log_helper(duk_context *ctx, const char *error_name) { duk_idx_t i, n; n = duk_get_top(ctx); duk_get_global_string(ctx, "console"); duk_get_prop_string(ctx, -1, "format"); for (i = 0; i < n; i++) { if (duk_check_type_mask(ctx, i, DUK_TYPE_MASK_OBJECT)) { /* Slow path formatting. */ duk_dup(ctx, -1); /* console.format */ duk_dup(ctx, i); duk_call(ctx, 1); duk_replace(ctx, i); /* arg[i] = console.format(arg[i]); */ } } duk_pop_2(ctx); duk_push_string(ctx, " "); duk_insert(ctx, 0); duk_join(ctx, n); if (error_name) { duk_push_error_object(ctx, DUK_ERR_ERROR, "%s", duk_require_string(ctx, -1)); duk_push_string(ctx, "name"); duk_push_string(ctx, error_name); duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_VALUE); /* to get e.g. 'Trace: 1 2 3' */ duk_get_prop_string(ctx, -1, "stack"); } printf("%s\n", duk_to_string(ctx, -1)); return 0; }
static duk_ret_t test_modsearch_module(duk_context *ignored_ctx, void *udata) { duk_context *ctx; (void) udata; ctx = duk_create_heap_default(); if (!ctx) { printf("Failed to create heap\n"); return 0; } /* Dummy print() binding. */ duk_push_c_function(ctx, my_print, 1); duk_put_global_string(ctx, "print"); /* Register Duktape.modSearch. */ duk_eval_string(ctx, "(function (fun) { Duktape.modSearch = fun; })"); duk_push_c_function(ctx, my_modsearch, 4 /*nargs*/); duk_call(ctx, 1); duk_pop(ctx); /* Require test. */ duk_eval_string_noresult(ctx, "var mod = require('my_module'); print(mod.FLAG_FOO); mod.func1();"); printf("final top: %ld\n", (long) duk_get_top(ctx)); duk_destroy_heap(ctx); return 0; }
void _gum_duk_create_subclass (duk_context * ctx, const gchar * parent, const gchar * name, duk_c_function constructor, gint constructor_nargs, duk_c_function finalize) { duk_push_global_object (ctx); duk_get_prop_string (ctx, -1, "Object"); duk_get_prop_string (ctx, -1, "create"); duk_get_prop_string (ctx, -3, parent); duk_get_prop_string (ctx, -1, "prototype"); duk_dup (ctx, -3); duk_dup (ctx, -2); duk_call (ctx, 1); if (constructor != NULL) duk_push_c_function (ctx, constructor, constructor_nargs); else duk_push_object (ctx); duk_dup (ctx, -2); if (finalize != NULL) { duk_push_c_function (ctx, finalize, 2); duk_set_finalizer (ctx, -2); } duk_put_prop_string (ctx, -2, "prototype"); duk_put_prop_string (ctx, -7, name); duk_pop_n (ctx, 6); }
// Assumes nargs are the top of the stack. Rest comes from request // Return value is not left on the stack. void duv_resolve(uv_req_t* req, int nargs) { duk_context *ctx = req->data; duv_push_handle(ctx, req); // stack: args... obj duk_get_prop_string(ctx, -1, "\xff""uv-callback"); // stack: args... obj callback duk_del_prop_string(ctx, -2, "\xff""uv-callback"); // stack: args... obj callback if (!duk_is_function(ctx, -1)) { // stack: args... obj callback duk_pop_n(ctx, 2 + nargs); return; } duk_remove(ctx, -2); // stack: args... callback duk_insert(ctx, -(nargs + 1)); // stack: callback args... duk_call(ctx, nargs); // stack: result duk_pop(ctx); // Remove the request from the GC roots duv_remove_handle(ctx, req); }
static duk_ret_t test_1(duk_context *ctx, void *udata) { (void) udata; duk_eval_string(ctx, "(function (x) { print(Duktape.enc('jx', x)); })"); duk_push_object(ctx); /* Ordinary property */ duk_push_int(ctx, 1); duk_put_prop_string(ctx, -2, "foo"); /* obj.foo = 1 */ /* Internal property \xFF\xFFabc, technically enumerable (based on * property attributes) but because of internal property special * behavior, does not enumerate. */ duk_push_int(ctx, 2); duk_put_prop_string(ctx, -2, "\xff\xff" "abc"); /* obj[\xff\xffabc] = 2, internal property */ /* Another property with invalid UTF-8 data but doesn't begin with * \xFF => gets enumerated and JX prints out an approximate key. */ duk_push_int(ctx, 3); duk_put_prop_string(ctx, -2, " \xff" "bar"); /* obj[ \xffbar] = 3, invalid utf-8 but not an internal property */ duk_call(ctx, 1); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_basic(duk_context *ctx, void *udata) { (void) udata; duk_push_c_function(ctx, dummy_func, 1); duk_push_string(ctx, "length"); duk_push_int(ctx, 3); duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_CLEAR_WRITABLE | DUK_DEFPROP_CLEAR_ENUMERABLE | DUK_DEFPROP_SET_CONFIGURABLE); printf("added own .length\n"); duk_eval_string(ctx, "(function (fn) {\n" " print(typeof fn);\n" " var desc = Object.getOwnPropertyDescriptor(fn, 'length');\n" " print(desc.writable);\n" " print(desc.enumerable);\n" " print(desc.configurable);\n" " print(desc.value);\n" "})"); duk_dup(ctx, -2); duk_call(ctx, 1); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_ecma_call_success(duk_context *ctx) { duk_idx_t i; /* Ensure stack space for a lot of elements. */ duk_require_stack(ctx, STACK_REQUIRE + 1); /* Make a function call. Call handling resizes the value stack * back and forth. At the end, the value stack guaranteed size * must include the STACK_REQUIRE checked above. */ duk_eval_string(ctx, "(function () { print('hello from ecma func'); return 123 })"); duk_call(ctx, 0 /*nargs*/); printf("duk_call: %s\n", duk_safe_to_string(ctx, -1)); /* It would be quite awkward for user code to have no stack * guarantees at this point, i.e. require the user code to * call duk_require_stack(ctx, STACK_REQUIRE) again here. */ for (i = 0; i < STACK_REQUIRE; i++) { duk_push_int(ctx, 123); } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
DUK_LOCAL duk_ret_t duk__finalize_helper(duk_context *ctx, void *udata) { duk_hthread *thr; DUK_ASSERT(ctx != NULL); thr = (duk_hthread *) ctx; DUK_UNREF(udata); DUK_DDD(DUK_DDDPRINT("protected finalization helper running")); /* [... obj] */ /* XXX: Finalizer lookup should traverse the prototype chain (to allow * inherited finalizers) but should not invoke accessors or proxy object * behavior. At the moment this lookup will invoke proxy behavior, so * caller must ensure that this function is not called if the target is * a Proxy. */ duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_FINALIZER); /* -> [... obj finalizer] */ if (!duk_is_callable(ctx, -1)) { DUK_DDD(DUK_DDDPRINT("-> no finalizer or finalizer not callable")); return 0; } duk_dup_m2(ctx); duk_push_boolean(ctx, DUK_HEAP_HAS_FINALIZER_NORESCUE(thr->heap)); DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling finalizer")); duk_call(ctx, 2); /* [ ... obj finalizer obj heapDestruct ] -> [ ... obj retval ] */ DUK_DDD(DUK_DDDPRINT("finalizer finished successfully")); return 0; /* Note: we rely on duk_safe_call() to fix up the stack for the caller, * so we don't need to pop stuff here. There is no return value; * caller determines rescued status based on object refcount. */ }
static duk_ret_t test_1(duk_context *ctx, void *udata) { (void) udata; /* Lightfunc, must sanitize the address for the expect string. */ duk_eval_string(ctx, "(function (v) {\n" " print(String(v).replace(/light_[0-9a-fA-f_]+/, 'light_PTR'));\n" "})"); duk_push_c_lightfunc(ctx, dummy_func, 0 /*nargs*/, 0 /*length*/, 0 /*magic*/); duk_call(ctx, 1); duk_pop(ctx); /* Function with a .name containing invalid characters. * * This is not currently handled very well: the .toString() output * uses the name as is, which can make the output technically * incorrect because it won't parse as a function. However, the * only way to create such functions is from C code so this is a * minor issue. */ duk_push_c_function(ctx, dummy_func, 0 /*nargs*/); duk_push_string(ctx, "name"); duk_push_string(ctx, "dummy {"); duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_FORCE); printf("%s\n", duk_to_string(ctx, -1)); duk_pop(ctx); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* Basic dump/load test which exercises all constant types and has an inner * function. Hex dumping the bytecode provides an exact test case dependency * to the dump format so that any accidental changes break the test. */ static duk_ret_t test_basic(duk_context *ctx) { unsigned char *p; duk_size_t i, sz; /* Integer constants generate LDINT now so also use a fractional * constant to exercise number constants. * * Compiled as a program; force source filename. */ duk_push_string(ctx, "print('hello', (function adder(x,y) { return x+y; })(1, 2), 3.14);"); duk_push_string(ctx, "fakeFilename.js"); duk_compile(ctx, 0); duk_dump_function(ctx); printf("dump result type: %d\n", (int) duk_get_type(ctx, -1)); fflush(stdout); p = (unsigned char *) duk_get_buffer(ctx, -1, &sz); for (i = 0; i < sz; i++) { printf("%02x", (int) p[i]); } printf("\n"); fflush(stdout); /* Load test function from dump and execute it. */ duk_load_function(ctx); printf("load result type: %d\n", (int) duk_get_type(ctx, -1)); fflush(stdout); duk_call(ctx, 0); printf("call result type: %d\n", (int) duk_get_type(ctx, -1)); fflush(stdout); printf("call result: %s\n", duk_safe_to_string(ctx, -1)); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t deep_helper_2(duk_context *ctx) { duk_push_string(ctx, "(function () {\n" " var fn = function noFileName(n, v) { if (n > 0) { noFileName(n - 1, v); } else { v(); } return 123; };\n" " print('delete: ' + delete fn.fileName);\n" " return fn;\n" "})()"); duk_push_string(ctx, "dummy_filename.js"); duk_compile(ctx, DUK_COMPILE_EVAL); duk_call(ctx, 0); printf("target depth: %d\n", (int) depth_hack); duk_push_int(ctx, depth_hack - 3); /* account for: one func already in callstack; first call into the helper; final call to target */ duk_push_c_function(ctx, target_func_hack, 0); duk_call(ctx, 2); return 0; }
static void setup_arraybuffer(duk_context *ctx, duk_idx_t idx) { idx = duk_require_normalize_index(ctx, idx); duk_eval_string(ctx, "(function (plain_buffer) {\n" " return new ArrayBuffer(plain_buffer);\n" "})\n"); duk_dup(ctx, idx); duk_call(ctx, 1); }
static void dump_prop(duk_context *ctx) { duk_eval_string(ctx, "(function (obj) {\n" " print(Duktape.enc('jx', Object.getOwnPropertyDescriptor(obj, 'prop')));\n" "})"); duk_dup(ctx, -2); duk_call(ctx, 1); duk_pop(ctx); }
static duk_ret_t havefile2_helper_2(duk_context *ctx) { duk_push_string(ctx, "(function () {\n" " var fn = function noFileName(v) { v(); return 123; };\n" " print('delete: ' + delete fn.fileName);\n" " return fn;\n" "})()"); duk_push_string(ctx, "dummy_filename.js"); duk_compile(ctx, DUK_COMPILE_EVAL); duk_call(ctx, 0); duk_push_c_function(ctx, target_func_hack, 0); duk_push_string(ctx, "fileName"); duk_push_string(ctx, "dummy_filename.c"); duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_WRITABLE | DUK_DEFPROP_SET_CONFIGURABLE); duk_call(ctx, 1); return 0; }
static duk_ret_t test_instanceof(duk_context *ctx, void *udata) { (void) udata; prep(ctx); /* For 'a instanceof b', the [[HasInstance]] algorithm looks up * b.prototype and then walks the internal prototype chain of 'a' * looking for b.prototype. The rvalue must also be a Function. * So we need a temporary object wrapping one of the objects * created by prep(). */ /* obj0 instanceof { prototype: obj0 } -> true, found */ duk_eval_string(ctx, "(function (a,b) { print(typeof a, typeof b); print(a instanceof b); })"); duk_dup(ctx, 0); duk_eval_string(ctx, "(function() {})"); duk_dup(ctx, 0); duk_put_prop_string(ctx, -2, "prototype"); duk_call(ctx, 2); duk_pop(ctx); /* obj0 instanceof { prototype: obj1 } -> true, found */ duk_eval_string(ctx, "(function (a,b) { print(typeof a, typeof b); print(a instanceof b); })"); duk_dup(ctx, 0); duk_eval_string(ctx, "(function() {})"); duk_dup(ctx, 0); duk_put_prop_string(ctx, -2, "prototype"); duk_call(ctx, 2); duk_pop(ctx); /* obj0 instanceof { prototype: dummy } -> error, loop */ duk_eval_string(ctx, "(function (a,b) { print(typeof a, typeof b); print(a instanceof b); })"); duk_dup(ctx, 0); duk_eval_string(ctx, "(function() {})"); duk_push_object(ctx); duk_put_prop_string(ctx, -2, "prototype"); duk_call(ctx, 2); duk_pop(ctx); return 0; }
static void setup_typedarray(duk_context *ctx, duk_idx_t idx, const char *name) { idx = duk_require_normalize_index(ctx, idx); duk_push_sprintf(ctx, "(function (plain_buffer) {\n" " return new %s(new ArrayBuffer(plain_buffer));\n" "})\n", name); duk_eval(ctx); duk_dup(ctx, idx); duk_call(ctx, 1); }
static void shared_read_write_index(duk_context *ctx, duk_size_t resize_to) { /* [ plain_buffer buffer ] */ duk_eval_string(ctx, "(function (buf) {\n" " print('length', buf.length);\n" " print(buf[0] = 1);\n" " print(buf[99] = 2);\n" " print(buf[100] = 3);\n" /* outside 'limit', not virtual -> becomes concrete property */ " print(0, buf[0]);\n" /* in buffer */ " print(99, buf[99]);\n" /* in buffer */ " print(100, buf[100]);\n" /* outside duk_hbufferobject 'limit', not virtual */ "})\n"); duk_dup(ctx, 1); duk_call(ctx, 1); duk_pop(ctx); /* Resize to fewer number of bytes. */ duk_resize_buffer(ctx, 0, resize_to); /* Reads inside the duk_hbufferobject limit but outside the underlying * buffer return zero; writes are ignored. */ duk_eval_string(ctx, "(function (buf) {\n" " print('length', buf.length);\n" " print(buf[0] = 10);\n" " print(buf[94] = 11);\n" " print(buf[95] = 12);\n" " print(buf[99] = 13);\n" " print(buf[100] = 14);\n" " print(0, buf[0]);\n" /* in buffer */ " print(94, buf[94]);\n" /* in buffer */ " print(95, buf[95]);\n" /* inside duk_hbufferobject 'limit', but outside buffer */ " print(99, buf[99]);\n" /* inside duk_hbufferobject 'limit', but outside buffer */ " print(100, buf[100]);\n" /* outside duk_hbufferobject 'limit', not virtual */ "})\n"); duk_dup(ctx, 1); duk_call(ctx, 1); duk_pop(ctx); }
static duk_ret_t test_1(duk_context *ctx, void *udata) { (void) udata; duk_eval_string_noresult(ctx, "this.myFinalizer = function myfin(o) {\n" " print('finalizer, rescuing object', JSON.stringify(o));\n" " var global = new Function('return this')();\n" " global.rescued = o;\n" "}\n" ); /* First call; object gets finalized when call returns and call * handling does a duk_set_top() call. The object is rescued and * later reused. */ duk_push_c_function(ctx, my_func, 3 /*nargs*/); duk_push_null(ctx); duk_eval_string(ctx, "(function () {\n" " var res = { name: 'my object' };\n" " Duktape.fin(res, myFinalizer);\n" " return res;\n" "})()\n"); duk_push_null(ctx); printf("calling\n"); duk_call(ctx, 3); printf("returned\n"); duk_pop(ctx); /* Object is reused for another call, and rescued again. */ duk_push_c_function(ctx, my_func, 3 /*nargs*/); duk_push_null(ctx); duk_eval_string(ctx, "rescued"); duk_eval_string_noresult(ctx, "rescued = null;"); duk_push_null(ctx); printf("calling\n"); duk_call(ctx, 3); printf("returned\n"); duk_pop(ctx); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t my_thrower_1(duk_context *ctx) { /* When an error is thrown during compilation, the source file/line * is always blamed. */ duk_push_string(ctx, "\n\n\nfoo="); duk_push_string(ctx, "dummy_source.js"); duk_compile(ctx, DUK_COMPILE_EVAL); duk_call(ctx, 0); return 0; }
void test(duk_context *ctx) { duk_int_t rc; /* From API doc */ duk_push_string(ctx, "print('Hello world!'); 123;"); duk_eval(ctx); printf("return value is: %lf\n", duk_get_number(ctx, -1)); duk_pop(ctx); /* Function expression */ duk_push_string(ctx, "(function adder(x,y) { return x+y; })"); duk_eval(ctx); /* [ func ] */ duk_push_int(ctx, 123); duk_push_int(ctx, 234); duk_call(ctx, 2); /* [ func 123 234 ] -> [ result ] */ printf("adder(123, 234) -> %lf\n", duk_get_number(ctx, -1)); duk_pop(ctx); /* Protected eval with success */ duk_push_string(ctx, "print('Hello world!'); 123;"); rc = duk_peval(ctx); printf("return value is: %s (rc=%d)\n", duk_safe_to_string(ctx, -1), (int) rc); duk_pop(ctx); /* Protected eval with failure */ duk_push_string(ctx, "throw new Error('eval error');"); rc = duk_peval(ctx); printf("return value is: %s (rc=%d)\n", duk_safe_to_string(ctx, -1), (int) rc); duk_pop(ctx); /* Protected eval with syntax error */ duk_push_string(ctx, "obj = {"); rc = duk_peval(ctx); printf("return value is: %s (rc=%d)\n", duk_safe_to_string(ctx, -1), (int) rc); duk_pop(ctx); /* Plain eval with no result */ printf("top=%ld\n", (long) duk_get_top(ctx)); duk_push_string(ctx, "print('doing eval');"); duk_eval_noresult(ctx); /* Protected eval with no result, no error */ printf("top=%ld\n", (long) duk_get_top(ctx)); duk_push_string(ctx, "print('doing peval');"); rc = duk_peval_noresult(ctx); printf("rc=%d\n", (int) rc); /* Protected eval with no result, syntax error */ printf("top=%ld\n", (long) duk_get_top(ctx)); duk_push_string(ctx, "print('doing peval'); obj = {"); rc = duk_peval_noresult(ctx); printf("rc=%d\n", (int) rc); printf("top: %ld\n", (long) duk_get_top(ctx)); }