DUK_EXTERNAL sjs_vm_t* sjs_vm_create(void) { sjs_vm_t* vm; vm = calloc(1, sizeof(*vm)); assert(vm); vm->ctx = duk_create_heap(NULL, /* alloc function */ NULL, /* realloc function */ NULL, /* free function */ NULL, /* user data */ sjs__duk_fatal_handler /* fatal error handler */ ); assert(vm->ctx != NULL); /* setup builtin modules */ sjs__setup_system_module(vm); sjs__setup_global_module(vm); sjs__setup_modsearch(vm); /* setup es6 shim */ duk_eval_string_noresult(vm->ctx, (char*) sjs__es6shim_src); /* run bootstrap code */ duk_eval_string_noresult(vm->ctx, SJS__BOOTSTRAP_CODE); return vm; }
/* 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; }
void test(duk_context *ctx) { duk_idx_t arr_idx; duk_push_int(ctx, 123); /* dummy */ arr_idx = duk_push_bare_array(ctx); printf("arr_idx = %ld\n", (long) arr_idx); duk_get_prototype(ctx, -1); printf("prototype is undefined: %ld\n", (long) duk_is_undefined(ctx, -1)); duk_pop(ctx); duk_push_string(ctx, "foo"); duk_put_prop_index(ctx, arr_idx, 0); duk_push_string(ctx, "bar"); duk_put_prop_index(ctx, arr_idx, 1); /* Array is now: [ "foo", "bar" ], and array.length is 2 (automatically * updated for ECMAScript arrays). The array being bare does not affect * JSON serialization. */ printf("duk_is_array(%ld) = %d\n", (long) arr_idx, (int) duk_is_array(ctx, arr_idx)); duk_eval_string_noresult(ctx, "Array.prototype[5] = 'inherit';"); (void) duk_get_prop_index(ctx, arr_idx, 5); printf("arr[5] = '%s'\n", duk_to_string(ctx, -1)); duk_pop(ctx); duk_json_encode(ctx, arr_idx); /* in-place */ printf("json encoded: %s\n", duk_get_string(ctx, arr_idx)); printf("top=%ld\n", (long) duk_get_top(ctx)); }
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; }
/* Thread with shared and fresh globals. */ static duk_ret_t test_2(duk_context *ctx, void *udata) { duk_context *ctx_a; duk_context *ctx_b; (void) udata; duk_eval_string_noresult(ctx, "this.globalFoo = 'bar';"); duk_push_thread(ctx); ctx_a = duk_require_context(ctx, -1); duk_push_thread_new_globalenv(ctx); ctx_b = duk_require_context(ctx, -1); printf("top: %ld\n", (long) duk_get_top(ctx)); /* Dummy print() binding. */ duk_push_c_function(ctx_b, my_print, 1); duk_put_global_string(ctx_b, "print"); /* index 0: thread with globals shared with 'ctx' (has globalFoo) * index 1: thread with globals separate with 'ctx' */ /* Print globalFoo. */ duk_peval_string_noresult(ctx_a, "print('context a: ' + String(this.globalFoo));"); duk_peval_string_noresult(ctx_b, "print('context b: ' + String(this.globalFoo));"); return 0; }
static duk_ret_t test_2(duk_context *ctx, void *udata) { duk_time_components comp; duk_double_t t; (void) udata; /* ECMAScript components-to-time (UTC): * * - Year argument has a hack for two-digit years (e.g. Date.UTC(99, ...) * creates a time value for year 1999. * - Month argument is zero-based. * - Day-of-month argument is one-based. * - Values are normalized automatically, so e.g. specifying * minutes as 120 is interpreted as 2 hours etc. */ duk_eval_string_noresult(ctx, "(function () {\n" " var d = new Date(Date.UTC(2016, 0, 2, 3, 4, 5, 6));\n" /* 2016-01-02 03:04:05.006Z */ " print(d.valueOf())\n" " d = new Date(Date.UTC(2016, 0, 2, 3, 0, 4 * 60 + 5, 6));\n" /* 2016-01-02 03:04:05.006Z */ " print(d.valueOf())\n" "})();"); /* C API equivalent; note that: * * - No special handling for two-digit years. */ memset((void *) &comp, 0, sizeof(comp)); comp.year = 2016; comp.month = 0; comp.day = 2; comp.hours = 3; comp.minutes = 4; comp.seconds = 5; comp.milliseconds = 6.0; comp.weekday = 0; /* ignored */ t = duk_components_to_time(ctx, &comp); printf("time: %lf\n", t); memset((void *) &comp, 0, sizeof(comp)); comp.year = 2016; comp.month = 0; comp.day = 2; comp.hours = 3; comp.minutes = 0; comp.seconds = 4 * 60 + 5; /* wrapping: 4 minutes, 5 seconds */ comp.milliseconds = 6.0; comp.weekday = 0; /* ignored */ t = duk_components_to_time(ctx, &comp); printf("time: %lf\n", t); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
void test(duk_context *ctx) { /* For manual testing: */ #if 0 duk_eval_string_noresult(ctx, "this.PRINT_STACK = true;"); #else duk_eval_string_noresult(ctx, "this.PRINT_STACK = false;"); #endif TEST_SAFE_CALL(test_empty_1); TEST_SAFE_CALL(test_empty_2); TEST_SAFE_CALL(test_empty_3); TEST_SAFE_CALL(test_empty_4); TEST_SAFE_CALL(test_nofile_1); TEST_SAFE_CALL(test_nofile_2); TEST_SAFE_CALL(test_nofile_3); TEST_SAFE_CALL(test_nofile_4); TEST_SAFE_CALL(test_havefile1_1); TEST_SAFE_CALL(test_havefile1_2); TEST_SAFE_CALL(test_havefile1_3); TEST_SAFE_CALL(test_havefile1_4); TEST_SAFE_CALL(test_havefile2_1); TEST_SAFE_CALL(test_havefile2_2); TEST_SAFE_CALL(test_havefile2_3); TEST_SAFE_CALL(test_havefile2_4); TEST_SAFE_CALL(test_deep_1a); TEST_SAFE_CALL(test_deep_1b); TEST_SAFE_CALL(test_deep_1c); TEST_SAFE_CALL(test_deep_1d); TEST_SAFE_CALL(test_deep_2a); TEST_SAFE_CALL(test_deep_2b); TEST_SAFE_CALL(test_deep_2c); TEST_SAFE_CALL(test_deep_2d); TEST_SAFE_CALL(test_deep_3a); TEST_SAFE_CALL(test_deep_3b); TEST_SAFE_CALL(test_deep_3c); TEST_SAFE_CALL(test_deep_3d); TEST_SAFE_CALL(test_deep_4a); TEST_SAFE_CALL(test_deep_4b); TEST_SAFE_CALL(test_deep_4c); TEST_SAFE_CALL(test_deep_4d); }
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 test_nonwritable(duk_context *ctx, void *udata) { duk_bool_t ret; (void) udata; duk_eval_string_noresult(ctx, "Object.defineProperty(this, 'nonWritable', " "{ value: 'foo', writable: false, enumerable: false, configurable: false });" ); printf("top: %ld\n", (long) duk_get_top(ctx)); duk_push_string(ctx, "bar"); ret = duk_put_global_string(ctx, "nonWritable"); printf("top: %ld\n", (long) duk_get_top(ctx)); printf("ret: %ld\n", (long) ret); duk_eval_string_noresult(ctx, "print(nonWritable);"); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_1(duk_context *ctx, void *udata) { (void) udata; duk_push_global_object(ctx); duk_push_c_function(ctx, my_print, DUK_VARARGS); duk_put_prop_string(ctx, -2, "print"); duk_pop(ctx); duk_eval_string_noresult(ctx, "print('foo', 'bar');"); return 0; }
void test(duk_context *ctx) { duk_eval_string(ctx, "1+2"); printf("1+2=%d\n", (int) duk_get_int(ctx, -1)); duk_pop(ctx); duk_push_c_function(ctx, native_print, 1); duk_put_global_string(ctx, "print"); duk_push_c_function(ctx, native_adder, DUK_VARARGS); duk_put_global_string(ctx, "adder"); duk_eval_string_noresult(ctx, "print('2+3=' + adder(2, 3));"); }
static duk_ret_t test_2_inner(duk_context *ctx) { /* Eval happens inside a Duktape/C activation, so we're currently in * in strict mode. In Duktape 0.11.0 and prior, the 'foo2' declaration * would go into a temporary lexical environment and would not be visible * in the global object. The code can still read (and write) properties * of the global object. */ printf("context is strict: %d\n", duk_is_strict_call(ctx)); duk_eval_string_noresult(ctx, "print('test_2 evalcode, typeof Math:', typeof Math); var foo2 = 'bar';"); return 0; }
static duk_ret_t test_1(duk_context *ctx, void *udata) { (void) udata; /* Check that Function.prototype.name is writable. */ duk_eval_string_noresult(ctx, "var pd = Object.getOwnPropertyDescriptor(Function.prototype, 'name');\n" "print('writable:', pd.writable);\n" "print('enumerable:', pd.enumerable);\n" "print('configurable:', pd.configurable);\n"); duk_push_c_function(ctx, my_func, 0); duk_push_string(ctx, "name"); duk_push_string(ctx, "my_func_name"); duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE); duk_put_global_string(ctx, "MyFunc"); duk_eval_string_noresult(ctx, "print('MyFunc.name:', MyFunc.name);\n"); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
void duk_console_init(duk_context *ctx, duk_uint_t flags) { duk_push_object(ctx); /* Custom function to format objects; user can replace. * For now, try JX-formatting and if that fails, fall back * to ToString(v). */ duk_eval_string(ctx, "(function format(v){" "try{" "return Duktape.enc('jx',v);" "}catch(e){" "return ""+v;" "}" "})"); duk_put_prop_string(ctx, -2, "format"); duk__console_reg_vararg_func(ctx, duk__console_assert, "assert"); duk__console_reg_vararg_func(ctx, duk__console_log, "log"); duk__console_reg_vararg_func(ctx, duk__console_log, "debug"); /* alias to console.log */ duk__console_reg_vararg_func(ctx, duk__console_trace, "trace"); duk__console_reg_vararg_func(ctx, duk__console_info, "info"); duk__console_reg_vararg_func(ctx, duk__console_warn, "warn"); duk__console_reg_vararg_func(ctx, duk__console_error, "error"); duk__console_reg_vararg_func(ctx, duk__console_error, "exception"); /* alias to console.error */ duk__console_reg_vararg_func(ctx, duk__console_dir, "dir"); duk_put_global_string(ctx, "console"); /* Proxy wrapping: ensures any undefined console method calls are * ignored silently. This is required specifically by the * DeveloperToolsWG proposal (and is implemented also by Firefox: * https://bugzilla.mozilla.org/show_bug.cgi?id=629607). */ if (flags & DUK_CONSOLE_PROXY_WRAPPER) { duk_eval_string_noresult(ctx, "(function(){" "var D=function(){};" "console=new Proxy(console,{" "get:function(t,k){" "var v=t[k];" "return typeof v==='function'?v:D;" "}" "});" "})();" ); } }
static duk_ret_t test_1(duk_context *ctx, void *udata) { (void) udata; duk_eval_string(ctx, "new Proxy(this, {\n" " get: function (targ, key, recv) { print('GET', key); if (key in targ) { return targ[key]; } else { return 'replaced'; } },\n" " has: function (targ, key) { print('HAS', key); return true; }\n" "})"); duk_set_global_object(ctx); duk_get_global_string(ctx, "Math"); printf("%s\n", duk_safe_to_string(ctx, -1)); duk_pop(ctx); duk_get_global_string(ctx, "nonExistent"); printf("%s\n", duk_safe_to_string(ctx, -1)); duk_pop(ctx); duk_eval_string_noresult(ctx, "print(typeof Math);"); duk_eval_string_noresult(ctx, "print(typeof nonExistent);"); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_basic(duk_context *ctx, void *udata) { duk_bool_t ret; (void) udata; printf("top: %ld\n", (long) duk_get_top(ctx)); duk_push_string(ctx, "1.2.3"); ret = duk_put_global_string(ctx, "myAppVersion" "\x00" "ignored"); printf("top: %ld\n", (long) duk_get_top(ctx)); printf("ret: %ld\n", (long) ret); duk_eval_string_noresult(ctx, "print(myAppVersion);"); printf("top: %ld\n", (long) duk_get_top(ctx)); duk_push_string(ctx, "nulval"); ret = duk_put_global_lstring(ctx, "nul" "\x00" "keyx", 7); printf("top: %ld\n", (long) duk_get_top(ctx)); printf("ret: %ld\n", (long) ret); duk_eval_string_noresult(ctx, "print(new Function('return this')()['nul\\u0000key']);"); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_basic(duk_context *ctx, void *udata) { duk_bool_t ret; (void) udata; printf("top: %ld\n", (long) duk_get_top(ctx)); duk_push_string(ctx, "1.2.3"); ret = duk_put_global_string(ctx, "myAppVersion"); printf("top: %ld\n", (long) duk_get_top(ctx)); printf("ret: %ld\n", (long) ret); duk_eval_string_noresult(ctx, "print(myAppVersion);"); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_1(duk_context *ctx) { const char *str; /* Eval happens outside of a Duktape/C activation. The eval code was * executed in non-strict mode also in Duktape 0.11.0 and prior. */ printf("context is strict: %d\n", duk_is_strict_call(ctx)); duk_eval_string_noresult(ctx, "print('test_1 evalcode, typeof Math:', typeof Math); var foo1 = 'bar';"); duk_push_global_object(ctx); duk_get_prop_string(ctx, -1, "foo1"); str = duk_get_string(ctx, -1); printf("global.foo1=%s\n", str ? str : "NULL"); duk_pop_2(ctx); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_use_module(duk_context *ignored_ctx) { duk_context *ctx; ctx = duk_create_heap_default(); if (!ctx) { printf("Failed to create heap\n"); return 0; } duk_push_c_function(ctx, dukopen_my_module, 0); duk_call(ctx, 0); duk_put_global_string(ctx, "my_module"); duk_eval_string_noresult(ctx, "my_module.func2()"); printf("final top: %ld\n", (long) duk_get_top(ctx)); duk_destroy_heap(ctx); return 0; }
static duk_ret_t test_1(duk_context *ctx, void *udata) { duk_time_components comp; (void) udata; /* ECMAScript time-to-components (UTC): * * - d.getUTCMonth() is zero-based. * - d.getUTCDate() (day in month) is one-based. * - d.getUTCDay() (weekday) is zero-based. */ duk_eval_string_noresult(ctx, "(function () {\n" " var d = new Date(1451703845006);\n" /* 2016-01-02 03:04:05.006Z */ " print(d.valueOf());\n" " print('year', d.getUTCFullYear());\n" " print('month', d.getUTCMonth());\n" " print('day', d.getUTCDate());\n" " print('hours', d.getUTCHours());\n" " print('minutes', d.getUTCMinutes());\n" " print('seconds', d.getUTCSeconds());\n" " print('milliseconds', d.getUTCMilliseconds());\n" " print('weekday', d.getUTCDay());\n" "})();"); /* C API equivalent. */ duk_time_to_components(ctx, 1451703845006.0, &comp); printf("year: %d\n", (int) comp.year); printf("month: %d\n", (int) comp.month); printf("day: %d\n", (int) comp.day); printf("hours: %d\n", (int) comp.hours); printf("minutes: %d\n", (int) comp.minutes); printf("seconds: %d\n", (int) comp.seconds); printf("milliseconds: %lf\n", (double) comp.milliseconds); printf("weekday: %d\n", (int) comp.weekday); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* Self-references for a function established through a function declaration * is unfortunately not automatically supported. The self-reference generates * bytecode that performs a slow path GETVAR for the function name; the GETVAR * normally gets satisfied by looking it up from the global object. But if * we dump/load the function, only the function object is resurrected while the * global binding is not. */ static duk_ret_t test_name_binding_funcdecl(duk_context *ctx) { duk_compile_string(ctx, 0 /*flags: program*/, "function declaredTest() {\n" " print('i am a ' + typeof declaredTest);\n" "}"); duk_call(ctx, 0); duk_pop(ctx); duk_get_global_string(ctx, "declaredTest"); duk_dump_function(ctx); duk_eval_string_noresult(ctx, "declaredTest = 123;"); /* lose original */ duk_load_function(ctx); duk_call(ctx, 0); /* Because the declaredTest binding itself is not resurrected (only * the function itself is), the "typeof declaredTest" will refer to * the fake "declaredTest = 123" value, i.e. a number. */ printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static void register_dump_buffer_info(duk_context *ctx) { duk_eval_string_noresult(ctx, "function dumpBufferInfo (v) {\n" " var p = Object.getPrototypeOf(v);\n" " var instof = [];\n" " var prot = [];\n" " if (v instanceof Buffer) { instof.push('Buffer'); }\n" " if (v instanceof ArrayBuffer) { instof.push('ArrayBuffer'); }\n" " if (v instanceof DataView) { instof.push('DataView'); }\n" " if (v instanceof Int8Array) { instof.push('Int8Array'); }\n" " if (v instanceof Uint8Array) { instof.push('Uint8Array'); }\n" " if (v instanceof Uint8ClampedArray) { instof.push('Uint8ClampedArray'); }\n" " if (v instanceof Int16Array) { instof.push('Int16Array'); }\n" " if (v instanceof Uint16Array) { instof.push('Uint16Array'); }\n" " if (v instanceof Int32Array) { instof.push('Int32Array'); }\n" " if (v instanceof Uint32Array) { instof.push('Uint32Array'); }\n" " if (v instanceof Float32Array) { instof.push('Float32Array'); }\n" " if (v instanceof Float64Array) { instof.push('Float64Array'); }\n" " if (p === Buffer.prototype) { prot.push('Buffer.prototype'); }\n" " if (p === ArrayBuffer.prototype) { prot.push('ArrayBuffer.prototype'); }\n" " if (p === DataView.prototype) { prot.push('DataView.prototype'); }\n" " if (p === Int8Array.prototype) { prot.push('Int8Array.prototype'); }\n" " if (p === Uint8Array.prototype) { prot.push('Uint8Array.prototype'); }\n" " if (p === Uint8ClampedArray.prototype) { prot.push('Uint8ClampedArray.prototype'); }\n" " if (p === Int16Array.prototype) { prot.push('Int16Array.prototype'); }\n" " if (p === Uint16Array.prototype) { prot.push('Uint16Array.prototype'); }\n" " if (p === Int32Array.prototype) { prot.push('Int32Array.prototype'); }\n" " if (p === Uint32Array.prototype) { prot.push('Uint32Array.prototype'); }\n" " if (p === Float32Array.prototype) { prot.push('Float32Array.prototype'); }\n" " if (p === Float64Array.prototype) { prot.push('Float64Array.prototype'); }\n" " print(typeof v, Object.prototype.toString.call(v), v.length, v.byteOffset, v.byteLength, v.BYTES_PER_ELEMENT, typeof v.buffer);\n" " print(v instanceof Buffer, v instanceof ArrayBuffer, v instanceof DataView, v instanceof Int8Array, v instanceof Uint8Array, v instanceof Uint8ClampedArray, v instanceof Int16Array, v instanceof Uint16Array, v instanceof Int32Array, v instanceof Uint32Array, v instanceof Float32Array, v instanceof Float64Array, '->', instof.join(','));\n" " print(p === Buffer.prototype, p === ArrayBuffer.prototype, p === DataView.prototype, p === Int8Array.prototype, p === Uint8Array.prototype, p === Uint8ClampedArray.prototype, p === Int16Array.prototype, p === Uint16Array.prototype, p === Int32Array.prototype, p === Uint32Array.prototype, p === Float32Array.prototype, p === Float64Array.prototype, '->', prot.join(','));\n" "}"); }
/* Thread with shared and fresh globals. */ static int test_2(duk_context *ctx) { duk_context *ctx_a; duk_context *ctx_b; duk_eval_string_noresult(ctx, "this.globalFoo = 'bar';"); duk_push_thread(ctx); ctx_a = duk_require_context(ctx, -1); duk_push_thread_new_globalenv(ctx); ctx_b = duk_require_context(ctx, -1); printf("top: %d\n", duk_get_top(ctx)); /* index 0: thread with globals shared with 'ctx' (has globalFoo) * index 1: thread with globals separate with 'ctx' */ /* Print globalFoo. */ duk_peval_string_noresult(ctx_a, "print('context a: ' + String(this.globalFoo));"); duk_peval_string_noresult(ctx_b, "print('context b: ' + String(this.globalFoo));"); return 0; }
int main(int argc, char *argv[]) { /* initialize js environment */ duk_context *ctx = duk_create_heap_default(); /* add native functions to js environment */ duk_push_global_object(ctx); /* 'read' */ duk_push_c_function(ctx, js_read_file, 1); duk_put_prop_string(ctx, -2, "read"); #ifdef USE_PROMPT /* 'prompt' */ duk_push_c_function(ctx, js_prompt, 1); duk_put_prop_string(ctx, -2, "prompt"); #endif /* 'get' */ duk_push_c_function(ctx, js_level_get, 2); duk_put_prop_string(ctx, -2, "get"); /* 'set' */ duk_push_c_function(ctx, js_level_set, 3); duk_put_prop_string(ctx, -2, "set"); /* 'register' */ duk_push_c_function(ctx, js_register_block, 3); duk_put_prop_string(ctx, -2, "register"); /* 'load_file' */ duk_push_c_function(ctx, js_load_file, 1); duk_put_prop_string(ctx, -2, "load_file"); /* 'fill' */ duk_push_c_function(ctx, js_algo_fill, 1); duk_put_prop_string(ctx, -2, "fill"); /* 'findall' */ duk_push_c_function(ctx, js_algo_findall, 1); duk_put_prop_string(ctx, -2, "findall"); /* 'neighbors_of' */ duk_push_c_function(ctx, js_algo_neighbors_of, 3); duk_put_prop_string(ctx, -2, "neighbors_of"); /* 'distance' */ duk_push_c_function(ctx, js_algo_raycast, 4); duk_put_prop_string(ctx, -2, "raycast"); /* pop global object */ duk_pop(ctx); /* try to load some basic functionality */ if (duk_peval_file(ctx, "base/base.js") != 0) { //printf("Failed to load 'base/base.js': %s\n", duk_safe_to_string(ctx, -1)); /* When failing to load base/base.js, se simple, default module loader. */ duk_eval_string_noresult(ctx, "Duktape.modSearch = function(id) { return read(id); };"); } duk_pop(ctx); if (argc > 1) { /* run garbage collector (twice as told by the docs) */ duk_gc(ctx, 0); duk_gc(ctx, 0); /* where to save the png */ char *export_file = "generated_map"; int generate_num = 1; int save_png_disabled = 0; /* parse command line flags */ for (int i = 0; i < argc; ++i) { if (!strcmp(argv[i], "--width") || !strcmp(argv[i], "-w")) { if (i + 1 < argc) js_level_width = atoi(argv[i + 1]); } else if (!strcmp(argv[i], "--height") || !strcmp(argv[i], "-h")) { if (i + 1 < argc) js_level_height = atoi(argv[i + 1]); } else if (!strcmp(argv[i], "-o") || !strcmp(argv[i], "--output")) { if (i + 1 < argc) export_file = argv[i + 1]; } else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--count")) { if (i + 1 < argc) generate_num = atoi(argv[i + 1]); } else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--no-export")) { save_png_disabled = 1; } } /* reserve enough memory for level */ js_level = malloc(sizeof(int) * js_level_width * js_level_height); blocks = malloc(sizeof(struct color) * blocks_max_len); /* set all zeroes, maybe change this use to calloc */ memset(js_level, 0, sizeof(int) * js_level_width * js_level_height); /* declare & assign global variable Width & Height */ duk_push_int(ctx, js_level_width); duk_put_global_string(ctx, "Width"); duk_push_int(ctx, js_level_height); duk_put_global_string(ctx, "Height"); /* can generate multiple maps */ for (int i = 0; i < generate_num; ++i) { if (duk_peval_file(ctx, argv[1]) != 0) { printf("('%s' #%d) %s\n", argv[1], i, duk_safe_to_string(ctx, -1)); } duk_pop(ctx); /* export the level with a special name */ char export_file_num[256]; if (generate_num > 1) { sprintf(export_file_num, "%s_%d.png", export_file, i); } else { sprintf(export_file_num, "%s.png", export_file); } /* export the level as png */ if (!save_png_disabled) export_level(export_file_num); } /* free all memory */ free(js_level); free(blocks); } else { /* tell the user how to use this */ print_usage(argv[0]); } /* clean up */ duk_destroy_heap(ctx); return 0; }
//void duk_eval_string_noresult(duk_context *ctx, const char *src); void aperl_duk_eval_string_noresult(duk_context *ctx, const char *src) { duk_eval_string_noresult(ctx, src); }
DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) { duk_context *ctx = (duk_context *) thr; duk_bitdecoder_ctx bd_ctx; duk_bitdecoder_ctx *bd = &bd_ctx; /* convenience */ duk_hobject *h; duk_small_uint_t i, j; DUK_D(DUK_DPRINT("INITBUILTINS BEGIN")); DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx)); bd->data = (const duk_uint8_t *) duk_builtins_data; bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH; /* * First create all built-in bare objects on the empty valstack. * During init, their indices will correspond to built-in indices. * * Built-ins will be reachable from both valstack and thr->builtins. */ /* XXX: there is no need to resize valstack because builtin count * is much less than the default space; assert for it. */ DUK_DD(DUK_DDPRINT("create empty built-ins")); DUK_ASSERT_TOP(ctx, 0); for (i = 0; i < DUK_NUM_BUILTINS; i++) { duk_small_uint_t class_num; duk_small_int_t len = -1; /* must be signed */ class_num = (duk_small_uint_t) duk_bd_decode(bd, DUK__CLASS_BITS); len = (duk_small_int_t) duk_bd_decode_flagged(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/); if (class_num == DUK_HOBJECT_CLASS_FUNCTION) { duk_small_uint_t natidx; duk_small_uint_t stridx; duk_int_t c_nargs; /* must hold DUK_VARARGS */ duk_c_function c_func; duk_int16_t magic; DUK_DDD(DUK_DDDPRINT("len=%ld", (long) len)); DUK_ASSERT(len >= 0); natidx = (duk_small_uint_t) duk_bd_decode(bd, DUK__NATIDX_BITS); stridx = (duk_small_uint_t) duk_bd_decode(bd, DUK__STRIDX_BITS); c_func = duk_bi_native_functions[natidx]; c_nargs = (duk_small_uint_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, len /*def_value*/); if (c_nargs == DUK__NARGS_VARARGS_MARKER) { c_nargs = DUK_VARARGS; } /* XXX: set magic directly here? (it could share the c_nargs arg) */ duk_push_c_function_noexotic(ctx, c_func, c_nargs); h = duk_require_hobject(ctx, -1); DUK_ASSERT(h != NULL); /* Currently all built-in native functions are strict. * duk_push_c_function() now sets strict flag, so * assert for it. */ DUK_ASSERT(DUK_HOBJECT_HAS_STRICT(h)); /* XXX: function properties */ duk_push_hstring_stridx(ctx, stridx); duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE); /* Almost all global level Function objects are constructable * but not all: Function.prototype is a non-constructable, * callable Function. */ if (duk_bd_decode_flag(bd)) { DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE(h)); } else { DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h); } /* Cast converts magic to 16-bit signed value */ magic = (duk_int16_t) duk_bd_decode_flagged(bd, DUK__MAGIC_BITS, 0 /*def_value*/); ((duk_hnativefunction *) h)->magic = magic; } else { /* XXX: ARRAY_PART for Array prototype? */ duk_push_object_helper(ctx, DUK_HOBJECT_FLAG_EXTENSIBLE, -1); /* no prototype or class yet */ h = duk_require_hobject(ctx, -1); DUK_ASSERT(h != NULL); } DUK_HOBJECT_SET_CLASS_NUMBER(h, class_num); thr->builtins[i] = h; DUK_HOBJECT_INCREF(thr, &h->hdr); if (len >= 0) { /* * For top-level objects, 'length' property has the following * default attributes: non-writable, non-enumerable, non-configurable * (E5 Section 15). * * However, 'length' property for Array.prototype has attributes * expected of an Array instance which are different: writable, * non-enumerable, non-configurable (E5 Section 15.4.5.2). * * This is currently determined implicitly based on class; there are * no attribute flags in the init data. */ duk_push_int(ctx, len); duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, (class_num == DUK_HOBJECT_CLASS_ARRAY ? /* only Array.prototype matches */ DUK_PROPDESC_FLAGS_W : DUK_PROPDESC_FLAGS_NONE)); } /* enable exotic behaviors last */ if (class_num == DUK_HOBJECT_CLASS_ARRAY) { DUK_HOBJECT_SET_EXOTIC_ARRAY(h); } if (class_num == DUK_HOBJECT_CLASS_STRING) { DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h); } /* some assertions */ DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h)); /* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */ DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(h)); DUK_ASSERT(!DUK_HOBJECT_HAS_COMPILEDFUNCTION(h)); /* DUK_HOBJECT_FLAG_NATIVEFUNCTION varies */ DUK_ASSERT(!DUK_HOBJECT_HAS_THREAD(h)); DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h)); /* currently, even for Array.prototype */ /* DUK_HOBJECT_FLAG_STRICT varies */ DUK_ASSERT(!DUK_HOBJECT_HAS_NATIVEFUNCTION(h) || /* all native functions have NEWENV */ DUK_HOBJECT_HAS_NEWENV(h)); DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(h)); DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(h)); DUK_ASSERT(!DUK_HOBJECT_HAS_ENVRECCLOSED(h)); /* DUK_HOBJECT_FLAG_EXOTIC_ARRAY varies */ /* DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ varies */ DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)); DUK_DDD(DUK_DDDPRINT("created built-in %ld, class=%ld, length=%ld", (long) i, (long) class_num, (long) len)); } /* * Then decode the builtins init data (see genbuiltins.py) to * init objects */ DUK_DD(DUK_DDPRINT("initialize built-in object properties")); for (i = 0; i < DUK_NUM_BUILTINS; i++) { duk_small_uint_t t; duk_small_uint_t num; DUK_DDD(DUK_DDDPRINT("initializing built-in object at index %ld", (long) i)); h = thr->builtins[i]; t = (duk_small_uint_t) duk_bd_decode(bd, DUK__BIDX_BITS); if (t != DUK__NO_BIDX_MARKER) { DUK_DDD(DUK_DDDPRINT("set internal prototype: built-in %ld", (long) t)); DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[t]); } t = (duk_small_uint_t) duk_bd_decode(bd, DUK__BIDX_BITS); if (t != DUK__NO_BIDX_MARKER) { /* 'prototype' property for all built-in objects (which have it) has attributes: * [[Writable]] = false, * [[Enumerable]] = false, * [[Configurable]] = false */ DUK_DDD(DUK_DDDPRINT("set external prototype: built-in %ld", (long) t)); duk_xdef_prop_stridx_builtin(ctx, i, DUK_STRIDX_PROTOTYPE, t, DUK_PROPDESC_FLAGS_NONE); } t = (duk_small_uint_t) duk_bd_decode(bd, DUK__BIDX_BITS); if (t != DUK__NO_BIDX_MARKER) { /* 'constructor' property for all built-in objects (which have it) has attributes: * [[Writable]] = true, * [[Enumerable]] = false, * [[Configurable]] = true */ DUK_DDD(DUK_DDDPRINT("set external constructor: built-in %ld", (long) t)); duk_xdef_prop_stridx_builtin(ctx, i, DUK_STRIDX_CONSTRUCTOR, t, DUK_PROPDESC_FLAGS_WC); } /* normal valued properties */ num = (duk_small_uint_t) duk_bd_decode(bd, DUK__NUM_NORMAL_PROPS_BITS); DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld normal valued properties", (long) i, (long) num)); for (j = 0; j < num; j++) { duk_small_uint_t stridx; duk_small_uint_t prop_flags; stridx = (duk_small_uint_t) duk_bd_decode(bd, DUK__STRIDX_BITS); /* * Property attribute defaults are defined in E5 Section 15 (first * few pages); there is a default for all properties and a special * default for 'length' properties. Variation from the defaults is * signaled using a single flag bit in the bitstream. */ if (duk_bd_decode_flag(bd)) { prop_flags = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_FLAGS_BITS); } else { if (stridx == DUK_STRIDX_LENGTH) { prop_flags = DUK_PROPDESC_FLAGS_NONE; } else { prop_flags = DUK_PROPDESC_FLAGS_WC; } } t = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_TYPE_BITS); DUK_DDD(DUK_DDDPRINT("built-in %ld, normal-valued property %ld, stridx %ld, flags 0x%02lx, type %ld", (long) i, (long) j, (long) stridx, (unsigned long) prop_flags, (long) t)); switch (t) { case DUK__PROP_TYPE_DOUBLE: { duk_double_union du; duk_small_uint_t k; for (k = 0; k < 8; k++) { /* Encoding endianness must match target memory layout, * build scripts and genbuiltins.py must ensure this. */ du.uc[k] = (duk_uint8_t) duk_bd_decode(bd, 8); } duk_push_number(ctx, du.d); /* push operation normalizes NaNs */ break; } case DUK__PROP_TYPE_STRING: { duk_small_uint_t n; duk_small_uint_t k; duk_uint8_t *p; n = (duk_small_uint_t) duk_bd_decode(bd, DUK__STRING_LENGTH_BITS); p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, n); for (k = 0; k < n; k++) { *p++ = (duk_uint8_t) duk_bd_decode(bd, DUK__STRING_CHAR_BITS); } duk_to_string(ctx, -1); break; } case DUK__PROP_TYPE_STRIDX: { duk_small_uint_t n; n = (duk_small_uint_t) duk_bd_decode(bd, DUK__STRIDX_BITS); DUK_ASSERT_DISABLE(n >= 0); /* unsigned */ DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS); duk_push_hstring_stridx(ctx, n); break; } case DUK__PROP_TYPE_BUILTIN: { duk_small_uint_t bidx; bidx = (duk_small_uint_t) duk_bd_decode(bd, DUK__BIDX_BITS); DUK_ASSERT(bidx != DUK__NO_BIDX_MARKER); duk_dup(ctx, (duk_idx_t) bidx); break; } case DUK__PROP_TYPE_UNDEFINED: { duk_push_undefined(ctx); break; } case DUK__PROP_TYPE_BOOLEAN_TRUE: { duk_push_true(ctx); break; } case DUK__PROP_TYPE_BOOLEAN_FALSE: { duk_push_false(ctx); break; } case DUK__PROP_TYPE_ACCESSOR: { duk_small_uint_t natidx_getter = (duk_small_uint_t) duk_bd_decode(bd, DUK__NATIDX_BITS); duk_small_uint_t natidx_setter = (duk_small_uint_t) duk_bd_decode(bd, DUK__NATIDX_BITS); duk_c_function c_func_getter; duk_c_function c_func_setter; /* XXX: this is a bit awkward because there is no exposed helper * in the API style, only this internal helper. */ DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, stridx=%ld, getteridx=%ld, setteridx=%ld, flags=0x%04lx", (long) i, (long) stridx, (long) natidx_getter, (long) natidx_setter, (unsigned long) prop_flags)); c_func_getter = duk_bi_native_functions[natidx_getter]; c_func_setter = duk_bi_native_functions[natidx_setter]; duk_push_c_function_noconstruct_noexotic(ctx, c_func_getter, 0); /* always 0 args */ duk_push_c_function_noconstruct_noexotic(ctx, c_func_setter, 1); /* always 1 arg */ /* XXX: magic for getter/setter? */ prop_flags |= DUK_PROPDESC_FLAG_ACCESSOR; /* accessor flag not encoded explicitly */ duk_hobject_define_accessor_internal(thr, duk_require_hobject(ctx, i), DUK_HTHREAD_GET_STRING(thr, stridx), duk_require_hobject(ctx, -2), duk_require_hobject(ctx, -1), prop_flags); duk_pop_2(ctx); /* getter and setter, now reachable through object */ goto skip_value; } default: { /* exhaustive */ DUK_UNREACHABLE(); } } DUK_ASSERT((prop_flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0); duk_xdef_prop_stridx(ctx, i, stridx, prop_flags); skip_value: continue; /* avoid empty label at the end of a compound statement */ } /* native function properties */ num = (duk_small_uint_t) duk_bd_decode(bd, DUK__NUM_FUNC_PROPS_BITS); DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld function valued properties", (long) i, (long) num)); for (j = 0; j < num; j++) { duk_small_uint_t stridx; duk_small_uint_t natidx; duk_int_t c_nargs; /* must hold DUK_VARARGS */ duk_small_uint_t c_length; duk_int16_t magic; duk_c_function c_func; duk_hnativefunction *h_func; #if defined(DUK_USE_LIGHTFUNC_BUILTINS) duk_small_int_t lightfunc_eligible; #endif stridx = (duk_small_uint_t) duk_bd_decode(bd, DUK__STRIDX_BITS); natidx = (duk_small_uint_t) duk_bd_decode(bd, DUK__NATIDX_BITS); c_length = (duk_small_uint_t) duk_bd_decode(bd, DUK__LENGTH_PROP_BITS); c_nargs = (duk_int_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, (duk_int32_t) c_length /*def_value*/); if (c_nargs == DUK__NARGS_VARARGS_MARKER) { c_nargs = DUK_VARARGS; } c_func = duk_bi_native_functions[natidx]; DUK_DDD(DUK_DDDPRINT("built-in %ld, function-valued property %ld, stridx %ld, natidx %ld, length %ld, nargs %ld", (long) i, (long) j, (long) stridx, (long) natidx, (long) c_length, (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs))); /* Cast converts magic to 16-bit signed value */ magic = (duk_int16_t) duk_bd_decode_flagged(bd, DUK__MAGIC_BITS, 0); #if defined(DUK_USE_LIGHTFUNC_BUILTINS) lightfunc_eligible = ((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) && (c_length <= DUK_LFUNC_LENGTH_MAX) && (magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX); if (stridx == DUK_STRIDX_EVAL || stridx == DUK_STRIDX_YIELD || stridx == DUK_STRIDX_RESUME || stridx == DUK_STRIDX_REQUIRE) { /* These functions have trouble working as lightfuncs. * Some of them have specific asserts and some may have * additional properties (e.g. 'require.id' may be written). */ DUK_D(DUK_DPRINT("reject as lightfunc: stridx=%d, i=%d, j=%d", (int) stridx, (int) i, (int) j)); lightfunc_eligible = 0; } if (lightfunc_eligible) { duk_tval tv_lfunc; duk_small_uint_t lf_nargs = (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs); duk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs); DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags); duk_push_tval(ctx, &tv_lfunc); DUK_D(DUK_DPRINT("built-in function eligible as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld -> %!iT", (int) i, (int) j, (long) c_length, (long) c_nargs, (long) magic, duk_get_tval(ctx, -1))); goto lightfunc_skip; } DUK_D(DUK_DPRINT("built-in function NOT ELIGIBLE as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld", (int) i, (int) j, (long) c_length, (long) c_nargs, (long) magic)); #endif /* DUK_USE_LIGHTFUNC_BUILTINS */ /* [ (builtin objects) ] */ duk_push_c_function_noconstruct_noexotic(ctx, c_func, c_nargs); h_func = duk_require_hnativefunction(ctx, -1); DUK_UNREF(h_func); /* Currently all built-in native functions are strict. * This doesn't matter for many functions, but e.g. * String.prototype.charAt (and other string functions) * rely on being strict so that their 'this' binding is * not automatically coerced. */ DUK_HOBJECT_SET_STRICT((duk_hobject *) h_func); /* No built-in functions are constructable except the top * level ones (Number, etc). */ DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_func)); /* XXX: any way to avoid decoding magic bit; there are quite * many function properties and relatively few with magic values. */ h_func->magic = magic; /* [ (builtin objects) func ] */ duk_push_int(ctx, c_length); duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE); duk_push_hstring_stridx(ctx, stridx); duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE); /* XXX: other properties of function instances; 'arguments', 'caller'. */ DUK_DD(DUK_DDPRINT("built-in object %ld, function property %ld -> %!T", (long) i, (long) j, (duk_tval *) duk_get_tval(ctx, -1))); /* [ (builtin objects) func ] */ /* * The default property attributes are correct for all * function valued properties of built-in objects now. */ #if defined(DUK_USE_LIGHTFUNC_BUILTINS) lightfunc_skip: #endif duk_xdef_prop_stridx(ctx, i, stridx, DUK_PROPDESC_FLAGS_WC); /* [ (builtin objects) ] */ } } /* * Special post-tweaks, for cases not covered by the init data format. * * - Set Date.prototype.toGMTString to Date.prototype.toUTCString. * toGMTString is required to have the same Function object as * toUTCString in E5 Section B.2.6. Note that while Smjs respects * this, V8 does not (the Function objects are distinct). * * - Make DoubleError non-extensible. * * - Add info about most important effective compile options to Duktape. * * - Possibly remove some properties (values or methods) which are not * desirable with current feature options but are not currently * conditional in init data. */ duk_get_prop_stridx(ctx, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_UTC_STRING); duk_xdef_prop_stridx(ctx, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_GMT_STRING, DUK_PROPDESC_FLAGS_WC); h = duk_require_hobject(ctx, DUK_BIDX_DOUBLE_ERROR); DUK_ASSERT(h != NULL); DUK_HOBJECT_CLEAR_EXTENSIBLE(h); #if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY) DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features")); (void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_DELPROP_FLAG_THROW); #endif #if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF) DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features")); (void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_DELPROP_FLAG_THROW); #endif duk_push_string(ctx, /* Endianness indicator */ #if defined(DUK_USE_INTEGER_LE) "l" #elif defined(DUK_USE_INTEGER_BE) "b" #elif defined(DUK_USE_INTEGER_ME) /* integer mixed endian not really used now */ "m" #else "?" #endif #if defined(DUK_USE_DOUBLE_LE) "l" #elif defined(DUK_USE_DOUBLE_BE) "b" #elif defined(DUK_USE_DOUBLE_ME) "m" #else "?" #endif #if defined(DUK_USE_BYTEORDER_FORCED) "f" #endif " " /* Packed or unpacked tval */ #if defined(DUK_USE_PACKED_TVAL) "p" #else "u" #endif #if defined(DUK_USE_FASTINT) "f" #endif " " /* Low memory options */ #if defined(DUK_USE_STRTAB_CHAIN) "c" /* chain */ #elif defined(DUK_USE_STRTAB_PROBE) "p" /* probe */ #else "?" #endif #if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16) "n" #endif #if defined(DUK_USE_HEAPPTR16) "h" #endif #if defined(DUK_USE_DATAPTR16) "d" #endif #if defined(DUK_USE_FUNCPTR16) "f" #endif #if defined(DUK_USE_REFCOUNT16) "R" #endif #if defined(DUK_USE_STRHASH16) "H" #endif #if defined(DUK_USE_STRLEN16) "S" #endif #if defined(DUK_USE_BUFLEN16) "B" #endif #if defined(DUK_USE_OBJSIZES16) "O" #endif #if defined(DUK_USE_LIGHTFUNC_BUILTINS) "L" #endif " " /* Object property allocation layout */ #if defined(DUK_USE_HOBJECT_LAYOUT_1) "p1" #elif defined(DUK_USE_HOBJECT_LAYOUT_2) "p2" #elif defined(DUK_USE_HOBJECT_LAYOUT_3) "p3" #else "p?" #endif " " /* Alignment guarantee */ #if defined(DUK_USE_ALIGN_4) "a4" #elif defined(DUK_USE_ALIGN_8) "a8" #else "a1" #endif " " /* Architecture, OS, and compiler strings */ DUK_USE_ARCH_STRING " " DUK_USE_OS_STRING " " DUK_USE_COMPILER_STRING); duk_xdef_prop_stridx(ctx, DUK_BIDX_DUKTAPE, DUK_STRIDX_ENV, DUK_PROPDESC_FLAGS_WC); /* * InitJS code - Ecmascript code evaluated from a built-in source * which provides e.g. backward compatibility. User can also provide * JS code to be evaluated at startup. */ #ifdef DUK_USE_BUILTIN_INITJS /* XXX: compression */ DUK_DD(DUK_DDPRINT("running built-in initjs")); duk_eval_string(ctx, (const char *) duk_initjs_data); /* initjs data is NUL terminated */ duk_pop(ctx); #endif /* DUK_USE_BUILTIN_INITJS */ #ifdef DUK_USE_USER_INITJS /* XXX: compression (as an option) */ DUK_DD(DUK_DDPRINT("running user initjs")); duk_eval_string_noresult(ctx, (const char *) DUK_USE_USER_INITJS); #endif /* DUK_USE_USER_INITJS */ /* * Since built-ins are not often extended, compact them. */ DUK_DD(DUK_DDPRINT("compact built-ins")); for (i = 0; i < DUK_NUM_BUILTINS; i++) { duk_hobject_compact_props(thr, thr->builtins[i]); } DUK_D(DUK_DPRINT("INITBUILTINS END")); #ifdef DUK_USE_DDPRINT for (i = 0; i < DUK_NUM_BUILTINS; i++) { DUK_DD(DUK_DDPRINT("built-in object %ld after initialization and compacting: %!@iO", (long) i, (duk_heaphdr *) thr->builtins[i])); } #endif /* * Pop built-ins from stack: they are now INCREF'd and * reachable from the builtins[] array. */ duk_pop_n(ctx, DUK_NUM_BUILTINS); DUK_ASSERT_TOP(ctx, 0); }
int main(int argc, char *argv[]) { duk_context *ctx = duk_create_heap_default(); duk_int_t rc; (void) argc; (void) argv; /* suppress warning */ printf("*** test1 - duk_pcall()\n"); duk_push_c_function(ctx, test1, 0); rc = duk_pcall(ctx, 0); printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); duk_pop(ctx); printf("\n"); printf("*** test1 - duk_safe_call()\n"); rc = duk_safe_call(ctx, test1, 0, 1); printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); duk_pop(ctx); printf("\n"); printf("*** test1 - ecmascript try-catch\n"); duk_push_c_function(ctx, test1, 0); duk_put_global_string(ctx, "test1"); duk_eval_string_noresult(ctx, "try {\n" " test1();\n" "} catch (e) {\n" " print(e.stack || e);\n" "}\n"); printf("\n"); printf("*** test2 - duk_pcall()\n"); duk_push_c_function(ctx, test2, 0); rc = duk_pcall(ctx, 0); printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); duk_pop(ctx); printf("\n"); printf("*** test2 - duk_safe_call()\n"); rc = duk_safe_call(ctx, test2, 0, 1); printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); duk_pop(ctx); printf("\n"); printf("*** test2 - ecmascript try-catch\n"); duk_push_c_function(ctx, test2, 0); duk_put_global_string(ctx, "test2"); duk_eval_string_noresult(ctx, "try {\n" " test2();\n" "} catch (e) {\n" " print(e.stack || e);\n" "}\n"); printf("\n"); printf("*** test3 - duk_pcall()\n"); duk_push_c_function(ctx, test3, 0); rc = duk_pcall(ctx, 0); printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); duk_pop(ctx); printf("\n"); printf("*** test3 - duk_safe_call()\n"); rc = duk_safe_call(ctx, test3, 0, 1); printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); duk_pop(ctx); printf("\n"); printf("*** test3 - ecmascript try-catch\n"); duk_push_c_function(ctx, test3, 0); duk_put_global_string(ctx, "test3"); duk_eval_string_noresult(ctx, "try {\n" " test3();\n" "} catch (e) {\n" " print(e.stack || e);\n" "}\n"); printf("\n"); printf("*** test4 - duk_pcall()\n"); duk_push_c_function(ctx, test4, 0); rc = duk_pcall(ctx, 0); printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); duk_pop(ctx); printf("\n"); printf("*** test4 - duk_safe_call()\n"); rc = duk_safe_call(ctx, test4, 0, 1); printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); duk_pop(ctx); printf("\n"); printf("*** test4 - ecmascript try-catch\n"); duk_push_c_function(ctx, test4, 0); duk_put_global_string(ctx, "test4"); duk_eval_string_noresult(ctx, "try {\n" " test4();\n" "} catch (e) {\n" " print(e.stack || e);\n" "}\n"); printf("\n"); printf("*** test5 - duk_pcall()\n"); duk_push_c_function(ctx, test5, 0); rc = duk_pcall(ctx, 0); printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); duk_pop(ctx); printf("\n"); printf("*** test5 - duk_safe_call()\n"); rc = duk_safe_call(ctx, test5, 0, 1); printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1)); duk_pop(ctx); printf("\n"); printf("*** test5 - ecmascript try-catch\n"); duk_push_c_function(ctx, test5, 0); duk_put_global_string(ctx, "test5"); duk_eval_string_noresult(ctx, "try {\n" " test5();\n" "} catch (e) {\n" " print(e.stack || e);\n" "}\n"); printf("\n"); printf("*** done\n"); duk_destroy_heap(ctx); return 0; }
void register_dukos(duk_context *ctx) { dukos_core(ctx); duk_put_global_string(ctx, "os"); duk_eval_string_noresult(ctx, "Duktape.modLoaded['os'] = os"); }
static duk_ret_t test_func(duk_context *ctx, void *udata) { (void) udata; if (ctx) { printf("dummy - return here\n"); fflush(stdout); return 0; } /* Up-to-date for Duktape 1.3.0, alphabetical order: * $ cd website/api; ls *.yaml */ (void) duk_alloc_raw(ctx, 0); (void) duk_alloc(ctx, 0); (void) duk_base64_decode(ctx, 0); (void) duk_base64_encode(ctx, 0); (void) duk_buffer_to_string(ctx, 0); (void) duk_call_method(ctx, 0); (void) duk_call_prop(ctx, 0, 0); (void) duk_call(ctx, 0); (void) duk_char_code_at(ctx, 0, 0); (void) duk_check_stack_top(ctx, 0); (void) duk_check_stack(ctx, 0); (void) duk_check_type_mask(ctx, 0, 0); (void) duk_check_type(ctx, 0, 0); (void) duk_compact(ctx, 0); (void) duk_compile_lstring_filename(ctx, 0, "dummy", 0); (void) duk_compile_lstring(ctx, 0, "dummy", 0); (void) duk_compile_string_filename(ctx, 0, "dummy"); (void) duk_compile_string(ctx, 0, "dummy"); (void) duk_compile(ctx, 0); (void) duk_concat(ctx, 0); (void) duk_config_buffer(ctx, 0, NULL, 0); (void) duk_copy(ctx, 0, 0); (void) duk_create_heap_default(); (void) duk_create_heap(NULL, NULL, NULL, NULL, NULL); (void) duk_debugger_attach(ctx, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); (void) duk_debugger_cooperate(ctx); (void) duk_debugger_detach(ctx); (void) duk_debugger_notify(ctx, 0); (void) duk_debugger_pause(ctx); (void) duk_decode_string(ctx, 0, NULL, NULL); (void) duk_def_prop(ctx, 0, 0); (void) duk_del_prop_index(ctx, 0, 0); (void) duk_del_prop_string(ctx, 0, "dummy"); (void) duk_del_prop(ctx, 0); (void) duk_destroy_heap(ctx); (void) duk_dump_function(ctx); (void) duk_dup_top(ctx); (void) duk_dup(ctx, 0); (void) duk_enum(ctx, 0, 0); (void) duk_equals(ctx, 0, 0); duk_error_va(ctx, 0, NULL, NULL); duk_error(ctx, 0, "dummy"); /* (void) cast won't work without variadic macros */ (void) duk_eval_lstring_noresult(ctx, "dummy", 0); (void) duk_eval_lstring(ctx, "dummy", 0); (void) duk_eval_noresult(ctx); (void) duk_eval_string_noresult(ctx, "dummy"); (void) duk_eval_string(ctx, "dummy"); (void) duk_eval(ctx); (void) duk_fatal(ctx, "dummy"); (void) duk_free_raw(ctx, NULL); (void) duk_free(ctx, NULL); (void) duk_gc(ctx, 0); (void) duk_get_boolean(ctx, 0); (void) duk_get_buffer_data(ctx, 0, NULL); (void) duk_get_buffer(ctx, 0, NULL); (void) duk_get_c_function(ctx, 0); (void) duk_get_context(ctx, 0); (void) duk_get_current_magic(ctx); (void) duk_get_error_code(ctx, 0); (void) duk_get_finalizer(ctx, 0); (void) duk_get_global_string(ctx, 0); (void) duk_get_heapptr(ctx, 0); (void) duk_get_int(ctx, 0); (void) duk_get_length(ctx, 0); (void) duk_get_lstring(ctx, 0, NULL); (void) duk_get_magic(ctx, 0); (void) duk_get_memory_functions(ctx, NULL); (void) duk_get_number(ctx, 0); (void) duk_get_pointer(ctx, 0); (void) duk_get_prop_index(ctx, 0, 0); (void) duk_get_prop_string(ctx, 0, "dummy"); (void) duk_get_prop(ctx, 0); (void) duk_get_prototype(ctx, 0); (void) duk_get_string(ctx, 0); (void) duk_get_top_index(ctx); (void) duk_get_top(ctx); (void) duk_get_type_mask(ctx, 0); (void) duk_get_type(ctx, 0); (void) duk_get_uint(ctx, 0); (void) duk_has_prop_index(ctx, 0, 0); (void) duk_has_prop_string(ctx, 0, "dummy"); (void) duk_has_prop(ctx, 0); (void) duk_hex_decode(ctx, 0); (void) duk_hex_encode(ctx, 0); (void) duk_insert(ctx, 0); (void) duk_instanceof(ctx, 0, 0); (void) duk_is_array(ctx, 0); (void) duk_is_boolean(ctx, 0); (void) duk_is_bound_function(ctx, 0); (void) duk_is_buffer(ctx, 0); (void) duk_is_callable(ctx, 0); (void) duk_is_c_function(ctx, 0); (void) duk_is_constructor_call(ctx); (void) duk_is_dynamic_buffer(ctx, 0); (void) duk_is_ecmascript_function(ctx, 0); (void) duk_is_error(ctx, 0); (void) duk_is_eval_error(ctx, 0); (void) duk_is_fixed_buffer(ctx, 0); (void) duk_is_function(ctx, 0); (void) duk_is_lightfunc(ctx, 0); (void) duk_is_nan(ctx, 0); (void) duk_is_null_or_undefined(ctx, 0); (void) duk_is_null(ctx, 0); (void) duk_is_number(ctx, 0); (void) duk_is_object_coercible(ctx, 0); (void) duk_is_object(ctx, 0); (void) duk_is_pointer(ctx, 0); (void) duk_is_primitive(ctx, 0); (void) duk_is_range_error(ctx, 0); (void) duk_is_reference_error(ctx, 0); (void) duk_is_strict_call(ctx); (void) duk_is_string(ctx, 0); (void) duk_is_syntax_error(ctx, 0); (void) duk_is_thread(ctx, 0); (void) duk_is_type_error(ctx, 0); (void) duk_is_undefined(ctx, 0); (void) duk_is_uri_error(ctx, 0); (void) duk_is_valid_index(ctx, 0); (void) duk_join(ctx, 0); (void) duk_json_decode(ctx, 0); (void) duk_json_encode(ctx, 0); (void) duk_load_function(ctx); (void) duk_map_string(ctx, 0, NULL, NULL); (void) duk_new(ctx, 0); (void) duk_next(ctx, 0, 0); (void) duk_normalize_index(ctx, 0); (void) duk_pcall_method(ctx, 0); (void) duk_pcall_prop(ctx, 0, 0); (void) duk_pcall(ctx, 0); (void) duk_pcompile_lstring_filename(ctx, 0, "dummy", 0); (void) duk_pcompile_lstring(ctx, 0, "dummy", 0); (void) duk_pcompile_string_filename(ctx, 0, "dummy"); (void) duk_pcompile_string(ctx, 0, "dummy"); (void) duk_pcompile(ctx, 0); (void) duk_peval_lstring_noresult(ctx, "dummy", 0); (void) duk_peval_lstring(ctx, "dummy", 0); (void) duk_peval_noresult(ctx); (void) duk_peval_string_noresult(ctx, "dummy"); (void) duk_peval_string(ctx, "dummy"); (void) duk_peval(ctx); (void) duk_pnew(ctx, 0); (void) duk_pop_2(ctx); (void) duk_pop_3(ctx); (void) duk_pop_n(ctx, 0); (void) duk_pop(ctx); (void) duk_push_array(ctx); (void) duk_push_boolean(ctx, 0); (void) duk_push_buffer_object(ctx, 0, 0, 0, 0); (void) duk_push_buffer(ctx, 0, 0); (void) duk_push_c_function(ctx, NULL, 0); (void) duk_push_c_lightfunc(ctx, NULL, 0, 0, 0); (void) duk_push_context_dump(ctx); (void) duk_push_current_function(ctx); (void) duk_push_current_thread(ctx); (void) duk_push_dynamic_buffer(ctx, 0); (void) duk_push_error_object_va(ctx, 0, NULL, NULL); (void) duk_push_error_object(ctx, 0, "dummy"); (void) duk_push_external_buffer(ctx); (void) duk_push_false(ctx); (void) duk_push_fixed_buffer(ctx, 0); (void) duk_push_global_object(ctx); (void) duk_push_global_stash(ctx); (void) duk_push_heap_stash(ctx); (void) duk_push_heapptr(ctx, NULL); (void) duk_push_int(ctx, 0); (void) duk_push_lstring(ctx, "dummy", 0); (void) duk_push_nan(ctx); (void) duk_push_null(ctx); (void) duk_push_number(ctx, 0.0); (void) duk_push_object(ctx); (void) duk_push_pointer(ctx, NULL); (void) duk_push_sprintf(ctx, "dummy"); (void) duk_push_string(ctx, "dummy"); (void) duk_push_this(ctx); (void) duk_push_thread_new_globalenv(ctx); (void) duk_push_thread_stash(ctx, NULL); (void) duk_push_thread(ctx); (void) duk_push_true(ctx); (void) duk_push_uint(ctx, 0); (void) duk_push_undefined(ctx); (void) duk_push_vsprintf(ctx, "dummy", NULL); (void) duk_put_function_list(ctx, 0, NULL); (void) duk_put_global_string(ctx, NULL); (void) duk_put_number_list(ctx, 0, NULL); (void) duk_put_prop_index(ctx, 0, 0); (void) duk_put_prop_string(ctx, 0, "dummy"); (void) duk_put_prop(ctx, 0); (void) duk_realloc_raw(ctx, NULL, 0); (void) duk_realloc(ctx, NULL, 0); (void) duk_remove(ctx, 0); (void) duk_replace(ctx, 0); (void) duk_require_boolean(ctx, 0); (void) duk_require_buffer_data(ctx, 0, NULL); (void) duk_require_buffer(ctx, 0, NULL); (void) duk_require_c_function(ctx, 0); (void) duk_require_callable(ctx, 0); (void) duk_require_context(ctx, 0); (void) duk_require_function(ctx, 0); (void) duk_require_heapptr(ctx, 0); (void) duk_require_int(ctx, 0); (void) duk_require_lstring(ctx, 0, NULL); (void) duk_require_normalize_index(ctx, 0); (void) duk_require_null(ctx, 0); (void) duk_require_number(ctx, 0); (void) duk_require_object_coercible(ctx, 0); (void) duk_require_pointer(ctx, 0); (void) duk_require_stack_top(ctx, 0); (void) duk_require_stack(ctx, 0); (void) duk_require_string(ctx, 0); (void) duk_require_top_index(ctx); (void) duk_require_type_mask(ctx, 0, 0); (void) duk_require_uint(ctx, 0); (void) duk_require_undefined(ctx, 0); (void) duk_require_valid_index(ctx, 0); (void) duk_resize_buffer(ctx, 0, 0); (void) duk_safe_call(ctx, NULL, NULL, 0, 0); (void) duk_safe_to_lstring(ctx, 0, NULL); (void) duk_safe_to_string(ctx, 0); (void) duk_set_finalizer(ctx, 0); (void) duk_set_global_object(ctx); (void) duk_set_magic(ctx, 0, 0); (void) duk_set_prototype(ctx, 0); (void) duk_set_top(ctx, 0); (void) duk_steal_buffer(ctx, 0, NULL); (void) duk_strict_equals(ctx, 0, 0); (void) duk_substring(ctx, 0, 0, 0); (void) duk_swap_top(ctx, 0); (void) duk_swap(ctx, 0, 0); (void) duk_throw(ctx); (void) duk_to_boolean(ctx, 0); (void) duk_to_buffer(ctx, 0, NULL); (void) duk_to_defaultvalue(ctx, 0, 0); (void) duk_to_dynamic_buffer(ctx, 0, NULL); (void) duk_to_fixed_buffer(ctx, 0, NULL); (void) duk_to_int32(ctx, 0); (void) duk_to_int(ctx, 0); (void) duk_to_lstring(ctx, 0, NULL); (void) duk_to_null(ctx, 0); (void) duk_to_number(ctx, 0); (void) duk_to_object(ctx, 0); (void) duk_to_pointer(ctx, 0); (void) duk_to_primitive(ctx, 0, 0); (void) duk_to_string(ctx, 0); (void) duk_to_uint16(ctx, 0); (void) duk_to_uint32(ctx, 0); (void) duk_to_uint(ctx, 0); (void) duk_to_undefined(ctx, 0); (void) duk_trim(ctx, 0); (void) duk_xcopy_top(ctx, NULL, 0); (void) duk_xmove_top(ctx, NULL, 0); printf("never here\n"); fflush(stdout); return 0; }
void register_dukzip(duk_context *ctx) { dukzip_core(ctx); duk_put_global_string(ctx, "zip"); duk_eval_string_noresult(ctx, "Duktape.modLoaded['zip'] = zip"); }