diff --git a/src/modules/app_jsdt/duk_config.h b/src/modules/app_jsdt/duk_config.h index 130168a990d..c7cebdec54b 100644 --- a/src/modules/app_jsdt/duk_config.h +++ b/src/modules/app_jsdt/duk_config.h @@ -1,9 +1,9 @@ /* * duk_config.h configuration header generated by genconfig.py. * - * Git commit: 6001888049cb42656f8649db020e804bcdeca6a7 - * Git describe: v2.5.0 - * Git branch: master + * Git commit: fffa346eff06a8764b02c31d4336f63a773a95c3 + * Git describe: v2.6.0 + * Git branch: v2-maintenance * * Supported platforms: * - Mac OSX, iPhone, Darwin @@ -964,9 +964,7 @@ #elif defined(DUK_F_PPC64) /* --- PowerPC 64-bit --- */ #define DUK_USE_ARCH_STRING "ppc64" -#if !defined(DUK_USE_BYTEORDER) -#define DUK_USE_BYTEORDER 3 -#endif +/* No forced byteorder (both little and big endian are possible). */ #undef DUK_USE_PACKED_TVAL #define DUK_F_PACKED_TVAL_PROVIDED #elif defined(DUK_F_SPARC32) @@ -2917,6 +2915,8 @@ typedef struct duk_hthread duk_context; #define DUK_USE_CACHE_CATCHER #define DUK_USE_CALLSTACK_LIMIT 10000 #define DUK_USE_CBOR_BUILTIN +#define DUK_USE_CBOR_DEC_RECLIMIT 1000 +#define DUK_USE_CBOR_ENC_RECLIMIT 1000 #define DUK_USE_CBOR_SUPPORT #define DUK_USE_COMPILER_RECLIMIT 2500 #define DUK_USE_COROUTINE_SUPPORT diff --git a/src/modules/app_jsdt/duktape.c b/src/modules/app_jsdt/duktape.c index 9e058040653..cd2f7919024 100644 --- a/src/modules/app_jsdt/duktape.c +++ b/src/modules/app_jsdt/duktape.c @@ -1,8 +1,8 @@ /* - * Single source autogenerated distributable for Duktape 2.5.0. + * Single source autogenerated distributable for Duktape 2.6.0. * - * Git commit 6001888049cb42656f8649db020e804bcdeca6a7 (v2.5.0). - * Git branch master. + * Git commit fffa346eff06a8764b02c31d4336f63a773a95c3 (v2.6.0). + * Git branch v2-maintenance. * * See Duktape AUTHORS.rst and LICENSE.txt for copyright and * licensing information. @@ -525,7 +525,8 @@ typedef union duk_double_union duk_double_union; } while (0) #define DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL(u) do { \ - if (DUK__DBLUNION_IS_NAN_NOTFULL((u))) { \ + /* Check must be full. */ \ + if (DUK__DBLUNION_IS_NAN_FULL((u))) { \ DUK__DBLUNION_SET_NAN_NOTFULL((u)); \ } \ } while (0) @@ -537,12 +538,11 @@ typedef union duk_double_union duk_double_union; */ #if defined(DUK_USE_PACKED_TVAL) -#if defined(DUK_USE_FULL_TVAL) #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u) DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL((u)) #define DUK_DBLUNION_IS_NAN(u) DUK__DBLUNION_IS_NAN_FULL((u)) #define DUK_DBLUNION_IS_NORMALIZED_NAN(u) DUK__DBLUNION_IS_NORMALIZED_NAN_FULL((u)) #define DUK_DBLUNION_SET_NAN(d) DUK__DBLUNION_SET_NAN_FULL((d)) -#else +#if 0 #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u) DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL((u)) #define DUK_DBLUNION_IS_NAN(u) DUK__DBLUNION_IS_NAN_NOTFULL((u)) #define DUK_DBLUNION_IS_NORMALIZED_NAN(u) DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL((u)) @@ -3141,10 +3141,12 @@ DUK_INTERNAL_DECL duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y); /* JSON */ #define DUK_STR_FMT_PTR "%p" #define DUK_STR_FMT_INVALID_JSON "invalid json (at offset %ld)" -#define DUK_STR_JSONDEC_RECLIMIT "json decode recursion limit" -#define DUK_STR_JSONENC_RECLIMIT "json encode recursion limit" #define DUK_STR_CYCLIC_INPUT "cyclic input" +/* Generic codec */ +#define DUK_STR_DEC_RECLIMIT "decode recursion limit" +#define DUK_STR_ENC_RECLIMIT "encode recursion limit" + /* Object property access */ #define DUK_STR_INVALID_BASE "invalid base value" #define DUK_STR_STRICT_CALLER_READ "cannot read strict 'caller'" @@ -11289,14 +11291,14 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = { 137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35, 23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165, 19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70, -72,115,96,0,0,0,0,0,2,234,32,91,60,165,195,201,194,8,134,149,216,162,0,192, -41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,195, -192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,1, -119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,36, -98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,0, -83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,102, -8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,20, -28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179, +72,115,96,0,0,0,0,0,15,106,32,91,60,165,195,201,194,8,134,149,216,162,0, +192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176, +195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20, +1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219, +36,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0, +0,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1, +102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48, +20,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179, 216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235, 81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168, 166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149, @@ -11489,7 +11491,7 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = { 137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35, 23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165, 19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70, -72,115,96,32,106,2,128,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0, +72,115,96,32,106,15,0,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0, 192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176, 195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20, 1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219, @@ -11689,14 +11691,14 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = { 137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35, 23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165, 19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70, -72,115,96,0,2,234,32,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0,192, -41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,195, -192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,1, -119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,36, -98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,0, -83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,102, -8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,20, -28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179, +72,115,96,0,15,106,32,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0, +192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176, +195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20, +1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219, +36,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0, +0,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1, +102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48, +20,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179, 216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235, 81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168, 166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149, @@ -16443,6 +16445,7 @@ struct duk_internal_thread_state { duk_ljstate lj; duk_bool_t creating_error; duk_hthread *curr_thread; + duk_uint8_t thread_state; duk_int_t call_recursion_depth; }; @@ -16541,6 +16544,7 @@ DUK_EXTERNAL void duk_suspend(duk_hthread *thr, duk_thread_state *state) { duk_memcpy((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate)); snapshot->creating_error = heap->creating_error; snapshot->curr_thread = heap->curr_thread; + snapshot->thread_state = thr->state; snapshot->call_recursion_depth = heap->call_recursion_depth; lj->jmpbuf_ptr = NULL; @@ -16550,6 +16554,8 @@ DUK_EXTERNAL void duk_suspend(duk_hthread *thr, duk_thread_state *state) { heap->creating_error = 0; heap->curr_thread = NULL; heap->call_recursion_depth = 0; + + thr->state = DUK_HTHREAD_STATE_INACTIVE; } DUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state) { @@ -16566,6 +16572,8 @@ DUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state) { DUK_ASSERT(thr->heap->pf_prevent_count == 0); DUK_ASSERT(thr->heap->creating_error == 0); + thr->state = snapshot->thread_state; + heap = thr->heap; duk_memcpy((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate)); @@ -20026,7 +20034,7 @@ DUK_EXTERNAL void *duk_require_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_ } /* Get the active buffer data area for a plain buffer or a buffer object. - * Return NULL if the value is not a buffer. Note that a buffer may + * Return NULL if the the value is not a buffer. Note that a buffer may * have a NULL data pointer when its size is zero, the optional 'out_isbuffer' * argument allows caller to detect this reliably. */ @@ -30090,6 +30098,8 @@ typedef struct { duk_uint8_t *buf_end; duk_size_t len; duk_idx_t idx_buf; + duk_uint_t recursion_depth; + duk_uint_t recursion_limit; } duk_cbor_encode_context; typedef struct { @@ -30097,6 +30107,8 @@ typedef struct { const duk_uint8_t *buf; duk_size_t off; duk_size_t len; + duk_uint_t recursion_depth; + duk_uint_t recursion_limit; } duk_cbor_decode_context; DUK_LOCAL void duk__cbor_encode_value(duk_cbor_encode_context *enc_ctx); @@ -30120,6 +30132,34 @@ DUK_LOCAL void duk__cbor_encode_error(duk_cbor_encode_context *enc_ctx) { (void) duk_type_error(enc_ctx->thr, "cbor encode error"); } +DUK_LOCAL void duk__cbor_encode_req_stack(duk_cbor_encode_context *enc_ctx) { + duk_require_stack(enc_ctx->thr, 4); +} + +DUK_LOCAL void duk__cbor_encode_objarr_entry(duk_cbor_encode_context *enc_ctx) { + duk_hthread *thr = enc_ctx->thr; + + /* Native stack check in object/array recursion. */ + duk_native_stack_check(thr); + + /* When working with deeply recursive structures, this is important + * to ensure there's no effective depth limit. + */ + duk__cbor_encode_req_stack(enc_ctx); + + DUK_ASSERT(enc_ctx->recursion_depth <= enc_ctx->recursion_limit); + if (enc_ctx->recursion_depth >= enc_ctx->recursion_limit) { + DUK_ERROR_RANGE(thr, DUK_STR_ENC_RECLIMIT); + DUK_WO_NORETURN(return;); + } + enc_ctx->recursion_depth++; +} + +DUK_LOCAL void duk__cbor_encode_objarr_exit(duk_cbor_encode_context *enc_ctx) { + DUK_ASSERT(enc_ctx->recursion_depth > 0); + enc_ctx->recursion_depth--; +} + /* Check that a size_t is in uint32 range to avoid out-of-range casts. */ DUK_LOCAL void duk__cbor_encode_sizet_uint32_check(duk_cbor_encode_context *enc_ctx, duk_size_t len) { if (DUK_UNLIKELY(sizeof(duk_size_t) > sizeof(duk_uint32_t) && len > (duk_size_t) DUK_UINT32_MAX)) { @@ -30522,6 +30562,8 @@ DUK_LOCAL void duk__cbor_encode_object(duk_cbor_encode_context *enc_ctx) { /* Caller must ensure space. */ DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8); + duk__cbor_encode_objarr_entry(enc_ctx); + /* XXX: Support for specific built-ins like Date and RegExp. */ if (duk_is_array(enc_ctx->thr, -1)) { /* Shortest encoding for arrays >= 256 in length is actually @@ -30546,7 +30588,7 @@ DUK_LOCAL void duk__cbor_encode_object(duk_cbor_encode_context *enc_ctx) { duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U); duk__cbor_encode_ensure(enc_ctx, len); p = enc_ctx->ptr; - duk_memcpy((void *) p, (const void *) buf, len); + duk_memcpy_unsafe((void *) p, (const void *) buf, len); p += len; enc_ctx->ptr = p; } else { @@ -30585,6 +30627,8 @@ DUK_LOCAL void duk__cbor_encode_object(duk_cbor_encode_context *enc_ctx) { enc_ctx->ptr = p; } } + + duk__cbor_encode_objarr_exit(enc_ctx); } DUK_LOCAL void duk__cbor_encode_buffer(duk_cbor_encode_context *enc_ctx) { @@ -30601,7 +30645,7 @@ DUK_LOCAL void duk__cbor_encode_buffer(duk_cbor_encode_context *enc_ctx) { duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U); duk__cbor_encode_ensure(enc_ctx, len); p = enc_ctx->ptr; - duk_memcpy((void *) p, (const void *) buf, len); + duk_memcpy_unsafe((void *) p, (const void *) buf, len); p += len; enc_ctx->ptr = p; } @@ -30648,11 +30692,6 @@ DUK_LOCAL void duk__cbor_encode_value(duk_cbor_encode_context *enc_ctx) { * This can be improved by registering custom tags with IANA. */ - /* When working with deeply recursive structures, this is important - * to ensure there's no effective depth limit. - */ - duk_require_stack(enc_ctx->thr, 4); - /* Reserve space for up to 64-bit types (1 initial byte + 8 * followup bytes). This allows encoding of integers, floats, * string/buffer length fields, etc without separate checks @@ -30720,12 +30759,33 @@ DUK_LOCAL void duk__cbor_encode_value(duk_cbor_encode_context *enc_ctx) { * Decoding */ -DUK_LOCAL void duk__cbor_req_stack(duk_cbor_decode_context *dec_ctx) { +DUK_LOCAL void duk__cbor_decode_error(duk_cbor_decode_context *dec_ctx) { + (void) duk_type_error(dec_ctx->thr, "cbor decode error"); +} + +DUK_LOCAL void duk__cbor_decode_req_stack(duk_cbor_decode_context *dec_ctx) { duk_require_stack(dec_ctx->thr, 4); } -DUK_LOCAL void duk__cbor_decode_error(duk_cbor_decode_context *dec_ctx) { - (void) duk_type_error(dec_ctx->thr, "cbor decode error"); +DUK_LOCAL void duk__cbor_decode_objarr_entry(duk_cbor_decode_context *dec_ctx) { + duk_hthread *thr = dec_ctx->thr; + + /* Native stack check in object/array recursion. */ + duk_native_stack_check(thr); + + duk__cbor_decode_req_stack(dec_ctx); + + DUK_ASSERT(dec_ctx->recursion_depth <= dec_ctx->recursion_limit); + if (dec_ctx->recursion_depth >= dec_ctx->recursion_limit) { + DUK_ERROR_RANGE(thr, DUK_STR_DEC_RECLIMIT); + DUK_WO_NORETURN(return;); + } + dec_ctx->recursion_depth++; +} + +DUK_LOCAL void duk__cbor_decode_objarr_exit(duk_cbor_decode_context *dec_ctx) { + DUK_ASSERT(dec_ctx->recursion_depth > 0); + dec_ctx->recursion_depth--; } DUK_LOCAL duk_uint8_t duk__cbor_decode_readbyte(duk_cbor_decode_context *dec_ctx) { @@ -31004,9 +31064,7 @@ DUK_LOCAL void duk__cbor_decode_join_buffers(duk_cbor_decode_context *dec_ctx, d buf_data = (duk_uint8_t *) duk_require_buffer(dec_ctx->thr, idx, &buf_size); if (p != NULL) { - if (buf_size > 0U) { - duk_memcpy((void *) p, (const void *) buf_data, buf_size); - } + duk_memcpy_unsafe((void *) p, (const void *) buf_data, buf_size); p += buf_size; } else { total_size += buf_size; @@ -31171,7 +31229,7 @@ DUK_LOCAL void duk__cbor_decode_string(duk_cbor_decode_context *dec_ctx, duk_uin DUK_LOCAL duk_bool_t duk__cbor_decode_array(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) { duk_uint32_t idx, len; - duk__cbor_req_stack(dec_ctx); + duk__cbor_decode_objarr_entry(dec_ctx); /* Support arrays up to 0xfffffffeU in length. 0xffffffff is * used as an indefinite length marker. @@ -31181,7 +31239,7 @@ DUK_LOCAL duk_bool_t duk__cbor_decode_array(duk_cbor_decode_context *dec_ctx, du } else { len = duk__cbor_decode_aival_uint32(dec_ctx, ib); if (len == 0xffffffffUL) { - return 0; + goto failure; } } @@ -31193,7 +31251,7 @@ DUK_LOCAL duk_bool_t duk__cbor_decode_array(duk_cbor_decode_context *dec_ctx, du } if (idx == len) { if (ai == 0x1fU) { - return 0; + goto failure; } break; } @@ -31201,24 +31259,32 @@ DUK_LOCAL duk_bool_t duk__cbor_decode_array(duk_cbor_decode_context *dec_ctx, du duk_put_prop_index(dec_ctx->thr, -2, (duk_uarridx_t) idx); idx++; if (idx == 0U) { - return 0; /* wrapped */ + goto failure; /* wrapped */ } } +#if 0 + success: +#endif + duk__cbor_decode_objarr_exit(dec_ctx); return 1; + + failure: + /* No need to unwind recursion checks, caller will throw. */ + return 0; } DUK_LOCAL duk_bool_t duk__cbor_decode_map(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) { duk_uint32_t count; - duk__cbor_req_stack(dec_ctx); + duk__cbor_decode_objarr_entry(dec_ctx); if (ai == 0x1fU) { count = 0xffffffffUL; } else { count = duk__cbor_decode_aival_uint32(dec_ctx, ib); if (count == 0xffffffffUL) { - return 0; + goto failure; } } @@ -31249,7 +31315,15 @@ DUK_LOCAL duk_bool_t duk__cbor_decode_map(duk_cbor_decode_context *dec_ctx, duk_ duk_put_prop(dec_ctx->thr, -3); } +#if 0 + success: +#endif + duk__cbor_decode_objarr_exit(dec_ctx); return 1; + + failure: + /* No need to unwind recursion checks, caller will throw. */ + return 0; } DUK_LOCAL duk_double_t duk__cbor_decode_float(duk_cbor_decode_context *dec_ctx) { @@ -31626,8 +31700,13 @@ DUK_LOCAL void duk__cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t enco enc_ctx.buf = buf; enc_ctx.buf_end = buf + enc_ctx.len; + enc_ctx.recursion_depth = 0; + enc_ctx.recursion_limit = DUK_USE_CBOR_ENC_RECLIMIT; + duk_dup(thr, idx); + duk__cbor_encode_req_stack(&enc_ctx); duk__cbor_encode_value(&enc_ctx); + DUK_ASSERT(enc_ctx.recursion_depth == 0); duk_resize_buffer(enc_ctx.thr, enc_ctx.idx_buf, (duk_size_t) (enc_ctx.ptr - enc_ctx.buf)); duk_replace(thr, idx); } @@ -31649,8 +31728,12 @@ DUK_LOCAL void duk__cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t deco dec_ctx.off = 0; /* dec_ctx.len: set above */ - duk__cbor_req_stack(&dec_ctx); + dec_ctx.recursion_depth = 0; + dec_ctx.recursion_limit = DUK_USE_CBOR_DEC_RECLIMIT; + + duk__cbor_decode_req_stack(&dec_ctx); duk__cbor_decode_value(&dec_ctx); + DUK_ASSERT(dec_ctx.recursion_depth == 0); if (dec_ctx.off != dec_ctx.len) { (void) duk_type_error(thr, "trailing garbage"); } @@ -36373,28 +36456,28 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_hthread *thr) { #define DUK__JSON_STRINGIFY_BUFSIZE 128 #define DUK__JSON_MAX_ESC_LEN 10 /* '\Udeadbeef' */ -DUK_LOCAL_DECL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL void duk__json_dec_syntax_error(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL void duk__json_dec_eat_white(duk_json_dec_ctx *js_ctx); #if defined(DUK_USE_JX) -DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL duk_uint8_t duk__json_dec_peek(duk_json_dec_ctx *js_ctx); #endif -DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n); -DUK_LOCAL_DECL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx); -DUK_LOCAL_DECL void duk__dec_string(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL duk_uint8_t duk__json_dec_get(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL duk_uint8_t duk__json_dec_get_nonwhite(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL duk_uint_fast32_t duk__json_dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n); +DUK_LOCAL_DECL void duk__json_dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx); +DUK_LOCAL_DECL void duk__json_dec_string(duk_json_dec_ctx *js_ctx); #if defined(DUK_USE_JX) -DUK_LOCAL_DECL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_pointer(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_buffer(duk_json_dec_ctx *js_ctx); -#endif -DUK_LOCAL_DECL void duk__dec_number(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_object(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_array(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_value(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL void duk__json_dec_plain_string(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL void duk__json_dec_pointer(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL void duk__json_dec_buffer(duk_json_dec_ctx *js_ctx); +#endif +DUK_LOCAL_DECL void duk__json_dec_number(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL void duk__json_dec_objarr_entry(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL void duk__json_dec_objarr_exit(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL void duk__json_dec_object(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL void duk__json_dec_array(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL void duk__json_dec_value(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL void duk__json_dec_reviver_walk(duk_json_dec_ctx *js_ctx); DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch); DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2); @@ -36405,29 +36488,29 @@ DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p); #endif DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx); DUK_LOCAL_DECL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q); -DUK_LOCAL_DECL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k); -DUK_LOCAL_DECL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str); -DUK_LOCAL_DECL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top); -DUK_LOCAL_DECL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top); -DUK_LOCAL_DECL void duk__enc_object(duk_json_enc_ctx *js_ctx); -DUK_LOCAL_DECL void duk__enc_array(duk_json_enc_ctx *js_ctx); -DUK_LOCAL_DECL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder); -DUK_LOCAL_DECL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv); -DUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx); +DUK_LOCAL_DECL void duk__json_enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k); +DUK_LOCAL_DECL void duk__json_enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str); +DUK_LOCAL_DECL void duk__json_enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top); +DUK_LOCAL_DECL void duk__json_enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top); +DUK_LOCAL_DECL void duk__json_enc_object(duk_json_enc_ctx *js_ctx); +DUK_LOCAL_DECL void duk__json_enc_array(duk_json_enc_ctx *js_ctx); +DUK_LOCAL_DECL duk_bool_t duk__json_enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder); +DUK_LOCAL_DECL duk_bool_t duk__json_enc_allow_into_proplist(duk_tval *tv); +DUK_LOCAL_DECL void duk__json_enc_double(duk_json_enc_ctx *js_ctx); #if defined(DUK_USE_FASTINT) -DUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv); +DUK_LOCAL_DECL void duk__json_enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv); #endif #if defined(DUK_USE_JX) || defined(DUK_USE_JC) -DUK_LOCAL_DECL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h); -DUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr); +DUK_LOCAL_DECL void duk__json_enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h); +DUK_LOCAL_DECL void duk__json_enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr); #if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_LOCAL_DECL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj); +DUK_LOCAL_DECL void duk__json_enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj); #endif #endif #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH) -DUK_LOCAL_DECL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h); +DUK_LOCAL_DECL void duk__json_enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h); #endif -DUK_LOCAL_DECL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth); +DUK_LOCAL_DECL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth); /* * Helper tables @@ -36552,7 +36635,7 @@ DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = { * CESU-8 encodings. */ -DUK_LOCAL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL void duk__json_dec_syntax_error(duk_json_dec_ctx *js_ctx) { /* Shared handler to minimize parser size. Cause will be * hidden, unfortunately, but we'll have an offset which * is often quite enough. @@ -36562,7 +36645,7 @@ DUK_LOCAL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) { DUK_WO_NORETURN(return;); } -DUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL void duk__json_dec_eat_white(duk_json_dec_ctx *js_ctx) { const duk_uint8_t *p; duk_uint8_t t; @@ -36593,24 +36676,24 @@ DUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) { } #if defined(DUK_USE_JX) -DUK_LOCAL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL duk_uint8_t duk__json_dec_peek(duk_json_dec_ctx *js_ctx) { DUK_ASSERT(js_ctx->p <= js_ctx->p_end); return *js_ctx->p; } #endif -DUK_LOCAL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL duk_uint8_t duk__json_dec_get(duk_json_dec_ctx *js_ctx) { DUK_ASSERT(js_ctx->p <= js_ctx->p_end); return *js_ctx->p++; } -DUK_LOCAL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) { - duk__dec_eat_white(js_ctx); - return duk__dec_get(js_ctx); +DUK_LOCAL duk_uint8_t duk__json_dec_get_nonwhite(duk_json_dec_ctx *js_ctx) { + duk__json_dec_eat_white(js_ctx); + return duk__json_dec_get(js_ctx); } /* For JX, expressing the whole unsigned 32-bit range matters. */ -DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) { +DUK_LOCAL duk_uint_fast32_t duk__json_dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) { duk_small_uint_t i; duk_uint_fast32_t res = 0; duk_uint8_t x; @@ -36619,7 +36702,7 @@ DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, for (i = 0; i < n; i++) { /* XXX: share helper from lexer; duk_lexer.c / hexval(). */ - x = duk__dec_get(js_ctx); + x = duk__json_dec_get(js_ctx); DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld", (long) i, (long) n, (long) res, (long) x)); @@ -36638,12 +36721,12 @@ DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, return res; syntax_error: - duk__dec_syntax_error(js_ctx); + duk__json_dec_syntax_error(js_ctx); DUK_UNREACHABLE(); return 0; } -DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) { +DUK_LOCAL void duk__json_dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) { duk_hstring *h; const duk_uint8_t *p; duk_uint8_t x, y; @@ -36665,7 +36748,7 @@ DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t st if (x == 0) { break; } - y = duk__dec_get(js_ctx); + y = duk__json_dec_get(js_ctx); if (x != y) { /* Catches EOF of JSON input. */ goto syntax_error; @@ -36676,18 +36759,18 @@ DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t st return; syntax_error: - duk__dec_syntax_error(js_ctx); + duk__json_dec_syntax_error(js_ctx); DUK_UNREACHABLE(); } -DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) { +DUK_LOCAL duk_small_int_t duk__json_dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) { duk_uint_fast32_t cp; /* EOF (-1) will be cast to an unsigned value first * and then re-cast for the switch. In any case, it * will match the default case (syntax error). */ - cp = (duk_uint_fast32_t) duk__dec_get(js_ctx); + cp = (duk_uint_fast32_t) duk__json_dec_get(js_ctx); switch (cp) { case DUK_ASC_BACKSLASH: break; case DUK_ASC_DOUBLEQUOTE: break; @@ -36698,13 +36781,13 @@ DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_u case DUK_ASC_LC_F: cp = 0x0c; break; case DUK_ASC_LC_B: cp = 0x08; break; case DUK_ASC_LC_U: { - cp = duk__dec_decode_hex_escape(js_ctx, 4); + cp = duk__json_dec_decode_hex_escape(js_ctx, 4); break; } #if defined(DUK_USE_JX) case DUK_ASC_UC_U: { if (js_ctx->flag_ext_custom) { - cp = duk__dec_decode_hex_escape(js_ctx, 8); + cp = duk__json_dec_decode_hex_escape(js_ctx, 8); } else { return 1; /* syntax error */ } @@ -36712,7 +36795,7 @@ DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_u } case DUK_ASC_LC_X: { if (js_ctx->flag_ext_custom) { - cp = duk__dec_decode_hex_escape(js_ctx, 2); + cp = duk__json_dec_decode_hex_escape(js_ctx, 2); } else { return 1; /* syntax error */ } @@ -36729,7 +36812,7 @@ DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_u return 0; } -DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL void duk__json_dec_string(duk_json_dec_ctx *js_ctx) { duk_hthread *thr = js_ctx->thr; duk_bufwriter_ctx bw_alloc; duk_bufwriter_ctx *bw; @@ -36788,7 +36871,7 @@ DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) { * quite slow but it's uncommon). */ js_ctx->p = p; - if (duk__dec_string_escape(js_ctx, &q) != 0) { + if (duk__json_dec_string_escape(js_ctx, &q) != 0) { goto syntax_error; } break; @@ -36805,12 +36888,12 @@ DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) { q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, DUK_UNICODE_MAX_XUTF8_LENGTH, q); - x = duk__dec_get(js_ctx); + x = duk__json_dec_get(js_ctx); if (x == DUK_ASC_DOUBLEQUOTE) { break; } else if (x == DUK_ASC_BACKSLASH) { - if (duk__dec_string_escape(js_ctx, &q) != 0) { + if (duk__json_dec_string_escape(js_ctx, &q) != 0) { goto syntax_error; } } else if (x < 0x20) { @@ -36830,7 +36913,7 @@ DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) { return; syntax_error: - duk__dec_syntax_error(js_ctx); + duk__json_dec_syntax_error(js_ctx); DUK_UNREACHABLE(); } @@ -36838,7 +36921,7 @@ DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) { /* Decode a plain string consisting entirely of identifier characters. * Used to parse plain keys (e.g. "foo: 123"). */ -DUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL void duk__json_dec_plain_string(duk_json_dec_ctx *js_ctx) { duk_hthread *thr = js_ctx->thr; const duk_uint8_t *p; duk_small_int_t x; @@ -36880,7 +36963,7 @@ DUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) { #endif /* DUK_USE_JX */ #if defined(DUK_USE_JX) -DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL void duk__json_dec_pointer(duk_json_dec_ctx *js_ctx) { duk_hthread *thr = js_ctx->thr; const duk_uint8_t *p; duk_small_int_t x; @@ -36927,13 +37010,13 @@ DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) { return; syntax_error: - duk__dec_syntax_error(js_ctx); + duk__json_dec_syntax_error(js_ctx); DUK_UNREACHABLE(); } #endif /* DUK_USE_JX */ #if defined(DUK_USE_JX) -DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL void duk__json_dec_buffer(duk_json_dec_ctx *js_ctx) { duk_hthread *thr = js_ctx->thr; const duk_uint8_t *p; duk_uint8_t *buf; @@ -36985,13 +37068,13 @@ DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) { return; syntax_error: - duk__dec_syntax_error(js_ctx); + duk__json_dec_syntax_error(js_ctx); DUK_UNREACHABLE(); } #endif /* DUK_USE_JX */ /* Parse a number, other than NaN or +/- Infinity */ -DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL void duk__json_dec_number(duk_json_dec_ctx *js_ctx) { duk_hthread *thr = js_ctx->thr; const duk_uint8_t *p_start; const duk_uint8_t *p; @@ -37047,7 +37130,7 @@ DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) { (duk_tval *) duk_get_tval(thr, -1))); duk_numconv_parse(thr, 10 /*radix*/, s2n_flags); if (duk_is_nan(thr, -1)) { - duk__dec_syntax_error(js_ctx); + duk__json_dec_syntax_error(js_ctx); } DUK_ASSERT(duk_is_number(thr, -1)); DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T", @@ -37056,22 +37139,24 @@ DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) { /* [ ... num ] */ } -DUK_LOCAL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL void duk__json_dec_objarr_entry(duk_json_dec_ctx *js_ctx) { duk_hthread *thr = js_ctx->thr; duk_require_stack(thr, DUK_JSON_DEC_REQSTACK); /* c recursion check */ + duk_native_stack_check(thr); + DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0); /* unsigned */ DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit); if (js_ctx->recursion_depth >= js_ctx->recursion_limit) { - DUK_ERROR_RANGE(thr, DUK_STR_JSONDEC_RECLIMIT); + DUK_ERROR_RANGE(thr, DUK_STR_DEC_RECLIMIT); DUK_WO_NORETURN(return;); } js_ctx->recursion_depth++; } -DUK_LOCAL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL void duk__json_dec_objarr_exit(duk_json_dec_ctx *js_ctx) { /* c recursion check */ DUK_ASSERT(js_ctx->recursion_depth > 0); @@ -37079,14 +37164,14 @@ DUK_LOCAL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) { js_ctx->recursion_depth--; } -DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL void duk__json_dec_object(duk_json_dec_ctx *js_ctx) { duk_hthread *thr = js_ctx->thr; duk_int_t key_count; /* XXX: a "first" flag would suffice */ duk_uint8_t x; DUK_DDD(DUK_DDDPRINT("parse_object")); - duk__dec_objarr_entry(js_ctx); + duk__json_dec_objarr_entry(js_ctx); duk_push_object(thr); @@ -37094,7 +37179,7 @@ DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) { key_count = 0; for (;;) { - x = duk__dec_get_nonwhite(js_ctx); + x = duk__json_dec_get_nonwhite(js_ctx); DUK_DDD(DUK_DDDPRINT("parse_object: obj=%!T, x=%ld, key_count=%ld", (duk_tval *) duk_get_tval(thr, -1), @@ -37104,7 +37189,7 @@ DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) { if (x == DUK_ASC_COMMA && key_count > 0) { /* accept comma, expect new value */ - x = duk__dec_get_nonwhite(js_ctx); + x = duk__json_dec_get_nonwhite(js_ctx); } else if (x == DUK_ASC_RCURLY) { /* eat closing brace */ break; @@ -37121,11 +37206,11 @@ DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) { /* parse key and value */ if (x == DUK_ASC_DOUBLEQUOTE) { - duk__dec_string(js_ctx); + duk__json_dec_string(js_ctx); #if defined(DUK_USE_JX) } else if (js_ctx->flag_ext_custom && duk_unicode_is_identifier_start((duk_codepoint_t) x)) { - duk__dec_plain_string(js_ctx); + duk__json_dec_plain_string(js_ctx); #endif } else { goto syntax_error; @@ -37133,12 +37218,12 @@ DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) { /* [ ... obj key ] */ - x = duk__dec_get_nonwhite(js_ctx); + x = duk__json_dec_get_nonwhite(js_ctx); if (x != DUK_ASC_COLON) { goto syntax_error; } - duk__dec_value(js_ctx); + duk__json_dec_value(js_ctx); /* [ ... obj key val ] */ @@ -37154,22 +37239,22 @@ DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) { DUK_DDD(DUK_DDDPRINT("parse_object: final object is %!T", (duk_tval *) duk_get_tval(thr, -1))); - duk__dec_objarr_exit(js_ctx); + duk__json_dec_objarr_exit(js_ctx); return; syntax_error: - duk__dec_syntax_error(js_ctx); + duk__json_dec_syntax_error(js_ctx); DUK_UNREACHABLE(); } -DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL void duk__json_dec_array(duk_json_dec_ctx *js_ctx) { duk_hthread *thr = js_ctx->thr; duk_uarridx_t arr_idx; duk_uint8_t x; DUK_DDD(DUK_DDDPRINT("parse_array")); - duk__dec_objarr_entry(js_ctx); + duk__json_dec_objarr_entry(js_ctx); duk_push_array(thr); @@ -37177,7 +37262,7 @@ DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) { arr_idx = 0; for (;;) { - x = duk__dec_get_nonwhite(js_ctx); + x = duk__json_dec_get_nonwhite(js_ctx); DUK_DDD(DUK_DDDPRINT("parse_array: arr=%!T, x=%ld, arr_idx=%ld", (duk_tval *) duk_get_tval(thr, -1), @@ -37193,7 +37278,7 @@ DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) { break; } else if (arr_idx == 0) { /* accept anything, expect first value (EOF will be - * caught by duk__dec_value() below. + * caught by duk__json_dec_value() below. */ js_ctx->p--; /* backtrack (safe) */ } else { @@ -37203,7 +37288,7 @@ DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) { /* parse value */ - duk__dec_value(js_ctx); + duk__json_dec_value(js_ctx); /* [ ... arr val ] */ @@ -37222,30 +37307,30 @@ DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) { DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T", (duk_tval *) duk_get_tval(thr, -1))); - duk__dec_objarr_exit(js_ctx); + duk__json_dec_objarr_exit(js_ctx); return; syntax_error: - duk__dec_syntax_error(js_ctx); + duk__json_dec_syntax_error(js_ctx); DUK_UNREACHABLE(); } -DUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL void duk__json_dec_value(duk_json_dec_ctx *js_ctx) { duk_hthread *thr = js_ctx->thr; duk_uint8_t x; - x = duk__dec_get_nonwhite(js_ctx); + x = duk__json_dec_get_nonwhite(js_ctx); DUK_DDD(DUK_DDDPRINT("parse_value: initial x=%ld", (long) x)); - /* Note: duk__dec_req_stridx() backtracks one char */ + /* Note: duk__json_dec_req_stridx() backtracks one char */ if (x == DUK_ASC_DOUBLEQUOTE) { - duk__dec_string(js_ctx); + duk__json_dec_string(js_ctx); } else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) { #if defined(DUK_USE_JX) - if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__dec_peek(js_ctx) == DUK_ASC_UC_I) { - duk__dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY); /* "-Infinity", '-' has been eaten */ + if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__json_dec_peek(js_ctx) == DUK_ASC_UC_I) { + duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY); /* "-Infinity", '-' has been eaten */ duk_push_number(thr, -DUK_DOUBLE_INFINITY); } else { #else @@ -37253,60 +37338,63 @@ DUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) { #endif /* We already ate 'x', so backup one byte. */ js_ctx->p--; /* safe */ - duk__dec_number(js_ctx); + duk__json_dec_number(js_ctx); } } else if (x == DUK_ASC_LC_T) { - duk__dec_req_stridx(js_ctx, DUK_STRIDX_TRUE); + duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_TRUE); duk_push_true(thr); } else if (x == DUK_ASC_LC_F) { - duk__dec_req_stridx(js_ctx, DUK_STRIDX_FALSE); + duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_FALSE); duk_push_false(thr); } else if (x == DUK_ASC_LC_N) { - duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL); + duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL); duk_push_null(thr); #if defined(DUK_USE_JX) } else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) { - duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED); + duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED); duk_push_undefined(thr); } else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) { - duk__dec_req_stridx(js_ctx, DUK_STRIDX_NAN); + duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_NAN); duk_push_nan(thr); } else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) { - duk__dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY); + duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY); duk_push_number(thr, DUK_DOUBLE_INFINITY); } else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) { - duk__dec_pointer(js_ctx); + duk__json_dec_pointer(js_ctx); } else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) { - duk__dec_buffer(js_ctx); + duk__json_dec_buffer(js_ctx); #endif } else if (x == DUK_ASC_LCURLY) { - duk__dec_object(js_ctx); + duk__json_dec_object(js_ctx); } else if (x == DUK_ASC_LBRACKET) { - duk__dec_array(js_ctx); + duk__json_dec_array(js_ctx); } else { /* catches EOF (NUL) */ goto syntax_error; } - duk__dec_eat_white(js_ctx); + duk__json_dec_eat_white(js_ctx); /* [ ... val ] */ return; syntax_error: - duk__dec_syntax_error(js_ctx); + duk__json_dec_syntax_error(js_ctx); DUK_UNREACHABLE(); } -/* Recursive value reviver, implements the Walk() algorithm. No C recursion - * check is done here because the initial parsing step will already ensure - * there is a reasonable limit on C recursion depth and hence object depth. +/* Recursive value reviver, implements the Walk() algorithm. The parsing + * step ensures there is a reasonable depth limit to the input. However, + * the reviver may create more depth by editing object or array entries, so + * we have both C recursion limit and native stack checks here. */ -DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL void duk__json_dec_reviver_walk(duk_json_dec_ctx *js_ctx) { duk_hthread *thr = js_ctx->thr; duk_hobject *h; duk_uarridx_t i, arr_len; + duk__json_dec_objarr_entry(js_ctx); + DUK_DDD(DUK_DDDPRINT("walk: top=%ld, holder=%!T, name=%!T", (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -2), @@ -37329,7 +37417,7 @@ DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) { duk_dup_top(thr); (void) duk_push_uint_to_hstring(thr, (duk_uint_t) i); /* -> [ ... holder name val val ToString(i) ] */ - duk__dec_reviver_walk(js_ctx); /* -> [ ... holder name val new_elem ] */ + duk__json_dec_reviver_walk(js_ctx); /* -> [ ... holder name val new_elem ] */ if (duk_is_undefined(thr, -1)) { duk_pop(thr); @@ -37356,7 +37444,7 @@ DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) { duk_dup_m2(thr); /* [ ... holder name val enum obj_key val obj_key ] */ - duk__dec_reviver_walk(js_ctx); + duk__json_dec_reviver_walk(js_ctx); /* [ ... holder name val enum obj_key new_elem ] */ if (duk_is_undefined(thr, -1)) { @@ -37385,6 +37473,8 @@ DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) { duk_insert(thr, -4); /* -> [ ... reviver holder name val ] */ duk_call_method(thr, 2); /* -> [ ... res ] */ + duk__json_dec_objarr_exit(js_ctx); + DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T", (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -1))); } @@ -37494,7 +37584,7 @@ DUK_LOCAL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uin return q; } -DUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) { +DUK_LOCAL void duk__json_enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) { const duk_int8_t *p, *p_start, *p_end; /* Note: intentionally signed. */ duk_size_t k_len; duk_codepoint_t cp; @@ -37537,7 +37627,7 @@ DUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) } quote_normally: - duk__enc_quote_string(js_ctx, k); + duk__json_enc_quote_string(js_ctx, k); } /* The Quote(value) operation: quote a string. @@ -37545,13 +37635,13 @@ DUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) * Stack policy: [ ] -> [ ]. */ -DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) { +DUK_LOCAL void duk__json_enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) { duk_hthread *thr = js_ctx->thr; const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp; duk_uint8_t *q; duk_ucodepoint_t cp; /* typed for duk_unicode_decode_xutf8() */ - DUK_DDD(DUK_DDDPRINT("duk__enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str)); + DUK_DDD(DUK_DDDPRINT("duk__json_enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str)); DUK_ASSERT(h_str != NULL); p_start = DUK_HSTRING_GET_DATA(h_str); @@ -37682,7 +37772,7 @@ DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_st /* Encode a double (checked by caller) from stack top. Stack top may be * replaced by serialized string but is not popped (caller does that). */ -DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) { +DUK_LOCAL void duk__json_enc_double(duk_json_enc_ctx *js_ctx) { duk_hthread *thr; duk_tval *tv; duk_double_t d; @@ -37746,7 +37836,7 @@ DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) { #if defined(DUK_USE_FASTINT) /* Encode a fastint from duk_tval ptr, no value stack effects. */ -DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) { +DUK_LOCAL void duk__json_enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) { duk_int64_t v; /* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328 @@ -37771,7 +37861,7 @@ DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) { #if defined(DUK_USE_JX) || defined(DUK_USE_JC) #if defined(DUK_USE_HEX_FASTPATH) -DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) { +DUK_LOCAL duk_uint8_t *duk__json_enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) { duk_uint8_t *q; duk_uint16_t *q16; duk_small_uint_t x; @@ -37829,7 +37919,7 @@ DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size return q; } #else /* DUK_USE_HEX_FASTPATH */ -DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) { +DUK_LOCAL duk_uint8_t *duk__json_enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) { const duk_uint8_t *p; const duk_uint8_t *p_end; duk_uint8_t *q; @@ -37848,7 +37938,7 @@ DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size } #endif /* DUK_USE_HEX_FASTPATH */ -DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) { +DUK_LOCAL void duk__json_enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) { duk_hthread *thr; duk_uint8_t *q; duk_size_t space; @@ -37880,7 +37970,7 @@ DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_d #if defined(DUK_USE_JX) { *q++ = DUK_ASC_PIPE; - q = duk__enc_buffer_data_hex(buf_data, buf_len, q); + q = duk__json_enc_buffer_data_hex(buf_data, buf_len, q); *q++ = DUK_ASC_PIPE; } @@ -37893,7 +37983,7 @@ DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_d DUK_ASSERT(js_ctx->flag_ext_compatible); duk_memcpy((void *) q, (const void *) "{\"_buf\":\"", 9); /* len: 9 */ q += 9; - q = duk__enc_buffer_data_hex(buf_data, buf_len, q); + q = duk__json_enc_buffer_data_hex(buf_data, buf_len, q); *q++ = DUK_ASC_DOUBLEQUOTE; *q++ = DUK_ASC_RCURLY; } @@ -37902,15 +37992,15 @@ DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_d DUK_BW_SET_PTR(thr, &js_ctx->bw, q); } -DUK_LOCAL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) { - duk__enc_buffer_data(js_ctx, +DUK_LOCAL void duk__json_enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) { + duk__json_enc_buffer_data(js_ctx, (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h)); } #endif /* DUK_USE_JX || DUK_USE_JC */ #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH) -DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) { +DUK_LOCAL void duk__json_enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) { duk_size_t i, n; const duk_uint8_t *buf; duk_uint8_t *q; @@ -37934,7 +38024,7 @@ DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuff buf = (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h); if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) { for (i = 0; i < n; i++) { - duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1); + duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1); q = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, 32); q += DUK_SPRINTF((char *) q, "\"%lu\": %u,", (unsigned long) i, (unsigned int) buf[i]); DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q); @@ -37950,14 +38040,14 @@ DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuff DUK__UNEMIT_1(js_ctx); /* eat trailing comma */ if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) { - duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth); + duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth); } DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY); } #endif /* DUK_USE_JSON_STRINGIFY_FASTPATH */ #if defined(DUK_USE_JX) || defined(DUK_USE_JC) -DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) { +DUK_LOCAL void duk__json_enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) { char buf[64]; /* XXX: how to figure correct size? */ const char *fmt; @@ -37995,14 +38085,14 @@ DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) { #if defined(DUK_USE_BUFFEROBJECT_SUPPORT) #if defined(DUK_USE_JX) || defined(DUK_USE_JC) -DUK_LOCAL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj) { +DUK_LOCAL void duk__json_enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj) { DUK_HBUFOBJ_ASSERT_VALID(h_bufobj); if (h_bufobj->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) { DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL); } else { /* Handle both full and partial slice (as long as covered). */ - duk__enc_buffer_data(js_ctx, + duk__json_enc_buffer_data(js_ctx, (duk_uint8_t *) DUK_HBUFOBJ_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj), (duk_size_t) h_bufobj->length); } @@ -38014,7 +38104,7 @@ DUK_LOCAL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj) * directly related to indent depth. */ #if defined(DUK_USE_PREFER_SIZE) -DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) { +DUK_LOCAL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) { DUK_ASSERT(js_ctx->h_gap != NULL); DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0); /* caller guarantees */ @@ -38024,7 +38114,7 @@ DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t dept } } #else /* DUK_USE_PREFER_SIZE */ -DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) { +DUK_LOCAL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) { const duk_uint8_t *gap_data; duk_size_t gap_len; duk_size_t avail_bytes; /* bytes of indent available for copying */ @@ -38077,13 +38167,14 @@ DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t dept #endif /* DUK_USE_PREFER_SIZE */ /* Shared entry handling for object/array serialization. */ -DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) { +DUK_LOCAL void duk__json_enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) { duk_hthread *thr = js_ctx->thr; duk_hobject *h_target; duk_uint_fast32_t i, n; *entry_top = duk_get_top(thr); + duk_native_stack_check(thr); duk_require_stack(thr, DUK_JSON_ENC_REQSTACK); /* Loop check using a hybrid approach: a fixed-size visited[] array @@ -38121,7 +38212,7 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_ DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0); /* unsigned */ DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit); if (js_ctx->recursion_depth >= js_ctx->recursion_limit) { - DUK_ERROR_RANGE(thr, DUK_STR_JSONENC_RECLIMIT); + DUK_ERROR_RANGE(thr, DUK_STR_ENC_RECLIMIT); DUK_WO_NORETURN(return;); } js_ctx->recursion_depth++; @@ -38131,7 +38222,7 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_ } /* Shared exit handling for object/array serialization. */ -DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) { +DUK_LOCAL void duk__json_enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) { duk_hthread *thr = js_ctx->thr; duk_hobject *h_target; @@ -38163,7 +38254,7 @@ DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_t * * Stack policy: [ object ] -> [ object ]. */ -DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) { +DUK_LOCAL void duk__json_enc_object(duk_json_enc_ctx *js_ctx) { duk_hthread *thr = js_ctx->thr; duk_hstring *h_key; duk_idx_t entry_top; @@ -38173,9 +38264,9 @@ DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) { duk_uarridx_t arr_len, i; duk_size_t prev_size; - DUK_DDD(DUK_DDDPRINT("duk__enc_object: obj=%!T", (duk_tval *) duk_get_tval(thr, -1))); + DUK_DDD(DUK_DDDPRINT("duk__json_enc_object: obj=%!T", (duk_tval *) duk_get_tval(thr, -1))); - duk__enc_objarr_entry(js_ctx, &entry_top); + duk__json_enc_objarr_entry(js_ctx, &entry_top); idx_obj = entry_top - 1; @@ -38217,17 +38308,17 @@ DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) { prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw); if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) { - duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth); - duk__enc_key_autoquote(js_ctx, h_key); + duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth); + duk__json_enc_key_autoquote(js_ctx, h_key); DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE); } else { - duk__enc_key_autoquote(js_ctx, h_key); + duk__json_enc_key_autoquote(js_ctx, h_key); DUK__EMIT_1(js_ctx, DUK_ASC_COLON); } /* [ ... key ] */ - if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_obj) == 0)) { + if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_obj) == 0)) { /* Value would yield 'undefined', so skip key altogether. * Side effects have already happened. */ @@ -38245,12 +38336,12 @@ DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) { DUK__UNEMIT_1(js_ctx); /* eat trailing comma */ if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) { DUK_ASSERT(js_ctx->recursion_depth >= 1); - duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U); + duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U); } } DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY); - duk__enc_objarr_exit(js_ctx, &entry_top); + duk__json_enc_objarr_exit(js_ctx, &entry_top); DUK_ASSERT_TOP(thr, entry_top); } @@ -38259,17 +38350,17 @@ DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) { * * Stack policy: [ array ] -> [ array ]. */ -DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) { +DUK_LOCAL void duk__json_enc_array(duk_json_enc_ctx *js_ctx) { duk_hthread *thr = js_ctx->thr; duk_idx_t entry_top; duk_idx_t idx_arr; duk_bool_t emitted; duk_uarridx_t i, arr_len; - DUK_DDD(DUK_DDDPRINT("duk__enc_array: array=%!T", + DUK_DDD(DUK_DDDPRINT("duk__json_enc_array: array=%!T", (duk_tval *) duk_get_tval(thr, -1))); - duk__enc_objarr_entry(js_ctx, &entry_top); + duk__json_enc_objarr_entry(js_ctx, &entry_top); idx_arr = entry_top - 1; @@ -38286,14 +38377,14 @@ DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) { if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) { DUK_ASSERT(js_ctx->recursion_depth >= 1); - duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth); + duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth); } (void) duk_push_uint_to_hstring(thr, (duk_uint_t) i); /* -> [ ... key ] */ /* [ ... key ] */ - if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_arr) == 0)) { + if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_arr) == 0)) { /* Value would normally be omitted, replace with 'null'. */ DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL); } else { @@ -38311,12 +38402,12 @@ DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) { DUK__UNEMIT_1(js_ctx); /* eat trailing comma */ if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) { DUK_ASSERT(js_ctx->recursion_depth >= 1); - duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U); + duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U); } } DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET); - duk__enc_objarr_exit(js_ctx, &entry_top); + duk__json_enc_objarr_exit(js_ctx, &entry_top); DUK_ASSERT_TOP(thr, entry_top); } @@ -38325,14 +38416,14 @@ DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) { * * Stack policy: [ ... key ] -> [ ... ] */ -DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) { +DUK_LOCAL duk_bool_t duk__json_enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) { duk_hthread *thr = js_ctx->thr; duk_tval *tv; duk_tval *tv_holder; duk_tval *tv_key; duk_small_int_t c; - DUK_DDD(DUK_DDDPRINT("duk__enc_value: idx_holder=%ld, holder=%!T, key=%!T", + DUK_DDD(DUK_DDDPRINT("duk__json_enc_value: idx_holder=%ld, holder=%!T, key=%!T", (long) idx_holder, (duk_tval *) duk_get_tval(thr, idx_holder), (duk_tval *) duk_get_tval(thr, -1))); @@ -38402,7 +38493,7 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold duk_hbufobj *h_bufobj; h_bufobj = (duk_hbufobj *) h; DUK_HBUFOBJ_ASSERT_VALID(h_bufobj); - duk__enc_bufobj(js_ctx, h_bufobj); + duk__json_enc_bufobj(js_ctx, h_bufobj); goto pop2_emitted; } /* Otherwise bufferobjects get serialized as normal objects. */ @@ -38498,7 +38589,7 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold #if defined(DUK_USE_JX) || defined(DUK_USE_JC) /* When JX/JC not in use, the type mask above will avoid this case if needed. */ case DUK_TAG_POINTER: { - duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv)); + duk__json_enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv)); break; } #endif /* DUK_USE_JX || DUK_USE_JC */ @@ -38508,7 +38599,7 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) { goto pop2_undef; } - duk__enc_quote_string(js_ctx, h); + duk__json_enc_quote_string(js_ctx, h); break; } case DUK_TAG_OBJECT: { @@ -38521,9 +38612,9 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h)); if (duk_js_isarray_hobject(h)) { - duk__enc_array(js_ctx); + duk__json_enc_array(js_ctx); } else { - duk__enc_object(js_ctx); + duk__json_enc_object(js_ctx); } break; } @@ -38536,7 +38627,7 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold case DUK_TAG_BUFFER: { #if defined(DUK_USE_JX) || defined(DUK_USE_JC) if (js_ctx->flag_ext_custom_or_compatible) { - duk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv)); + duk__json_enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv)); break; } #endif @@ -38545,7 +38636,7 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold * to handle realloc side effects correctly. */ duk_to_object(thr, -1); - duk__enc_object(js_ctx); + duk__json_enc_object(js_ctx); break; } case DUK_TAG_LIGHTFUNC: { @@ -38564,7 +38655,7 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold /* Number serialization has a significant impact relative to * other fast path code, so careful fast path for fastints. */ - duk__enc_fastint_tval(js_ctx, tv); + duk__json_enc_fastint_tval(js_ctx, tv); break; #endif default: { @@ -38574,7 +38665,7 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold /* XXX: A fast path for usual integers would be useful when * fastint support is not enabled. */ - duk__enc_double(js_ctx); + duk__json_enc_double(js_ctx); break; } } @@ -38591,7 +38682,7 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold } /* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */ -DUK_LOCAL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv) { +DUK_LOCAL duk_bool_t duk__json_enc_allow_into_proplist(duk_tval *tv) { duk_small_int_t c; /* XXX: some kind of external internal type checker? @@ -38674,7 +38765,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) { goto emit_undefined; } - duk__enc_quote_string(js_ctx, h); + duk__json_enc_quote_string(js_ctx, h); break; } case DUK_TAG_OBJECT: { @@ -38719,7 +38810,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit); if (js_ctx->recursion_depth >= js_ctx->recursion_limit) { DUK_DD(DUK_DDPRINT("fast path recursion limit")); - DUK_ERROR_RANGE(js_ctx->thr, DUK_STR_JSONDEC_RECLIMIT); + DUK_ERROR_RANGE(js_ctx->thr, DUK_STR_DEC_RECLIMIT); DUK_WO_NORETURN(return 0;); } @@ -38846,11 +38937,11 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw); if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) { - duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth); - duk__enc_key_autoquote(js_ctx, k); + duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth); + duk__json_enc_key_autoquote(js_ctx, k); DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE); } else { - duk__enc_key_autoquote(js_ctx, k); + duk__json_enc_key_autoquote(js_ctx, k); DUK__EMIT_1(js_ctx, DUK_ASC_COLON); } @@ -38873,7 +38964,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du DUK__UNEMIT_1(js_ctx); /* eat trailing comma */ if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) { DUK_ASSERT(js_ctx->recursion_depth >= 1); - duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U); + duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U); } } DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY); @@ -38901,7 +38992,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du duk_bool_t has_inherited; if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) { - duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth); + duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth); } if (DUK_LIKELY(i < asize)) { @@ -38950,7 +39041,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du DUK__UNEMIT_1(js_ctx); /* eat trailing comma */ if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) { DUK_ASSERT(js_ctx->recursion_depth >= 1); - duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U); + duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U); } } DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET); @@ -38992,7 +39083,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function); #if defined(DUK_USE_BUFFEROBJECT_SUPPORT) } else if (c_bit & c_bufobj) { - duk__enc_bufobj(js_ctx, (duk_hbufobj *) obj); + duk__json_enc_bufobj(js_ctx, (duk_hbufobj *) obj); #endif #endif } else if (c_bit & c_abort) { @@ -39032,7 +39123,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du #if defined(DUK_USE_JX) || defined(DUK_USE_JC) if (js_ctx->flag_ext_custom_or_compatible) { - duk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv)); + duk__json_enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv)); break; } #endif @@ -39040,13 +39131,13 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du /* Plain buffers mimic Uint8Arrays, and have enumerable index * properties. */ - duk__enc_buffer_json_fastpath(js_ctx, DUK_TVAL_GET_BUFFER(tv)); + duk__json_enc_buffer_json_fastpath(js_ctx, DUK_TVAL_GET_BUFFER(tv)); break; } case DUK_TAG_POINTER: { #if defined(DUK_USE_JX) || defined(DUK_USE_JC) if (js_ctx->flag_ext_custom_or_compatible) { - duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv)); + duk__json_enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv)); break; } else { goto emit_undefined; @@ -39068,7 +39159,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du /* Number serialization has a significant impact relative to * other fast path code, so careful fast path for fastints. */ - duk__enc_fastint_tval(js_ctx, tv); + duk__json_enc_fastint_tval(js_ctx, tv); break; } #endif @@ -39081,7 +39172,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du /* XXX: Stack discipline is annoying, could be changed in numconv. */ duk_push_tval(js_ctx->thr, tv); - duk__enc_double(js_ctx); + duk__json_enc_double(js_ctx); duk_pop(js_ctx->thr); #if 0 @@ -39193,14 +39284,15 @@ void duk_bi_json_parse_helper(duk_hthread *thr, DUK_HSTRING_GET_BYTELEN(h_text); DUK_ASSERT(*(js_ctx->p_end) == 0x00); - duk__dec_value(js_ctx); /* -> [ ... value ] */ + duk__json_dec_value(js_ctx); /* -> [ ... value ] */ + DUK_ASSERT(js_ctx->recursion_depth == 0); - /* Trailing whitespace has been eaten by duk__dec_value(), so if + /* Trailing whitespace has been eaten by duk__json_dec_value(), so if * we're not at end of input here, it's a SyntaxError. */ if (js_ctx->p != js_ctx->p_end) { - duk__dec_syntax_error(js_ctx); + duk__json_dec_syntax_error(js_ctx); } if (duk_is_callable(thr, idx_reviver)) { @@ -39218,7 +39310,9 @@ void duk_bi_json_parse_helper(duk_hthread *thr, (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1))); - duk__dec_reviver_walk(js_ctx); /* [ ... val root "" ] -> [ ... val val' ] */ + DUK_ASSERT(js_ctx->recursion_depth == 0); + duk__json_dec_reviver_walk(js_ctx); /* [ ... val root "" ] -> [ ... val val' ] */ + DUK_ASSERT(js_ctx->recursion_depth == 0); duk_remove_m2(thr); /* -> [ ... val' ] */ } else { DUK_DDD(DUK_DDDPRINT("reviver does not exist or is not callable: %!T", @@ -39366,14 +39460,14 @@ void duk_bi_json_stringify_helper(duk_hthread *thr, duk_uarridx_t plist_idx = 0; duk_small_uint_t enum_flags; - js_ctx->idx_proplist = duk_push_array(thr); /* XXX: array internal? */ + js_ctx->idx_proplist = duk_push_bare_array(thr); enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY | DUK_ENUM_SORT_ARRAY_INDICES; /* expensive flag */ duk_enum(thr, idx_replacer, enum_flags); while (duk_next(thr, -1 /*enum_index*/, 1 /*get_value*/)) { /* [ ... proplist enum_obj key val ] */ - if (duk__enc_allow_into_proplist(duk_get_tval(thr, -1))) { + if (duk__json_enc_allow_into_proplist(duk_get_tval(thr, -1))) { /* XXX: duplicates should be eliminated here */ DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept", (duk_tval *) duk_get_tval(thr, -2), @@ -39533,7 +39627,7 @@ void duk_bi_json_stringify_helper(duk_hthread *thr, js_ctx->recursion_limit = DUK_USE_JSON_ENC_RECLIMIT; DUK_ASSERT(js_ctx->recursion_depth == 0); - if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_holder) == 0)) { /* [ ... holder key ] -> [ ... holder ] */ + if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_holder) == 0)) { /* [ ... holder key ] -> [ ... holder ] */ /* Result is undefined. */ duk_push_undefined(thr); } else { @@ -41436,7 +41530,9 @@ DUK_INTERNAL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h } /* [ obj trap_result res_arr propname ] */ - duk_put_prop_index(thr, -2, idx++); + duk_push_uarridx(thr, idx++); + duk_insert(thr, -2); + duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_WEC); continue; skip_key: @@ -42461,6 +42557,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) { #endif /* DUK_USE_REGEXP_SUPPORT */ const duk_uint8_t *p_start, *p_end, *p; /* input string scan */ const duk_uint8_t *q_start; /* match string */ + duk_size_t p_blen; duk_size_t q_blen; #if defined(DUK_USE_REGEXP_SUPPORT) @@ -42469,13 +42566,19 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) { p_start = DUK_HSTRING_GET_DATA(h_input); p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input); + p_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_input); p = p_start; h_search = duk_known_hstring(thr, 0); q_start = DUK_HSTRING_GET_DATA(h_search); q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search); + if (q_blen > p_blen) { + break; /* no match */ + } + p_end -= q_blen; /* ensure full memcmp() fits in while */ + DUK_ASSERT(p_end >= p); match_start_coff = 0; @@ -43290,44 +43393,65 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_hthread *thr) #if defined(DUK_USE_ES6) DUK_INTERNAL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_hthread *thr) { duk_int_t magic; - duk_hstring *h; + duk_hstring *h_target; + duk_size_t blen_target; duk_hstring *h_search; duk_size_t blen_search; - const duk_uint8_t *p_cmp_start; - duk_bool_t result; + duk_int_t off; + duk_bool_t result = 0; + duk_size_t blen_left; - h = duk_push_this_coercible_to_string(thr); - DUK_ASSERT(h != NULL); + /* Because string byte lengths are in [0,DUK_INT_MAX] it's safe to + * subtract two string lengths without overflow. + */ + DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= DUK_INT_MAX); + + h_target = duk_push_this_coercible_to_string(thr); + DUK_ASSERT(h_target != NULL); h_search = duk__str_tostring_notregexp(thr, 0); DUK_ASSERT(h_search != NULL); magic = duk_get_current_magic(thr); - p_cmp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h); + /* Careful to avoid pointer overflows in the matching logic. */ + + blen_target = DUK_HSTRING_GET_BYTELEN(h_target); blen_search = DUK_HSTRING_GET_BYTELEN(h_search); +#if 0 + /* If search string is longer than the target string, we can + * never match. Could check explicitly, but should be handled + * correctly below. + */ + if (blen_search > blen_target) { + goto finish; + } +#endif + + off = 0; if (duk_is_undefined(thr, 1)) { if (magic) { - p_cmp_start = p_cmp_start + DUK_HSTRING_GET_BYTELEN(h) - blen_search; + off = (duk_int_t) blen_target - (duk_int_t) blen_search; } else { - /* p_cmp_start already OK */ + DUK_ASSERT(off == 0); } } else { duk_int_t len; duk_int_t pos; DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= DUK_INT_MAX); - len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h); + len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_target); pos = duk_to_int_clamped(thr, 1, 0, len); DUK_ASSERT(pos >= 0 && pos <= len); + off = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_target, (duk_uint_fast32_t) pos); if (magic) { - p_cmp_start -= blen_search; /* Conceptually subtracted last, but do already here. */ + off -= (duk_int_t) blen_search; } - DUK_ASSERT(pos >= 0 && pos <= len); - - p_cmp_start += duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) pos); + } + if (off < 0 || off > (duk_int_t) blen_target) { + goto finish; } /* The main comparison can be done using a memcmp() rather than @@ -43337,16 +43461,18 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_hthread * * comparison range. */ - result = 0; - if (p_cmp_start >= DUK_HSTRING_GET_DATA(h) && - (duk_size_t) (p_cmp_start - (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h)) + blen_search <= DUK_HSTRING_GET_BYTELEN(h)) { - if (duk_memcmp((const void *) p_cmp_start, - (const void *) DUK_HSTRING_GET_DATA(h_search), - (size_t) blen_search) == 0) { + DUK_ASSERT(off >= 0); + DUK_ASSERT((duk_size_t) off <= blen_target); + blen_left = blen_target - (duk_size_t) off; + if (blen_left >= blen_search) { + const duk_uint8_t *p_cmp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_target) + off; + const duk_uint8_t *p_search = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_search); + if (duk_memcmp_unsafe((const void *) p_cmp_start, (const void *) p_search, (size_t) blen_search) == 0) { result = 1; } } + finish: duk_push_boolean(thr, result); return 1; } @@ -52244,6 +52370,7 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags #if defined(DUK_USE_VOLUNTARY_GC) duk_size_t tmp; #endif + duk_bool_t entry_creating_error; DUK_STATS_INC(heap, stats_ms_try_count); #if defined(DUK_USE_DEBUG) @@ -52314,6 +52441,8 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags DUK_ASSERT(heap->ms_running == 0); heap->ms_prevent_count = 1; heap->ms_running = 1; + entry_creating_error = heap->creating_error; + heap->creating_error = 0; /* * Free activation/catcher freelists on every mark-and-sweep for now. @@ -52444,6 +52573,7 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags DUK_ASSERT(heap->ms_running == 1); heap->ms_prevent_count = 0; heap->ms_running = 0; + heap->creating_error = entry_creating_error; /* for nested error handling, see GH-2278 */ /* * Assertions after @@ -55979,6 +56109,13 @@ DUK_LOCAL void duk__sort_enum_keys_es6(duk_hthread *thr, duk_hobject *h_obj, duk keys[idx_insert] = h_curr; } } + + /* Entry part has been reordered now with no side effects. + * If the object has a hash part, it will now be incorrect + * and we need to rehash. Do that by forcing a resize to + * the current size. + */ + duk_hobject_resize_entrypart(thr, h_obj, DUK_HOBJECT_GET_ESIZE(h_obj)); } /* @@ -56844,7 +56981,7 @@ DUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_i * duk_tval copies is not problematic with respect to side effects; * care must be taken when holding and using argument duk_tval pointers. * - * - If a finalizer is executed, it may operate on the same object + * - If a finalizer is executed, it may operate on the the same object * we're currently dealing with. For instance, the finalizer might * delete a certain property which has already been looked up and * confirmed to exist. Ideally finalizers would be disabled if GC @@ -74164,10 +74301,13 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_ */ test_func_decl = allow_source_elem; #if defined(DUK_USE_NONSTD_FUNC_STMT) - /* Lenient: allow function declarations outside top level in - * non-strict mode but reject them in strict mode. + /* Lenient: allow function declarations outside top level in both + * strict and non-strict modes. However, don't allow labelled + * function declarations in strict mode. */ - test_func_decl = test_func_decl || !comp_ctx->curr_func.is_strict; + test_func_decl = test_func_decl || + !comp_ctx->curr_func.is_strict || + label_id < 0; #endif /* DUK_USE_NONSTD_FUNC_STMT */ /* Strict: never allow function declarations outside top level. */ if (test_func_decl) { @@ -77196,17 +77336,21 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation DUK_DD(DUK_DDPRINT("-> yield an error, converted to a throw in the resumer, propagate")); goto check_longjmp; } else { - duk_hthread_activation_unwind_norz(resumer); - duk__handle_yield(thr, resumer, &thr->heap->lj.value1); + /* When handling the yield, the last reference to + * 'thr' may disappear. + */ + DUK_GC_TORTURE(resumer->heap); + duk_hthread_activation_unwind_norz(resumer); + DUK_GC_TORTURE(resumer->heap); thr->state = DUK_HTHREAD_STATE_YIELDED; thr->resumer = NULL; DUK_HTHREAD_DECREF_NORZ(thr, resumer); resumer->state = DUK_HTHREAD_STATE_RUNNING; DUK_HEAP_SWITCH_THREAD(thr->heap, resumer); -#if 0 - thr = resumer; /* not needed, as we exit right away */ -#endif + duk__handle_yield(thr, resumer, &thr->heap->lj.value1); + thr = resumer; + DUK_GC_TORTURE(resumer->heap); DUK_DD(DUK_DDPRINT("-> yield a value, restart execution in resumer")); retval = DUK__LONGJMP_RESTART; @@ -83909,6 +84053,7 @@ void duk__putvar_helper(duk_hthread *thr, duk_tval *val, duk_bool_t strict) { duk__id_lookup_result ref; + duk_tval tv_tmp_val; duk_tval tv_tmp_obj; duk_tval tv_tmp_key; duk_bool_t parents; @@ -83926,10 +84071,13 @@ void duk__putvar_helper(duk_hthread *thr, DUK_ASSERT(val != NULL); /* env and act may be NULL */ - DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env); - DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name); + DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env); + DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name); DUK_ASSERT_REFCOUNT_NONZERO_TVAL(val); + DUK_TVAL_SET_TVAL(&tv_tmp_val, val); /* Stabilize. */ + val = NULL; + /* * In strict mode E5 protects 'eval' and 'arguments' from being * assigned to (or even declared anywhere). Attempt to do so @@ -83961,7 +84109,7 @@ void duk__putvar_helper(duk_hthread *thr, tv_val = ref.value; DUK_ASSERT(tv_val != NULL); - DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, val); /* side effects */ + DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, &tv_tmp_val); /* side effects */ /* ref.value invalidated here */ } else { @@ -83969,7 +84117,7 @@ void duk__putvar_helper(duk_hthread *thr, DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder); DUK_TVAL_SET_STRING(&tv_tmp_key, name); - (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, strict); + (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, &tv_tmp_val, strict); /* ref.value invalidated here */ } @@ -83994,7 +84142,7 @@ void duk__putvar_helper(duk_hthread *thr, DUK_TVAL_SET_OBJECT(&tv_tmp_obj, thr->builtins[DUK_BIDX_GLOBAL]); DUK_TVAL_SET_STRING(&tv_tmp_key, name); - (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, 0); /* 0 = no throw */ + (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, &tv_tmp_val, 0); /* 0 = no throw */ /* NB: 'val' may be invalidated here because put_value may realloc valstack, * caller beware. @@ -91415,10 +91563,12 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_ * as 'undefined'. The same is done when saved[] pointers are insane * (this should, of course, never happen in practice). */ + duk_push_uarridx(thr, (duk_uarridx_t) (i / 2)); + if (re_ctx.saved[i] && re_ctx.saved[i + 1] && re_ctx.saved[i + 1] >= re_ctx.saved[i]) { duk_push_lstring(thr, (const char *) re_ctx.saved[i], - (duk_size_t) (re_ctx.saved[i+1] - re_ctx.saved[i])); + (duk_size_t) (re_ctx.saved[i + 1] - re_ctx.saved[i])); if (i == 0) { /* Assumes that saved[0] and saved[1] are always * set by regexp bytecode (if not, char_end_offset @@ -91431,8 +91581,8 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_ duk_push_undefined(thr); } - /* [ ... re_obj input bc saved_buf res_obj val ] */ - duk_put_prop_index(thr, -2, (duk_uarridx_t) (i / 2)); + /* [ ... re_obj input bc saved_buf res_obj idx val ] */ + duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_WEC); } /* [ ... re_obj input bc saved_buf res_obj ] */ diff --git a/src/modules/app_jsdt/duktape.h b/src/modules/app_jsdt/duktape.h index 7850c996f23..e5b46c23425 100644 --- a/src/modules/app_jsdt/duktape.h +++ b/src/modules/app_jsdt/duktape.h @@ -1,13 +1,13 @@ /* - * Duktape public API for Duktape 2.5.0. + * Duktape public API for Duktape 2.6.0. * * See the API reference for documentation on call semantics. The exposed, * supported API is between the "BEGIN PUBLIC API" and "END PUBLIC API" * comments. Other parts of the header are Duktape internal and related to * e.g. platform/compiler/feature detection. * - * Git commit 6001888049cb42656f8649db020e804bcdeca6a7 (v2.5.0). - * Git branch master. + * Git commit fffa346eff06a8764b02c31d4336f63a773a95c3 (v2.6.0). + * Git branch v2-maintenance. * * See Duktape AUTHORS.rst and LICENSE.txt for copyright and * licensing information. @@ -176,16 +176,16 @@ * development snapshots have 99 for patch level (e.g. 0.10.99 would be a * development version after 0.10.0 but before the next official release). */ -#define DUK_VERSION 20500L +#define DUK_VERSION 20600L /* Git commit, describe, and branch for Duktape build. Useful for * non-official snapshot builds so that application code can easily log * which Duktape snapshot was used. Not available in the ECMAScript * environment. */ -#define DUK_GIT_COMMIT "6001888049cb42656f8649db020e804bcdeca6a7" -#define DUK_GIT_DESCRIBE "v2.5.0" -#define DUK_GIT_BRANCH "master" +#define DUK_GIT_COMMIT "fffa346eff06a8764b02c31d4336f63a773a95c3" +#define DUK_GIT_DESCRIBE "v2.6.0" +#define DUK_GIT_BRANCH "v2-maintenance" /* External duk_config.h provides platform/compiler/OS dependent * typedefs and macros, and DUK_USE_xxx config options so that