/** * * performance tips * https://www.ibm.com/developerworks/library/j-jni/ * */ jobject duk_to_java_object(duk_context *ctx, JNIEnv* env, int i){ int type = duk_get_type(ctx, i); if(type == DUK_TYPE_BOOLEAN){ jboolean value = duk_to_boolean(ctx, i); DEBUG_LOG("ScriptEngine","invoke_java_method call, convert %d args to boolean %d", i, value); jmethodID methodID = (*env)->GetMethodID(env, java_boolean_class, "<init>", "(Z)V"); jobject booleanObject = (*env)->NewObject(env, java_boolean_class, methodID, value); return booleanObject; }else if(type == DUK_TYPE_NUMBER){ jdouble value = duk_to_number(ctx, i); jclass doubleClass = (*env)->FindClass(env, "java/lang/Double"); jmethodID methodID = (*env)->GetMethodID(env, doubleClass, "<init>", "(D)V"); jobject numberObject = (*env)->NewObject(env, doubleClass, methodID, value); (*env)->DeleteLocalRef(env, doubleClass); DEBUG_LOG("ScriptEngine","invoke_java_method call, convert %d args to number %f", i, value); return numberObject; }else if(type == DUK_TYPE_STRING){ const char* chs = duk_to_string(ctx, i); DEBUG_LOG("ScriptEngine","invoke_java_method call, convert %d args to string %s", i, chs); return (*env)->NewStringUTF(env, chs); }else if(type == DUK_TYPE_OBJECT){ if(duk_get_prop_string(ctx, i, JAVA_OBJECT_MARK)){ DEBUG_LOG("ScriptEngine","invoke_java_method call, convert %d args to java object", i); jobject value = duk_to_pointer(ctx, -1); duk_pop(ctx); return (*env)->NewLocalRef(env, value); }else{ duk_pop(ctx); if(duk_get_prop_string(ctx, i, JS_REF_MARK)){ DEBUG_LOG("ScriptEngine","reuse javascript object's JSRef"); jweak weakRef = duk_to_pointer(ctx, -1); jobject jsRefObject = (*env)->NewLocalRef(env, weakRef); duk_pop(ctx); if(jsRefObject != NULL){ return jsRefObject; } }else{ duk_pop(ctx); } duk_dup(ctx, i); jint ref = duk_js_ref(ctx); if(ref != 0){ DEBUG_LOG("ScriptEngine","convert javascript object to JSRef Ref Value %d ", ref); jobject engine = get_engine_from_context(ctx); DEBUG_LOG("ScriptEngine","convert javascript object to JSRef Ref Value"); jobject jsRefObject = (*env)->NewObject(env, js_ref_class, js_ref_new_method, engine, ref); jweak jsWeakRef = (*env)->NewWeakGlobalRef(env, jsRefObject); duk_dup(ctx, i); duk_push_pointer(ctx, jsWeakRef); duk_put_prop_string(ctx, -2, JS_REF_MARK); duk_pop(ctx); DEBUG_LOG("ScriptEngine","convert javascript object to JSRef Ref Value Success"); return jsRefObject; } return NULL; } } DEBUG_LOG("ScriptEngine","invoke_java_method call, unhandled type convert %d args to null %s", i, duk_to_string(ctx, i)); return NULL; }
static void duk__push_module_object(duk_context *ctx, const char *id, duk_bool_t main) { duk_push_object(ctx); /* Set this as the main module, if requested */ if (main) { duk_push_global_stash(ctx); duk_dup(ctx, -2); duk_put_prop_string(ctx, -2, "\xff" "mainModule"); duk_pop(ctx); } /* Node.js uses the canonicalized filename of a module for both module.id * and module.filename. We have no concept of a file system here, so just * use the module ID for both values. */ duk_push_string(ctx, id); duk_dup(ctx, -1); duk_put_prop_string(ctx, -3, "filename"); duk_put_prop_string(ctx, -2, "id"); /* module.exports = {} */ duk_push_object(ctx); duk_put_prop_string(ctx, -2, "exports"); /* module.loaded = false */ duk_push_false(ctx); duk_put_prop_string(ctx, -2, "loaded"); /* module.require */ duk__push_require_function(ctx, id); duk_put_prop_string(ctx, -2, "require"); }
duk_ret_t dukky_svg_element___proto(duk_context *ctx) { /* Add read/write property */ duk_dup(ctx, 0); duk_push_string(ctx, "style"); duk_push_c_function(ctx, dukky_svg_element_style_getter, 0); duk_push_c_function(ctx, dukky_svg_element_style_setter, 1); duk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER | DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE); duk_pop(ctx); /* Set the destructor */ duk_dup(ctx, 0); duk_push_c_function(ctx, dukky_svg_element___destructor, 1); duk_set_finalizer(ctx, -2); duk_pop(ctx); /* Set the constructor */ duk_dup(ctx, 0); duk_push_c_function(ctx, dukky_svg_element___constructor, 1); duk_put_prop_string(ctx, -2, "\xFF\xFFNETSURF_DUKTAPE_INIT"); duk_pop(ctx); return 1; /* The prototype object */ }
/* 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; }
/* Prepare value stack for a method call through an object property. * May currently throw an error e.g. when getting the property. */ DUK_LOCAL void duk__call_prop_prep_stack(duk_context *ctx, duk_idx_t normalized_obj_idx, duk_idx_t nargs) { DUK_ASSERT_CTX_VALID(ctx); DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_idx=%ld, nargs=%ld, stacktop=%ld", (long) normalized_obj_idx, (long) nargs, (long) duk_get_top(ctx))); /* [... key arg1 ... argN] */ /* duplicate key */ duk_dup(ctx, -nargs - 1); /* Note: -nargs alone would fail for nargs == 0, this is OK */ duk_get_prop(ctx, normalized_obj_idx); DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(ctx, -1))); /* [... key arg1 ... argN func] */ duk_replace(ctx, -nargs - 2); /* [... func arg1 ... argN] */ duk_dup(ctx, normalized_obj_idx); duk_insert(ctx, -nargs - 1); /* [... func this arg1 ... argN] */ }
void _gum_duk_push_proxy (duk_context * ctx, duk_idx_t target, duk_c_function getter, duk_c_function setter) { duk_dup (ctx, target); duk_get_global_string (ctx, "Proxy"); duk_dup (ctx, -2); duk_push_object (ctx); if (getter != NULL) { duk_push_c_function (ctx, getter, 3); duk_put_prop_string (ctx, -2, "get"); } if (setter != NULL) { duk_push_c_function (ctx, setter, 4); duk_put_prop_string (ctx, -2, "set"); } duk_new (ctx, 2); duk_swap_top (ctx, -2); duk_pop (ctx); }
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); }
static duk_ret_t Component_SetProperty(duk_context* ctx) { /* 'this' binding: handler * [0]: target * [1]: key * [2]: val * [3]: receiver (proxy) */ const char* attrName = duk_to_string(ctx, 1); if (attrName && attrName[0] >= 'a' && attrName[0] <= 'z') { IComponent* comp = GetWeakObject<IComponent>(ctx, 0); if (comp) { IAttribute* attr = comp->AttributeById(String(attrName)); AssignAttributeValue(ctx, 2, attr, AttributeChange::Default); return 1; } } // Fallthrough to ordinary properties duk_dup(ctx, 1); duk_dup(ctx, 2); duk_put_prop(ctx, 0); duk_push_true(ctx); return 1; }
duk_ret_t dukky_before_unload_event___proto(duk_context *ctx) { /* Set this prototype's prototype (left-parent) */ /* get prototype */ duk_get_global_string(ctx, dukky_magic_string_prototypes); duk_get_prop_string(ctx, -1, "\xFF\xFFNETSURF_DUKTAPE_PROTOTYPE_EVENT"); duk_replace(ctx, -2); duk_set_prototype(ctx, 0); /* Add read/write property */ duk_dup(ctx, 0); duk_push_string(ctx, "returnValue"); duk_push_c_function(ctx, dukky_before_unload_event_returnValue_getter, 0); duk_push_c_function(ctx, dukky_before_unload_event_returnValue_setter, 1); duk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER | DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE); duk_pop(ctx); /* Set the destructor */ duk_dup(ctx, 0); duk_push_c_function(ctx, dukky_before_unload_event___destructor, 1); duk_set_finalizer(ctx, -2); duk_pop(ctx); /* Set the constructor */ duk_dup(ctx, 0); duk_push_c_function(ctx, dukky_before_unload_event___constructor, 2); duk_put_prop_string(ctx, -2, "\xFF\xFFNETSURF_DUKTAPE_INIT"); duk_pop(ctx); return 1; /* The prototype object */ }
/* _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; }
static duk_ret_t test_1(duk_context *ctx) { duk_size_t i, n; char *buf; duk_set_top(ctx, 0); duk_push_undefined(ctx); duk_push_null(ctx); duk_push_true(ctx); duk_push_false(ctx); duk_push_nan(ctx); duk_push_number(ctx, -INFINITY); duk_push_number(ctx, +INFINITY); duk_push_number(ctx, -0.0); duk_push_number(ctx, +0.0); duk_push_int(ctx, 123); duk_push_string(ctx, "foo"); duk_push_lstring(ctx, "foo\0bar", 7); /* internal NULs are kept */ duk_push_object(ctx); buf = (char *) duk_push_fixed_buffer(ctx, 0); buf = (char *) duk_push_fixed_buffer(ctx, 16); for (i = 0; i < 16; i++) { buf[i] = i; } buf = (char *) duk_push_dynamic_buffer(ctx, 0); buf = (char *) duk_push_dynamic_buffer(ctx, 16); for (i = 0; i < 16; i++) { buf[i] = i; } duk_push_pointer(ctx, (void *) NULL); duk_push_pointer(ctx, (void *) 0xdeadbeef); n = duk_get_top(ctx); printf("top: %ld\n", (long) n); for (i = 0; i < n; i++) { duk_int_t t1, t2; void *ptr; duk_size_t sz; duk_dup(ctx, i); t1 = duk_get_type(ctx, -1); sz = (duk_size_t) 0xdeadbeef; ptr = duk_to_buffer(ctx, -1, &sz); t2 = duk_get_type(ctx, -1); printf("index %ld, type %ld -> %ld, ptr-is-NULL %d, size %lu\n", (long) i, (long) t1, (long) t2, (sz == 0 ? -1 : (ptr == NULL ? 1 : 0)), (unsigned long) sz); dump_buffer(ctx); duk_pop(ctx); /* just check that this doesn't break */ duk_dup(ctx, i); ptr = duk_to_buffer(ctx, -1, NULL); duk_pop(ctx); } return 0; }
static duk_ret_t test_is_prototype_of(duk_context *ctx, void *udata) { (void) udata; prep(ctx); /* obj0.isPrototypeOf(dummy) -> false, traverses prototype chain of dummy */ duk_eval_string(ctx, "Object.prototype.isPrototypeOf"); duk_dup(ctx, 0); duk_push_object(ctx); duk_call_method(ctx, 1); printf("Object.prototype.isPrototypeOf result: %s\n", duk_safe_to_string(ctx, -1)); duk_pop(ctx); /* obj0.isPrototypeOf(obj1) -> true, traverses prototype chain of obj1 */ duk_eval_string(ctx, "Object.prototype.isPrototypeOf"); duk_dup(ctx, 0); duk_dup(ctx, 1); duk_call_method(ctx, 1); printf("Object.prototype.isPrototypeOf result: %s\n", duk_safe_to_string(ctx, -1)); duk_pop(ctx); /* dummy.isPrototypeOf(obj0) -> traverses prototype chain of obj0 and throws */ duk_eval_string(ctx, "Object.prototype.isPrototypeOf"); duk_push_object(ctx); duk_dup(ctx, 0); duk_call_method(ctx, 1); printf("Object.prototype.isPrototypeOf result: %s\n", duk_safe_to_string(ctx, -1)); duk_pop(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; }
void test(duk_context *ctx) { int i, n; duk_push_c_function(ctx, func, 0); duk_push_undefined(ctx); duk_push_null(ctx); duk_push_true(ctx); duk_push_false(ctx); duk_push_number(ctx, 123.456); duk_push_string(ctx, "foo"); duk_push_object(ctx); duk_push_array(ctx); duk_push_fixed_buffer(ctx, 16); duk_push_pointer(ctx, (void *) 0xdeadbeef); n = duk_get_top(ctx); printf("top: %d\n", n); for (i = 1; i < n; i++) { duk_dup(ctx, 0); duk_dup(ctx, i); duk_call_method(ctx, 0); /* [ ... func this ] -> [ ret ] */ duk_pop(ctx); } }
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; }
DUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx) { duk_hobject *h_target; duk_hobject *h_handler; if (!duk_is_constructor_call(ctx)) { return DUK_RET_TYPE_ERROR; } /* Reject a proxy object as the target because it would need * special handler in property lookups. (ES6 has no such restriction) */ h_target = duk_require_hobject_or_lfunc_coerce(ctx, 0); DUK_ASSERT(h_target != NULL); if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h_target)) { return DUK_RET_TYPE_ERROR; } /* Reject a proxy object as the handler because it would cause * potentially unbounded recursion. (ES6 has no such restriction) */ h_handler = duk_require_hobject_or_lfunc_coerce(ctx, 1); DUK_ASSERT(h_handler != NULL); if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h_handler)) { return DUK_RET_TYPE_ERROR; } /* XXX: the returned value is exotic in ES6, but we use a * simple object here with no prototype. Without a prototype, * [[DefaultValue]] coercion fails which is abit confusing. * No callable check/handling in the current Proxy subset. */ (void) duk_push_object_helper_proto(ctx, DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT), NULL); DUK_ASSERT_TOP(ctx, 3); /* Make _Target and _Handler non-configurable and non-writable. * They can still be forcibly changed by C code (both user and * Duktape internal), but not by Ecmascript code. */ /* Proxy target */ duk_dup(ctx, 0); duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE); /* Proxy handler */ duk_dup(ctx, 1); duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_HANDLER, DUK_PROPDESC_FLAGS_NONE); return 1; /* replacement handler */ }
static duk_ret_t test_typedarray_set_1(duk_context *ctx, void *udata) { int i, dst, src; unsigned char *data; (void) udata; data = (unsigned char *) duk_push_dynamic_buffer(ctx, 10); /* index 0 */ for (i = 0; i < 10; i++) { data[i] = 0x40 + i; } /* Some combinations are not set() compatible and cause a RangeError * (source longer than target). But this set should exercise byte copy, * fast copy, and slow copy code paths. */ setup_typedarray(ctx, 0, "Uint8Array"); /* index 1, length 10 */ setup_typedarray_slice(ctx, 0, "Uint8Array", 2, 5); /* index 2, length 5 */ setup_typedarray(ctx, 0, "Uint16Array"); /* index 3, length 5 */ setup_typedarray_slice(ctx, 0, "Uint16Array", 2, 3); /* index 4, length 3 */ duk_eval_string(ctx, "[ 1, 2, 3, 4, 5 ]"); /* index 5, length 5 */ for (i = 10; i >= 0; i--) { duk_resize_buffer(ctx, 0, i); /* Various copy combinations. Resulting buffer is omitted; * when both dst and src are typedarrays they share the same * underlying buffer. so the results are a bit confusing (and * not important to memory safety). */ for (dst = 1; dst <= 4; dst++) { for (src = 1; src <= 5; src++) { printf("%d %d %d\n", i, dst, src); duk_eval_string(ctx, "(function (dst, src) {\n" " for (var i = 0; i < dst.length; i++) { dst[i] = 0x11; }\n" " try { dst.set(src); } catch (e) { print(e.name); }\n" "})\n"); duk_dup(ctx, dst); duk_dup(ctx, src); duk_call(ctx, 2); duk_pop(ctx); } } } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* * Serializes various data types into a buffer. Leaves the buffer on the top of the stack. */ static uint8_t* SerializeToBuffer(duk_context* ctx, duk_idx_t idx, duk_size_t* sz) { uint8_t* ptr; switch (duk_get_type(ctx, idx)) { case DUK_TYPE_BUFFER: duk_dup(ctx, idx); ptr = duk_get_buffer(ctx, -1, sz); break; case DUK_TYPE_BOOLEAN: ptr = duk_push_fixed_buffer(ctx, 1); ptr[0] = duk_get_boolean(ctx, idx); *sz = 1; break; case DUK_TYPE_NUMBER: ptr = duk_push_fixed_buffer(ctx, 1); ptr[0] = duk_get_int(ctx, idx); *sz = 1; break; case DUK_TYPE_STRING: duk_dup(ctx, idx); ptr = duk_to_fixed_buffer(ctx, -1, sz); break; case DUK_TYPE_OBJECT: if (duk_is_array(ctx, idx)) { duk_idx_t i; duk_idx_t len = duk_get_length(ctx, idx); ptr = duk_push_fixed_buffer(ctx, len); for (i = 0; i < len; ++i) { duk_get_prop_index(ctx, idx, i); ptr[i] = duk_require_uint(ctx, -1); duk_pop(ctx); } *sz = len; } else { duk_error(ctx, DUK_ERR_TYPE_ERROR, "Can only serialize arrays of numbers"); } break; default: duk_error(ctx, DUK_ERR_TYPE_ERROR, "Cannot serialize"); break; } return ptr; }
static duk_ret_t test_json_serialize_1(duk_context *ctx, void *udata) { unsigned char *data; int i; duk_uarridx_t arridx = 0; (void) udata; data = (unsigned char *) duk_push_dynamic_buffer(ctx, 20); for (i = 0; i < 20; i++) { data[i] = 0x40 + i; } duk_push_array(ctx); /* index 1 */ setup_duktape_buffer(ctx, 0); duk_put_prop_index(ctx, 1, arridx++); setup_nodejs_buffer(ctx, 0); duk_put_prop_index(ctx, 1, arridx++); setup_nodejs_buffer_slice(ctx, 0, 3, 5); duk_put_prop_index(ctx, 1, arridx++); setup_arraybuffer(ctx, 0); duk_put_prop_index(ctx, 1, arridx++); setup_typedarray(ctx, 0, "Uint8Array"); duk_put_prop_index(ctx, 1, arridx++); setup_typedarray_slice(ctx, 0, "Uint8Array", 2, 6); duk_put_prop_index(ctx, 1, arridx++); setup_typedarray(ctx, 0, "Uint32Array"); duk_put_prop_index(ctx, 1, arridx++); setup_typedarray_slice(ctx, 0, "Uint32Array", 4, 1); duk_put_prop_index(ctx, 1, arridx++); /* Serialize with a full backing buffer first. */ for (i = 20; i >= 0; i--) { printf("resize to %d\n", i); duk_resize_buffer(ctx, 0, i); duk_dup(ctx, 1); duk_json_encode(ctx, -1); printf("%s\n", duk_to_string(ctx, -1)); duk_pop(ctx); duk_eval_string(ctx, "(function (v) { print(Duktape.enc('jx', v)); })"); duk_dup(ctx, 1); duk_call(ctx, 1); duk_pop(ctx); } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_nodejs_buffer_write_1(duk_context *ctx, void *udata) { int i, dst, src; unsigned char *data; (void) udata; data = (unsigned char *) duk_push_dynamic_buffer(ctx, 10); /* index 0 */ for (i = 0; i < 10; i++) { data[i] = 0x40 + i; } setup_nodejs_buffer(ctx, 0); /* index 1 */ setup_nodejs_buffer_slice(ctx, 0, 1, 4); /* index 2 */ setup_nodejs_buffer_slice(ctx, 0, 3, 7); /* index 3 */ setup_nodejs_buffer_slice(ctx, 0, 6, 9); /* index 4 */ duk_push_string(ctx, ""); /* index 5 */ duk_push_string(ctx, "fo"); /* index 6 */ duk_push_string(ctx, "bar"); /* index 7 */ duk_push_string(ctx, "quux"); /* index 8 */ for (i = 10; i >= 0; i--) { duk_resize_buffer(ctx, 0, i); /* The resulting buffers are not printed here; they're not very * intuitive because both the source and the destination share * the same underlying buffer. */ for (dst = 1; dst <= 4; dst++) { for (src = 5; src <= 8; src++) { printf("%d %d %d\n", i, dst, src); duk_eval_string(ctx, "(function (dst, src) {\n" " for (var i = 0; i < dst.length; i++) { dst[i] = 0x11; }\n" " dst.write(src);\n" " for (var i = 0; i < dst.length; i++) { dst[i] = 0x11; }\n" " dst.write(src, 1);\n" "})"); duk_dup(ctx, dst); duk_dup(ctx, src); duk_call(ctx, 2); duk_pop(ctx); } } } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_1(duk_context *ctx) { duk_push_c_function(ctx, my_func, 0); duk_dup(ctx, 0); /* -> [ func func ] */ duk_call(ctx, 0); /* -> [ func ret ] */ duk_pop(ctx); /* -> [ func ] */ duk_dup(ctx, 0); /* -> [ func func ] */ duk_new(ctx, 0); /* -> [ func ret ] */ duk_pop(ctx); /* -> [ func ] */ duk_pop(ctx); return 0; }
/* Place a `module` object on the top of the value stack into the require cache * based on its `.id` property. As a convenience to the caller, leave the * object on top of the value stack afterwards. */ static void duk__put_cached_module(duk_context *ctx) { /* [ ... module ] */ duk_push_global_stash(ctx); (void) duk_get_prop_string(ctx, -1, "\xff" "requireCache"); duk_dup(ctx, -3); /* [ ... module stash req_cache module ] */ (void) duk_get_prop_string(ctx, -1, "id"); duk_dup(ctx, -2); duk_put_prop(ctx, -4); duk_pop_3(ctx); /* [ ... module ] */ }
DUK_EXTERNAL duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_index, duk_bool_t get_value) { DUK_ASSERT_CTX_VALID(ctx); duk_require_hobject(ctx, enum_index); duk_dup(ctx, enum_index); return duk_hobject_enumerator_next(ctx, get_value); }
DUK_EXTERNAL void duk_push_context_dump(duk_context *ctx) { duk_idx_t idx; duk_idx_t top; /* We don't duk_require_stack() here now, but rely on the caller having * enough space. */ top = duk_get_top(ctx); duk_push_array(ctx); for (idx = 0; idx < top; idx++) { duk_dup(ctx, idx); duk_put_prop_index(ctx, -2, idx); } /* XXX: conversion errors should not propagate outwards. * Perhaps values need to be coerced individually? */ duk_bi_json_stringify_helper(ctx, duk_get_top_index(ctx), /*idx_value*/ DUK_INVALID_INDEX, /*idx_replacer*/ DUK_INVALID_INDEX, /*idx_space*/ DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_ASCII_ONLY | DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/); duk_push_sprintf(ctx, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(ctx, -1)); duk_replace(ctx, -3); /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */ duk_pop(ctx); DUK_ASSERT(duk_is_string(ctx, -1)); }
AJ_Status AJS_UnmarshalPropArgs(duk_context* ctx, AJ_Message* msg, uint8_t accessor, duk_idx_t msgIdx) { AJ_Status status; const char* iface; const char* prop; const char* signature; uint32_t propId; uint8_t secure = FALSE; AJ_InfoPrintf(("PushPropArgs\n")); if (accessor == AJ_PROP_GET_ALL) { status = AJ_UnmarshalArgs(msg, "s", &iface); if (status == AJ_OK) { duk_push_string(ctx, iface); /* * Save interface (read-only) so we know how to marshal the reply values */ duk_push_string(ctx, AJS_HIDDEN_PROP("propIface")); duk_dup(ctx, -2); duk_def_prop(ctx, msgIdx, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE); } /* * This call always returns an error status because the interface name we are passing in is * invalid but it will indicate if security is required so we can perform the check below */ AJ_IdentifyProperty(msg, iface, "", &propId, &signature, &secure); } else { status = AJ_UnmarshalArgs(msg, "ss", &iface, &prop); if (status == AJ_OK) { status = AJ_IdentifyProperty(msg, iface, prop, &propId, &signature, &secure); if (status == AJ_OK) { duk_push_string(ctx, iface); duk_push_string(ctx, prop); if (accessor == AJ_PROP_GET) { /* * If we are getting a property save the signature so we know how to marshal the * value in the reply. */ duk_push_string(ctx, AJS_HIDDEN_PROP("propSig")); duk_push_string(ctx, signature); duk_def_prop(ctx, msgIdx, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE); } else { /* * Push the value to set */ status = PushArg(ctx, msg); } } } } /* * If the interface is secure check the message is encrypted */ if ((status == AJ_OK) && secure && !(msg->hdr->flags & AJ_FLAG_ENCRYPTED)) { status = AJ_ERR_SECURITY; AJ_WarnPrintf(("Security violation accessing property\n")); } return status; }
gpointer _gum_duk_steal_data (duk_context * ctx, duk_idx_t index) { gpointer result = NULL; duk_dup (ctx, index); duk_get_prop_string (ctx, -1, "\xff" "priv"); if (!duk_is_undefined (ctx, -1)) { result = duk_require_pointer (ctx, -1); duk_pop (ctx); duk_push_pointer (ctx, NULL); duk_put_prop_string (ctx, -2, "\xff" "priv"); duk_pop (ctx); } else { duk_pop_2 (ctx); } return result; }
static duk_ret_t Entity_GetProperty(duk_context* ctx) { /* 'this' binding: handler * [0]: target * [1]: key * [2]: receiver (proxy) */ const char* compTypeName = duk_to_string(ctx, 1); // Component properties must be lowercase to optimize speed, as this is called for every property access. // Exception: do not look up Name component, as Entity also has its own "name" property if (compTypeName && compTypeName[0] >= 'a' && compTypeName[0] <= 'z' && strcmp(compTypeName, "name")) { Entity* entity = GetWeakObject<Entity>(ctx, 0); if (entity) { String compTypeStr(compTypeName); IComponent* comp = entity->Component(compTypeStr); if (comp) { PushWeakObject(ctx, comp); return 1; } } } // Fallthrough to ordinary properties duk_dup(ctx, 1); duk_get_prop(ctx, 0); return 1; }
DUK_EXTERNAL void duk_enum(duk_context *ctx, duk_idx_t obj_index, duk_uint_t enum_flags) { DUK_ASSERT_CTX_VALID(ctx); duk_dup(ctx, obj_index); duk_require_hobject_or_lfunc_coerce(ctx, -1); duk_hobject_enumerator_create(ctx, enum_flags); /* [target] -> [enum] */ }
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; }
DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_context *ctx, duk_small_uint_t stridx_key) { /* Attempt to write 'stack', 'fileName', 'lineNumber' works as if * user code called Object.defineProperty() to create an overriding * own property. This allows user code to overwrite .fileName etc * intuitively as e.g. "err.fileName = 'dummy'" as one might expect. * See https://github.com/svaarala/duktape/issues/387. */ DUK_ASSERT_TOP(ctx, 1); /* fixed arg count: value */ duk_push_this(ctx); duk_push_hstring_stridx(ctx, (duk_small_int_t) stridx_key); duk_dup(ctx, 0); /* [ ... obj key value ] */ DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T", duk_get_tval(ctx, -3), duk_get_tval(ctx, -2), duk_get_tval(ctx, -1))); duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE | DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/ DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE); return 0; }