static int UIButton_Popup(duk_context* ctx) { if (!duk_is_object(ctx, 0)) { duk_push_string(ctx, "UIButton.popup first argument must be an object"); duk_throw(ctx); } if (!duk_is_callable(ctx, 1)) { duk_push_string(ctx, "UIButton.popup second argument must be callable"); duk_throw(ctx); } JSVM* vm = JSVM::GetJSVM(ctx); duk_enum(ctx, 0, DUK_ENUM_OWN_PROPERTIES_ONLY); UISelectItemSource* source = new UISelectItemSource(vm->GetContext()); while (duk_next(ctx, -1, 0)) { String key = duk_get_string(ctx, -1); duk_get_prop(ctx, 0); if (duk_is_array(ctx, -1)) { // need to support this, for skin image, etc assert(0); } else if (duk_is_string(ctx, -1)) { // id String id = duk_get_string(ctx, -1); source->AddItem(new UISelectItem(vm->GetContext(), key, id)); } else { duk_push_string(ctx, "UIButton.popup data object key is not an array or string"); duk_throw(ctx); } duk_pop(ctx); // pop key value } duk_pop(ctx); // pop enum object duk_push_this(ctx); duk_dup(ctx, 1); duk_put_prop_string(ctx, -2, "__popup_menu_callback"); UIButton* button = js_to_class_instance<UIButton>(ctx, -1, 0); UIMenuWindow* menuWindow = new UIMenuWindow(vm->GetContext(), button, "__popup-menu"); menuWindow->Show(source); duk_pop(ctx); return 0; }
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_assign(duk_hthread *thr) { duk_idx_t nargs; duk_int_t idx; nargs = duk_get_top_require_min(thr, 1 /*min_top*/); duk_to_object(thr, 0); for (idx = 1; idx < nargs; idx++) { /* E7 19.1.2.1 (step 4a) */ if (duk_is_null_or_undefined(thr, idx)) { continue; } /* duk_enum() respects ES2015+ [[OwnPropertyKeys]] ordering, which is * convenient here. */ duk_to_object(thr, idx); duk_enum(thr, idx, DUK_ENUM_OWN_PROPERTIES_ONLY); while (duk_next(thr, -1, 1 /*get_value*/)) { /* [ target ... enum key value ] */ duk_put_prop(thr, 0); /* [ target ... enum ] */ } /* Could pop enumerator, but unnecessary because of duk_set_top() * below. */ } duk_set_top(thr, 1); return 1; }
int* getIntArray(duk_context *ctx, int stackIndex) { static int* result = NULL; if(duk_is_array(ctx, stackIndex)) { int resultLen = duk_get_length(ctx, stackIndex); result = (int*)malloc( resultLen * sizeof(int) ); memset(result,0,resultLen); duk_enum(ctx, stackIndex, DUK_ENUM_ARRAY_INDICES_ONLY); // NOT stackIndex because waits enumIndex that is -1 int idx=0; while (duk_next(ctx, -1, 1)) { // in JS/duktape toto[1] <=> toto["1"] // that's why keys are strings const char* k = duk_to_string(ctx, -2); int v = duk_to_int(ctx, -1); //printf("key=%s, value=%d\n", k, v); result[idx++] = v; duk_pop_2(ctx); } duk_pop(ctx); // duk_enum } else { printf("Found NO array\n"); } return result; }
static duk_ret_t test_new_1(duk_context *ctx) { /* Create a constructor (function object). Its "prototype" property * controls the internal prototype of created instances. */ duk_push_c_function(ctx, my_func_1, 0); duk_eval_string(ctx, "({ name: 'my prototype' })"); duk_put_prop_string(ctx, -2, "prototype"); duk_new(ctx, 0); /* -> [ ret ] */ duk_pop(ctx); /* If constructor returns an object, it replaces the fresh object * created for the constructor "this" binding. */ duk_push_c_function(ctx, my_func_2, 0); duk_eval_string(ctx, "({ name: 'my prototype' })"); duk_put_prop_string(ctx, -2, "prototype"); duk_new(ctx, 0); /* -> [ ret ] */ duk_enum(ctx, -1, 0 /*enum_flags*/); while (duk_next(ctx, -1, 1 /*get_value*/)) { printf("key='%s', value='%s'\n", duk_to_string(ctx, -2), duk_to_string(ctx, -1)); duk_pop_2(ctx); } duk_pop(ctx); 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 countObjectProperties(duk_context* ctx, duk_uint_t enum_flags, duk_idx_t obj_index) { int count = 0; duk_enum(ctx, obj_index, enum_flags); while(duk_next(ctx, -1, 0)) { duk_pop(ctx); ++count; } duk_pop(ctx); return count; }
AJ_Status AJS_HandleJoinSessionReply(duk_context* ctx, AJ_Message* msg) { const char* peer = NULL; SessionInfo* sessionInfo = NULL; uint32_t replySerial = msg->replySerial; uint8_t joined = FALSE; AJS_GetGlobalStashObject(ctx, "sessions"); duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY); while (duk_next(ctx, -1, 1)) { peer = duk_get_string(ctx, -2); AJ_ASSERT(duk_is_object(ctx, -1)); duk_get_prop_string(ctx, -1, "info"); sessionInfo = duk_get_buffer(ctx, -1, NULL); AJ_ASSERT(sessionInfo); duk_pop_3(ctx); if (sessionInfo->replySerial == replySerial) { uint32_t sessionId; uint32_t replyStatus; /* * Check if the join was successful */ AJ_UnmarshalArgs(msg, "uu", &replyStatus, &sessionId); if (replyStatus == AJ_JOINSESSION_REPLY_SUCCESS) { /* * TODO - if we have a well-known name send a ping to get the unique name */ sessionInfo->sessionId = sessionId; joined = TRUE; } sessionInfo->replySerial = 0; break; } } duk_pop(ctx); /* Pop the enum */ if (joined) { /* * TODO - we may need to initiate authentication with the remote peer */ AnnouncementCallbacks(ctx, peer, sessionInfo); } /* Pop "sessions" */ duk_pop(ctx); return AJ_OK; }
// Duktape.modSearch function, needed for loading modules with require() duk_ret_t module_search(duk_context *ctx) { const char *id = duk_require_string(ctx, 0); // C modules: add functions to exports variable (3rd argument) and return undefined for (int i = 0; i < c_module_count; i++) { if (!strcmp(c_module_list[i].name, id)) { duk_push_c_function(ctx, c_module_list[i].init_func, 0); duk_call(ctx, 0); duk_enum(ctx, -1, 0); while(duk_next(ctx, -1, 1)) { duk_put_prop(ctx, 2); } duk_pop_2(ctx); return 0; } } // JS modules: return source code as a string // Read from file "modname.js.tns" int module_filename_len = strlen(id) + strlen(".js.tns") + 1; char *module_filename = malloc(module_filename_len); if (!module_filename) goto error; snprintf(module_filename, module_filename_len, "%s.js.tns", id); FILE *module_file = fopen(module_filename, "r"); free(module_filename); if (!module_file) goto error; if (fseek(module_file, 0, SEEK_END) != 0) goto error; long module_file_size = ftell(module_file); if (module_file_size == -1) goto error; rewind(module_file); char *src = malloc(module_file_size); if (!src) goto error; fread(src, 1, module_file_size, module_file); if (ferror(module_file)) goto error; fclose(module_file); duk_push_lstring(ctx, src, module_file_size); free(src); return 1; error: duk_push_error_object(ctx, DUK_ERR_ERROR, "module %s not found: %s", id, strerror(errno)); duk_throw(ctx); }
static duk_ret_t my_func_1(duk_context *ctx) { printf("duk_is_constructor_call: %d\n", (int) duk_is_constructor_call(ctx)); /* check 'this'; it should have internal prototype set below to * constructor's "prototype" property. */ duk_push_this(ctx); duk_push_string(ctx, "own_value"); duk_put_prop_string(ctx, -2, "own_key"); duk_enum(ctx, -1, 0 /*enum_flags*/); while (duk_next(ctx, -1, 1 /*get_value*/)) { printf("key='%s', value='%s'\n", duk_to_string(ctx, -2), duk_to_string(ctx, -1)); duk_pop_2(ctx); } duk_pop(ctx); duk_pop(ctx); return 0; }
/* * Delete session info object pointed to by sessionId. If sessionId * is zero then delete all session info objects. */ static AJ_Status RemoveSessions(duk_context* ctx, uint32_t sessionId) { AJ_Status status = AJ_OK; AJS_GetGlobalStashObject(ctx, "sessions"); duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY); while (duk_next(ctx, -1, 1)) { SessionInfo* sessionInfo; const char* peer = duk_get_string(ctx, -2); duk_get_prop_string(ctx, -1, "info"); sessionInfo = duk_get_buffer(ctx, -1, NULL); duk_pop_3(ctx); if (sessionId == 0) { AJ_InfoPrintf(("RemoveSessions(): Leaving session: %u\n", sessionInfo->sessionId)); status = AJ_BusLeaveSession(AJS_GetBusAttachment(), sessionInfo->sessionId); } else if (sessionInfo->sessionId == sessionId) { status = AJ_BusLeaveSession(AJS_GetBusAttachment(), sessionInfo->sessionId); duk_del_prop_string(ctx, -2, peer); break; } } duk_pop_2(ctx); /* * TODO - this is not all that useful because it only indicates that a peer has gone away * without being able to specify exactly which services are affected. The problem is we cannot * hold a reference to the service object because we a relying on the service object finalizer * to clean up sessions that are no longer in use. If we hold a reference the finalizer will * never get called. */ if (sessionId != 0) { AJS_GetAllJoynProperty(ctx, "onPeerDisconnected"); if (duk_is_callable(ctx, -1)) { if (duk_pcall(ctx, 0) != DUK_EXEC_SUCCESS) { AJS_ConsoleSignalError(ctx); } } duk_pop(ctx); } else { AJS_ClearGlobalStashObject(ctx, "sessions"); } return status; }
int UI_DebugGetUIKeepAliveCount(duk_context* ctx) { duk_push_global_stash(ctx); duk_get_prop_string(ctx, -1, "__jsui_widgetkeepalive"); duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY); double count = 0; while (duk_next(ctx, -1 , 0)) { duk_pop(ctx); /* pop_key */ count++; } duk_pop_n(ctx, 3); /* pop enum object, keep alive object, and stash */ duk_push_number(ctx, count); return 1; }
static VALUE ctx_stack_to_value(struct state *state, int index) { duk_context *ctx = state->ctx; size_t len; const char *buf; int type; state->was_complex = 0; type = duk_get_type(ctx, index); switch (type) { case DUK_TYPE_NULL: case DUK_TYPE_UNDEFINED: return Qnil; case DUK_TYPE_NUMBER: return rb_float_new(duk_get_number(ctx, index)); case DUK_TYPE_BOOLEAN: return duk_get_boolean(ctx, index) ? Qtrue : Qfalse; case DUK_TYPE_STRING: buf = duk_get_lstring(ctx, index, &len); VALUE str = rb_str_new(buf, len); return decode_cesu8(state, str); case DUK_TYPE_OBJECT: if (duk_is_function(ctx, index)) { state->was_complex = 1; return state->complex_object; } else if (duk_is_array(ctx, index)) { VALUE ary = rb_ary_new(); duk_enum(ctx, index, DUK_ENUM_ARRAY_INDICES_ONLY); while (duk_next(ctx, -1, 1)) { rb_ary_store(ary, duk_to_int(ctx, -2), ctx_stack_to_value(state, -1)); duk_pop_2(ctx); } duk_pop(ctx); return ary; } else if (duk_is_object(ctx, index)) { VALUE hash = rb_hash_new(); duk_enum(ctx, index, DUK_ENUM_OWN_PROPERTIES_ONLY); while (duk_next(ctx, -1, 1)) { VALUE key = ctx_stack_to_value(state, -2); VALUE val = ctx_stack_to_value(state, -1); duk_pop_2(ctx); if (state->was_complex) continue; rb_hash_aset(hash, key, val); } duk_pop(ctx); return hash; } else { state->was_complex = 1; return state->complex_object; } case DUK_TYPE_BUFFER: case DUK_TYPE_POINTER: default: return state->complex_object; } return Qnil; }
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 duk_enum(duk_context *ctx, duk_idx_t obj_index, duk_uint_t enum_flags); void aperl_duk_enum(duk_context *ctx, duk_idx_t obj_index, duk_uint_t enum_flags) { duk_enum(ctx, obj_index, enum_flags); }
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx) { duk_small_uint_t pass; duk_uint_t defprop_flags; duk_hobject *obj; duk_idx_t idx_value; duk_hobject *get; duk_hobject *set; /* Lightfunc handling by ToObject() coercion. */ obj = duk_require_hobject_or_lfunc_coerce(ctx, 0); /* target */ DUK_ASSERT(obj != NULL); duk_to_object(ctx, 1); /* properties object */ DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT", (duk_tval *) duk_get_tval(ctx, 0), (duk_tval *) duk_get_tval(ctx, 1))); /* * Two pass approach to processing the property descriptors. * On first pass validate and normalize all descriptors before * any changes are made to the target object. On second pass * make the actual modifications to the target object. * * Right now we'll just use the same normalize/validate helper * on both passes, ignoring its outputs on the first pass. */ for (pass = 0; pass < 2; pass++) { duk_set_top(ctx, 2); /* -> [ hobject props ] */ duk_enum(ctx, 1, DUK_ENUM_OWN_PROPERTIES_ONLY /*enum_flags*/); for (;;) { duk_hstring *key; /* [ hobject props enum(props) ] */ duk_set_top(ctx, 3); if (!duk_next(ctx, 2, 1 /*get_value*/)) { break; } DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT", (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1))); /* [ hobject props enum(props) key desc ] */ duk_hobject_prepare_property_descriptor(ctx, 4 /*idx_desc*/, &defprop_flags, &idx_value, &get, &set); /* [ hobject props enum(props) key desc value? getter? setter? ] */ if (pass == 0) { continue; } key = duk_get_hstring(ctx, 3); DUK_ASSERT(key != NULL); duk_hobject_define_property_helper(ctx, defprop_flags, obj, key, idx_value, get, set); } } /* * Return target object */ duk_dup(ctx, 0); return 1; }
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_hthread *thr) { duk_small_uint_t pass; duk_uint_t defprop_flags; duk_hobject *obj; duk_idx_t idx_value; duk_hobject *get; duk_hobject *set; /* Lightfunc and plain buffer handling by ToObject() coercion. */ obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER); DUK_ASSERT(obj != NULL); duk_to_object(thr, 1); /* properties object */ DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT", (duk_tval *) duk_get_tval(thr, 0), (duk_tval *) duk_get_tval(thr, 1))); /* * Two pass approach to processing the property descriptors. * On first pass validate and normalize all descriptors before * any changes are made to the target object. On second pass * make the actual modifications to the target object. * * Right now we'll just use the same normalize/validate helper * on both passes, ignoring its outputs on the first pass. */ for (pass = 0; pass < 2; pass++) { duk_set_top(thr, 2); /* -> [ hobject props ] */ duk_enum(thr, 1, DUK_ENUM_OWN_PROPERTIES_ONLY | DUK_ENUM_INCLUDE_SYMBOLS /*enum_flags*/); for (;;) { duk_hstring *key; /* [ hobject props enum(props) ] */ duk_set_top(thr, 3); if (!duk_next(thr, 2, 1 /*get_value*/)) { break; } DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT", (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1))); /* [ hobject props enum(props) key desc ] */ duk_hobject_prepare_property_descriptor(thr, 4 /*idx_desc*/, &defprop_flags, &idx_value, &get, &set); /* [ hobject props enum(props) key desc [multiple values] ] */ if (pass == 0) { continue; } /* This allows symbols on purpose. */ key = duk_known_hstring(thr, 3); DUK_ASSERT(key != NULL); duk_hobject_define_property_helper(thr, defprop_flags, obj, key, idx_value, get, set, 1 /*throw_flag*/); } } /* * Return target object */ duk_dup_0(thr); return 1; }
/* basic enum success cases */ int test_1(duk_context *ctx) { duk_set_top(ctx, 0); printf("object with own properties only, enum with get_value=0\n"); duk_eval_string(ctx, "({ 1: 1, foo: 2, bar: 3, quux: 4, 2: 5 })"); duk_enum(ctx, -1, 0 /*enum_flags*/); /* [ obj enum ] */ while (duk_next(ctx, -1 /*enum_index*/, 0 /*get_value*/)) { printf("key: '%s'\n", duk_get_string(ctx, -1)); duk_pop(ctx); } duk_pop_2(ctx); printf("object with own properties only, enum with get_value=1\n"); duk_eval_string(ctx, "({ 1: 1, foo: 2, bar: 3, quux: 4, 2: 5 })"); duk_enum(ctx, -1, 0 /*enum_flags*/); /* [ obj enum ] */ while (duk_next(ctx, -1 /*enum_index*/, 1 /*get_value*/)) { printf("key: '%s', value: '%s'\n", duk_get_string(ctx, -2), duk_to_string(ctx, -1)); duk_pop_2(ctx); } duk_pop(ctx); duk_pop(ctx); printf("object with inherited, enumerable properties, enum with get_value=1\n"); duk_eval_string(ctx, "(function () { var o = Object.create({ parent: 'inherited' }); o.foo = 'bar'; return o; })()"); duk_enum(ctx, -1, 0 /*enum_flags*/); /* [ obj enum ] */ while (duk_next(ctx, -1 /*enum_index*/, 1 /*get_value*/)) { printf("key: '%s', value: '%s'\n", duk_get_string(ctx, -2), duk_to_string(ctx, -1)); duk_pop_2(ctx); } duk_pop(ctx); duk_pop(ctx); printf("object with own non-enumerable properties, enum with get_value=1, don't enum inherited properties\n"); duk_eval_string(ctx, "(function () { var o = Object.create({ parent: 'inherited' }); " "Object.defineProperty(o, 'enumerable_prop', { value: 123, writable: true, enumerable: true, configurable: true}); " "Object.defineProperty(o, 'nonenumerable_prop', { value: 234, writable: true, enumerable: false, configurable: true}); " " return o; })()"); printf("- enum only enumerable own properties\n"); duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY /*enum_flags*/); /* [ obj enum ] */ while (duk_next(ctx, -1 /*enum_index*/, 1 /*get_value*/)) { printf("key: '%s', value: '%s'\n", duk_get_string(ctx, -2), duk_to_string(ctx, -1)); duk_pop_2(ctx); } duk_pop(ctx); printf("- enum all own properties\n"); duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY | DUK_ENUM_INCLUDE_NONENUMERABLE /*enum_flags*/); /* [ obj enum ] */ while (duk_next(ctx, -1 /*enum_index*/, 1 /*get_value*/)) { printf("key: '%s', value: '%s'\n", duk_get_string(ctx, -2), duk_to_string(ctx, -1)); duk_pop_2(ctx); } duk_pop(ctx); duk_pop(ctx); printf("object with string and array index keys, enum with get_value=1\n"); duk_eval_string(ctx, "({ foo: 'val1', 999: 'val2', 1: 'val3', 123: 'val4', 234: 'val5', 2: 'val6', bar: 'val7' })"); printf("- enum array indices only, not sorted\n"); duk_enum(ctx, -1, DUK_ENUM_ARRAY_INDICES_ONLY /*enum_flags*/); /* [ obj enum ] */ while (duk_next(ctx, -1 /*enum_index*/, 1 /*get_value*/)) { printf("key: '%s', value: '%s'\n", duk_get_string(ctx, -2), duk_to_string(ctx, -1)); duk_pop_2(ctx); } duk_pop(ctx); printf("- enum array indices only, sorted\n"); duk_enum(ctx, -1, DUK_ENUM_ARRAY_INDICES_ONLY | DUK_ENUM_SORT_ARRAY_INDICES /*enum_flags*/); /* [ obj enum ] */ while (duk_next(ctx, -1 /*enum_index*/, 1 /*get_value*/)) { printf("key: '%s', value: '%s'\n", duk_get_string(ctx, -2), duk_to_string(ctx, -1)); duk_pop_2(ctx); } duk_pop(ctx); duk_pop(ctx); /* XXX: there is no test for DUK_ENUM_INCLUDE_INTERNAL now, * this is a bit difficult because internal properties are * not exposed or stable. */ printf("final top: %d\n", duk_get_top(ctx)); return 0; }