static int sys1_poll(duk_context *ctx) { int nfds = duk_to_int(ctx, 1); int timeout = duk_to_int(ctx, 2); int i, rc; struct pollfd *fds; fds = malloc(sizeof(struct pollfd)*nfds); memset(fds, 0, sizeof(struct pollfd)*nfds); for(i=0;i<nfds;i++) { duk_get_prop_index(ctx, 0, i); duk_get_prop_string(ctx, 3, "fd"); fds[i].fd = duk_to_int(ctx, 4); duk_get_prop_string(ctx, 3, "events"); fds[i].events = duk_to_int(ctx, 5); duk_pop_n(ctx, 3); } rc = poll(fds, nfds, timeout); duk_push_object(ctx); duk_push_int(ctx, rc); duk_put_prop_string(ctx, -2, "rc"); duk_dup(ctx, 0); // dup reference to arg0 array for(i=0;i<nfds;i++) { duk_get_prop_index(ctx, -1, i); // fetch object from array at i duk_push_int(ctx, fds[i].revents); duk_put_prop_string(ctx, -2, "revents"); // put revents into object duk_pop(ctx); // remove object from stack } duk_put_prop_string(ctx, -2, "fds"); return 1; }
/* duk_get_prop_index(), success cases */ static duk_ret_t test_3a(duk_context *ctx) { duk_ret_t rc; prep(ctx); rc = duk_get_prop_index(ctx, 0, 31337); printf("obj[31337] -> rc=%d, result='%s'\n", (int) rc, duk_to_string(ctx, -1)); duk_pop(ctx); rc = duk_get_prop_index(ctx, 0, 123); printf("obj[123] -> rc=%d, result='%s'\n", (int) rc, duk_to_string(ctx, -1)); duk_pop(ctx); rc = duk_get_prop_index(ctx, 1, 31337); printf("arr[31337] -> rc=%d, result='%s'\n", (int) rc, duk_to_string(ctx, -1)); duk_pop(ctx); rc = duk_get_prop_index(ctx, 1, 2); printf("arr[2] -> rc=%d, result='%s'\n", (int) rc, duk_to_string(ctx, -1)); duk_pop(ctx); rc = duk_get_prop_index(ctx, 2, 5); printf("'test_string'[5] -> rc=%d, result='%s'\n", (int) rc, duk_to_string(ctx, -1)); duk_pop(ctx); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* * High precission time. If an optional array is given * it returns the difference. */ static duk_ret_t time_hrtime(duk_context* ctx) { uint64_t t = sjs_time_hrtime(); uint64_t sec; uint64_t nsec; if (duk_is_array(ctx, 0)) { uint64_t t0; uint64_t sec0; uint64_t nsec0; duk_get_prop_index(ctx, 0, 0); sec0 = duk_require_uint(ctx, -1); duk_pop(ctx); duk_get_prop_index(ctx, 0, 1); nsec0 = duk_require_uint(ctx, -1); duk_pop(ctx); t0 = sec0 * NANOS_PER_SEC + nsec0; t -= t0; } sec = t / NANOS_PER_SEC; nsec = t % NANOS_PER_SEC; duk_push_array(ctx); duk_push_uint(ctx, sec); duk_put_prop_index(ctx, -2, 0); duk_push_uint(ctx, nsec); duk_put_prop_index(ctx, -2, 1); return 1; }
static void remapCallback(void* data, s32 x, s32 y, RemapResult* result) { RemapData* remap = (RemapData*)data; duk_context* duk = remap->duk; duk_push_heapptr(duk, remap->remap); duk_push_int(duk, result->index); duk_push_int(duk, x); duk_push_int(duk, y); duk_pcall(duk, 3); if(duk_is_array(duk, -1)) { duk_get_prop_index(duk, -1, 0); result->index = duk_to_int(duk, -1); duk_pop(duk); duk_get_prop_index(duk, -1, 1); result->flip = duk_to_int(duk, -1); duk_pop(duk); duk_get_prop_index(duk, -1, 2); result->rotate = duk_to_int(duk, -1); duk_pop(duk); } else { result->index = duk_to_int(duk, -1); } duk_pop(duk); }
DUK_LOCAL void duk__array_sort_swap(duk_context *ctx, duk_int_t l, duk_int_t r) { duk_bool_t have_l, have_r; duk_idx_t idx_obj = 1; /* fixed offset in valstack */ if (l == r) { return; } /* swap elements; deal with non-existent elements correctly */ have_l = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) l); have_r = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) r); if (have_r) { /* right exists, [[Put]] regardless whether or not left exists */ duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) l); } else { duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) l); duk_pop(ctx); } if (have_l) { duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) r); } else { duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) r); duk_pop(ctx); } }
static int sys1_execve(duk_context *ctx) { const char *filename = duk_to_string(ctx, 0); int rc; char **argv; char **envp; int argc = 0, envc = 0, i; // count arguments // FIXME: Use duk_get_length() instead ? while(1) { rc = duk_get_prop_index(ctx, 1, argc); duk_pop(ctx); if(rc == 0) break; argc++; } argv = malloc(sizeof(char*)*(argc+1)); for(i=0;i<argc;i++) { duk_get_prop_index(ctx, 1, i); argv[i] = (char*) duk_to_string(ctx, 3); duk_pop(ctx); } argv[i] = (void*)0; // count arguments // FIXME: Use duk_get_length() instead ? while(1) { rc = duk_get_prop_index(ctx, 2, envc); duk_pop(ctx); if(rc == 0) break; envc++; } envp = malloc(sizeof(char*)*(envc+1)); for(i=0;i<envc;i++) { duk_get_prop_index(ctx, 2, i); envp[i] = (char*) duk_to_string(ctx, 3); duk_pop(ctx); } envp[i] = (void*)0; rc = execve(filename, argv, envp); duk_push_int(ctx, rc); return 1; }
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 js_PointSeries(duk_context* ctx) { duk_require_object_coercible(ctx, 0); color_t color = duk_require_sphere_color(ctx, 1); size_t num_points; int x, y; ALLEGRO_VERTEX* vertices; ALLEGRO_COLOR vtx_color; size_t i; if (!duk_is_array(ctx, 0)) duk_error_ni(ctx, -1, DUK_ERR_ERROR, "PointSeries(): First argument must be an array"); duk_get_prop_string(ctx, 0, "length"); num_points = duk_get_uint(ctx, 0); duk_pop(ctx); if (num_points < 1) duk_error_ni(ctx, -1, DUK_ERR_RANGE_ERROR, "PointSeries(): One or more vertices required"); if (num_points > INT_MAX) duk_error_ni(ctx, -1, DUK_ERR_RANGE_ERROR, "PointSeries(): Too many vertices"); if ((vertices = calloc(num_points, sizeof(ALLEGRO_VERTEX))) == NULL) duk_error_ni(ctx, -1, DUK_ERR_ERROR, "PointSeries(): Failed to allocate vertex buffer"); vtx_color = nativecolor(color); for (i = 0; i < num_points; ++i) { duk_get_prop_index(ctx, 0, (duk_uarridx_t)i); duk_get_prop_string(ctx, 0, "x"); x = duk_require_int(ctx, -1); duk_pop(ctx); duk_get_prop_string(ctx, 0, "y"); y = duk_require_int(ctx, -1); duk_pop(ctx); duk_pop(ctx); vertices[i].x = x + 0.5; vertices[i].y = y + 0.5; vertices[i].color = vtx_color; } al_draw_prim(vertices, NULL, NULL, 0, (int)num_points, ALLEGRO_PRIM_POINT_LIST); free(vertices); return 0; }
bool StyleContext::evalFilter(FunctionID _id) const { if (!duk_get_global_string(m_ctx, FUNC_ID)) { logMsg("Error: evalFilterFn - functions not initialized\n"); return false; } if (!duk_get_prop_index(m_ctx, -1, _id)) { logMsg("Error: evalFilterFn - function %d not set\n", _id); } if (duk_pcall(m_ctx, 0) != 0) { logMsg("Error: evalFilterFn: %s\n", duk_safe_to_string(m_ctx, -1)); } bool result = false; if (duk_is_boolean(m_ctx, -1)) { result = duk_get_boolean(m_ctx, -1); } // pop result duk_pop(m_ctx); // pop fns obj duk_pop(m_ctx); DUMP("evalFilterFn\n"); return result; }
bool StyleContext::evalFunction(FunctionID id) { // Get all functions (array) in context if (!duk_get_global_string(m_ctx, FUNC_ID)) { LOGE("EvalFilterFn - functions array not initialized"); duk_pop(m_ctx); // pop [undefined] sitting at stack top return false; } // Get function at index `id` from functions array, put it at stack top if (!duk_get_prop_index(m_ctx, -1, id)) { LOGE("EvalFilterFn - function %d not set", id); duk_pop(m_ctx); // pop "undefined" sitting at stack top duk_pop(m_ctx); // pop functions (array) now sitting at stack top return false; } // pop fns array duk_remove(m_ctx, -2); // call popped function (sitting at stack top), evaluated value is put on stack top if (duk_pcall(m_ctx, 0) != 0) { LOGE("EvalFilterFn: %s", duk_safe_to_string(m_ctx, -1)); duk_pop(m_ctx); return false; } return true; }
duk_ret_t JavaScriptObject::finalizer(duk_context* ctx) { // Remove this pointers from the JS object's property. if (duk_get_prop_string(ctx, -1, WRAPPER_THIS_PROP_NAME)) { const duk_size_t length = duk_get_length(ctx, -1); for (duk_uarridx_t i = 0; i < length; ++i) { duk_get_prop_index(ctx, -1, i); JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(duk_get_pointer(ctx, -1)); if (obj && obj->m_instance) { // Null out the instance pointer - it's been garbage collected! obj->m_instance = nullptr; if (obj->m_nextFinalizer) { // Continue with the next finalizer in the chain. obj->m_nextFinalizer(ctx); } } duk_pop(ctx); } } // Pop the array (or undefined if there was none). duk_pop(ctx); return 0; }
Variant DuktapeScriptFunction::call(const std::vector<Variant> & args) { // Get function wrapper from stash duk_push_global_stash(m_context); duk_get_prop_index(m_context, -1, m_stashIndex); // Push arguments for (Variant var : args) { m_scriptBackend->pushToDukStack(var); } // Call function duk_int_t error = duk_pcall(m_context, args.size()); // Check for error if (error) { // Raise script exception m_scriptBackend->m_scriptContext->scriptException(std::string(duk_safe_to_string(m_context, -1))); duk_pop_2(m_context); return Variant(); } // Convert return value Variant value = m_scriptBackend->fromDukStack(-1); duk_pop_2(m_context); return value; }
void JSEventDispatcher::EndSendEvent(Context* context, Object* sender, StringHash eventType, VariantMap& eventData) { if (!jsEvents_.Contains(eventType)) return; JSVM* vm = JSVM::GetJSVM(NULL); if (!vm) return; duk_context* ctx = vm->GetJSContext(); duk_push_global_stash(ctx); duk_get_prop_index(ctx, -1, JS_GLOBALSTASH_VARIANTMAP_CACHE); duk_push_pointer(ctx, (void*) &eventData); duk_get_prop(ctx, -2); // If this issue is addressed, revisit this to simply remove // the variantmap object from the cache, if the user explicitly // keeps the event object alive in a local closure, that is allowed // (though, will keep object properties from being GC'd) // https://github.com/svaarala/duktape/issues/229 // Ok, this is unfortunate, in an event callback it is possible // to capture the Proxy object which represents the event VariantMap // in a function() {} closure, which will keep the event data alive // until the function happens to be gc'd (it is a member of the eventhandler) // which will leave things like scenes up if there was a P_SCENE event data // member, etc // So, we need to check if we have an object in the variant map cache // and thense call it's delete property method on the Proxy, which will clear // all the data (the proxy can still be alive as a captured local, though // the members won't be held // This all makes it that much more important that the pointer to eventData // is consistent across entire event, otherwise references may be held // see note above about: https://github.com/svaarala/duktape/issues/229 if (duk_is_object(ctx, -1)) { // deletes all properties, thus freeing references, even if // the variant map object is held onto by script (it will be invalid, post // event send) // see JSAPI.cpp variantmap_property_deleteproperty duk_del_prop_index(ctx, -1, 0); duk_push_pointer(ctx, (void*) &eventData); duk_push_undefined(ctx); // clear the variant map object from the cache duk_put_prop(ctx, -4); } duk_pop_3(ctx); }
DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx) { duk_uint32_t len; duk_uint32_t middle; duk_uint32_t lower, upper; duk_bool_t have_lower, have_upper; len = duk__push_this_obj_len_u32(ctx); middle = len / 2; /* If len <= 1, middle will be 0 and for-loop bails out * immediately (0 < 0 -> false). */ for (lower = 0; lower < middle; lower++) { DUK_ASSERT(len >= 2); DUK_ASSERT_TOP(ctx, 2); DUK_ASSERT(len >= lower + 1); upper = len - lower - 1; have_lower = duk_get_prop_index(ctx, -2, (duk_uarridx_t) lower); have_upper = duk_get_prop_index(ctx, -3, (duk_uarridx_t) upper); /* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */ if (have_upper) { duk_put_prop_index(ctx, -4, (duk_uarridx_t) lower); } else { duk_del_prop_index(ctx, -4, (duk_uarridx_t) lower); duk_pop(ctx); } if (have_lower) { duk_put_prop_index(ctx, -3, (duk_uarridx_t) upper); } else { duk_del_prop_index(ctx, -3, (duk_uarridx_t) upper); duk_pop(ctx); } DUK_ASSERT_TOP(ctx, 2); } DUK_ASSERT_TOP(ctx, 2); duk_pop(ctx); /* -> [ ToObject(this) ] */ return 1; }
DUK_INTERNAL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx) { duk_idx_t nargs; duk_uint32_t len; duk_uint32_t i; nargs = duk_get_top(ctx); len = duk__push_this_obj_len_u32(ctx); /* stack[0...nargs-1] = unshift args (vararg) * stack[nargs] = ToObject(this) * stack[nargs+1] = ToUint32(length) */ DUK_ASSERT_TOP(ctx, nargs + 2); /* Note: unshift() may operate on indices above unsigned 32-bit range * and the final length may be >= 2**32. However, we restrict the * final result to 32-bit range for practicality. */ if (len + (duk_uint32_t) nargs < len) { DUK_D(DUK_DPRINT("Array.prototype.unshift() would go beyond 32-bit length, throw")); return DUK_RET_RANGE_ERROR; } i = len; while (i > 0) { DUK_ASSERT_TOP(ctx, nargs + 2); i--; /* k+argCount-1; note that may be above 32-bit range */ if (duk_get_prop_index(ctx, -2, (duk_uarridx_t) i)) { /* fromPresent = true */ /* [ ... ToObject(this) ToUint32(length) val ] */ duk_put_prop_index(ctx, -3, (duk_uarridx_t) (i + nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */ } else { /* fromPresent = false */ /* [ ... ToObject(this) ToUint32(length) val ] */ duk_pop(ctx); duk_del_prop_index(ctx, -2, (duk_uarridx_t) (i + nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */ } DUK_ASSERT_TOP(ctx, nargs + 2); } for (i = 0; i < (duk_uint32_t) nargs; i++) { DUK_ASSERT_TOP(ctx, nargs + 2); duk_dup(ctx, i); /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */ duk_put_prop_index(ctx, -3, (duk_uarridx_t) i); DUK_ASSERT_TOP(ctx, nargs + 2); } DUK_ASSERT_TOP(ctx, nargs + 2); duk_push_u32(ctx, len + nargs); duk_dup_top(ctx); /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */ duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH); return 1; }
DUK_INTERNAL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx) { duk_uint32_t len; duk_int_t start, end; duk_int_t i; duk_uarridx_t idx; duk_uint32_t res_length = 0; /* XXX: len >= 0x80000000 won't work below because we need to be * able to represent -len. */ len = duk__push_this_obj_len_u32_limited(ctx); duk_push_array(ctx); /* stack[0] = start * stack[1] = end * stack[2] = ToObject(this) * stack[3] = ToUint32(length) * stack[4] = result array */ start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len); if (start < 0) { start = len + start; } /* XXX: could duk_is_undefined() provide defaulting undefined to 'len' * (the upper limit)? */ if (duk_is_undefined(ctx, 1)) { end = len; } else { end = duk_to_int_clamped(ctx, 1, -((duk_int_t) len), (duk_int_t) len); if (end < 0) { end = len + end; } } DUK_ASSERT(start >= 0 && (duk_uint32_t) start <= len); DUK_ASSERT(end >= 0 && (duk_uint32_t) end <= len); idx = 0; for (i = start; i < end; i++) { DUK_ASSERT_TOP(ctx, 5); if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) { duk_xdef_prop_index_wec(ctx, 4, idx); res_length = idx + 1; } else { duk_pop(ctx); } idx++; DUK_ASSERT_TOP(ctx, 5); } duk_push_u32(ctx, res_length); duk_xdef_prop_stridx(ctx, 4, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); DUK_ASSERT_TOP(ctx, 5); return 1; }
DUK_INTERNAL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx) { duk_idx_t len; duk_idx_t i; DUK_ASSERT_TOP(ctx, 2); /* not a vararg function */ duk_push_this(ctx); if (!duk_is_callable(ctx, -1)) { DUK_DDD(DUK_DDDPRINT("func is not callable")); goto type_error; } duk_insert(ctx, 0); DUK_ASSERT_TOP(ctx, 3); DUK_DDD(DUK_DDDPRINT("func=%!iT, thisArg=%!iT, argArray=%!iT", (duk_tval *) duk_get_tval(ctx, 0), (duk_tval *) duk_get_tval(ctx, 1), (duk_tval *) duk_get_tval(ctx, 2))); /* [ func thisArg argArray ] */ if (duk_is_null_or_undefined(ctx, 2)) { DUK_DDD(DUK_DDDPRINT("argArray is null/undefined, no args")); len = 0; } else if (!duk_is_object(ctx, 2)) { goto type_error; } else { DUK_DDD(DUK_DDDPRINT("argArray is an object")); /* XXX: make this an internal helper */ duk_get_prop_stridx(ctx, 2, DUK_STRIDX_LENGTH); len = (duk_idx_t) duk_to_uint32(ctx, -1); /* ToUint32() coercion required */ duk_pop(ctx); duk_require_stack(ctx, len); DUK_DDD(DUK_DDDPRINT("argArray length is %ld", (long) len)); for (i = 0; i < len; i++) { duk_get_prop_index(ctx, 2, i); } } duk_remove(ctx, 2); DUK_ASSERT_TOP(ctx, 2 + len); /* [ func thisArg arg1 ... argN ] */ DUK_DDD(DUK_DDDPRINT("apply, func=%!iT, thisArg=%!iT, len=%ld", (duk_tval *) duk_get_tval(ctx, 0), (duk_tval *) duk_get_tval(ctx, 1), (long) len)); duk_call_method(ctx, len); return 1; type_error: return DUK_RET_TYPE_ERROR; }
void PushWeakObject(duk_context* ctx, Object* object) { if (!object) { duk_push_null(ctx); return; } duk_push_heap_stash(ctx); // Check if the wrapper for the object already exists in stash // This is required so that comparisons of object references (e.g. against the me property) work properly if (duk_has_prop_index(ctx, -1, (size_t)object)) { duk_get_prop_index(ctx, -1, (size_t)object); WeakPtr<Object>* oldPtr = GetWeakPtr(ctx, -1); if (oldPtr && oldPtr->Get() == object) { duk_remove(ctx, -2); // Remove stash return; } else duk_pop(ctx); // Valid existing wrapper not found } duk_push_object(ctx); WeakPtr<Object>* ptr = new WeakPtr<Object>(object); duk_push_pointer(ctx, ptr); duk_put_prop_string(ctx, -2, "\xff""weak"); duk_push_c_function(ctx, WeakPtr_Finalizer, 1); duk_set_finalizer(ctx, -2); // Set prototype. If not found, use base class prototype (e.g. IComponent) duk_get_global_string(ctx, object->GetTypeName().CString()); if (!duk_is_object(ctx, -1)) { duk_pop(ctx); duk_get_global_string(ctx, object->GetTypeInfo()->GetBaseTypeInfo()->GetTypeName().CString()); } duk_get_prop_string(ctx, -1, "prototype"); duk_set_prototype(ctx, -3); duk_pop(ctx); // Proxied property access handling for scene, entity & component if (object->GetType() == Scene::GetTypeStatic()) SetupProxy(ctx, SceneProxyFunctions); if (object->GetType() == Entity::GetTypeStatic()) SetupProxy(ctx, EntityProxyFunctions); else if (dynamic_cast<IComponent*>(object)) SetupProxy(ctx, ComponentProxyFunctions); // Store to stash duk_dup(ctx, -1); duk_put_prop_index(ctx, -3, (size_t)object); duk_remove(ctx, -2); // Remove stash }
int duk_bi_array_prototype_slice(duk_context *ctx) { unsigned int len; int start, end; int idx; int i; duk_uint32_t res_length = 0; len = duk__push_this_obj_len_u32(ctx); duk_push_array(ctx); /* stack[0] = start * stack[1] = end * stack[2] = ToObject(this) * stack[3] = ToUint32(length) * stack[4] = result array */ start = duk_to_int_clamped(ctx, 0, -len, len); /* FIXME: does not support full 32-bit range */ if (start < 0) { start = len + start; } /* FIXME: could duk_is_undefined() provide defaulting undefined to 'len' * (the upper limit)? */ if (duk_is_undefined(ctx, 1)) { end = len; } else { end = duk_to_int_clamped(ctx, 1, -len, len); if (end < 0) { end = len + end; } } DUK_ASSERT(start >= 0 && (duk_uint32_t) start <= len); DUK_ASSERT(end >= 0 && (duk_uint32_t) end <= len); idx = 0; for (i = start; i < end; i++) { DUK_ASSERT_TOP(ctx, 5); if (duk_get_prop_index(ctx, 2, i)) { duk_def_prop_index(ctx, 4, idx, DUK_PROPDESC_FLAGS_WEC); res_length = idx + 1; } else { duk_pop(ctx); } idx++; DUK_ASSERT_TOP(ctx, 5); } duk_push_int(ctx, res_length); /* FIXME */ duk_def_prop_stridx(ctx, 4, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); DUK_ASSERT_TOP(ctx, 5); return 1; }
int duk_bi_array_prototype_unshift(duk_context *ctx) { unsigned int nargs; unsigned int len; unsigned int i; double final_len; /* FIXME: duk_get_top return type */ nargs = (unsigned int) duk_get_top(ctx); len = duk__push_this_obj_len_u32(ctx); /* stack[0...nargs-1] = unshift args (vararg) * stack[nargs] = ToObject(this) * stack[nargs+1] = ToUint32(length) */ DUK_ASSERT_TOP(ctx, nargs + 2); /* Note: unshift() may operate on indices above unsigned 32-bit range * and the final length may be >= 2**32. Hence we use 'double' vars * here, when appropriate. */ i = len; while (i > 0) { DUK_ASSERT_TOP(ctx, nargs + 2); i--; duk_push_number(ctx, ((double) i) + ((double) nargs)); /* k+argCount-1; note that may be above 32-bit range */ if (duk_get_prop_index(ctx, -3, i)) { /* fromPresent = true */ /* [ ... ToObject(this) ToUint32(length) to val ] */ duk_put_prop(ctx, -4); /* -> [ ... ToObject(this) ToUint32(length) ] */ /* FIXME: Throw */ } else { /* fromPresent = false */ /* [ ... ToObject(this) ToUint32(length) to val ] */ duk_pop(ctx); duk_del_prop(ctx, -3); /* -> [ ... ToObject(this) ToUint32(length) ] */ /* FIXME: Throw */ } DUK_ASSERT_TOP(ctx, nargs + 2); } for (i = 0; i < nargs; i++) { DUK_ASSERT_TOP(ctx, nargs + 2); duk_dup(ctx, i); /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */ duk_put_prop_index(ctx, -3, i); /* FIXME: Throw */ DUK_ASSERT_TOP(ctx, nargs + 2); } DUK_ASSERT_TOP(ctx, nargs + 2); final_len = ((double) len) + ((double) nargs); duk_push_number(ctx, final_len); duk_dup_top(ctx); /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */ duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH); /* FIXME: Throw */ return 1; }
/* duk_get_prop_index(), invalid index */ int test_3b(duk_context *ctx) { int rc; prep(ctx); rc = duk_get_prop_index(ctx, 234, 123); printf("obj[123] -> rc=%d, result='%s'\n", rc, duk_to_string(ctx, -1)); duk_pop(ctx); printf("final top: %d\n", duk_get_top(ctx)); return 0; }
/* duk_get_prop_index(), DUK_INVALID_INDEX */ static duk_ret_t test_3c(duk_context *ctx) { duk_ret_t rc; prep(ctx); rc = duk_get_prop_index(ctx, DUK_INVALID_INDEX, 123); printf("obj[123] -> rc=%d, result='%s'\n", (int) rc, duk_to_string(ctx, -1)); duk_pop(ctx); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* * Looks for an interface that defines a specific member. * * TODO - check for ambiguity - same member defined on multiple interfaces */ static const char* FindInterfaceForMember(duk_context* ctx, duk_idx_t mbrIdx, const char** member) { const char* iface = NULL; uint8_t found = FALSE; size_t numInterfaces; duk_idx_t listIdx; duk_get_prop_string(ctx, -1, "interfaces"); numInterfaces = duk_get_length(ctx, -1); listIdx = AJS_GetAllJoynProperty(ctx, "interfaceDefinition"); if (duk_is_object(ctx, mbrIdx)) { /* * Expect an object of form { member:"org.foo.interface" } */ duk_enum(ctx, mbrIdx, DUK_ENUM_OWN_PROPERTIES_ONLY); if (!duk_next(ctx, -1, 1)) { duk_error(ctx, DUK_ERR_TYPE_ERROR, "Require object of form { 'member-name':'interface-name' }"); } iface = duk_require_string(ctx, -1); if (!AJ_StringFindFirstOf(iface, ".") == -1) { duk_error(ctx, DUK_ERR_TYPE_ERROR, "Interface name '%s' is not a dotted name", iface); } *member = duk_require_string(ctx, -2); duk_get_prop_string(ctx, listIdx, iface); if (duk_is_undefined(ctx, -1)) { duk_error(ctx, DUK_ERR_REFERENCE_ERROR, "Unknown interface: '%s'", iface); } found = duk_has_prop_string(ctx, -1, *member); duk_pop_n(ctx, 4); } else { size_t i; /* * Expect a string */ *member = duk_require_string(ctx, mbrIdx); for (i = 0; !found && (i < numInterfaces); ++i) { duk_get_prop_index(ctx, -2, i); iface = duk_require_string(ctx, -1); duk_get_prop_string(ctx, listIdx, iface); /* * See if the requested member exists on this interface */ found = duk_has_prop_string(ctx, -1, *member); duk_pop_2(ctx); } } duk_pop_2(ctx); if (!found) { duk_error(ctx, DUK_ERR_REFERENCE_ERROR, "Unknown member: '%s'", *member); } return iface; }
int duk_bi_array_prototype_reverse(duk_context *ctx) { unsigned int len; unsigned int middle; unsigned int lower, upper; int have_lower, have_upper; len = duk__push_this_obj_len_u32(ctx); middle = len / 2; for (lower = 0; lower < middle; lower++) { DUK_ASSERT_TOP(ctx, 2); upper = len - lower - 1; have_lower = duk_get_prop_index(ctx, -2, lower); have_upper = duk_get_prop_index(ctx, -3, upper); /* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */ if (have_upper) { duk_put_prop_index(ctx, -4, lower); /* FIXME: Throw */ } else { duk_del_prop_index(ctx, -4, lower); duk_pop(ctx); } if (have_lower) { duk_put_prop_index(ctx, -3, upper); } else { duk_del_prop_index(ctx, -3, upper); duk_pop(ctx); } DUK_ASSERT_TOP(ctx, 2); } DUK_ASSERT_TOP(ctx, 2); duk_pop(ctx); /* -> [ ToObject(this) ] */ return 1; }
void GCObjectPool::addNewList() { Isolate *isolate = Isolate::GetCurrent(); duk_context *ctx = isolate->GetDukContext(); // Get the "refs" array in the heap stash duk_push_global_stash(ctx); duk_get_prop_string(ctx, -1, "__object_list"); duk_remove(ctx, -2); int type = duk_get_type(ctx, -1); int freeSlot; // freeSlot = scopeList[0] duk_get_prop_index(ctx, -1, 0); // <scopeList> <scopeList[0]> freeSlot = duk_get_int(ctx, -1); duk_pop(ctx); // <scopeList> if (freeSlot != 0) { // scopeList[0] = scopeList[freeSlot] duk_get_prop_index(ctx, -1, (duk_uarridx_t) freeSlot); // <scopeList> <scopeList[freeSlot]> duk_put_prop_index(ctx, -2, 0); // <scopeList> } else { // freeSlot = scopeList.length; freeSlot = (int) duk_get_length(ctx, -1); } duk_push_array(ctx); list_ptr_ = duk_get_heapptr(ctx, -1); // <scopeList> <scope> // scopeList[freeSlot] = scope duk_put_prop_index(ctx, -2, (duk_uarridx_t) freeSlot); // <scopeList> // Remove the refs array from the stack. duk_pop(ctx); // list_idx_ = freeSlot; }
/* * like luaL_ref, but assumes storage in "refs" property of heap stash */ int mn_ref(duk_context *ctx) { int ref; if (duk_is_undefined(ctx, -1)) { duk_pop(ctx); return 0; } /* Get the "refs" array in the heap stash */ duk_push_heap_stash(ctx); duk_get_prop_string(ctx, -1, "refs"); duk_remove(ctx, -2); /* ref = refs[0] */ duk_get_prop_index(ctx, -1, 0); ref = duk_get_int(ctx, -1); duk_pop(ctx); /* If there was a free slot, remove it from the list */ if (ref != 0) { /* refs[0] = refs[ref] */ duk_get_prop_index(ctx, -1, ref); duk_put_prop_index(ctx, -2, 0); } else { /* Otherwise use the end of the list */ ref = duk_get_length(ctx, -1); } /* Swap the array and the user value in the stack */ duk_insert(ctx, -2); /* refs[ref] = value */ duk_put_prop_index(ctx, -2, ref); /* Remove the refs array from the stack. */ duk_pop(ctx); return ref; }
gboolean _gum_duk_parse_bytes (duk_context * ctx, duk_idx_t index, GBytes ** bytes) { gpointer data; duk_size_t size; data = duk_get_buffer_data (ctx, index, &size); if (data != NULL) { *bytes = g_bytes_new (data, size); return TRUE; } else if (duk_is_array (ctx, index)) { duk_size_t i; duk_get_prop_string (ctx, index, "length"); size = duk_get_uint (ctx, -1); duk_pop (ctx); if (size >= GUM_MAX_JS_BYTE_ARRAY_LENGTH) return FALSE; data = g_malloc (size); for (i = 0; i != size; i++) { duk_get_prop_index (ctx, index, (duk_uarridx_t) i); ((guint8 *) data)[i] = duk_get_uint (ctx, -1) & 0xff; duk_pop (ctx); } *bytes = g_bytes_new_take (data, size); return TRUE; } else if (duk_is_null_or_undefined (ctx, index) || duk_is_boolean (ctx, index) || duk_is_number (ctx, index) || duk_is_nan (ctx, index) || duk_is_string (ctx, index) || duk_is_function (ctx, index)) { return FALSE; } *bytes = g_bytes_new (NULL, 0); return TRUE; }
/* duk_get_prop_index(), invalid index */ static duk_ret_t test_getpropindex_b(duk_context *ctx, void *udata) { duk_ret_t rc; (void) udata; prep(ctx); rc = duk_get_prop_index(ctx, 234, 123); printf("obj[123] -> rc=%d, result='%s'\n", (int) rc, duk_to_string(ctx, -1)); duk_pop(ctx); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
int GlobalStash::AddObject(void *ptr) { Isolate *isolate = Isolate::GetCurrent(); duk_context *ctx = isolate->GetDukContext(); // Get the "refs" array in the heap stash duk_push_global_stash(ctx); duk_get_prop_string(ctx, -1, name_); duk_remove(ctx, -2); int type = duk_get_type(ctx, -1); int freeSlot; // freeSlot = scopeList[0] duk_get_prop_index(ctx, -1, 0); // <scopeList> <scopeList[0]> freeSlot = duk_get_int(ctx, -1); duk_pop(ctx); // <scopeList> if (freeSlot != 0) { // scopeList[0] = scopeList[freeSlot] duk_get_prop_index(ctx, -1, (duk_uarridx_t) freeSlot); // <scopeList> <scopeList[freeSlot]> duk_put_prop_index(ctx, -2, 0); // <scopeList> } else { // freeSlot = scopeList.length; freeSlot = (int) duk_get_length(ctx, -1); } duk_push_heapptr(ctx, ptr); // <scopeList> <scope> // scopeList[freeSlot] = scope duk_put_prop_index(ctx, -2, (duk_uarridx_t) freeSlot); // <scopeList> // Remove the refs array from the stack. duk_pop(ctx); // return freeSlot; }
DUK_INTERNAL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx) { duk_uint32_t len; duk_uint32_t i; len = duk__push_this_obj_len_u32(ctx); if (len == 0) { duk_push_int(ctx, 0); duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH); return 0; } duk_get_prop_index(ctx, 0, 0); /* stack[0] = object (this) * stack[1] = ToUint32(length) * stack[2] = elem at index 0 (retval) */ for (i = 1; i < len; i++) { DUK_ASSERT_TOP(ctx, 3); if (duk_get_prop_index(ctx, 0, (duk_uarridx_t) i)) { /* fromPresent = true */ duk_put_prop_index(ctx, 0, (duk_uarridx_t) (i - 1)); } else { /* fromPresent = false */ duk_del_prop_index(ctx, 0, (duk_uarridx_t) (i - 1)); duk_pop(ctx); } } duk_del_prop_index(ctx, 0, (duk_uarridx_t) (len - 1)); duk_push_u32(ctx, (duk_uint32_t) (len - 1)); duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH); DUK_ASSERT_TOP(ctx, 3); return 1; }