http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/5977aa27/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_string.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_string.c b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_string.c deleted file mode 100644 index 3f1acac..0000000 --- a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_string.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * String manipulation - */ - -#include "duk_internal.h" - -DUK_LOCAL void duk__concat_and_join_helper(duk_context *ctx, duk_idx_t count_in, duk_bool_t is_join) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_uint_t count; - duk_uint_t i; - duk_size_t idx; - duk_size_t len; - duk_hstring *h; - duk_uint8_t *buf; - - DUK_ASSERT_CTX_VALID(ctx); - - if (DUK_UNLIKELY(count_in <= 0)) { - if (count_in < 0) { - DUK_ERROR_API(thr, DUK_STR_INVALID_COUNT); - return; - } - DUK_ASSERT(count_in == 0); - duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING); - return; - } - count = (duk_uint_t) count_in; - - if (is_join) { - duk_size_t t1, t2, limit; - h = duk_to_hstring(ctx, -((duk_idx_t) count) - 1); - DUK_ASSERT(h != NULL); - - /* A bit tricky overflow test, see doc/code-issues.rst. */ - t1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h); - t2 = (duk_size_t) (count - 1); - limit = (duk_size_t) DUK_HSTRING_MAX_BYTELEN; - if (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) { - /* Combined size of separators already overflows */ - goto error_overflow; - } - len = (duk_size_t) (t1 * t2); - } else { - len = (duk_size_t) 0; - } - - for (i = count; i >= 1; i--) { - duk_size_t new_len; - duk_to_string(ctx, -((duk_idx_t) i)); - h = duk_require_hstring(ctx, -((duk_idx_t) i)); - new_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h); - - /* Impose a string maximum length, need to handle overflow - * correctly. - */ - if (new_len < len || /* wrapped */ - new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) { - goto error_overflow; - } - len = new_len; - } - - DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes", - (unsigned long) count, (unsigned long) len)); - - /* use stack allocated buffer to ensure reachability in errors (e.g. intern error) */ - buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, len); - DUK_ASSERT(buf != NULL); - - /* [... (sep) str1 str2 ... strN buf] */ - - idx = 0; - for (i = count; i >= 1; i--) { - if (is_join && i != count) { - h = duk_require_hstring(ctx, -((duk_idx_t) count) - 2); /* extra -1 for buffer */ - DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h)); - idx += DUK_HSTRING_GET_BYTELEN(h); - } - h = duk_require_hstring(ctx, -((duk_idx_t) i) - 1); /* extra -1 for buffer */ - DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h)); - idx += DUK_HSTRING_GET_BYTELEN(h); - } - - DUK_ASSERT(idx == len); - - /* [... (sep) str1 str2 ... strN buf] */ - - /* get rid of the strings early to minimize memory use before intern */ - - if (is_join) { - duk_replace(ctx, -((duk_idx_t) count) - 2); /* overwrite sep */ - duk_pop_n(ctx, count); - } else { - duk_replace(ctx, -((duk_idx_t) count) - 1); /* overwrite str1 */ - duk_pop_n(ctx, count-1); - } - - /* [... buf] */ - - (void) duk_to_string(ctx, -1); - - /* [... res] */ - return; - - error_overflow: - DUK_ERROR_RANGE(thr, DUK_STR_CONCAT_RESULT_TOO_LONG); -} - -DUK_EXTERNAL void duk_concat(duk_context *ctx, duk_idx_t count) { - DUK_ASSERT_CTX_VALID(ctx); - - duk__concat_and_join_helper(ctx, count, 0 /*is_join*/); -} - -DUK_EXTERNAL void duk_join(duk_context *ctx, duk_idx_t count) { - DUK_ASSERT_CTX_VALID(ctx); - - duk__concat_and_join_helper(ctx, count, 1 /*is_join*/); -} - -/* XXX: could map/decode be unified with duk_unicode_support.c code? - * Case conversion needs also the character surroundings though. - */ - -DUK_EXTERNAL void duk_decode_string(duk_context *ctx, duk_idx_t index, duk_decode_char_function callback, void *udata) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hstring *h_input; - const duk_uint8_t *p, *p_start, *p_end; - duk_codepoint_t cp; - - DUK_ASSERT_CTX_VALID(ctx); - - h_input = duk_require_hstring(ctx, index); - DUK_ASSERT(h_input != NULL); - - p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input); - p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input); - p = p_start; - - for (;;) { - if (p >= p_end) { - break; - } - cp = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end); - callback(udata, cp); - } -} - -DUK_EXTERNAL void duk_map_string(duk_context *ctx, duk_idx_t index, duk_map_char_function callback, void *udata) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hstring *h_input; - duk_bufwriter_ctx bw_alloc; - duk_bufwriter_ctx *bw; - const duk_uint8_t *p, *p_start, *p_end; - duk_codepoint_t cp; - - DUK_ASSERT_CTX_VALID(ctx); - - index = duk_normalize_index(ctx, index); - - h_input = duk_require_hstring(ctx, index); - DUK_ASSERT(h_input != NULL); - - bw = &bw_alloc; - DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* reasonable output estimate */ - - p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input); - p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input); - p = p_start; - - for (;;) { - /* XXX: could write output in chunks with fewer ensure calls, - * but relative benefit would be small here. - */ - - if (p >= p_end) { - break; - } - cp = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end); - cp = callback(udata, cp); - - DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp); - } - - DUK_BW_COMPACT(thr, bw); - duk_to_string(ctx, -1); - duk_replace(ctx, index); -} - -DUK_EXTERNAL void duk_substring(duk_context *ctx, duk_idx_t index, duk_size_t start_offset, duk_size_t end_offset) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hstring *h; - duk_hstring *res; - duk_size_t start_byte_offset; - duk_size_t end_byte_offset; - - DUK_ASSERT_CTX_VALID(ctx); - - index = duk_require_normalize_index(ctx, index); - h = duk_require_hstring(ctx, index); - DUK_ASSERT(h != NULL); - - if (end_offset >= DUK_HSTRING_GET_CHARLEN(h)) { - end_offset = DUK_HSTRING_GET_CHARLEN(h); - } - if (start_offset > end_offset) { - start_offset = end_offset; - } - - DUK_ASSERT_DISABLE(start_offset >= 0); - DUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h)); - DUK_ASSERT_DISABLE(end_offset >= 0); - DUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h)); - - /* guaranteed by string limits */ - DUK_ASSERT(start_offset <= DUK_UINT32_MAX); - DUK_ASSERT(end_offset <= DUK_UINT32_MAX); - - start_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset); - end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset); - - DUK_ASSERT(end_byte_offset >= start_byte_offset); - DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX); /* guaranteed by string limits */ - - /* no size check is necessary */ - res = duk_heap_string_intern_checked(thr, - DUK_HSTRING_GET_DATA(h) + start_byte_offset, - (duk_uint32_t) (end_byte_offset - start_byte_offset)); - - duk_push_hstring(ctx, res); - duk_replace(ctx, index); -} - -/* XXX: this is quite clunky. Add Unicode helpers to scan backwards and - * forwards with a callback to process codepoints? - */ -DUK_EXTERNAL void duk_trim(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hstring *h; - const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2; /* pointers for scanning */ - const duk_uint8_t *q_start, *q_end; /* start (incl) and end (excl) of trimmed part */ - duk_codepoint_t cp; - - DUK_ASSERT_CTX_VALID(ctx); - - index = duk_require_normalize_index(ctx, index); - h = duk_require_hstring(ctx, index); - DUK_ASSERT(h != NULL); - - p_start = DUK_HSTRING_GET_DATA(h); - p_end = p_start + DUK_HSTRING_GET_BYTELEN(h); - - p = p_start; - while (p < p_end) { - p_tmp1 = p; - cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end); - if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) { - break; - } - p = p_tmp1; - } - q_start = p; - if (p == p_end) { - /* entire string is whitespace */ - q_end = p; - goto scan_done; - } - - p = p_end; - while (p > p_start) { - p_tmp1 = p; - while (p > p_start) { - p--; - if (((*p) & 0xc0) != 0x80) { - break; - } - } - p_tmp2 = p; - - cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end); - if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) { - p = p_tmp1; - break; - } - } - q_end = p; - - scan_done: - /* This may happen when forward and backward scanning disagree - * (possible for non-extended-UTF-8 strings). - */ - if (q_end < q_start) { - q_end = q_start; - } - - DUK_ASSERT(q_start >= p_start && q_start <= p_end); - DUK_ASSERT(q_end >= p_start && q_end <= p_end); - DUK_ASSERT(q_end >= q_start); - - DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p", - (const void *) p_start, (const void *) p_end, - (const void *) q_start, (const void *) q_end)); - - if (q_start == p_start && q_end == p_end) { - DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)")); - return; - } - - duk_push_lstring(ctx, (const char *) q_start, (duk_size_t) (q_end - q_start)); - duk_replace(ctx, index); -} - -DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_context *ctx, duk_idx_t index, duk_size_t char_offset) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hstring *h; - duk_ucodepoint_t cp; - - DUK_ASSERT_CTX_VALID(ctx); - - h = duk_require_hstring(ctx, index); - DUK_ASSERT(h != NULL); - - DUK_ASSERT_DISABLE(char_offset >= 0); /* always true, arg is unsigned */ - if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) { - return 0; - } - - DUK_ASSERT(char_offset <= DUK_UINT_MAX); /* guaranteed by string limits */ - cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset); - return (duk_codepoint_t) cp; -}
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/5977aa27/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_var.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_var.c b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_var.c deleted file mode 100644 index 6ac790e..0000000 --- a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_var.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Variable access - */ - -#include "duk_internal.h" - -DUK_EXTERNAL void duk_get_var(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_activation *act; - duk_hstring *h_varname; - duk_small_int_t throw_flag = 1; /* always throw ReferenceError for unresolvable */ - - DUK_ASSERT_CTX_VALID(ctx); - - h_varname = duk_require_hstring(ctx, -1); /* XXX: tostring? */ - DUK_ASSERT(h_varname != NULL); - - act = duk_hthread_get_current_activation(thr); - if (act) { - (void) duk_js_getvar_activation(thr, act, h_varname, throw_flag); /* -> [ ... varname val this ] */ - } else { - /* Outside any activation -> look up from global. */ - DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL); - (void) duk_js_getvar_envrec(thr, thr->builtins[DUK_BIDX_GLOBAL_ENV], h_varname, throw_flag); - } - - /* [ ... varname val this ] (because throw_flag == 1, always resolved) */ - - duk_pop(ctx); - duk_remove(ctx, -2); - - /* [ ... val ] */ - - /* Return value would be pointless: because throw_flag==1, we always - * throw if the identifier doesn't resolve. - */ - return; -} - -DUK_EXTERNAL void duk_put_var(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_activation *act; - duk_hstring *h_varname; - duk_tval *tv_val; - duk_small_int_t throw_flag; - - DUK_ASSERT_CTX_VALID(ctx); - - h_varname = duk_require_hstring(ctx, -2); /* XXX: tostring? */ - DUK_ASSERT(h_varname != NULL); - - tv_val = duk_require_tval(ctx, -1); - - throw_flag = duk_is_strict_call(ctx); - - act = duk_hthread_get_current_activation(thr); - if (act) { - duk_js_putvar_activation(thr, act, h_varname, tv_val, throw_flag); /* -> [ ... varname val this ] */ - } else { - /* Outside any activation -> put to global. */ - DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL); - duk_js_putvar_envrec(thr, thr->builtins[DUK_BIDX_GLOBAL_ENV], h_varname, tv_val, throw_flag); - } - - /* [ ... varname val ] */ - - duk_pop_2(ctx); - - /* [ ... ] */ - - return; -} - -DUK_EXTERNAL duk_bool_t duk_del_var(duk_context *ctx) { - DUK_ASSERT_CTX_VALID(ctx); - - DUK_ERROR_UNIMPLEMENTED_DEFMSG((duk_hthread *) ctx); - return 0; -} - -DUK_EXTERNAL duk_bool_t duk_has_var(duk_context *ctx) { - DUK_ASSERT_CTX_VALID(ctx); - - DUK_ERROR_UNIMPLEMENTED_DEFMSG((duk_hthread *) ctx); - return 0; -} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/5977aa27/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_bi_array.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_bi_array.c b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_bi_array.c deleted file mode 100644 index dfb93df..0000000 --- a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_bi_array.c +++ /dev/null @@ -1,1445 +0,0 @@ -/* - * Array built-ins - * - * Note that most Array built-ins are intentionally generic and work even - * when the 'this' binding is not an Array instance. To ensure this, - * Array algorithms do not assume "magical" Array behavior for the "length" - * property, for instance. - * - * XXX: the "Throw" flag should be set for (almost?) all [[Put]] and - * [[Delete]] operations, but it's currently false throughout. Go through - * all put/delete cases and check throw flag use. Need a new API primitive - * which allows throws flag to be specified. - * - * XXX: array lengths above 2G won't work reliably. There are many places - * where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff], - * i.e. -33- bits). Although array 'length' cannot be written to be outside - * the unsigned 32-bit range (E5.1 Section 15.4.5.1 throws a RangeError if so) - * some intermediate values may be above 0xffffffff and this may not be always - * correctly handled now (duk_uint32_t is not enough for all algorithms). - * - * For instance, push() can legitimately write entries beyond length 0xffffffff - * and cause a RangeError only at the end. To do this properly, the current - * push() implementation tracks the array index using a 'double' instead of a - * duk_uint32_t (which is somewhat awkward). See test-bi-array-push-maxlen.js. - * - * On using "put" vs. "def" prop - * ============================= - * - * Code below must be careful to use the appropriate primitive as it matters - * for compliance. When using "put" there may be inherited properties in - * Array.prototype which cause side effects when values are written. When - * using "define" there are no such side effects, and many test262 test cases - * check for this (for real world code, such side effects are very rare). - * Both "put" and "define" are used in the E5.1 specification; as a rule, - * "put" is used when modifying an existing array (or a non-array 'this' - * binding) and "define" for setting values into a fresh result array. - * - * Also note that Array instance 'length' should be writable, but not - * enumerable and definitely not configurable: even Duktape code internally - * assumes that an Array instance will always have a 'length' property. - * Preventing deletion of the property is critical. - */ - -#include "duk_internal.h" - -/* Perform an intermediate join when this many elements have been pushed - * on the value stack. - */ -#define DUK__ARRAY_MID_JOIN_LIMIT 4096 - -/* Shared entry code for many Array built-ins. Note that length is left - * on stack (it could be popped, but that's not necessary). - */ -DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_context *ctx) { - duk_uint32_t len; - - (void) duk_push_this_coercible_to_object(ctx); - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LENGTH); - len = duk_to_uint32(ctx, -1); - - /* -> [ ... ToObject(this) ToUint32(length) ] */ - return len; -} - -DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_context *ctx) { - /* Range limited to [0, 0x7fffffff] range, i.e. range that can be - * represented with duk_int32_t. Use this when the method doesn't - * handle the full 32-bit unsigned range correctly. - */ - duk_uint32_t ret = duk__push_this_obj_len_u32(ctx); - if (DUK_UNLIKELY(ret >= 0x80000000UL)) { - DUK_ERROR_RANGE((duk_hthread *) ctx, DUK_STR_ARRAY_LENGTH_OVER_2G); - } - return ret; -} - -/* - * Constructor - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_constructor(duk_context *ctx) { - duk_idx_t nargs; - duk_double_t d; - duk_uint32_t len; - duk_idx_t i; - - nargs = duk_get_top(ctx); - duk_push_array(ctx); - - if (nargs == 1 && duk_is_number(ctx, 0)) { - /* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */ - d = duk_get_number(ctx, 0); - len = duk_to_uint32(ctx, 0); - if (((duk_double_t) len) != d) { - return DUK_RET_RANGE_ERROR; - } - - /* XXX: if 'len' is low, may want to ensure array part is kept: - * the caller is likely to want a dense array. - */ - duk_push_u32(ctx, len); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); /* [ ToUint32(len) array ToUint32(len) ] -> [ ToUint32(len) array ] */ - return 1; - } - - /* XXX: optimize by creating array into correct size directly, and - * operating on the array part directly; values can be memcpy()'d from - * value stack directly as long as refcounts are increased. - */ - for (i = 0; i < nargs; i++) { - duk_dup(ctx, i); - duk_xdef_prop_index_wec(ctx, -2, (duk_uarridx_t) i); - } - - duk_push_u32(ctx, (duk_uint32_t) nargs); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); - return 1; -} - -/* - * isArray() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx) { - duk_hobject *h; - - h = duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_ARRAY); - duk_push_boolean(ctx, (h != NULL)); - return 1; -} - -/* - * toString() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx) { - (void) duk_push_this_coercible_to_object(ctx); - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_JOIN); - - /* [ ... this func ] */ - if (!duk_is_callable(ctx, -1)) { - /* Fall back to the initial (original) Object.toString(). We don't - * currently have pointers to the built-in functions, only the top - * level global objects (like "Array") so this is now done in a bit - * of a hacky manner. It would be cleaner to push the (original) - * function and use duk_call_method(). - */ - - /* XXX: 'this' will be ToObject() coerced twice, which is incorrect - * but should have no visible side effects. - */ - DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString")); - duk_set_top(ctx, 0); - return duk_bi_object_prototype_to_string(ctx); /* has access to 'this' binding */ - } - - /* [ ... this func ] */ - - duk_insert(ctx, -2); - - /* [ ... func this ] */ - - DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT", - (duk_tval *) duk_get_tval(ctx, -2), - (duk_tval *) duk_get_tval(ctx, -1))); - duk_call_method(ctx, 0); - - return 1; -} - -/* - * concat() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx) { - duk_idx_t i, n; - duk_uarridx_t idx, idx_last; - duk_uarridx_t j, len; - duk_hobject *h; - - /* XXX: the insert here is a bit expensive if there are a lot of items. - * It could also be special cased in the outermost for loop quite easily - * (as the element is dup()'d anyway). - */ - - (void) duk_push_this_coercible_to_object(ctx); - duk_insert(ctx, 0); - n = duk_get_top(ctx); - duk_push_array(ctx); /* -> [ ToObject(this) item1 ... itemN arr ] */ - - /* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index() - * (which differs from the official algorithm). If no error is thrown, this - * doesn't matter as the length is updated at the end. However, if an error - * is thrown, the length will be unset. That shouldn't matter because the - * caller won't get a reference to the intermediate value. - */ - - idx = 0; - idx_last = 0; - for (i = 0; i < n; i++) { - DUK_ASSERT_TOP(ctx, n + 1); - - /* [ ToObject(this) item1 ... itemN arr ] */ - - duk_dup(ctx, i); - h = duk_get_hobject_with_class(ctx, -1, DUK_HOBJECT_CLASS_ARRAY); - if (!h) { - duk_xdef_prop_index_wec(ctx, -2, idx++); - idx_last = idx; - continue; - } - - /* [ ToObject(this) item1 ... itemN arr item(i) ] */ - - /* XXX: an array can have length higher than 32 bits; this is not handled - * correctly now. - */ - len = (duk_uarridx_t) duk_get_length(ctx, -1); - for (j = 0; j < len; j++) { - if (duk_get_prop_index(ctx, -1, j)) { - /* [ ToObject(this) item1 ... itemN arr item(i) item(i)[j] ] */ - duk_xdef_prop_index_wec(ctx, -3, idx++); - idx_last = idx; - } else { - idx++; - duk_pop(ctx); -#if defined(DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER) - /* According to E5.1 Section 15.4.4.4 nonexistent trailing - * elements do not affect 'length' of the result. Test262 - * and other engines disagree, so update idx_last here too. - */ - idx_last = idx; -#else - /* Strict standard behavior, ignore trailing elements for - * result 'length'. - */ -#endif - } - } - duk_pop(ctx); - } - - /* The E5.1 Section 15.4.4.4 algorithm doesn't set the length explicitly - * in the end, but because we're operating with an internal value which - * is known to be an array, this should be equivalent. - */ - duk_push_uarridx(ctx, idx_last); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); - - DUK_ASSERT_TOP(ctx, n + 1); - return 1; -} - -/* - * join(), toLocaleString() - * - * Note: checking valstack is necessary, but only in the per-element loop. - * - * Note: the trivial approach of pushing all the elements on the value stack - * and then calling duk_join() fails when the array contains a large number - * of elements. This problem can't be offloaded to duk_join() because the - * elements to join must be handled here and have special handling. Current - * approach is to do intermediate joins with very large number of elements. - * There is no fancy handling; the prefix gets re-joined multiple times. - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx) { - duk_uint32_t len, count; - duk_uint32_t idx; - duk_small_int_t to_locale_string = duk_get_current_magic(ctx); - duk_idx_t valstack_required; - - /* For join(), nargs is 1. For toLocaleString(), nargs is 0 and - * setting the top essentially pushes an undefined to the stack, - * thus defaulting to a comma separator. - */ - duk_set_top(ctx, 1); - if (duk_is_undefined(ctx, 0)) { - duk_pop(ctx); - duk_push_hstring_stridx(ctx, DUK_STRIDX_COMMA); - } else { - duk_to_string(ctx, 0); - } - - len = duk__push_this_obj_len_u32(ctx); - - /* [ sep ToObject(this) len ] */ - - DUK_DDD(DUK_DDDPRINT("sep=%!T, this=%!T, len=%lu", - (duk_tval *) duk_get_tval(ctx, 0), - (duk_tval *) duk_get_tval(ctx, 1), - (unsigned long) len)); - - /* The extra (+4) is tight. */ - valstack_required = (len >= DUK__ARRAY_MID_JOIN_LIMIT ? - DUK__ARRAY_MID_JOIN_LIMIT : len) + 4; - duk_require_stack(ctx, valstack_required); - - duk_dup(ctx, 0); - - /* [ sep ToObject(this) len sep ] */ - - count = 0; - idx = 0; - for (;;) { - if (count >= DUK__ARRAY_MID_JOIN_LIMIT || /* intermediate join to avoid valstack overflow */ - idx >= len) { /* end of loop (careful with len==0) */ - /* [ sep ToObject(this) len sep str0 ... str(count-1) ] */ - DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld", - (long) count, (long) idx, (long) len)); - duk_join(ctx, (duk_idx_t) count); /* -> [ sep ToObject(this) len str ] */ - duk_dup(ctx, 0); /* -> [ sep ToObject(this) len str sep ] */ - duk_insert(ctx, -2); /* -> [ sep ToObject(this) len sep str ] */ - count = 1; - } - if (idx >= len) { - /* if true, the stack already contains the final result */ - break; - } - - duk_get_prop_index(ctx, 1, (duk_uarridx_t) idx); - if (duk_is_null_or_undefined(ctx, -1)) { - duk_pop(ctx); - duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING); - } else { - if (to_locale_string) { - duk_to_object(ctx, -1); - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_TO_LOCALE_STRING); - duk_insert(ctx, -2); /* -> [ ... toLocaleString ToObject(val) ] */ - duk_call_method(ctx, 0); - duk_to_string(ctx, -1); - } else { - duk_to_string(ctx, -1); - } - } - - count++; - idx++; - } - - /* [ sep ToObject(this) len sep result ] */ - - return 1; -} - -/* - * pop(), push() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx) { - duk_uint32_t len; - duk_uint32_t idx; - - DUK_ASSERT_TOP(ctx, 0); - 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; - } - idx = len - 1; - - duk_get_prop_index(ctx, 0, (duk_uarridx_t) idx); - duk_del_prop_index(ctx, 0, (duk_uarridx_t) idx); - duk_push_u32(ctx, idx); - duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH); - return 1; -} - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx) { - /* Note: 'this' is not necessarily an Array object. The push() - * algorithm is supposed to work for other kinds of objects too, - * so the algorithm has e.g. an explicit update for the 'length' - * property which is normally "magical" in arrays. - */ - - duk_uint32_t len; - duk_idx_t i, n; - - n = duk_get_top(ctx); - len = duk__push_this_obj_len_u32(ctx); - - /* [ arg1 ... argN obj length ] */ - - /* Technically Array.prototype.push() can create an Array with length - * longer than 2^32-1, i.e. outside the 32-bit range. The final length - * is *not* wrapped to 32 bits in the specification. - * - * This implementation tracks length with a uint32 because it's much - * more practical. - * - * See: test-bi-array-push-maxlen.js. - */ - - if (len + (duk_uint32_t) n < len) { - DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw")); - return DUK_RET_RANGE_ERROR; - } - - for (i = 0; i < n; i++) { - duk_dup(ctx, i); - duk_put_prop_index(ctx, -3, len + i); - } - len += n; - - duk_push_u32(ctx, len); - duk_dup_top(ctx); - duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH); - - /* [ arg1 ... argN obj length new_length ] */ - return 1; -} - -/* - * sort() - * - * Currently qsort with random pivot. This is now really, really slow, - * because there is no fast path for array parts. - * - * Signed indices are used because qsort() leaves and degenerate cases - * may use a negative offset. - */ - -DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_context *ctx, duk_int_t idx1, duk_int_t idx2) { - duk_bool_t have1, have2; - duk_bool_t undef1, undef2; - duk_small_int_t ret; - duk_idx_t idx_obj = 1; /* fixed offsets in valstack */ - duk_idx_t idx_fn = 0; - duk_hstring *h1, *h2; - - /* Fast exit if indices are identical. This is valid for a non-existent property, - * for an undefined value, and almost always for ToString() coerced comparison of - * arbitrary values (corner cases where this is not the case include e.g. a an - * object with varying ToString() coercion). - * - * The specification does not prohibit "caching" of values read from the array, so - * assuming equality for comparing an index with itself falls into the category of - * "caching". - * - * Also, compareFn may be inconsistent, so skipping a call to compareFn here may - * have an effect on the final result. The specification does not require any - * specific behavior for inconsistent compare functions, so again, this fast path - * is OK. - */ - - if (idx1 == idx2) { - DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit", - (long) idx1, (long) idx2)); - return 0; - } - - have1 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx1); - have2 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx2); - - DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T", - (long) idx1, (long) idx2, (long) have1, (long) have2, - (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1))); - - if (have1) { - if (have2) { - ; - } else { - ret = -1; - goto pop_ret; - } - } else { - if (have2) { - ret = 1; - goto pop_ret; - } else { - ret = 0; - goto pop_ret; - } - } - - undef1 = duk_is_undefined(ctx, -2); - undef2 = duk_is_undefined(ctx, -1); - if (undef1) { - if (undef2) { - ret = 0; - goto pop_ret; - } else { - ret = 1; - goto pop_ret; - } - } else { - if (undef2) { - ret = -1; - goto pop_ret; - } else { - ; - } - } - - if (!duk_is_undefined(ctx, idx_fn)) { - duk_double_t d; - - /* no need to check callable; duk_call() will do that */ - duk_dup(ctx, idx_fn); /* -> [ ... x y fn ] */ - duk_insert(ctx, -3); /* -> [ ... fn x y ] */ - duk_call(ctx, 2); /* -> [ ... res ] */ - - /* The specification is a bit vague what to do if the return - * value is not a number. Other implementations seem to - * tolerate non-numbers but e.g. V8 won't apparently do a - * ToNumber(). - */ - - /* XXX: best behavior for real world compatibility? */ - - d = duk_to_number(ctx, -1); - if (d < 0.0) { - ret = -1; - } else if (d > 0.0) { - ret = 1; - } else { - ret = 0; - } - - duk_pop(ctx); - DUK_DDD(DUK_DDDPRINT("-> result %ld (from comparefn, after coercion)", (long) ret)); - return ret; - } - - /* string compare is the default (a bit oddly) */ - - h1 = duk_to_hstring(ctx, -2); - h2 = duk_to_hstring(ctx, -1); - DUK_ASSERT(h1 != NULL); - DUK_ASSERT(h2 != NULL); - - ret = duk_js_string_compare(h1, h2); /* retval is directly usable */ - goto pop_ret; - - pop_ret: - duk_pop_2(ctx); - DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret)); - return ret; -} - -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); - } -} - -#if defined(DUK_USE_DDDPRINT) -/* Debug print which visualizes the qsort partitioning process. */ -DUK_LOCAL void duk__debuglog_qsort_state(duk_context *ctx, duk_int_t lo, duk_int_t hi, duk_int_t pivot) { - char buf[4096]; - char *ptr = buf; - duk_int_t i, n; - n = (duk_int_t) duk_get_length(ctx, 1); - if (n > 4000) { - n = 4000; - } - *ptr++ = '['; - for (i = 0; i < n; i++) { - if (i == pivot) { - *ptr++ = '|'; - } else if (i == lo) { - *ptr++ = '<'; - } else if (i == hi) { - *ptr++ = '>'; - } else if (i >= lo && i <= hi) { - *ptr++ = '-'; - } else { - *ptr++ = ' '; - } - } - *ptr++ = ']'; - *ptr++ = '\0'; - - DUK_DDD(DUK_DDDPRINT("%s (lo=%ld, hi=%ld, pivot=%ld)", - (const char *) buf, (long) lo, (long) hi, (long) pivot)); -} -#endif - -DUK_LOCAL void duk__array_qsort(duk_context *ctx, duk_int_t lo, duk_int_t hi) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_int_t p, l, r; - - /* The lo/hi indices may be crossed and hi < 0 is possible at entry. */ - - DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T", - (long) lo, (long) hi, (duk_tval *) duk_get_tval(ctx, 1))); - - DUK_ASSERT_TOP(ctx, 3); - - /* In some cases it may be that lo > hi, or hi < 0; these - * degenerate cases happen e.g. for empty arrays, and in - * recursion leaves. - */ - - /* trivial cases */ - if (hi - lo < 1) { - DUK_DDD(DUK_DDDPRINT("degenerate case, return immediately")); - return; - } - DUK_ASSERT(hi > lo); - DUK_ASSERT(hi - lo + 1 >= 2); - - /* randomized pivot selection */ - p = lo + (duk_util_tinyrandom_get_bits(thr, 30) % (hi - lo + 1)); /* rnd in [lo,hi] */ - DUK_ASSERT(p >= lo && p <= hi); - DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld", - (long) lo, (long) hi, (long) p)); - - /* move pivot out of the way */ - duk__array_sort_swap(ctx, p, lo); - p = lo; - DUK_DDD(DUK_DDDPRINT("pivot moved out of the way: %!T", (duk_tval *) duk_get_tval(ctx, 1))); - - l = lo + 1; - r = hi; - for (;;) { - /* find elements to swap */ - for (;;) { - DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld", - (long) l, (long) r, (long) p)); - if (l >= hi) { - break; - } - if (duk__array_sort_compare(ctx, l, p) >= 0) { /* !(l < p) */ - break; - } - l++; - } - for (;;) { - DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld", - (long) l, (long) r, (long) p)); - if (r <= lo) { - break; - } - if (duk__array_sort_compare(ctx, p, r) >= 0) { /* !(p < r) */ - break; - } - r--; - } - if (l >= r) { - goto done; - } - DUK_ASSERT(l < r); - - DUK_DDD(DUK_DDDPRINT("swap %ld and %ld", (long) l, (long) r)); - - duk__array_sort_swap(ctx, l, r); - - DUK_DDD(DUK_DDDPRINT("after swap: %!T", (duk_tval *) duk_get_tval(ctx, 1))); - l++; - r--; - } - done: - /* Note that 'l' and 'r' may cross, i.e. r < l */ - DUK_ASSERT(l >= lo && l <= hi); - DUK_ASSERT(r >= lo && r <= hi); - - /* XXX: there's no explicit recursion bound here now. For the average - * qsort recursion depth O(log n) that's not really necessary: e.g. for - * 2**32 recursion depth would be about 32 which is OK. However, qsort - * worst case recursion depth is O(n) which may be a problem. - */ - - /* move pivot to its final place */ - DUK_DDD(DUK_DDDPRINT("before final pivot swap: %!T", (duk_tval *) duk_get_tval(ctx, 1))); - duk__array_sort_swap(ctx, lo, r); - -#if defined(DUK_USE_DDDPRINT) - duk__debuglog_qsort_state(ctx, lo, hi, r); -#endif - - DUK_DDD(DUK_DDDPRINT("recurse: pivot=%ld, obj=%!T", (long) r, (duk_tval *) duk_get_tval(ctx, 1))); - duk__array_qsort(ctx, lo, r - 1); - duk__array_qsort(ctx, r + 1, hi); -} - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx) { - duk_uint32_t len; - - /* XXX: len >= 0x80000000 won't work below because a signed type - * is needed by qsort. - */ - len = duk__push_this_obj_len_u32_limited(ctx); - - /* stack[0] = compareFn - * stack[1] = ToObject(this) - * stack[2] = ToUint32(length) - */ - - if (len > 0) { - /* avoid degenerate cases, so that (len - 1) won't underflow */ - duk__array_qsort(ctx, (duk_int_t) 0, (duk_int_t) (len - 1)); - } - - DUK_ASSERT_TOP(ctx, 3); - duk_pop(ctx); - return 1; /* return ToObject(this) */ -} - -/* - * splice() - */ - -/* XXX: this compiles to over 500 bytes now, even without special handling - * for an array part. Uses signed ints so does not handle full array range correctly. - */ - -/* XXX: can shift() / unshift() use the same helper? - * shift() is (close to?) <--> splice(0, 1) - * unshift is (close to?) <--> splice(0, 0, [items])? - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx) { - duk_idx_t nargs; - duk_uint32_t len; - duk_bool_t have_delcount; - duk_int_t item_count; - duk_int_t act_start; - duk_int_t del_count; - duk_int_t i, n; - - DUK_UNREF(have_delcount); - - nargs = duk_get_top(ctx); - if (nargs < 2) { - duk_set_top(ctx, 2); - nargs = 2; - have_delcount = 0; - } else { - have_delcount = 1; - } - - /* 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); - - act_start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len); - if (act_start < 0) { - act_start = len + act_start; - } - DUK_ASSERT(act_start >= 0 && act_start <= (duk_int_t) len); - -#ifdef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT - if (have_delcount) { -#endif - del_count = duk_to_int_clamped(ctx, 1, 0, len - act_start); -#ifdef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT - } else { - /* E5.1 standard behavior when deleteCount is not given would be - * to treat it just like if 'undefined' was given, which coerces - * ultimately to 0. Real world behavior is to splice to the end - * of array, see test-bi-array-proto-splice-no-delcount.js. - */ - del_count = len - act_start; - } -#endif - - DUK_ASSERT(nargs >= 2); - item_count = (duk_int_t) (nargs - 2); - - DUK_ASSERT(del_count >= 0 && del_count <= (duk_int_t) len - act_start); - DUK_ASSERT(del_count + act_start <= (duk_int_t) len); - - /* For now, restrict result array into 32-bit length range. */ - if (((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count) > (duk_double_t) DUK_UINT32_MAX) { - DUK_D(DUK_DPRINT("Array.prototype.splice() would go beyond 32-bit length, throw")); - return DUK_RET_RANGE_ERROR; - } - - duk_push_array(ctx); - - /* stack[0] = start - * stack[1] = deleteCount - * stack[2...nargs-1] = items - * stack[nargs] = ToObject(this) -3 - * stack[nargs+1] = ToUint32(length) -2 - * stack[nargs+2] = result array -1 - */ - - DUK_ASSERT_TOP(ctx, nargs + 3); - - /* Step 9: copy elements-to-be-deleted into the result array */ - - for (i = 0; i < del_count; i++) { - if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (act_start + i))) { - duk_xdef_prop_index_wec(ctx, -2, i); /* throw flag irrelevant (false in std alg) */ - } else { - duk_pop(ctx); - } - } - duk_push_u32(ctx, (duk_uint32_t) del_count); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); - - /* Steps 12 and 13: reorganize elements to make room for itemCount elements */ - - if (item_count < del_count) { - /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 1 - * -> [ A B F G H ] (conceptual intermediate step) - * -> [ A B . F G H ] (placeholder marked) - * [ A B C F G H ] (actual result at this point, C will be replaced) - */ - - DUK_ASSERT_TOP(ctx, nargs + 3); - - n = len - del_count; - for (i = act_start; i < n; i++) { - if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) { - duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count)); - } else { - duk_pop(ctx); - duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count)); - } - } - - DUK_ASSERT_TOP(ctx, nargs + 3); - - /* loop iterator init and limit changed from standard algorithm */ - n = len - del_count + item_count; - for (i = len - 1; i >= n; i--) { - duk_del_prop_index(ctx, -3, (duk_uarridx_t) i); - } - - DUK_ASSERT_TOP(ctx, nargs + 3); - } else if (item_count > del_count) { - /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 4 - * -> [ A B F G H ] (conceptual intermediate step) - * -> [ A B . . . . F G H ] (placeholder marked) - * [ A B C D E F F G H ] (actual result at this point) - */ - - DUK_ASSERT_TOP(ctx, nargs + 3); - - /* loop iterator init and limit changed from standard algorithm */ - for (i = len - del_count - 1; i >= act_start; i--) { - if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) { - duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count)); - } else { - duk_pop(ctx); - duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count)); - } - } - - DUK_ASSERT_TOP(ctx, nargs + 3); - } else { - /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 3 - * -> [ A B F G H ] (conceptual intermediate step) - * -> [ A B . . . F G H ] (placeholder marked) - * [ A B C D E F G H ] (actual result at this point) - */ - } - DUK_ASSERT_TOP(ctx, nargs + 3); - - /* Step 15: insert itemCount elements into the hole made above */ - - for (i = 0; i < item_count; i++) { - duk_dup(ctx, i + 2); /* args start at index 2 */ - duk_put_prop_index(ctx, -4, (duk_uarridx_t) (act_start + i)); - } - - /* Step 16: update length; note that the final length may be above 32 bit range - * (but we checked above that this isn't the case here) - */ - - duk_push_u32(ctx, len - del_count + item_count); - duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH); - - /* result array is already at the top of stack */ - DUK_ASSERT_TOP(ctx, nargs + 3); - return 1; -} - -/* - * reverse() - */ - -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; -} - -/* - * slice() - */ - -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; -} - -/* - * shift() - */ - -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; -} - -/* - * unshift() - */ - -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; -} - -/* - * indexOf(), lastIndexOf() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx) { - duk_idx_t nargs; - duk_int_t i, len; - duk_int_t from_index; - duk_small_int_t idx_step = duk_get_current_magic(ctx); /* idx_step is +1 for indexOf, -1 for lastIndexOf */ - - /* lastIndexOf() needs to be a vararg function because we must distinguish - * between an undefined fromIndex and a "not given" fromIndex; indexOf() is - * made vararg for symmetry although it doesn't strictly need to be. - */ - - nargs = duk_get_top(ctx); - duk_set_top(ctx, 2); - - /* XXX: must be able to represent -len */ - len = (duk_int_t) duk__push_this_obj_len_u32_limited(ctx); - if (len == 0) { - goto not_found; - } - - /* Index clamping is a bit tricky, we must ensure that we'll only iterate - * through elements that exist and that the specific requirements from E5.1 - * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially: - * - * - indexOf: clamp to [-len,len], negative handling -> [0,len], - * if clamped result is len, for-loop bails out immediately - * - * - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1], - * if clamped result is -1, for-loop bails out immediately - * - * If fromIndex is not given, ToInteger(undefined) = 0, which is correct - * for indexOf() but incorrect for lastIndexOf(). Hence special handling, - * and why lastIndexOf() needs to be a vararg function. - */ - - if (nargs >= 2) { - /* indexOf: clamp fromIndex to [-len, len] - * (if fromIndex == len, for-loop terminates directly) - * - * lastIndexOf: clamp fromIndex to [-len - 1, len - 1] - * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly) - */ - from_index = duk_to_int_clamped(ctx, - 1, - (idx_step > 0 ? -len : -len - 1), - (idx_step > 0 ? len : len - 1)); - if (from_index < 0) { - /* for lastIndexOf, result may be -1 (mark immediate termination) */ - from_index = len + from_index; - } - } else { - /* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but - * handle both indexOf and lastIndexOf specially here. - */ - if (idx_step > 0) { - from_index = 0; - } else { - from_index = len - 1; - } - } - - /* stack[0] = searchElement - * stack[1] = fromIndex - * stack[2] = object - * stack[3] = length (not needed, but not popped above) - */ - - for (i = from_index; i >= 0 && i < len; i += idx_step) { - DUK_ASSERT_TOP(ctx, 4); - - if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) { - DUK_ASSERT_TOP(ctx, 5); - if (duk_strict_equals(ctx, 0, 4)) { - duk_push_int(ctx, i); - return 1; - } - } - - duk_pop(ctx); - } - - not_found: - duk_push_int(ctx, -1); - return 1; -} - -/* - * every(), some(), forEach(), map(), filter() - */ - -#define DUK__ITER_EVERY 0 -#define DUK__ITER_SOME 1 -#define DUK__ITER_FOREACH 2 -#define DUK__ITER_MAP 3 -#define DUK__ITER_FILTER 4 - -/* XXX: This helper is a bit awkward because the handling for the different iteration - * callers is quite different. This now compiles to a bit less than 500 bytes, so with - * 5 callers the net result is about 100 bytes / caller. - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx) { - duk_uint32_t len; - duk_uint32_t i; - duk_uarridx_t k; - duk_bool_t bval; - duk_small_int_t iter_type = duk_get_current_magic(ctx); - duk_uint32_t res_length = 0; - - /* each call this helper serves has nargs==2 */ - DUK_ASSERT_TOP(ctx, 2); - - len = duk__push_this_obj_len_u32(ctx); - duk_require_callable(ctx, 0); - /* if thisArg not supplied, behave as if undefined was supplied */ - - if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) { - duk_push_array(ctx); - } else { - duk_push_undefined(ctx); - } - - /* stack[0] = callback - * stack[1] = thisArg - * stack[2] = object - * stack[3] = ToUint32(length) (unused, but avoid unnecessary pop) - * stack[4] = result array (or undefined) - */ - - k = 0; /* result index for filter() */ - for (i = 0; i < len; i++) { - DUK_ASSERT_TOP(ctx, 5); - - if (!duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) { -#if defined(DUK_USE_NONSTD_ARRAY_MAP_TRAILER) - /* Real world behavior for map(): trailing non-existent - * elements don't invoke the user callback, but are still - * counted towards result 'length'. - */ - if (iter_type == DUK__ITER_MAP) { - res_length = i + 1; - } -#else - /* Standard behavior for map(): trailing non-existent - * elements don't invoke the user callback and are not - * counted towards result 'length'. - */ -#endif - duk_pop(ctx); - continue; - } - - /* The original value needs to be preserved for filter(), hence - * this funny order. We can't re-get the value because of side - * effects. - */ - - duk_dup(ctx, 0); - duk_dup(ctx, 1); - duk_dup(ctx, -3); - duk_push_u32(ctx, i); - duk_dup(ctx, 2); /* [ ... val callback thisArg val i obj ] */ - duk_call_method(ctx, 3); /* -> [ ... val retval ] */ - - switch (iter_type) { - case DUK__ITER_EVERY: - bval = duk_to_boolean(ctx, -1); - if (!bval) { - /* stack top contains 'false' */ - return 1; - } - break; - case DUK__ITER_SOME: - bval = duk_to_boolean(ctx, -1); - if (bval) { - /* stack top contains 'true' */ - return 1; - } - break; - case DUK__ITER_FOREACH: - /* nop */ - break; - case DUK__ITER_MAP: - duk_dup(ctx, -1); - duk_xdef_prop_index_wec(ctx, 4, (duk_uarridx_t) i); /* retval to result[i] */ - res_length = i + 1; - break; - case DUK__ITER_FILTER: - bval = duk_to_boolean(ctx, -1); - if (bval) { - duk_dup(ctx, -2); /* orig value */ - duk_xdef_prop_index_wec(ctx, 4, (duk_uarridx_t) k); - k++; - res_length = k; - } - break; - default: - DUK_UNREACHABLE(); - break; - } - duk_pop_2(ctx); - - DUK_ASSERT_TOP(ctx, 5); - } - - switch (iter_type) { - case DUK__ITER_EVERY: - duk_push_true(ctx); - break; - case DUK__ITER_SOME: - duk_push_false(ctx); - break; - case DUK__ITER_FOREACH: - duk_push_undefined(ctx); - break; - case DUK__ITER_MAP: - case DUK__ITER_FILTER: - DUK_ASSERT_TOP(ctx, 5); - DUK_ASSERT(duk_is_array(ctx, -1)); /* topmost element is the result array already */ - duk_push_u32(ctx, res_length); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); - break; - default: - DUK_UNREACHABLE(); - break; - } - - return 1; -} - -/* - * reduce(), reduceRight() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx) { - duk_idx_t nargs; - duk_bool_t have_acc; - duk_uint32_t i, len; - duk_small_int_t idx_step = duk_get_current_magic(ctx); /* idx_step is +1 for reduce, -1 for reduceRight */ - - /* We're a varargs function because we need to detect whether - * initialValue was given or not. - */ - nargs = duk_get_top(ctx); - DUK_DDD(DUK_DDDPRINT("nargs=%ld", (long) nargs)); - - duk_set_top(ctx, 2); - len = duk__push_this_obj_len_u32(ctx); - if (!duk_is_callable(ctx, 0)) { - goto type_error; - } - - /* stack[0] = callback fn - * stack[1] = initialValue - * stack[2] = object (coerced this) - * stack[3] = length (not needed, but not popped above) - * stack[4] = accumulator - */ - - have_acc = 0; - if (nargs >= 2) { - duk_dup(ctx, 1); - have_acc = 1; - } - DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T", - (long) have_acc, (duk_tval *) duk_get_tval(ctx, 3))); - - /* For len == 0, i is initialized to len - 1 which underflows. - * The condition (i < len) will then exit the for-loop on the - * first round which is correct. Similarly, loop termination - * happens by i underflowing. - */ - - for (i = (idx_step >= 0 ? 0 : len - 1); - i < len; /* i >= 0 would always be true */ - i += idx_step) { - DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T", - (long) i, (long) len, (long) have_acc, - (long) duk_get_top(ctx), - (duk_tval *) duk_get_tval(ctx, 4))); - - DUK_ASSERT((have_acc && duk_get_top(ctx) == 5) || - (!have_acc && duk_get_top(ctx) == 4)); - - if (!duk_has_prop_index(ctx, 2, (duk_uarridx_t) i)) { - continue; - } - - if (!have_acc) { - DUK_ASSERT_TOP(ctx, 4); - duk_get_prop_index(ctx, 2, (duk_uarridx_t) i); - have_acc = 1; - DUK_ASSERT_TOP(ctx, 5); - } else { - DUK_ASSERT_TOP(ctx, 5); - duk_dup(ctx, 0); - duk_dup(ctx, 4); - duk_get_prop_index(ctx, 2, (duk_uarridx_t) i); - duk_push_u32(ctx, i); - duk_dup(ctx, 2); - DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T", - (duk_tval *) duk_get_tval(ctx, -5), (duk_tval *) duk_get_tval(ctx, -4), - (duk_tval *) duk_get_tval(ctx, -3), (duk_tval *) duk_get_tval(ctx, -2), - (duk_tval *) duk_get_tval(ctx, -1))); - duk_call(ctx, 4); - DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(ctx, -1))); - duk_replace(ctx, 4); - DUK_ASSERT_TOP(ctx, 5); - } - } - - if (!have_acc) { - goto type_error; - } - - DUK_ASSERT_TOP(ctx, 5); - return 1; - - type_error: - return DUK_RET_TYPE_ERROR; -} - -#undef DUK__ARRAY_MID_JOIN_LIMIT - -#undef DUK__ITER_EVERY -#undef DUK__ITER_SOME -#undef DUK__ITER_FOREACH -#undef DUK__ITER_MAP -#undef DUK__ITER_FILTER http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/5977aa27/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_bi_boolean.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_bi_boolean.c b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_bi_boolean.c deleted file mode 100644 index 5acea6d..0000000 --- a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_bi_boolean.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Boolean built-ins - */ - -#include "duk_internal.h" - -/* Shared helper to provide toString() and valueOf(). Checks 'this', gets - * the primitive value to stack top, and optionally coerces with ToString(). - */ -DUK_INTERNAL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx) { - duk_tval *tv; - duk_hobject *h; - duk_small_int_t coerce_tostring = duk_get_current_magic(ctx); - - /* XXX: there is room to use a shared helper here, many built-ins - * check the 'this' type, and if it's an object, check its class, - * then get its internal value, etc. - */ - - duk_push_this(ctx); - tv = duk_get_tval(ctx, -1); - DUK_ASSERT(tv != NULL); - - if (DUK_TVAL_IS_BOOLEAN(tv)) { - goto type_ok; - } else if (DUK_TVAL_IS_OBJECT(tv)) { - h = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h != NULL); - - if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_BOOLEAN) { - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE); - DUK_ASSERT(duk_is_boolean(ctx, -1)); - goto type_ok; - } - } - - return DUK_RET_TYPE_ERROR; - - type_ok: - if (coerce_tostring) { - duk_to_string(ctx, -1); - } - return 1; -} - -DUK_INTERNAL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *h_this; - - DUK_UNREF(thr); - - duk_to_boolean(ctx, 0); - - if (duk_is_constructor_call(ctx)) { - /* XXX: helper; rely on Boolean.prototype as being non-writable, non-configurable */ - duk_push_this(ctx); - h_this = duk_get_hobject(ctx, -1); - DUK_ASSERT(h_this != NULL); - DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE]); - - DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_BOOLEAN); - - duk_dup(ctx, 0); /* -> [ val obj val ] */ - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE); /* XXX: proper flags? */ - } /* unbalanced stack */ - - return 1; -}