Integrarted duktape in source.
h3rald h3rald@h3rald.com
Sun, 19 Jan 2020 18:35:05 +0100
7 files changed,
100929 insertions(+),
1 deletions(-)
M
.gitignore
→
.gitignore
@@ -14,3 +14,4 @@ *.exe
nakefile LiteStore_UserGuide.htm jester_integration +js
A
src/litestorepkg/duk_config.nim
@@ -0,0 +1,54 @@
+import strutils +const sourcePath = currentSourcePath().split({'\\', '/'})[0..^2].join("/") +{.passC: "-I\"" & sourcePath & "/src\"".} +const headerduk_config = sourcePath & "/src/duk_config.h" +type + duk_uint8_t* = uint8_t + duk_int8_t* = int8_t + duk_uint16_t* = uint16_t + duk_int16_t* = int16_t + duk_uint32_t* = uint32_t + duk_int32_t* = int32_t + duk_uint64_t* = uint64_t + duk_int64_t* = int64_t + duk_uint_least8_t* = uint_least8_t + duk_int_least8_t* = int_least8_t + duk_uint_least16_t* = uint_least16_t + duk_int_least16_t* = int_least16_t + duk_uint_least32_t* = uint_least32_t + duk_int_least32_t* = int_least32_t + duk_uint_least64_t* = uint_least64_t + duk_int_least64_t* = int_least64_t + duk_uint_fast8_t* = uint_fast8_t + duk_int_fast8_t* = int_fast8_t + duk_uint_fast16_t* = uint_fast16_t + duk_int_fast16_t* = int_fast16_t + duk_uint_fast32_t* = uint_fast32_t + duk_int_fast32_t* = int_fast32_t + duk_uint_fast64_t* = uint_fast64_t + duk_int_fast64_t* = int_fast64_t + duk_uintptr_t* = uintptr_t + duk_intptr_t* = intptr_t + duk_uintmax_t* = uintmax_t + duk_intmax_t* = intmax_t + duk_size_t* = csize + duk_ptrdiff_t* = ptrdiff_t + duk_int_t* = cint + duk_uint_t* = cuint + duk_int_fast_t* = duk_int_fast32_t + duk_uint_fast_t* = duk_uint_fast32_t + duk_small_int_t* = cint + duk_small_uint_t* = cuint + duk_small_int_fast_t* = duk_int_fast16_t + duk_small_uint_fast_t* = duk_uint_fast16_t + duk_bool_t* = duk_small_uint_t + duk_idx_t* = duk_int_t + duk_uidx_t* = duk_uint_t + duk_uarridx_t* = duk_uint_t + duk_ret_t* = duk_small_int_t + duk_errcode_t* = duk_int_t + duk_codepoint_t* = duk_int_t + duk_ucodepoint_t* = duk_uint_t + duk_float_t* = cfloat + duk_double_t* = cdouble + duk_context* = duk_hthread
M
src/litestorepkg/lib/api_v6.nim
→
src/litestorepkg/lib/api_v6.nim
@@ -8,7 +8,7 @@ pegs,
json, os, times, - duktape/js + duktape import types, contenttypes,@@ -933,7 +933,9 @@ except:
return resError(Http500, "An error occurred when executing custom resource code.") # Retrieve response ctx.duk_eval_string("JSON.stringify(ctx.response)") + echo "TEST!" let jResponse = parseJson($(ctx.duk_get_string(-1))) + echo jResponse ctx.duk_destroy_heap(); result.code = HttpCode(jResponse["code"].getInt) result.content = jResponse["content"].getStr
A
src/litestorepkg/lib/duktape.nim
@@ -0,0 +1,708 @@
+type + DTContext* = pointer +type + duk_int_t* = cint + duk_uint_t* = cuint + duk_uint8_t* = uint8 + duk_int8_t* = int8 + duk_uint16_t* = uint16 + duk_int16_t* = int16 + duk_uint32_t* = uint32 + duk_int32_t* = int32 + duk_uint64_t* = uint64 + duk_int64_t* = int64 + duk_small_int_t* = cint + duk_small_uint_t* = cuint + duk_bool_t* = cint + duk_idx_t* = duk_int_t + duk_uidx_t* = duk_uint_t + duk_uarridx_t* = duk_uint_t + duk_errcode_t* = duk_int_t + duk_codepoint_t* = duk_int_t + duk_ucodepoint_t* = duk_uint_t + duk_float_t* = cfloat + duk_double_t* = cdouble + duk_size_t* = cint + duk_ret_t* = cint + +import strutils +const sourcePath = currentSourcePath().split({'\\', '/'})[0..^2].join("/") +{.passC: "-I\"" & sourcePath & "/../vendor/duktape\"".} +const headerduktape = sourcePath & "/../vendor/duktape/duktape.h" +{.compile: "../vendor/duktape/duktape.c".} +const + DUK_VERSION* = 20201 + DUK_DEBUG_PROTOCOL_VERSION* = 2 + DUK_API_ENTRY_STACK* = 64 + DUK_TYPE_MIN* = 0 + DUK_TYPE_NONE* = 0 + DUK_TYPE_UNDEFINED* = 1 + DUK_TYPE_NULL* = 2 + DUK_TYPE_BOOLEAN* = 3 + DUK_TYPE_NUMBER* = 4 + DUK_TYPE_STRING* = 5 + DUK_TYPE_OBJECT* = 6 + DUK_TYPE_BUFFER* = 7 + DUK_TYPE_POINTER* = 8 + DUK_TYPE_LIGHTFUNC* = 9 + DUK_TYPE_MAX* = 9 + DUK_HINT_NONE* = 0 + DUK_HINT_STRING* = 1 + DUK_HINT_NUMBER* = 2 + DUK_ERR_NONE* = 0 + DUK_ERR_ERROR* = 1 + DUK_ERR_EVAL_ERROR* = 2 + DUK_ERR_RANGE_ERROR* = 3 + DUK_ERR_REFERENCE_ERROR* = 4 + DUK_ERR_SYNTAX_ERROR* = 5 + DUK_ERR_TYPE_ERROR* = 6 + DUK_ERR_URI_ERROR* = 7 + DUK_EXEC_SUCCESS* = 0 + DUK_EXEC_ERROR* = 1 + DUK_LEVEL_DEBUG* = 0 + DUK_LEVEL_DDEBUG* = 1 + DUK_LEVEL_DDDEBUG* = 2 + DUK_BUFOBJ_ARRAYBUFFER* = 0 + DUK_BUFOBJ_NODEJS_BUFFER* = 1 + DUK_BUFOBJ_DATAVIEW* = 2 + DUK_BUFOBJ_INT8ARRAY* = 3 + DUK_BUFOBJ_UINT8ARRAY* = 4 + DUK_BUFOBJ_UINT8CLAMPEDARRAY* = 5 + DUK_BUFOBJ_INT16ARRAY* = 6 + DUK_BUFOBJ_UINT16ARRAY* = 7 + DUK_BUFOBJ_INT32ARRAY* = 8 + DUK_BUFOBJ_UINT32ARRAY* = 9 + DUK_BUFOBJ_FLOAT32ARRAY* = 10 + DUK_BUFOBJ_FLOAT64ARRAY* = 11 + DUK_BUF_MODE_FIXED* = 0 + DUK_BUF_MODE_DYNAMIC* = 1 + DUK_BUF_MODE_DONTCARE* = 2 + DUK_DATE_MSEC_SECOND* = 1000 + DUK_DATE_MAX_ECMA_YEAR* = 275760 + DUK_DATE_IDX_YEAR* = 0 + DUK_DATE_IDX_MONTH* = 1 + DUK_DATE_IDX_DAY* = 2 + DUK_DATE_IDX_HOUR* = 3 + DUK_DATE_IDX_MINUTE* = 4 + DUK_DATE_IDX_SECOND* = 5 + DUK_DATE_IDX_MILLISECOND* = 6 + DUK_DATE_IDX_WEEKDAY* = 7 + DUK_DATE_IDX_NUM_PARTS* = 8 + DUK_DATE_FLAG_VALUE_SHIFT* = 12 + +type + duk_thread_state* {.importc: "duk_thread_state", header: headerduktape, bycopy.} = object + + duk_memory_functions* {.importc: "duk_memory_functions", header: headerduktape, + bycopy.} = object + + duk_function_list_entry* {.importc: "duk_function_list_entry", + header: headerduktape, bycopy.} = object + + duk_number_list_entry* {.importc: "duk_number_list_entry", header: headerduktape, + bycopy.} = object + + duk_time_components* {.importc: "duk_time_components", header: headerduktape, + bycopy.} = object + + duk_c_function* = proc (ctx: DTContext): duk_ret_t {.stdcall.} + duk_alloc_function* = proc (udata: pointer; size: duk_size_t): pointer {.stdcall.} + duk_realloc_function* = proc (udata: pointer; `ptr`: pointer; size: duk_size_t): pointer {. + stdcall.} + duk_free_function* = proc (udata: pointer; `ptr`: pointer) {.stdcall.} + duk_fatal_function* = proc (udata: pointer; msg: cstring) {.stdcall.} + duk_decode_char_function* = proc (udata: pointer; codepoint: duk_codepoint_t) {. + stdcall.} + duk_map_char_function* = proc (udata: pointer; codepoint: duk_codepoint_t): duk_codepoint_t {. + stdcall.} + duk_safe_call_function* = proc (ctx: DTContext; udata: pointer): duk_ret_t {. + stdcall.} + duk_debug_read_function* = proc (udata: pointer; buffer: cstring; length: duk_size_t): duk_size_t {. + stdcall.} + duk_debug_write_function* = proc (udata: pointer; buffer: cstring; length: duk_size_t): duk_size_t {. + stdcall.} + duk_debug_peek_function* = proc (udata: pointer): duk_size_t {.stdcall.} + duk_debug_read_flush_function* = proc (udata: pointer) {.stdcall.} + duk_debug_write_flush_function* = proc (udata: pointer) {.stdcall.} + duk_debug_request_function* = proc (ctx: DTContext; udata: pointer; + nvalues: duk_idx_t): duk_idx_t {.stdcall.} + duk_debug_detached_function* = proc (ctx: DTContext; udata: pointer) {.stdcall.} + +proc duk_create_heap*(alloc_func: duk_alloc_function; + realloc_func: duk_realloc_function; + free_func: duk_free_function; heap_udata: pointer; + fatal_handler: duk_fatal_function): DTContext {.stdcall, + importc: "duk_create_heap", header: headerduktape.} +proc duk_destroy_heap*(ctx: DTContext) {.stdcall, importc: "duk_destroy_heap", + header: headerduktape.} +proc duk_suspend*(ctx: DTContext; state: ptr duk_thread_state) {.stdcall, + importc: "duk_suspend", header: headerduktape.} +proc duk_resume*(ctx: DTContext; state: ptr duk_thread_state) {.stdcall, + importc: "duk_resume", header: headerduktape.} +proc duk_alloc_raw*(ctx: DTContext; size: duk_size_t): pointer {.stdcall, + importc: "duk_alloc_raw", header: headerduktape.} +proc duk_free_raw*(ctx: DTContext; `ptr`: pointer) {.stdcall, + importc: "duk_free_raw", header: headerduktape.} +proc duk_realloc_raw*(ctx: DTContext; `ptr`: pointer; size: duk_size_t): pointer {. + stdcall, importc: "duk_realloc_raw", header: headerduktape.} +proc duk_alloc*(ctx: DTContext; size: duk_size_t): pointer {.stdcall, + importc: "duk_alloc", header: headerduktape.} +proc duk_free*(ctx: DTContext; `ptr`: pointer) {.stdcall, importc: "duk_free", + header: headerduktape.} +proc duk_realloc*(ctx: DTContext; `ptr`: pointer; size: duk_size_t): pointer {. + stdcall, importc: "duk_realloc", header: headerduktape.} +proc duk_get_memory_functions*(ctx: DTContext; + out_funcs: ptr duk_memory_functions) {.stdcall, + importc: "duk_get_memory_functions", header: headerduktape.} +proc duk_gc*(ctx: DTContext; flags: duk_uint_t) {.stdcall, importc: "duk_gc", + header: headerduktape.} +proc duk_throw_raw*(ctx: DTContext) {.stdcall, importc: "duk_throw_raw", + header: headerduktape.} +proc duk_fatal_raw*(ctx: DTContext; err_msg: cstring) {.stdcall, + importc: "duk_fatal_raw", header: headerduktape.} +proc duk_error_raw*(ctx: DTContext; err_code: duk_errcode_t; filename: cstring; + line: duk_int_t; fmt: cstring) {.varargs, stdcall, + importc: "duk_error_raw", header: headerduktape.} +proc duk_is_strict_call*(ctx: DTContext): duk_bool_t {.stdcall, + importc: "duk_is_strict_call", header: headerduktape.} +proc duk_is_constructor_call*(ctx: DTContext): duk_bool_t {.stdcall, + importc: "duk_is_constructor_call", header: headerduktape.} +proc duk_normalize_index*(ctx: DTContext; idx: duk_idx_t): duk_idx_t {.stdcall, + importc: "duk_normalize_index", header: headerduktape.} +proc duk_require_normalize_index*(ctx: DTContext; idx: duk_idx_t): duk_idx_t {. + stdcall, importc: "duk_require_normalize_index", header: headerduktape.} +proc duk_is_valid_index*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_valid_index", header: headerduktape.} +proc duk_require_valid_index*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_require_valid_index", header: headerduktape.} +proc duk_get_top*(ctx: DTContext): duk_idx_t {.stdcall, importc: "duk_get_top", + header: headerduktape.} +proc duk_set_top*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_set_top", header: headerduktape.} +proc duk_get_top_index*(ctx: DTContext): duk_idx_t {.stdcall, + importc: "duk_get_top_index", header: headerduktape.} +proc duk_require_top_index*(ctx: DTContext): duk_idx_t {.stdcall, + importc: "duk_require_top_index", header: headerduktape.} +proc duk_check_stack*(ctx: DTContext; extra: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_check_stack", header: headerduktape.} +proc duk_require_stack*(ctx: DTContext; extra: duk_idx_t) {.stdcall, + importc: "duk_require_stack", header: headerduktape.} +proc duk_check_stack_top*(ctx: DTContext; top: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_check_stack_top", header: headerduktape.} +proc duk_require_stack_top*(ctx: DTContext; top: duk_idx_t) {.stdcall, + importc: "duk_require_stack_top", header: headerduktape.} +proc duk_swap*(ctx: DTContext; idx1: duk_idx_t; idx2: duk_idx_t) {.stdcall, + importc: "duk_swap", header: headerduktape.} +proc duk_swap_top*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_swap_top", header: headerduktape.} +proc duk_dup*(ctx: DTContext; from_idx: duk_idx_t) {.stdcall, importc: "duk_dup", + header: headerduktape.} +proc duk_dup_top*(ctx: DTContext) {.stdcall, importc: "duk_dup_top", + header: headerduktape.} +proc duk_insert*(ctx: DTContext; to_idx: duk_idx_t) {.stdcall, + importc: "duk_insert", header: headerduktape.} +proc duk_replace*(ctx: DTContext; to_idx: duk_idx_t) {.stdcall, + importc: "duk_replace", header: headerduktape.} +proc duk_copy*(ctx: DTContext; from_idx: duk_idx_t; to_idx: duk_idx_t) {.stdcall, + importc: "duk_copy", header: headerduktape.} +proc duk_remove*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_remove", header: headerduktape.} +proc duk_xcopymove_raw*(to_ctx: DTContext; from_ctx: DTContext; + count: duk_idx_t; is_copy: duk_bool_t) {.stdcall, + importc: "duk_xcopymove_raw", header: headerduktape.} +proc duk_push_undefined*(ctx: DTContext) {.stdcall, + importc: "duk_push_undefined", header: headerduktape.} +proc duk_push_null*(ctx: DTContext) {.stdcall, importc: "duk_push_null", + header: headerduktape.} +proc duk_push_boolean*(ctx: DTContext; val: duk_bool_t) {.stdcall, + importc: "duk_push_boolean", header: headerduktape.} +proc duk_push_true*(ctx: DTContext) {.stdcall, importc: "duk_push_true", + header: headerduktape.} +proc duk_push_false*(ctx: DTContext) {.stdcall, importc: "duk_push_false", + header: headerduktape.} +proc duk_push_number*(ctx: DTContext; val: duk_double_t) {.stdcall, + importc: "duk_push_number", header: headerduktape.} +proc duk_push_nan*(ctx: DTContext) {.stdcall, importc: "duk_push_nan", + header: headerduktape.} +proc duk_push_int*(ctx: DTContext; val: duk_int_t) {.stdcall, + importc: "duk_push_int", header: headerduktape.} +proc duk_push_uint*(ctx: DTContext; val: duk_uint_t) {.stdcall, + importc: "duk_push_uint", header: headerduktape.} +proc duk_push_string*(ctx: DTContext; str: cstring): cstring {.stdcall, + importc: "duk_push_string", header: headerduktape.} +proc duk_push_lstring*(ctx: DTContext; str: cstring; len: duk_size_t): cstring {. + stdcall, importc: "duk_push_lstring", header: headerduktape.} +proc duk_push_pointer*(ctx: DTContext; p: pointer) {.stdcall, + importc: "duk_push_pointer", header: headerduktape.} +proc duk_push_sprintf*(ctx: DTContext; fmt: cstring): cstring {.varargs, stdcall, + importc: "duk_push_sprintf", header: headerduktape.} +proc duk_push_this*(ctx: DTContext) {.stdcall, importc: "duk_push_this", + header: headerduktape.} +proc duk_push_current_function*(ctx: DTContext) {.stdcall, + importc: "duk_push_current_function", header: headerduktape.} +proc duk_push_current_thread*(ctx: DTContext) {.stdcall, + importc: "duk_push_current_thread", header: headerduktape.} +proc duk_push_global_object*(ctx: DTContext) {.stdcall, + importc: "duk_push_global_object", header: headerduktape.} +proc duk_push_heap_stash*(ctx: DTContext) {.stdcall, + importc: "duk_push_heap_stash", header: headerduktape.} +proc duk_push_global_stash*(ctx: DTContext) {.stdcall, + importc: "duk_push_global_stash", header: headerduktape.} +proc duk_push_thread_stash*(ctx: DTContext; target_ctx: DTContext) {. + stdcall, importc: "duk_push_thread_stash", header: headerduktape.} +proc duk_push_object*(ctx: DTContext): duk_idx_t {.stdcall, + importc: "duk_push_object", header: headerduktape.} +proc duk_push_bare_object*(ctx: DTContext): duk_idx_t {.stdcall, + importc: "duk_push_bare_object", header: headerduktape.} +proc duk_push_array*(ctx: DTContext): duk_idx_t {.stdcall, + importc: "duk_push_array", header: headerduktape.} +proc duk_push_c_function*(ctx: DTContext; `func`: duk_c_function; + nargs: duk_idx_t): duk_idx_t {.stdcall, + importc: "duk_push_c_function", header: headerduktape.} +proc duk_push_c_lightfunc*(ctx: DTContext; `func`: duk_c_function; + nargs: duk_idx_t; length: duk_idx_t; magic: duk_int_t): duk_idx_t {. + stdcall, importc: "duk_push_c_lightfunc", header: headerduktape.} +proc duk_push_thread_raw*(ctx: DTContext; flags: duk_uint_t): duk_idx_t {. + stdcall, importc: "duk_push_thread_raw", header: headerduktape.} +proc duk_push_proxy*(ctx: DTContext; proxy_flags: duk_uint_t): duk_idx_t {. + stdcall, importc: "duk_push_proxy", header: headerduktape.} +proc duk_push_error_object_raw*(ctx: DTContext; err_code: duk_errcode_t; + filename: cstring; line: duk_int_t; fmt: cstring): duk_idx_t {. + varargs, stdcall, importc: "duk_push_error_object_raw", header: headerduktape.} +proc duk_push_buffer_raw*(ctx: DTContext; size: duk_size_t; + flags: duk_small_uint_t): pointer {.stdcall, + importc: "duk_push_buffer_raw", header: headerduktape.} +proc duk_push_buffer_object*(ctx: DTContext; idx_buffer: duk_idx_t; + byte_offset: duk_size_t; byte_length: duk_size_t; + flags: duk_uint_t) {.stdcall, + importc: "duk_push_buffer_object", header: headerduktape.} +proc duk_push_heapptr*(ctx: DTContext; `ptr`: pointer): duk_idx_t {.stdcall, + importc: "duk_push_heapptr", header: headerduktape.} +proc duk_pop*(ctx: DTContext) {.stdcall, importc: "duk_pop", + header: headerduktape.} +proc duk_pop_n*(ctx: DTContext; count: duk_idx_t) {.stdcall, + importc: "duk_pop_n", header: headerduktape.} +proc duk_pop_2*(ctx: DTContext) {.stdcall, importc: "duk_pop_2", + header: headerduktape.} +proc duk_pop_3*(ctx: DTContext) {.stdcall, importc: "duk_pop_3", + header: headerduktape.} +proc duk_get_type*(ctx: DTContext; idx: duk_idx_t): duk_int_t {.stdcall, + importc: "duk_get_type", header: headerduktape.} +proc duk_check_type*(ctx: DTContext; idx: duk_idx_t; `type`: duk_int_t): duk_bool_t {. + stdcall, importc: "duk_check_type", header: headerduktape.} +proc duk_get_type_mask*(ctx: DTContext; idx: duk_idx_t): duk_uint_t {.stdcall, + importc: "duk_get_type_mask", header: headerduktape.} +proc duk_check_type_mask*(ctx: DTContext; idx: duk_idx_t; mask: duk_uint_t): duk_bool_t {. + stdcall, importc: "duk_check_type_mask", header: headerduktape.} +proc duk_is_undefined*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_undefined", header: headerduktape.} +proc duk_is_null*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_null", header: headerduktape.} +proc duk_is_boolean*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_boolean", header: headerduktape.} +proc duk_is_number*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_number", header: headerduktape.} +proc duk_is_nan*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_nan", header: headerduktape.} +proc duk_is_string*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_string", header: headerduktape.} +proc duk_is_object*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_object", header: headerduktape.} +proc duk_is_buffer*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_buffer", header: headerduktape.} +proc duk_is_buffer_data*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_buffer_data", header: headerduktape.} +proc duk_is_pointer*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_pointer", header: headerduktape.} +proc duk_is_lightfunc*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_lightfunc", header: headerduktape.} +proc duk_is_symbol*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_symbol", header: headerduktape.} +proc duk_is_array*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_array", header: headerduktape.} +proc duk_is_function*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_function", header: headerduktape.} +proc duk_is_c_function*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_c_function", header: headerduktape.} +proc duk_is_ecmascript_function*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {. + stdcall, importc: "duk_is_ecmascript_function", header: headerduktape.} +proc duk_is_bound_function*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {. + stdcall, importc: "duk_is_bound_function", header: headerduktape.} +proc duk_is_thread*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_thread", header: headerduktape.} +proc duk_is_constructable*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_constructable", header: headerduktape.} +proc duk_is_dynamic_buffer*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {. + stdcall, importc: "duk_is_dynamic_buffer", header: headerduktape.} +proc duk_is_fixed_buffer*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_is_fixed_buffer", header: headerduktape.} +proc duk_is_external_buffer*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {. + stdcall, importc: "duk_is_external_buffer", header: headerduktape.} +proc duk_get_error_code*(ctx: DTContext; idx: duk_idx_t): duk_errcode_t {. + stdcall, importc: "duk_get_error_code", header: headerduktape.} +proc duk_get_boolean*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_get_boolean", header: headerduktape.} +proc duk_get_number*(ctx: DTContext; idx: duk_idx_t): duk_double_t {.stdcall, + importc: "duk_get_number", header: headerduktape.} +proc duk_get_int*(ctx: DTContext; idx: duk_idx_t): duk_int_t {.stdcall, + importc: "duk_get_int", header: headerduktape.} +proc duk_get_uint*(ctx: DTContext; idx: duk_idx_t): duk_uint_t {.stdcall, + importc: "duk_get_uint", header: headerduktape.} +proc duk_get_string*(ctx: DTContext; idx: duk_idx_t): cstring {.stdcall, + importc: "duk_get_string", header: headerduktape.} +proc duk_get_lstring*(ctx: DTContext; idx: duk_idx_t; out_len: ptr duk_size_t): cstring {. + stdcall, importc: "duk_get_lstring", header: headerduktape.} +proc duk_get_buffer*(ctx: DTContext; idx: duk_idx_t; out_size: ptr duk_size_t): pointer {. + stdcall, importc: "duk_get_buffer", header: headerduktape.} +proc duk_get_buffer_data*(ctx: DTContext; idx: duk_idx_t; + out_size: ptr duk_size_t): pointer {.stdcall, + importc: "duk_get_buffer_data", header: headerduktape.} +proc duk_get_pointer*(ctx: DTContext; idx: duk_idx_t): pointer {.stdcall, + importc: "duk_get_pointer", header: headerduktape.} +proc duk_get_c_function*(ctx: DTContext; idx: duk_idx_t): duk_c_function {. + stdcall, importc: "duk_get_c_function", header: headerduktape.} +proc duk_get_context*(ctx: DTContext; idx: duk_idx_t): DTContext {.stdcall, + importc: "duk_get_context", header: headerduktape.} +proc duk_get_heapptr*(ctx: DTContext; idx: duk_idx_t): pointer {.stdcall, + importc: "duk_get_heapptr", header: headerduktape.} +proc duk_get_boolean_default*(ctx: DTContext; idx: duk_idx_t; + def_value: duk_bool_t): duk_bool_t {.stdcall, + importc: "duk_get_boolean_default", header: headerduktape.} +proc duk_get_number_default*(ctx: DTContext; idx: duk_idx_t; + def_value: duk_double_t): duk_double_t {.stdcall, + importc: "duk_get_number_default", header: headerduktape.} +proc duk_get_int_default*(ctx: DTContext; idx: duk_idx_t; def_value: duk_int_t): duk_int_t {. + stdcall, importc: "duk_get_int_default", header: headerduktape.} +proc duk_get_uint_default*(ctx: DTContext; idx: duk_idx_t; def_value: duk_uint_t): duk_uint_t {. + stdcall, importc: "duk_get_uint_default", header: headerduktape.} +proc duk_get_string_default*(ctx: DTContext; idx: duk_idx_t; def_value: cstring): cstring {. + stdcall, importc: "duk_get_string_default", header: headerduktape.} +proc duk_get_lstring_default*(ctx: DTContext; idx: duk_idx_t; + out_len: ptr duk_size_t; def_ptr: cstring; + def_len: duk_size_t): cstring {.stdcall, + importc: "duk_get_lstring_default", header: headerduktape.} +proc duk_get_buffer_default*(ctx: DTContext; idx: duk_idx_t; + out_size: ptr duk_size_t; def_ptr: pointer; + def_len: duk_size_t): pointer {.stdcall, + importc: "duk_get_buffer_default", header: headerduktape.} +proc duk_get_buffer_data_default*(ctx: DTContext; idx: duk_idx_t; + out_size: ptr duk_size_t; def_ptr: pointer; + def_len: duk_size_t): pointer {.stdcall, + importc: "duk_get_buffer_data_default", header: headerduktape.} +proc duk_get_pointer_default*(ctx: DTContext; idx: duk_idx_t; def_value: pointer): pointer {. + stdcall, importc: "duk_get_pointer_default", header: headerduktape.} +proc duk_get_c_function_default*(ctx: DTContext; idx: duk_idx_t; + def_value: duk_c_function): duk_c_function {. + stdcall, importc: "duk_get_c_function_default", header: headerduktape.} +proc duk_get_context_default*(ctx: DTContext; idx: duk_idx_t; + def_value: DTContext): DTContext {.stdcall, + importc: "duk_get_context_default", header: headerduktape.} +proc duk_get_heapptr_default*(ctx: DTContext; idx: duk_idx_t; def_value: pointer): pointer {. + stdcall, importc: "duk_get_heapptr_default", header: headerduktape.} +proc duk_opt_boolean*(ctx: DTContext; idx: duk_idx_t; def_value: duk_bool_t): duk_bool_t {. + stdcall, importc: "duk_opt_boolean", header: headerduktape.} +proc duk_opt_number*(ctx: DTContext; idx: duk_idx_t; def_value: duk_double_t): duk_double_t {. + stdcall, importc: "duk_opt_number", header: headerduktape.} +proc duk_opt_int*(ctx: DTContext; idx: duk_idx_t; def_value: duk_int_t): duk_int_t {. + stdcall, importc: "duk_opt_int", header: headerduktape.} +proc duk_opt_uint*(ctx: DTContext; idx: duk_idx_t; def_value: duk_uint_t): duk_uint_t {. + stdcall, importc: "duk_opt_uint", header: headerduktape.} +proc duk_opt_string*(ctx: DTContext; idx: duk_idx_t; def_ptr: cstring): cstring {. + stdcall, importc: "duk_opt_string", header: headerduktape.} +proc duk_opt_lstring*(ctx: DTContext; idx: duk_idx_t; out_len: ptr duk_size_t; + def_ptr: cstring; def_len: duk_size_t): cstring {.stdcall, + importc: "duk_opt_lstring", header: headerduktape.} +proc duk_opt_buffer*(ctx: DTContext; idx: duk_idx_t; out_size: ptr duk_size_t; + def_ptr: pointer; def_size: duk_size_t): pointer {.stdcall, + importc: "duk_opt_buffer", header: headerduktape.} +proc duk_opt_buffer_data*(ctx: DTContext; idx: duk_idx_t; + out_size: ptr duk_size_t; def_ptr: pointer; + def_size: duk_size_t): pointer {.stdcall, + importc: "duk_opt_buffer_data", header: headerduktape.} +proc duk_opt_pointer*(ctx: DTContext; idx: duk_idx_t; def_value: pointer): pointer {. + stdcall, importc: "duk_opt_pointer", header: headerduktape.} +proc duk_opt_c_function*(ctx: DTContext; idx: duk_idx_t; + def_value: duk_c_function): duk_c_function {.stdcall, + importc: "duk_opt_c_function", header: headerduktape.} +proc duk_opt_context*(ctx: DTContext; idx: duk_idx_t; def_value: DTContext): DTContext {. + stdcall, importc: "duk_opt_context", header: headerduktape.} +proc duk_opt_heapptr*(ctx: DTContext; idx: duk_idx_t; def_value: pointer): pointer {. + stdcall, importc: "duk_opt_heapptr", header: headerduktape.} +proc duk_require_undefined*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_require_undefined", header: headerduktape.} +proc duk_require_null*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_require_null", header: headerduktape.} +proc duk_require_boolean*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_require_boolean", header: headerduktape.} +proc duk_require_number*(ctx: DTContext; idx: duk_idx_t): duk_double_t {.stdcall, + importc: "duk_require_number", header: headerduktape.} +proc duk_require_int*(ctx: DTContext; idx: duk_idx_t): duk_int_t {.stdcall, + importc: "duk_require_int", header: headerduktape.} +proc duk_require_uint*(ctx: DTContext; idx: duk_idx_t): duk_uint_t {.stdcall, + importc: "duk_require_uint", header: headerduktape.} +proc duk_require_string*(ctx: DTContext; idx: duk_idx_t): cstring {.stdcall, + importc: "duk_require_string", header: headerduktape.} +proc duk_require_lstring*(ctx: DTContext; idx: duk_idx_t; + out_len: ptr duk_size_t): cstring {.stdcall, + importc: "duk_require_lstring", header: headerduktape.} +proc duk_require_object*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_require_object", header: headerduktape.} +proc duk_require_buffer*(ctx: DTContext; idx: duk_idx_t; + out_size: ptr duk_size_t): pointer {.stdcall, + importc: "duk_require_buffer", header: headerduktape.} +proc duk_require_buffer_data*(ctx: DTContext; idx: duk_idx_t; + out_size: ptr duk_size_t): pointer {.stdcall, + importc: "duk_require_buffer_data", header: headerduktape.} +proc duk_require_pointer*(ctx: DTContext; idx: duk_idx_t): pointer {.stdcall, + importc: "duk_require_pointer", header: headerduktape.} +proc duk_require_c_function*(ctx: DTContext; idx: duk_idx_t): duk_c_function {. + stdcall, importc: "duk_require_c_function", header: headerduktape.} +proc duk_require_context*(ctx: DTContext; idx: duk_idx_t): DTContext {. + stdcall, importc: "duk_require_context", header: headerduktape.} +proc duk_require_function*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_require_function", header: headerduktape.} +proc duk_require_heapptr*(ctx: DTContext; idx: duk_idx_t): pointer {.stdcall, + importc: "duk_require_heapptr", header: headerduktape.} +proc duk_to_undefined*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_to_undefined", header: headerduktape.} +proc duk_to_null*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_to_null", header: headerduktape.} +proc duk_to_boolean*(ctx: DTContext; idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_to_boolean", header: headerduktape.} +proc duk_to_number*(ctx: DTContext; idx: duk_idx_t): duk_double_t {.stdcall, + importc: "duk_to_number", header: headerduktape.} +proc duk_to_int*(ctx: DTContext; idx: duk_idx_t): duk_int_t {.stdcall, + importc: "duk_to_int", header: headerduktape.} +proc duk_to_uint*(ctx: DTContext; idx: duk_idx_t): duk_uint_t {.stdcall, + importc: "duk_to_uint", header: headerduktape.} +proc duk_to_int32*(ctx: DTContext; idx: duk_idx_t): duk_int32_t {.stdcall, + importc: "duk_to_int32", header: headerduktape.} +proc duk_to_uint32*(ctx: DTContext; idx: duk_idx_t): duk_uint32_t {.stdcall, + importc: "duk_to_uint32", header: headerduktape.} +proc duk_to_uint16*(ctx: DTContext; idx: duk_idx_t): duk_uint16_t {.stdcall, + importc: "duk_to_uint16", header: headerduktape.} +proc duk_to_string*(ctx: DTContext; idx: duk_idx_t): cstring {.stdcall, + importc: "duk_to_string", header: headerduktape.} +proc duk_to_lstring*(ctx: DTContext; idx: duk_idx_t; out_len: ptr duk_size_t): cstring {. + stdcall, importc: "duk_to_lstring", header: headerduktape.} +proc duk_to_buffer_raw*(ctx: DTContext; idx: duk_idx_t; + out_size: ptr duk_size_t; flags: duk_uint_t): pointer {. + stdcall, importc: "duk_to_buffer_raw", header: headerduktape.} +proc duk_to_pointer*(ctx: DTContext; idx: duk_idx_t): pointer {.stdcall, + importc: "duk_to_pointer", header: headerduktape.} +proc duk_to_object*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_to_object", header: headerduktape.} +proc duk_to_primitive*(ctx: DTContext; idx: duk_idx_t; hint: duk_int_t) {.stdcall, + importc: "duk_to_primitive", header: headerduktape.} +proc duk_safe_to_lstring*(ctx: DTContext; idx: duk_idx_t; + out_len: ptr duk_size_t): cstring {.stdcall, + importc: "duk_safe_to_lstring", header: headerduktape.} +proc duk_get_length*(ctx: DTContext; idx: duk_idx_t): duk_size_t {.stdcall, + importc: "duk_get_length", header: headerduktape.} +proc duk_set_length*(ctx: DTContext; idx: duk_idx_t; len: duk_size_t) {.stdcall, + importc: "duk_set_length", header: headerduktape.} +proc duk_base64_encode*(ctx: DTContext; idx: duk_idx_t): cstring {.stdcall, + importc: "duk_base64_encode", header: headerduktape.} +proc duk_base64_decode*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_base64_decode", header: headerduktape.} +proc duk_hex_encode*(ctx: DTContext; idx: duk_idx_t): cstring {.stdcall, + importc: "duk_hex_encode", header: headerduktape.} +proc duk_hex_decode*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_hex_decode", header: headerduktape.} +proc duk_json_encode*(ctx: DTContext; idx: duk_idx_t): cstring {.stdcall, + importc: "duk_json_encode", header: headerduktape.} +proc duk_json_decode*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_json_decode", header: headerduktape.} +proc duk_buffer_to_string*(ctx: DTContext; idx: duk_idx_t): cstring {.stdcall, + importc: "duk_buffer_to_string", header: headerduktape.} +proc duk_resize_buffer*(ctx: DTContext; idx: duk_idx_t; new_size: duk_size_t): pointer {. + stdcall, importc: "duk_resize_buffer", header: headerduktape.} +proc duk_steal_buffer*(ctx: DTContext; idx: duk_idx_t; out_size: ptr duk_size_t): pointer {. + stdcall, importc: "duk_steal_buffer", header: headerduktape.} +proc duk_config_buffer*(ctx: DTContext; idx: duk_idx_t; `ptr`: pointer; + len: duk_size_t) {.stdcall, importc: "duk_config_buffer", + header: headerduktape.} +proc duk_get_prop*(ctx: DTContext; obj_idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_get_prop", header: headerduktape.} +proc duk_get_prop_string*(ctx: DTContext; obj_idx: duk_idx_t; key: cstring): duk_bool_t {. + stdcall, importc: "duk_get_prop_string", header: headerduktape.} +proc duk_get_prop_lstring*(ctx: DTContext; obj_idx: duk_idx_t; key: cstring; + key_len: duk_size_t): duk_bool_t {.stdcall, + importc: "duk_get_prop_lstring", header: headerduktape.} +proc duk_get_prop_index*(ctx: DTContext; obj_idx: duk_idx_t; + arr_idx: duk_uarridx_t): duk_bool_t {.stdcall, + importc: "duk_get_prop_index", header: headerduktape.} +proc duk_get_prop_heapptr*(ctx: DTContext; obj_idx: duk_idx_t; `ptr`: pointer): duk_bool_t {. + stdcall, importc: "duk_get_prop_heapptr", header: headerduktape.} +proc duk_put_prop*(ctx: DTContext; obj_idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_put_prop", header: headerduktape.} +proc duk_put_prop_string*(ctx: DTContext; obj_idx: duk_idx_t; key: cstring): duk_bool_t {. + stdcall, importc: "duk_put_prop_string", header: headerduktape.} +proc duk_put_prop_lstring*(ctx: DTContext; obj_idx: duk_idx_t; key: cstring; + key_len: duk_size_t): duk_bool_t {.stdcall, + importc: "duk_put_prop_lstring", header: headerduktape.} +proc duk_put_prop_index*(ctx: DTContext; obj_idx: duk_idx_t; + arr_idx: duk_uarridx_t): duk_bool_t {.stdcall, + importc: "duk_put_prop_index", header: headerduktape.} +proc duk_put_prop_heapptr*(ctx: DTContext; obj_idx: duk_idx_t; `ptr`: pointer): duk_bool_t {. + stdcall, importc: "duk_put_prop_heapptr", header: headerduktape.} +proc duk_del_prop*(ctx: DTContext; obj_idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_del_prop", header: headerduktape.} +proc duk_del_prop_string*(ctx: DTContext; obj_idx: duk_idx_t; key: cstring): duk_bool_t {. + stdcall, importc: "duk_del_prop_string", header: headerduktape.} +proc duk_del_prop_lstring*(ctx: DTContext; obj_idx: duk_idx_t; key: cstring; + key_len: duk_size_t): duk_bool_t {.stdcall, + importc: "duk_del_prop_lstring", header: headerduktape.} +proc duk_del_prop_index*(ctx: DTContext; obj_idx: duk_idx_t; + arr_idx: duk_uarridx_t): duk_bool_t {.stdcall, + importc: "duk_del_prop_index", header: headerduktape.} +proc duk_del_prop_heapptr*(ctx: DTContext; obj_idx: duk_idx_t; `ptr`: pointer): duk_bool_t {. + stdcall, importc: "duk_del_prop_heapptr", header: headerduktape.} +proc duk_has_prop*(ctx: DTContext; obj_idx: duk_idx_t): duk_bool_t {.stdcall, + importc: "duk_has_prop", header: headerduktape.} +proc duk_has_prop_string*(ctx: DTContext; obj_idx: duk_idx_t; key: cstring): duk_bool_t {. + stdcall, importc: "duk_has_prop_string", header: headerduktape.} +proc duk_has_prop_lstring*(ctx: DTContext; obj_idx: duk_idx_t; key: cstring; + key_len: duk_size_t): duk_bool_t {.stdcall, + importc: "duk_has_prop_lstring", header: headerduktape.} +proc duk_has_prop_index*(ctx: DTContext; obj_idx: duk_idx_t; + arr_idx: duk_uarridx_t): duk_bool_t {.stdcall, + importc: "duk_has_prop_index", header: headerduktape.} +proc duk_has_prop_heapptr*(ctx: DTContext; obj_idx: duk_idx_t; `ptr`: pointer): duk_bool_t {. + stdcall, importc: "duk_has_prop_heapptr", header: headerduktape.} +proc duk_get_prop_desc*(ctx: DTContext; obj_idx: duk_idx_t; flags: duk_uint_t) {. + stdcall, importc: "duk_get_prop_desc", header: headerduktape.} +proc duk_def_prop*(ctx: DTContext; obj_idx: duk_idx_t; flags: duk_uint_t) {. + stdcall, importc: "duk_def_prop", header: headerduktape.} +proc duk_get_global_string*(ctx: DTContext; key: cstring): duk_bool_t {.stdcall, + importc: "duk_get_global_string", header: headerduktape.} +proc duk_get_global_lstring*(ctx: DTContext; key: cstring; key_len: duk_size_t): duk_bool_t {. + stdcall, importc: "duk_get_global_lstring", header: headerduktape.} +proc duk_put_global_string*(ctx: DTContext; key: cstring): duk_bool_t {.stdcall, + importc: "duk_put_global_string", header: headerduktape.} +proc duk_put_global_lstring*(ctx: DTContext; key: cstring; key_len: duk_size_t): duk_bool_t {. + stdcall, importc: "duk_put_global_lstring", header: headerduktape.} +proc duk_inspect_value*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_inspect_value", header: headerduktape.} +proc duk_inspect_callstack_entry*(ctx: DTContext; level: duk_int_t) {.stdcall, + importc: "duk_inspect_callstack_entry", header: headerduktape.} +proc duk_get_prototype*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_get_prototype", header: headerduktape.} +proc duk_set_prototype*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_set_prototype", header: headerduktape.} +proc duk_get_finalizer*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_get_finalizer", header: headerduktape.} +proc duk_set_finalizer*(ctx: DTContext; idx: duk_idx_t) {.stdcall, + importc: "duk_set_finalizer", header: headerduktape.} +proc duk_set_global_object*(ctx: DTContext) {.stdcall, + importc: "duk_set_global_object", header: headerduktape.} +proc duk_get_magic*(ctx: DTContext; idx: duk_idx_t): duk_int_t {.stdcall, + importc: "duk_get_magic", header: headerduktape.} +proc duk_set_magic*(ctx: DTContext; idx: duk_idx_t; magic: duk_int_t) {.stdcall, + importc: "duk_set_magic", header: headerduktape.} +proc duk_get_current_magic*(ctx: DTContext): duk_int_t {.stdcall, + importc: "duk_get_current_magic", header: headerduktape.} +proc duk_put_function_list*(ctx: DTContext; obj_idx: duk_idx_t; + funcs: ptr duk_function_list_entry) {.stdcall, + importc: "duk_put_function_list", header: headerduktape.} +proc duk_put_number_list*(ctx: DTContext; obj_idx: duk_idx_t; + numbers: ptr duk_number_list_entry) {.stdcall, + importc: "duk_put_number_list", header: headerduktape.} +proc duk_compact*(ctx: DTContext; obj_idx: duk_idx_t) {.stdcall, + importc: "duk_compact", header: headerduktape.} +proc duk_enum*(ctx: DTContext; obj_idx: duk_idx_t; enum_flags: duk_uint_t) {. + stdcall, importc: "duk_enum", header: headerduktape.} +proc duk_next*(ctx: DTContext; enum_idx: duk_idx_t; get_value: duk_bool_t): duk_bool_t {. + stdcall, importc: "duk_next", header: headerduktape.} +proc duk_seal*(ctx: DTContext; obj_idx: duk_idx_t) {.stdcall, + importc: "duk_seal", header: headerduktape.} +proc duk_freeze*(ctx: DTContext; obj_idx: duk_idx_t) {.stdcall, + importc: "duk_freeze", header: headerduktape.} +proc duk_concat*(ctx: DTContext; count: duk_idx_t) {.stdcall, + importc: "duk_concat", header: headerduktape.} +proc duk_join*(ctx: DTContext; count: duk_idx_t) {.stdcall, importc: "duk_join", + header: headerduktape.} +proc duk_decode_string*(ctx: DTContext; idx: duk_idx_t; + callback: duk_decode_char_function; udata: pointer) {. + stdcall, importc: "duk_decode_string", header: headerduktape.} +proc duk_map_string*(ctx: DTContext; idx: duk_idx_t; + callback: duk_map_char_function; udata: pointer) {.stdcall, + importc: "duk_map_string", header: headerduktape.} +proc duk_substring*(ctx: DTContext; idx: duk_idx_t; + start_char_offset: duk_size_t; end_char_offset: duk_size_t) {. + stdcall, importc: "duk_substring", header: headerduktape.} +proc duk_trim*(ctx: DTContext; idx: duk_idx_t) {.stdcall, importc: "duk_trim", + header: headerduktape.} +proc duk_char_code_at*(ctx: DTContext; idx: duk_idx_t; char_offset: duk_size_t): duk_codepoint_t {. + stdcall, importc: "duk_char_code_at", header: headerduktape.} +proc duk_equals*(ctx: DTContext; idx1: duk_idx_t; idx2: duk_idx_t): duk_bool_t {. + stdcall, importc: "duk_equals", header: headerduktape.} +proc duk_strict_equals*(ctx: DTContext; idx1: duk_idx_t; idx2: duk_idx_t): duk_bool_t {. + stdcall, importc: "duk_strict_equals", header: headerduktape.} +proc duk_samevalue*(ctx: DTContext; idx1: duk_idx_t; idx2: duk_idx_t): duk_bool_t {. + stdcall, importc: "duk_samevalue", header: headerduktape.} +proc duk_instanceof*(ctx: DTContext; idx1: duk_idx_t; idx2: duk_idx_t): duk_bool_t {. + stdcall, importc: "duk_instanceof", header: headerduktape.} +proc duk_call*(ctx: DTContext; nargs: duk_idx_t) {.stdcall, importc: "duk_call", + header: headerduktape.} +proc duk_call_method*(ctx: DTContext; nargs: duk_idx_t) {.stdcall, + importc: "duk_call_method", header: headerduktape.} +proc duk_call_prop*(ctx: DTContext; obj_idx: duk_idx_t; nargs: duk_idx_t) {. + stdcall, importc: "duk_call_prop", header: headerduktape.} +proc duk_pcall*(ctx: DTContext; nargs: duk_idx_t): duk_int_t {.stdcall, + importc: "duk_pcall", header: headerduktape.} +proc duk_pcall_method*(ctx: DTContext; nargs: duk_idx_t): duk_int_t {.stdcall, + importc: "duk_pcall_method", header: headerduktape.} +proc duk_pcall_prop*(ctx: DTContext; obj_idx: duk_idx_t; nargs: duk_idx_t): duk_int_t {. + stdcall, importc: "duk_pcall_prop", header: headerduktape.} +proc duk_new*(ctx: DTContext; nargs: duk_idx_t) {.stdcall, importc: "duk_new", + header: headerduktape.} +proc duk_pnew*(ctx: DTContext; nargs: duk_idx_t): duk_int_t {.stdcall, + importc: "duk_pnew", header: headerduktape.} +proc duk_safe_call*(ctx: DTContext; `func`: duk_safe_call_function; + udata: pointer; nargs: duk_idx_t; nrets: duk_idx_t): duk_int_t {. + stdcall, importc: "duk_safe_call", header: headerduktape.} +proc duk_eval_raw*(ctx: DTContext; src_buffer: cstring; src_length: duk_size_t; + flags: duk_uint_t): duk_int_t {.stdcall, importc: "duk_eval_raw", + header: headerduktape.} +proc duk_compile_raw*(ctx: DTContext; src_buffer: cstring; + src_length: duk_size_t; flags: duk_uint_t): duk_int_t {.stdcall, + importc: "duk_compile_raw", header: headerduktape.} +proc duk_dump_function*(ctx: DTContext) {.stdcall, + importc: "duk_dump_function", header: headerduktape.} +proc duk_load_function*(ctx: DTContext) {.stdcall, + importc: "duk_load_function", header: headerduktape.} +proc duk_push_context_dump*(ctx: DTContext) {.stdcall, + importc: "duk_push_context_dump", header: headerduktape.} +proc duk_debugger_attach*(ctx: DTContext; read_cb: duk_debug_read_function; + write_cb: duk_debug_write_function; + peek_cb: duk_debug_peek_function; + read_flush_cb: duk_debug_read_flush_function; + write_flush_cb: duk_debug_write_flush_function; + request_cb: duk_debug_request_function; + detached_cb: duk_debug_detached_function; udata: pointer) {. + stdcall, importc: "duk_debugger_attach", header: headerduktape.} +proc duk_debugger_detach*(ctx: DTContext) {.stdcall, + importc: "duk_debugger_detach", header: headerduktape.} +proc duk_debugger_cooperate*(ctx: DTContext) {.stdcall, + importc: "duk_debugger_cooperate", header: headerduktape.} +proc duk_debugger_notify*(ctx: DTContext; nvalues: duk_idx_t): duk_bool_t {. + stdcall, importc: "duk_debugger_notify", header: headerduktape.} +proc duk_debugger_pause*(ctx: DTContext) {.stdcall, + importc: "duk_debugger_pause", header: headerduktape.} +proc duk_get_now*(ctx: DTContext): duk_double_t {.stdcall, + importc: "duk_get_now", header: headerduktape.} +proc duk_time_to_components*(ctx: DTContext; timeval: duk_double_t; + comp: ptr duk_time_components) {.stdcall, + importc: "duk_time_to_components", header: headerduktape.} +proc duk_components_to_time*(ctx: DTContext; comp: ptr duk_time_components): duk_double_t {. + stdcall, importc: "duk_components_to_time", header: headerduktape.} +proc duk_create_heap_default*(): DTContext {.header: headerduktape.} +proc duk_eval_string*(ctx: DTContext, s: cstring) {.header: headerduktape.} +proc duk_pcompile_string*(ctx: DTContext, flags: duk_uint_t, s: cstring): duk_int_t {.header: headerduktape.} +proc duk_safe_to_string*(ctx: DTContext, idx: duk_idx_t): cstring {.header: headerduktape.} +# proc duk_to_string*(ctx: DTContext, index: cint): cstring {.header: headerduktape.} + +type + DTCFunction* = duk_c_function +
A
src/litestorepkg/vendor/duktape/duk_config.h
@@ -0,0 +1,3672 @@
+/* + * duk_config.h configuration header generated by genconfig.py. + * + * Git commit: 25420e773c5fbc50d5b46bf487fc45717e35b94f + * Git describe: v2.2.1 + * Git branch: v2.2-maintenance + * + * Supported platforms: + * - Mac OSX, iPhone, Darwin + * - Orbis + * - OpenBSD + * - Generic BSD + * - Atari ST TOS + * - AmigaOS + * - Durango (XboxOne) + * - Windows + * - Flashplayer (Crossbridge) + * - QNX + * - TI-Nspire + * - Emscripten + * - Linux + * - Solaris + * - AIX + * - HPUX + * - Generic POSIX + * - Cygwin + * - Generic UNIX + * - Generic fallback + * + * Supported architectures: + * - x86 + * - x64 + * - x32 + * - ARM 32-bit + * - ARM 64-bit + * - MIPS 32-bit + * - MIPS 64-bit + * - PowerPC 32-bit + * - PowerPC 64-bit + * - SPARC 32-bit + * - SPARC 64-bit + * - SuperH + * - Motorola 68k + * - Emscripten + * - Generic + * + * Supported compilers: + * - Clang + * - GCC + * - MSVC + * - Emscripten + * - TinyC + * - VBCC + * - Bruce's C compiler + * - Generic + * + */ + +#if !defined(DUK_CONFIG_H_INCLUDED) +#define DUK_CONFIG_H_INCLUDED + +/* + * Intermediate helper defines + */ + +/* DLL build detection */ +/* not configured for DLL build */ +#undef DUK_F_DLL_BUILD + +/* Apple OSX, iOS */ +#if defined(__APPLE__) +#define DUK_F_APPLE +#endif + +/* FreeBSD */ +#if defined(__FreeBSD__) || defined(__FreeBSD) +#define DUK_F_FREEBSD +#endif + +/* Orbis (PS4) variant */ +#if defined(DUK_F_FREEBSD) && defined(__ORBIS__) +#define DUK_F_ORBIS +#endif + +/* OpenBSD */ +#if defined(__OpenBSD__) || defined(__OpenBSD) +#define DUK_F_OPENBSD +#endif + +/* NetBSD */ +#if defined(__NetBSD__) || defined(__NetBSD) +#define DUK_F_NETBSD +#endif + +/* BSD variant */ +#if defined(DUK_F_FREEBSD) || defined(DUK_F_NETBSD) || defined(DUK_F_OPENBSD) || \ + defined(__bsdi__) || defined(__DragonFly__) +#define DUK_F_BSD +#endif + +/* Atari ST TOS. __TOS__ defined by PureC. No platform define in VBCC + * apparently, so to use with VBCC user must define __TOS__ manually. + */ +#if defined(__TOS__) +#define DUK_F_TOS +#endif + +/* Motorola 68K. Not defined by VBCC, so user must define one of these + * manually when using VBCC. + */ +#if defined(__m68k__) || defined(M68000) || defined(__MC68K__) +#define DUK_F_M68K +#endif + +/* AmigaOS. Neither AMIGA nor __amigaos__ is defined on VBCC, so user must + * define 'AMIGA' manually when using VBCC. + */ +#if defined(AMIGA) || defined(__amigaos__) +#define DUK_F_AMIGAOS +#endif + +/* PowerPC */ +#if defined(__powerpc) || defined(__powerpc__) || defined(__PPC__) +#define DUK_F_PPC +#if defined(__PPC64__) || defined(__LP64__) || defined(_LP64) +#define DUK_F_PPC64 +#else +#define DUK_F_PPC32 +#endif +#endif + +/* Durango (Xbox One) */ +#if defined(_DURANGO) || defined(_XBOX_ONE) +#define DUK_F_DURANGO +#endif + +/* Windows, both 32-bit and 64-bit */ +#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || \ + defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) +#define DUK_F_WINDOWS +#if defined(_WIN64) || defined(WIN64) +#define DUK_F_WIN64 +#else +#define DUK_F_WIN32 +#endif +#endif + +/* Flash player (e.g. Crossbridge) */ +#if defined(__FLASHPLAYER__) +#define DUK_F_FLASHPLAYER +#endif + +/* QNX */ +#if defined(__QNX__) +#define DUK_F_QNX +#endif + +/* TI-Nspire (using Ndless) */ +#if defined(_TINSPIRE) +#define DUK_F_TINSPIRE +#endif + +/* Emscripten (provided explicitly by user), improve if possible */ +#if defined(EMSCRIPTEN) +#define DUK_F_EMSCRIPTEN +#endif + +/* BCC (Bruce's C compiler): this is a "torture target" for compilation */ +#if defined(__BCC__) || defined(__BCC_VERSION__) +#define DUK_F_BCC +#endif + +/* Linux */ +#if defined(__linux) || defined(__linux__) || defined(linux) +#define DUK_F_LINUX +#endif + +/* illumos / Solaris */ +#if defined(__sun) && defined(__SVR4) +#define DUK_F_SUN +#if defined(__SUNPRO_C) && (__SUNPRO_C < 0x550) +#define DUK_F_OLD_SOLARIS +/* Defines _ILP32 / _LP64 required by DUK_F_X86/DUK_F_X64. Platforms + * are processed before architectures, so this happens before the + * DUK_F_X86/DUK_F_X64 detection is emitted. + */ +#include <sys/isa_defs.h> +#endif +#endif + +/* AIX */ +#if defined(_AIX) +/* defined(__xlc__) || defined(__IBMC__): works but too wide */ +#define DUK_F_AIX +#endif + +/* HPUX */ +#if defined(__hpux) +#define DUK_F_HPUX +#if defined(__ia64) +#define DUK_F_HPUX_ITANIUM +#endif +#endif + +/* POSIX */ +#if defined(__posix) +#define DUK_F_POSIX +#endif + +/* Cygwin */ +#if defined(__CYGWIN__) +#define DUK_F_CYGWIN +#endif + +/* Generic Unix (includes Cygwin) */ +#if defined(__unix) || defined(__unix__) || defined(unix) || \ + defined(DUK_F_LINUX) || defined(DUK_F_BSD) +#define DUK_F_UNIX +#endif + +/* C++ */ +#undef DUK_F_CPP +#if defined(__cplusplus) +#define DUK_F_CPP +#endif + +/* Intel x86 (32-bit), x64 (64-bit) or x32 (64-bit but 32-bit pointers), + * define only one of DUK_F_X86, DUK_F_X64, DUK_F_X32. + * https://sites.google.com/site/x32abi/ + * + * With DUK_F_OLD_SOLARIS the <sys/isa_defs.h> header must be included + * before this. + */ +#if defined(__amd64__) || defined(__amd64) || \ + defined(__x86_64__) || defined(__x86_64) || \ + defined(_M_X64) || defined(_M_AMD64) +#if defined(__ILP32__) || defined(_ILP32) +#define DUK_F_X32 +#else +#define DUK_F_X64 +#endif +#elif defined(i386) || defined(__i386) || defined(__i386__) || \ + defined(__i486__) || defined(__i586__) || defined(__i686__) || \ + defined(__IA32__) || defined(_M_IX86) || defined(__X86__) || \ + defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) +#if defined(__LP64__) || defined(_LP64) +/* This should not really happen, but would indicate x64. */ +#define DUK_F_X64 +#else +#define DUK_F_X86 +#endif +#endif + +/* ARM */ +#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(_M_ARM) || defined(__aarch64__) +#define DUK_F_ARM +#if defined(__LP64__) || defined(_LP64) || defined(__arm64) || defined(__arm64__) || defined(__aarch64__) +#define DUK_F_ARM64 +#else +#define DUK_F_ARM32 +#endif +#endif + +/* MIPS. Related defines: __MIPSEB__, __MIPSEL__, __mips_isa_rev, __LP64__ */ +#if defined(__mips__) || defined(mips) || defined(_MIPS_ISA) || \ + defined(_R3000) || defined(_R4000) || defined(_R5900) || \ + defined(_MIPS_ISA_MIPS1) || defined(_MIPS_ISA_MIPS2) || \ + defined(_MIPS_ISA_MIPS3) || defined(_MIPS_ISA_MIPS4) || \ + defined(__mips) || defined(__MIPS__) +#define DUK_F_MIPS +#if defined(__LP64__) || defined(_LP64) || defined(__mips64) || \ + defined(__mips64__) || defined(__mips_n64) +#define DUK_F_MIPS64 +#else +#define DUK_F_MIPS32 +#endif +#endif + +/* SPARC */ +#if defined(sparc) || defined(__sparc) || defined(__sparc__) +#define DUK_F_SPARC +#if defined(__LP64__) || defined(_LP64) +#define DUK_F_SPARC64 +#else +#define DUK_F_SPARC32 +#endif +#endif + +/* SuperH */ +#if defined(__sh__) || \ + defined(__sh1__) || defined(__SH1__) || \ + defined(__sh2__) || defined(__SH2__) || \ + defined(__sh3__) || defined(__SH3__) || \ + defined(__sh4__) || defined(__SH4__) || \ + defined(__sh5__) || defined(__SH5__) +#define DUK_F_SUPERH +#endif + +/* Clang */ +#if defined(__clang__) +#define DUK_F_CLANG +#endif + +/* C99 or above */ +#undef DUK_F_C99 +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +#define DUK_F_C99 +#endif + +/* C++11 or above */ +#undef DUK_F_CPP11 +#if defined(__cplusplus) && (__cplusplus >= 201103L) +#define DUK_F_CPP11 +#endif + +/* GCC. Clang also defines __GNUC__ so don't detect GCC if using Clang. */ +#if defined(__GNUC__) && !defined(__clang__) && !defined(DUK_F_CLANG) +#define DUK_F_GCC +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +/* Convenience, e.g. gcc 4.5.1 == 40501; http://stackoverflow.com/questions/6031819/emulating-gccs-builtin-unreachable */ +#define DUK_F_GCC_VERSION (__GNUC__ * 10000L + __GNUC_MINOR__ * 100L + __GNUC_PATCHLEVEL__) +#else +#error cannot figure out gcc version +#endif +#endif + +/* MinGW. Also GCC flags (DUK_F_GCC) are enabled now. */ +#if defined(__MINGW32__) || defined(__MINGW64__) +#define DUK_F_MINGW +#endif + +/* MSVC */ +#if defined(_MSC_VER) +/* MSVC preprocessor defines: http://msdn.microsoft.com/en-us/library/b0084kay.aspx + * _MSC_FULL_VER includes the build number, but it has at least two formats, see e.g. + * BOOST_MSVC_FULL_VER in http://www.boost.org/doc/libs/1_52_0/boost/config/compiler/visualc.hpp + */ +#define DUK_F_MSVC +#if defined(_MSC_FULL_VER) +#if (_MSC_FULL_VER > 100000000) +#define DUK_F_MSVC_FULL_VER _MSC_FULL_VER +#else +#define DUK_F_MSCV_FULL_VER (_MSC_FULL_VER * 10) +#endif +#endif +#endif /* _MSC_VER */ + +/* TinyC */ +#if defined(__TINYC__) +/* http://bellard.org/tcc/tcc-doc.html#SEC9 */ +#define DUK_F_TINYC +#endif + +/* VBCC */ +#if defined(__VBCC__) +#define DUK_F_VBCC +#endif + +#if defined(ANDROID) || defined(__ANDROID__) +#define DUK_F_ANDROID +#endif + +/* Atari Mint */ +#if defined(__MINT__) +#define DUK_F_MINT +#endif + +/* + * Platform autodetection + */ + +/* Workaround for older C++ compilers before including <inttypes.h>, + * see e.g.: https://sourceware.org/bugzilla/show_bug.cgi?id=15366 + */ +#if defined(__cplusplus) && !defined(__STDC_LIMIT_MACROS) +#define __STDC_LIMIT_MACROS +#endif +#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) +#define __STDC_CONSTANT_MACROS +#endif + +#if defined(DUK_F_APPLE) +/* --- Mac OSX, iPhone, Darwin --- */ +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_PRS_STRPTIME +#define DUK_USE_DATE_FMT_STRFTIME +#include <TargetConditionals.h> +#include <architecture/byte_order.h> +#include <sys/param.h> +#include <sys/time.h> +#include <time.h> + +/* http://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor */ +#if TARGET_IPHONE_SIMULATOR +#define DUK_USE_OS_STRING "iphone-sim" +#elif TARGET_OS_IPHONE +#define DUK_USE_OS_STRING "iphone" +#elif TARGET_OS_MAC +#define DUK_USE_OS_STRING "osx" +#else +#define DUK_USE_OS_STRING "osx-unknown" +#endif + +/* Use _setjmp() on Apple by default, see GH-55. */ +#define DUK_JMPBUF_TYPE jmp_buf +#define DUK_SETJMP(jb) _setjmp((jb)) +#define DUK_LONGJMP(jb) _longjmp((jb), 1) +#elif defined(DUK_F_ORBIS) +/* --- Orbis --- */ +/* Orbis = PS4 */ +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_S +/* no parsing (not an error) */ +#define DUK_USE_DATE_FMT_STRFTIME +#include <sys/types.h> +#include <machine/endian.h> +#include <sys/param.h> +#include <sys/time.h> +#include <time.h> + +#define DUK_USE_OS_STRING "orbis" +#elif defined(DUK_F_OPENBSD) +/* --- OpenBSD --- */ +/* http://www.monkey.org/openbsd/archive/ports/0401/msg00089.html */ +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_PRS_STRPTIME +#define DUK_USE_DATE_FMT_STRFTIME +#include <sys/types.h> +#include <sys/endian.h> +#include <sys/param.h> +#include <sys/time.h> +#include <time.h> + +#define DUK_USE_OS_STRING "openbsd" +#elif defined(DUK_F_BSD) +/* --- Generic BSD --- */ +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_PRS_STRPTIME +#define DUK_USE_DATE_FMT_STRFTIME +#include <sys/types.h> +#include <sys/endian.h> +#include <sys/param.h> +#include <sys/time.h> +#include <time.h> + +#define DUK_USE_OS_STRING "bsd" +#elif defined(DUK_F_TOS) +/* --- Atari ST TOS --- */ +#define DUK_USE_DATE_NOW_TIME +#define DUK_USE_DATE_TZO_GMTIME +/* no parsing (not an error) */ +#define DUK_USE_DATE_FMT_STRFTIME +#include <time.h> + +#define DUK_USE_OS_STRING "tos" + +/* TOS on M68K is always big endian. */ +#if !defined(DUK_USE_BYTEORDER) && defined(DUK_F_M68K) +#define DUK_USE_BYTEORDER 3 +#endif +#elif defined(DUK_F_AMIGAOS) +/* --- AmigaOS --- */ +#if defined(DUK_F_M68K) +/* AmigaOS on M68k */ +#define DUK_USE_DATE_NOW_TIME +#define DUK_USE_DATE_TZO_GMTIME +/* no parsing (not an error) */ +#define DUK_USE_DATE_FMT_STRFTIME +#include <time.h> +#elif defined(DUK_F_PPC) +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_PRS_STRPTIME +#define DUK_USE_DATE_FMT_STRFTIME +#include <time.h> +#if !defined(UINTPTR_MAX) +#define UINTPTR_MAX UINT_MAX +#endif +#else +#error AmigaOS but not M68K/PPC, not supported now +#endif + +#define DUK_USE_OS_STRING "amigaos" + +/* AmigaOS on M68K or PPC is always big endian. */ +#if !defined(DUK_USE_BYTEORDER) && (defined(DUK_F_M68K) || defined(DUK_F_PPC)) +#define DUK_USE_BYTEORDER 3 +#endif +#elif defined(DUK_F_DURANGO) +/* --- Durango (XboxOne) --- */ +/* Durango = XboxOne + * Configuration is nearly identical to Windows, except for + * DUK_USE_DATE_TZO_WINDOWS. + */ + +/* Initial fix: disable secure CRT related warnings when compiling Duktape + * itself (must be defined before including Windows headers). Don't define + * for user code including duktape.h. + */ +#if defined(DUK_COMPILING_DUKTAPE) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +/* MSVC does not have sys/param.h */ +#define DUK_USE_DATE_NOW_WINDOWS +#define DUK_USE_DATE_TZO_WINDOWS_NO_DST +/* Note: PRS and FMT are intentionally left undefined for now. This means + * there is no platform specific date parsing/formatting but there is still + * the ISO 8601 standard format. + */ +#if defined(DUK_COMPILING_DUKTAPE) +/* Only include when compiling Duktape to avoid polluting application build + * with a lot of unnecessary defines. + */ +#include <windows.h> +#endif + +#define DUK_USE_OS_STRING "durango" + +#if !defined(DUK_USE_BYTEORDER) +#define DUK_USE_BYTEORDER 1 +#endif +#elif defined(DUK_F_WINDOWS) +/* --- Windows --- */ +/* Windows version can't obviously be determined at compile time, + * but _WIN32_WINNT indicates the minimum version targeted: + * - https://msdn.microsoft.com/en-us/library/6sehtctf.aspx + */ + +/* Initial fix: disable secure CRT related warnings when compiling Duktape + * itself (must be defined before including Windows headers). Don't define + * for user code including duktape.h. + */ +#if defined(DUK_COMPILING_DUKTAPE) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +/* Windows 32-bit and 64-bit are currently the same. */ +/* MSVC does not have sys/param.h */ + +#if defined(DUK_COMPILING_DUKTAPE) +/* Only include when compiling Duktape to avoid polluting application build + * with a lot of unnecessary defines. + */ +#include <windows.h> +#endif + +/* GetSystemTimePreciseAsFileTime() available from Windows 8: + * https://msdn.microsoft.com/en-us/library/windows/desktop/hh706895(v=vs.85).aspx + */ +#if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS) || defined(DUK_USE_DATE_NOW_WINDOWS) +/* User forced provider. */ +#else +#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602) +#define DUK_USE_DATE_NOW_WINDOWS_SUBMS +#else +#define DUK_USE_DATE_NOW_WINDOWS +#endif +#endif + +#define DUK_USE_DATE_TZO_WINDOWS + +/* Note: PRS and FMT are intentionally left undefined for now. This means + * there is no platform specific date parsing/formatting but there is still + * the ISO 8601 standard format. + */ + +/* QueryPerformanceCounter() may go backwards in Windows XP, so enable for + * Vista and later: https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx#qpc_support_in_windows_versions + */ +#if !defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC) && \ + defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) +#define DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC +#endif + +#define DUK_USE_OS_STRING "windows" + +/* On Windows, assume we're little endian. Even Itanium which has a + * configurable endianness runs little endian in Windows. + */ +#if !defined(DUK_USE_BYTEORDER) +#define DUK_USE_BYTEORDER 1 +#endif +#elif defined(DUK_F_FLASHPLAYER) +/* --- Flashplayer (Crossbridge) --- */ +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_PRS_STRPTIME +#define DUK_USE_DATE_FMT_STRFTIME +#include <endian.h> +#include <sys/param.h> +#include <sys/time.h> +#include <time.h> + +#define DUK_USE_OS_STRING "flashplayer" + +#if !defined(DUK_USE_BYTEORDER) && defined(DUK_F_FLASHPLAYER) +#define DUK_USE_BYTEORDER 1 +#endif +#elif defined(DUK_F_QNX) +/* --- QNX --- */ +#if defined(DUK_F_QNX) && defined(DUK_COMPILING_DUKTAPE) +/* See: /opt/qnx650/target/qnx6/usr/include/sys/platform.h */ +#define _XOPEN_SOURCE 600 +#define _POSIX_C_SOURCE 200112L +#endif + +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_PRS_STRPTIME +#define DUK_USE_DATE_FMT_STRFTIME +#include <sys/types.h> +#include <sys/param.h> +#include <sys/time.h> +#include <time.h> + +#define DUK_USE_OS_STRING "qnx" +#elif defined(DUK_F_TINSPIRE) +/* --- TI-Nspire --- */ +#if defined(DUK_COMPILING_DUKTAPE) && !defined(_XOPEN_SOURCE) +#define _XOPEN_SOURCE /* e.g. strptime */ +#endif + +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_PRS_STRPTIME +#define DUK_USE_DATE_FMT_STRFTIME +#include <sys/types.h> +#include <sys/param.h> +#include <sys/time.h> +#include <time.h> + +#define DUK_USE_OS_STRING "tinspire" +#elif defined(DUK_F_EMSCRIPTEN) +/* --- Emscripten --- */ +#if defined(DUK_COMPILING_DUKTAPE) +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200809L +#endif +#if !defined(_GNU_SOURCE) +#define _GNU_SOURCE /* e.g. getdate_r */ +#endif +#if !defined(_XOPEN_SOURCE) +#define _XOPEN_SOURCE /* e.g. strptime */ +#endif +#endif /* DUK_COMPILING_DUKTAPE */ + +#include <sys/types.h> +#if defined(DUK_F_BCC) +/* no endian.h */ +#else +#include <endian.h> +#endif /* DUK_F_BCC */ +#include <sys/param.h> +#include <sys/time.h> +#include <time.h> +#include <stdint.h> + +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_PRS_STRPTIME +#define DUK_USE_DATE_FMT_STRFTIME + +#define DUK_USE_OS_STRING "emscripten" +#elif defined(DUK_F_LINUX) +/* --- Linux --- */ +#if defined(DUK_COMPILING_DUKTAPE) +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200809L +#endif +#if !defined(_GNU_SOURCE) +#define _GNU_SOURCE /* e.g. getdate_r */ +#endif +#if !defined(_XOPEN_SOURCE) +#define _XOPEN_SOURCE /* e.g. strptime */ +#endif +#endif /* DUK_COMPILING_DUKTAPE */ + +#include <sys/types.h> +#if defined(DUK_F_BCC) +/* no endian.h or stdint.h */ +#else +#include <endian.h> +#include <stdint.h> +#endif /* DUK_F_BCC */ +#include <sys/param.h> +#include <sys/time.h> +#include <time.h> + +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_PRS_STRPTIME +#define DUK_USE_DATE_FMT_STRFTIME + +#if 0 /* XXX: safe condition? */ +#define DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME +#endif + +#define DUK_USE_OS_STRING "linux" +#elif defined(DUK_F_SUN) +/* --- Solaris --- */ +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_PRS_STRPTIME +#define DUK_USE_DATE_FMT_STRFTIME + +#include <sys/types.h> +#if defined(DUK_F_OLD_SOLARIS) +/* Old Solaris with no endian.h, stdint.h */ +#define DUK_F_NO_STDINT_H +#if !defined(DUK_USE_BYTEORDER) +#define DUK_USE_BYTEORDER 3 +#endif +#else /* DUK_F_OLD_SOLARIS */ +#include <ast/endian.h> +#endif /* DUK_F_OLD_SOLARIS */ + +#include <sys/param.h> +#include <sys/time.h> +#include <time.h> + +#define DUK_USE_OS_STRING "solaris" +#elif defined(DUK_F_AIX) +/* --- AIX --- */ +#if !defined(DUK_USE_BYTEORDER) +#define DUK_USE_BYTEORDER 3 +#endif +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_PRS_STRPTIME +#define DUK_USE_DATE_FMT_STRFTIME +#include <sys/param.h> +#include <sys/time.h> +#include <time.h> + +#define DUK_USE_OS_STRING "aix" +#elif defined(DUK_F_HPUX) +/* --- HPUX --- */ +#define DUK_F_NO_STDINT_H +#if !defined(DUK_USE_BYTEORDER) +#define DUK_USE_BYTEORDER 3 +#endif +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_PRS_STRPTIME +#define DUK_USE_DATE_FMT_STRFTIME +#include <sys/param.h> +#include <sys/time.h> +#include <time.h> + +#define DUK_USE_OS_STRING "hpux" +#elif defined(DUK_F_POSIX) +/* --- Generic POSIX --- */ +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_PRS_STRPTIME +#define DUK_USE_DATE_FMT_STRFTIME +#include <sys/types.h> +#include <endian.h> +#include <sys/param.h> +#include <sys/time.h> +#include <time.h> + +#define DUK_USE_OS_STRING "posix" +#elif defined(DUK_F_CYGWIN) +/* --- Cygwin --- */ +/* don't use strptime() for now */ +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_FMT_STRFTIME +#include <sys/types.h> +#include <endian.h> +#include <sys/param.h> +#include <sys/time.h> +#include <time.h> + +#define DUK_JMPBUF_TYPE jmp_buf +#define DUK_SETJMP(jb) _setjmp((jb)) +#define DUK_LONGJMP(jb) _longjmp((jb), 1) + +#define DUK_USE_OS_STRING "windows" +#elif defined(DUK_F_UNIX) +/* --- Generic UNIX --- */ +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_PRS_STRPTIME +#define DUK_USE_DATE_FMT_STRFTIME +#include <time.h> +#include <sys/time.h> +#define DUK_USE_OS_STRING "unknown" +#else +/* --- Generic fallback --- */ +/* The most portable current time provider is time(), but it only has a + * one second resolution. + */ +#define DUK_USE_DATE_NOW_TIME + +/* The most portable way to figure out local time offset is gmtime(), + * but it's not thread safe so use with caution. + */ +#define DUK_USE_DATE_TZO_GMTIME + +/* Avoid custom date parsing and formatting for portability. */ +#undef DUK_USE_DATE_PRS_STRPTIME +#undef DUK_USE_DATE_FMT_STRFTIME + +/* Rely on C89 headers only; time.h must be here. */ +#include <time.h> + +#define DUK_USE_OS_STRING "unknown" +#endif /* autodetect platform */ + +/* Shared includes: C89 */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> /* varargs */ +#include <setjmp.h> +#include <stddef.h> /* e.g. ptrdiff_t */ +#include <math.h> +#include <limits.h> + +/* date.h is omitted, and included per platform */ + +/* Shared includes: stdint.h is C99 */ +#if defined(DUK_F_NO_STDINT_H) +/* stdint.h not available */ +#else +/* Technically C99 (C++11) but found in many systems. On some systems + * __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS must be defined before + * including stdint.h (see above). + */ +#include <stdint.h> +#endif + +#if defined(DUK_F_CPP) +#include <exception> /* std::exception */ +#endif + +/* + * Architecture autodetection + */ + +#if defined(DUK_F_X86) +/* --- x86 --- */ +#define DUK_USE_ARCH_STRING "x86" +#if !defined(DUK_USE_BYTEORDER) +#define DUK_USE_BYTEORDER 1 +#endif +/* XXX: This is technically not guaranteed because it's possible to configure + * an x86 to require aligned accesses with Alignment Check (AC) flag. + */ +#if !defined(DUK_USE_ALIGN_BY) +#define DUK_USE_ALIGN_BY 1 +#endif +#define DUK_USE_PACKED_TVAL +#define DUK_F_PACKED_TVAL_PROVIDED +#elif defined(DUK_F_X64) +/* --- x64 --- */ +#define DUK_USE_ARCH_STRING "x64" +#if !defined(DUK_USE_BYTEORDER) +#define DUK_USE_BYTEORDER 1 +#endif +/* XXX: This is technically not guaranteed because it's possible to configure + * an x86 to require aligned accesses with Alignment Check (AC) flag. + */ +#if !defined(DUK_USE_ALIGN_BY) +#define DUK_USE_ALIGN_BY 1 +#endif +#undef DUK_USE_PACKED_TVAL +#define DUK_F_PACKED_TVAL_PROVIDED +#elif defined(DUK_F_X32) +/* --- x32 --- */ +#define DUK_USE_ARCH_STRING "x32" +#if !defined(DUK_USE_BYTEORDER) +#define DUK_USE_BYTEORDER 1 +#endif +/* XXX: This is technically not guaranteed because it's possible to configure + * an x86 to require aligned accesses with Alignment Check (AC) flag. + */ +#if !defined(DUK_USE_ALIGN_BY) +#define DUK_USE_ALIGN_BY 1 +#endif +#define DUK_USE_PACKED_TVAL +#define DUK_F_PACKED_TVAL_PROVIDED +#elif defined(DUK_F_ARM32) +/* --- ARM 32-bit --- */ +#define DUK_USE_ARCH_STRING "arm32" +/* Byte order varies, so rely on autodetect. */ +#if !defined(DUK_USE_ALIGN_BY) +#define DUK_USE_ALIGN_BY 4 +#endif +#define DUK_USE_PACKED_TVAL +#define DUK_F_PACKED_TVAL_PROVIDED +#elif defined(DUK_F_ARM64) +/* --- ARM 64-bit --- */ +#define DUK_USE_ARCH_STRING "arm64" +/* Byte order varies, so rely on autodetect. */ +#if !defined(DUK_USE_ALIGN_BY) +#define DUK_USE_ALIGN_BY 8 +#endif +#undef DUK_USE_PACKED_TVAL +#define DUK_F_PACKED_TVAL_PROVIDED +#elif defined(DUK_F_MIPS32) +/* --- MIPS 32-bit --- */ +#define DUK_USE_ARCH_STRING "mips32" +/* MIPS byte order varies so rely on autodetection. */ +#if !defined(DUK_USE_ALIGN_BY) +#define DUK_USE_ALIGN_BY 8 +#endif +#define DUK_USE_PACKED_TVAL +#define DUK_F_PACKED_TVAL_PROVIDED +#elif defined(DUK_F_MIPS64) +/* --- MIPS 64-bit --- */ +#define DUK_USE_ARCH_STRING "mips64" +/* MIPS byte order varies so rely on autodetection. */ +#if !defined(DUK_USE_ALIGN_BY) +#define DUK_USE_ALIGN_BY 8 +#endif +#undef DUK_USE_PACKED_TVAL +#define DUK_F_PACKED_TVAL_PROVIDED +#elif defined(DUK_F_PPC32) +/* --- PowerPC 32-bit --- */ +#define DUK_USE_ARCH_STRING "ppc32" +#if !defined(DUK_USE_BYTEORDER) +#define DUK_USE_BYTEORDER 3 +#endif +#if !defined(DUK_USE_ALIGN_BY) +#define DUK_USE_ALIGN_BY 8 +#endif +#define DUK_USE_PACKED_TVAL +#define DUK_F_PACKED_TVAL_PROVIDED +#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 +#if !defined(DUK_USE_ALIGN_BY) +#define DUK_USE_ALIGN_BY 8 +#endif +#undef DUK_USE_PACKED_TVAL +#define DUK_F_PACKED_TVAL_PROVIDED +#elif defined(DUK_F_SPARC32) +/* --- SPARC 32-bit --- */ +#define DUK_USE_ARCH_STRING "sparc32" +/* SPARC byte order varies so rely on autodetection. */ +#if !defined(DUK_USE_ALIGN_BY) +#define DUK_USE_ALIGN_BY 8 +#endif +#define DUK_USE_PACKED_TVAL +#define DUK_F_PACKED_TVAL_PROVIDED +#elif defined(DUK_F_SPARC64) +/* --- SPARC 64-bit --- */ +#define DUK_USE_ARCH_STRING "sparc64" +/* SPARC byte order varies so rely on autodetection. */ +#if !defined(DUK_USE_ALIGN_BY) +#define DUK_USE_ALIGN_BY 8 +#endif +#undef DUK_USE_PACKED_TVAL +#define DUK_F_PACKED_TVAL_PROVIDED +#elif defined(DUK_F_SUPERH) +/* --- SuperH --- */ +#define DUK_USE_ARCH_STRING "sh" +/* Byte order varies, rely on autodetection. */ +/* Based on 'make checkalign' there are no alignment requirements on + * Linux SH4, but align by 4 is probably a good basic default. + */ +#if !defined(DUK_USE_ALIGN_BY) +#define DUK_USE_ALIGN_BY 4 +#endif +#define DUK_USE_PACKED_TVAL +#define DUK_F_PACKED_TVAL_PROVIDED +#elif defined(DUK_F_M68K) +/* --- Motorola 68k --- */ +#define DUK_USE_ARCH_STRING "m68k" +#if !defined(DUK_USE_BYTEORDER) +#define DUK_USE_BYTEORDER 3 +#endif +#if !defined(DUK_USE_ALIGN_BY) +#define DUK_USE_ALIGN_BY 8 +#endif +#define DUK_USE_PACKED_TVAL +#define DUK_F_PACKED_TVAL_PROVIDED +#elif defined(DUK_F_EMSCRIPTEN) +/* --- Emscripten --- */ +#define DUK_USE_ARCH_STRING "emscripten" +#if !defined(DUK_USE_BYTEORDER) +#define DUK_USE_BYTEORDER 1 +#endif +#if !defined(DUK_USE_ALIGN_BY) +#define DUK_USE_ALIGN_BY 8 +#endif +#undef DUK_USE_PACKED_TVAL +#define DUK_F_PACKED_TVAL_PROVIDED +#else +/* --- Generic --- */ +/* These are necessary wild guesses. */ +#define DUK_USE_ARCH_STRING "generic" +/* Rely on autodetection for byte order, alignment, and packed tval. */ +#endif /* autodetect architecture */ + +/* + * Compiler autodetection + */ + +#if defined(DUK_F_CLANG) +/* --- Clang --- */ +#if defined(DUK_F_C99) || defined(DUK_F_CPP11) +/* C99 / C++11 and above: rely on va_copy() which is required. */ +#define DUK_VA_COPY(dest,src) va_copy(dest,src) +#else +/* Clang: assume we have __va_copy() in non-C99 mode. */ +#define DUK_VA_COPY(dest,src) __va_copy(dest,src) +#endif + +#define DUK_NORETURN(decl) decl __attribute__((noreturn)) + +#if defined(__clang__) && defined(__has_builtin) +#if __has_builtin(__builtin_unreachable) +#define DUK_UNREACHABLE() do { __builtin_unreachable(); } while (0) +#endif +#endif + +#define DUK_USE_BRANCH_HINTS +#define DUK_LIKELY(x) __builtin_expect((x), 1) +#define DUK_UNLIKELY(x) __builtin_expect((x), 0) +#if defined(__clang__) && defined(__has_builtin) +#if __has_builtin(__builtin_unpredictable) +#define DUK_UNPREDICTABLE(x) __builtin_unpredictable((x)) +#endif +#endif + +#if defined(DUK_F_C99) || defined(DUK_F_CPP11) +#define DUK_NOINLINE __attribute__((noinline)) +#define DUK_INLINE inline +#define DUK_ALWAYS_INLINE inline __attribute__((always_inline)) +#endif + +/* DUK_HOT */ +/* DUK_COLD */ + +#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS) +/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're + * compiling Duktape or the application. + */ +#if defined(DUK_COMPILING_DUKTAPE) +#define DUK_EXTERNAL_DECL extern __declspec(dllexport) +#define DUK_EXTERNAL __declspec(dllexport) +#else +#define DUK_EXTERNAL_DECL extern __declspec(dllimport) +#define DUK_EXTERNAL should_not_happen +#endif +#if defined(DUK_SINGLE_FILE) +#define DUK_INTERNAL_DECL static +#define DUK_INTERNAL static +#else +#define DUK_INTERNAL_DECL extern +#define DUK_INTERNAL /*empty*/ +#endif +#define DUK_LOCAL_DECL static +#define DUK_LOCAL static +#else +#define DUK_EXTERNAL_DECL +#define DUK_EXTERNAL __attribute__ ((visibility("default"))) +#if defined(DUK_SINGLE_FILE) +#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG) +/* Minimize warnings for unused internal functions with GCC >= 3.1.1 and + * Clang. Based on documentation it should suffice to have the attribute + * in the declaration only, but in practice some warnings are generated unless + * the attribute is also applied to the definition. + */ +#define DUK_INTERNAL_DECL static __attribute__ ((unused)) +#define DUK_INTERNAL static __attribute__ ((unused)) +#else +#define DUK_INTERNAL_DECL static +#define DUK_INTERNAL static +#endif +#else +#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG) +#define DUK_INTERNAL_DECL __attribute__ ((visibility("hidden"))) __attribute__ ((unused)) extern +#define DUK_INTERNAL __attribute__ ((visibility("hidden"))) __attribute__ ((unused)) +#else +#define DUK_INTERNAL_DECL __attribute__ ((visibility("hidden"))) extern +#define DUK_INTERNAL __attribute__ ((visibility("hidden"))) +#endif +#endif +#define DUK_LOCAL_DECL static +#define DUK_LOCAL static +#endif + +#if defined(DUK_F_CPP) +#define DUK_USE_COMPILER_STRING "clang" +#else +#define DUK_USE_COMPILER_STRING "clang" +#endif + +#undef DUK_USE_VARIADIC_MACROS +#if defined(DUK_F_C99) || defined(DUK_F_CPP11) +#define DUK_USE_VARIADIC_MACROS +#endif + +#define DUK_USE_UNION_INITIALIZERS + +#undef DUK_USE_FLEX_C99 +#undef DUK_USE_FLEX_ZEROSIZE +#undef DUK_USE_FLEX_ONESIZE +#if defined(DUK_F_C99) +#define DUK_USE_FLEX_C99 +#else +#define DUK_USE_FLEX_ZEROSIZE +#endif + +#undef DUK_USE_GCC_PRAGMAS +#define DUK_USE_PACK_CLANG_ATTR +#elif defined(DUK_F_GCC) +/* --- GCC --- */ +#if defined(DUK_F_C99) || defined(DUK_F_CPP11) +/* C99 / C++11 and above: rely on va_copy() which is required. */ +#define DUK_VA_COPY(dest,src) va_copy(dest,src) +#else +/* GCC: assume we have __va_copy() in non-C99 mode. */ +#define DUK_VA_COPY(dest,src) __va_copy(dest,src) +#endif + +#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 20500L) +/* since gcc-2.5 */ +#define DUK_NORETURN(decl) decl __attribute__((noreturn)) +#endif + +#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L) +/* since gcc-4.5 */ +#define DUK_UNREACHABLE() do { __builtin_unreachable(); } while (0) +#endif + +#define DUK_USE_BRANCH_HINTS +#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L) +/* GCC: test not very accurate; enable only in relatively recent builds + * because of bugs in gcc-4.4 (http://lists.debian.org/debian-gcc/2010/04/msg00000.html) + */ +#define DUK_LIKELY(x) __builtin_expect((x), 1) +#define DUK_UNLIKELY(x) __builtin_expect((x), 0) +#endif +/* XXX: equivalent of clang __builtin_unpredictable? */ + +#if (defined(DUK_F_C99) || defined(DUK_F_CPP11)) && \ + defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 30101) +#define DUK_NOINLINE __attribute__((noinline)) +#define DUK_INLINE inline +#define DUK_ALWAYS_INLINE inline __attribute__((always_inline)) +#endif + +#if (defined(DUK_F_C99) || defined(DUK_F_CPP11)) && \ + defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40300) +#define DUK_HOT __attribute__((hot)) +#define DUK_COLD __attribute__((cold)) +#endif + +#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS) +/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're + * compiling Duktape or the application. + */ +#if defined(DUK_COMPILING_DUKTAPE) +#define DUK_EXTERNAL_DECL extern __declspec(dllexport) +#define DUK_EXTERNAL __declspec(dllexport) +#else +#define DUK_EXTERNAL_DECL extern __declspec(dllimport) +#define DUK_EXTERNAL should_not_happen +#endif +#if defined(DUK_SINGLE_FILE) +#define DUK_INTERNAL_DECL static +#define DUK_INTERNAL static +#else +#define DUK_INTERNAL_DECL extern +#define DUK_INTERNAL /*empty*/ +#endif +#define DUK_LOCAL_DECL static +#define DUK_LOCAL static +#elif defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40000) +#define DUK_EXTERNAL_DECL +#define DUK_EXTERNAL __attribute__ ((visibility("default"))) +#if defined(DUK_SINGLE_FILE) +#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG) +/* Minimize warnings for unused internal functions with GCC >= 3.1.1 and + * Clang. Based on documentation it should suffice to have the attribute + * in the declaration only, but in practice some warnings are generated unless + * the attribute is also applied to the definition. + */ +#define DUK_INTERNAL_DECL static __attribute__ ((unused)) +#define DUK_INTERNAL static __attribute__ ((unused)) +#else +#define DUK_INTERNAL_DECL static +#define DUK_INTERNAL static +#endif +#else +#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG) +#define DUK_INTERNAL_DECL __attribute__ ((visibility("hidden"))) __attribute__ ((unused)) extern +#define DUK_INTERNAL __attribute__ ((visibility("hidden"))) __attribute__ ((unused)) +#else +#define DUK_INTERNAL_DECL __attribute__ ((visibility("hidden"))) extern +#define DUK_INTERNAL __attribute__ ((visibility("hidden"))) +#endif +#endif +#define DUK_LOCAL_DECL static +#define DUK_LOCAL static +#endif + +#if defined(DUK_F_MINGW) +#if defined(DUK_F_CPP) +#define DUK_USE_COMPILER_STRING "mingw++" +#else +#define DUK_USE_COMPILER_STRING "mingw" +#endif +#else +#if defined(DUK_F_CPP) +#define DUK_USE_COMPILER_STRING "g++" +#else +#define DUK_USE_COMPILER_STRING "gcc" +#endif +#endif + +#undef DUK_USE_VARIADIC_MACROS +#if defined(DUK_F_C99) || (defined(DUK_F_CPP11) && defined(__GNUC__)) +#define DUK_USE_VARIADIC_MACROS +#endif + +#define DUK_USE_UNION_INITIALIZERS + +#undef DUK_USE_FLEX_C99 +#undef DUK_USE_FLEX_ZEROSIZE +#undef DUK_USE_FLEX_ONESIZE +#if defined(DUK_F_C99) +#define DUK_USE_FLEX_C99 +#else +#define DUK_USE_FLEX_ZEROSIZE +#endif + +#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40600) +#define DUK_USE_GCC_PRAGMAS +#else +#undef DUK_USE_GCC_PRAGMAS +#endif + +#define DUK_USE_PACK_GCC_ATTR +#elif defined(DUK_F_MSVC) +/* --- MSVC --- */ +/* http://msdn.microsoft.com/en-us/library/aa235362(VS.60).aspx */ +#define DUK_NORETURN(decl) __declspec(noreturn) decl + +/* XXX: DUK_UNREACHABLE for msvc? */ + +#undef DUK_USE_BRANCH_HINTS + +/* XXX: DUK_LIKELY, DUK_UNLIKELY for msvc? */ +/* XXX: DUK_NOINLINE, DUK_INLINE, DUK_ALWAYS_INLINE for msvc? */ + +#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS) +/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're + * compiling Duktape or the application. + */ +#if defined(DUK_COMPILING_DUKTAPE) +#define DUK_EXTERNAL_DECL extern __declspec(dllexport) +#define DUK_EXTERNAL __declspec(dllexport) +#else +#define DUK_EXTERNAL_DECL extern __declspec(dllimport) +#define DUK_EXTERNAL should_not_happen +#endif +#if defined(DUK_SINGLE_FILE) +#define DUK_INTERNAL_DECL static +#define DUK_INTERNAL static +#else +#define DUK_INTERNAL_DECL extern +#define DUK_INTERNAL /*empty*/ +#endif +#define DUK_LOCAL_DECL static +#define DUK_LOCAL static +#endif + +#if defined(DUK_F_CPP) +#define DUK_USE_COMPILER_STRING "msvc++" +#else +#define DUK_USE_COMPILER_STRING "msvc" +#endif + +#undef DUK_USE_VARIADIC_MACROS +#if defined(DUK_F_C99) +#define DUK_USE_VARIADIC_MACROS +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) +/* VS2005+ should have variadic macros even when they're not C99. */ +#define DUK_USE_VARIADIC_MACROS +#endif + +#undef DUK_USE_UNION_INITIALIZERS +#if defined(_MSC_VER) && (_MSC_VER >= 1800) +/* VS2013+ supports union initializers but there's a bug involving union-inside-struct: + * https://connect.microsoft.com/VisualStudio/feedback/details/805981 + * The bug was fixed (at least) in VS2015 so check for VS2015 for now: + * https://blogs.msdn.microsoft.com/vcblog/2015/07/01/c-compiler-front-end-fixes-in-vs2015/ + * Manually tested using VS2013, CL reports 18.00.31101, so enable for VS2013 too. + */ +#define DUK_USE_UNION_INITIALIZERS +#endif + +#undef DUK_USE_FLEX_C99 +#undef DUK_USE_FLEX_ZEROSIZE +#undef DUK_USE_FLEX_ONESIZE +#if defined(DUK_F_C99) +#define DUK_USE_FLEX_C99 +#else +#define DUK_USE_FLEX_ZEROSIZE +#endif + +#undef DUK_USE_GCC_PRAGMAS + +#define DUK_USE_PACK_MSVC_PRAGMA + +/* These have been tested from VS2008 onwards; may work in older VS versions + * too but not enabled by default. + */ +#if defined(_MSC_VER) && (_MSC_VER >= 1500) +#define DUK_NOINLINE __declspec(noinline) +#define DUK_INLINE __inline +#define DUK_ALWAYS_INLINE __forceinline +#endif + +#if defined(_MSC_VER) && (_MSC_VER >= 1900) +#define DUK_SNPRINTF snprintf +#define DUK_VSNPRINTF vsnprintf +#else +/* (v)snprintf() is missing before MSVC 2015. Note that _(v)snprintf() does + * NOT NUL terminate on truncation, but Duktape code never assumes that. + * http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 + */ +#define DUK_SNPRINTF _snprintf +#define DUK_VSNPRINTF _vsnprintf +#endif + +/* Avoid warning when doing DUK_UNREF(some_function). */ +#if defined(_MSC_VER) && (_MSC_VER < 1500) +#pragma warning(disable: 4100 4101 4550 4551) +#define DUK_UNREF(x) +#else +#define DUK_UNREF(x) do { __pragma(warning(suppress:4100 4101 4550 4551)) (x); } while (0) +#endif + +/* Older versions of MSVC don't support the LL/ULL suffix. */ +#define DUK_U64_CONSTANT(x) x##ui64 +#define DUK_I64_CONSTANT(x) x##i64 +#elif defined(DUK_F_EMSCRIPTEN) +/* --- Emscripten --- */ +#define DUK_NORETURN(decl) decl __attribute__((noreturn)) + +#if defined(__clang__) && defined(__has_builtin) +#if __has_builtin(__builtin_unreachable) +#define DUK_UNREACHABLE() do { __builtin_unreachable(); } while (0) +#endif +#endif + +#define DUK_USE_BRANCH_HINTS +#define DUK_LIKELY(x) __builtin_expect((x), 1) +#define DUK_UNLIKELY(x) __builtin_expect((x), 0) +#if defined(__clang__) && defined(__has_builtin) +#if __has_builtin(__builtin_unpredictable) +#define DUK_UNPREDICTABLE(x) __builtin_unpredictable((x)) +#endif +#endif + +#if defined(DUK_F_C99) || defined(DUK_F_CPP11) +#define DUK_NOINLINE __attribute__((noinline)) +#define DUK_INLINE inline +#define DUK_ALWAYS_INLINE inline __attribute__((always_inline)) +#endif + +#define DUK_EXTERNAL_DECL +#define DUK_EXTERNAL __attribute__ ((visibility("default"))) +#if defined(DUK_SINGLE_FILE) +#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG) +/* Minimize warnings for unused internal functions with GCC >= 3.1.1 and + * Clang. Based on documentation it should suffice to have the attribute + * in the declaration only, but in practice some warnings are generated unless + * the attribute is also applied to the definition. + */ +#define DUK_INTERNAL_DECL static __attribute__ ((unused)) +#define DUK_INTERNAL static __attribute__ ((unused)) +#else +#define DUK_INTERNAL_DECL static +#define DUK_INTERNAL static +#endif +#else +#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG) +#define DUK_INTERNAL_DECL __attribute__ ((visibility("hidden"))) __attribute__ ((unused)) extern +#define DUK_INTERNAL __attribute__ ((visibility("hidden"))) __attribute__ ((unused)) +#else +#define DUK_INTERNAL_DECL __attribute__ ((visibility("hidden"))) extern +#define DUK_INTERNAL __attribute__ ((visibility("hidden"))) +#endif +#endif +#define DUK_LOCAL_DECL static +#define DUK_LOCAL static + +#define DUK_USE_COMPILER_STRING "emscripten" + +#undef DUK_USE_VARIADIC_MACROS +#if defined(DUK_F_C99) || defined(DUK_F_CPP11) +#define DUK_USE_VARIADIC_MACROS +#endif + +#define DUK_USE_UNION_INITIALIZERS + +#undef DUK_USE_FLEX_C99 +#undef DUK_USE_FLEX_ZEROSIZE +#undef DUK_USE_FLEX_ONESIZE +#if defined(DUK_F_C99) +#define DUK_USE_FLEX_C99 +#else +#define DUK_USE_FLEX_ZEROSIZE +#endif + +#undef DUK_USE_GCC_PRAGMAS +#define DUK_USE_PACK_CLANG_ATTR +#elif defined(DUK_F_TINYC) +/* --- TinyC --- */ +#undef DUK_USE_BRANCH_HINTS + +#if defined(DUK_F_CPP) +#define DUK_USE_COMPILER_STRING "tinyc++" +#else +#define DUK_USE_COMPILER_STRING "tinyc" +#endif + +/* http://bellard.org/tcc/tcc-doc.html#SEC7 */ +#define DUK_USE_VARIADIC_MACROS + +#define DUK_USE_UNION_INITIALIZERS + +/* Most portable, wastes space */ +#define DUK_USE_FLEX_ONESIZE + +/* Most portable, potentially wastes space */ +#define DUK_USE_PACK_DUMMY_MEMBER +#elif defined(DUK_F_VBCC) +/* --- VBCC --- */ +#undef DUK_USE_BRANCH_HINTS + +#if defined(DUK_F_CPP) +#define DUK_USE_COMPILER_STRING "vbcc-c++" +#else +#define DUK_USE_COMPILER_STRING "vbcc" +#endif + +#undef DUK_USE_VARIADIC_MACROS +#if defined(DUK_F_C99) || defined(DUK_F_CPP11) +#define DUK_USE_VARIADIC_MACROS +#endif + +/* VBCC supports C99 so check only for C99 for union initializer support. + * Designated union initializers would possibly work even without a C99 check. + */ +#undef DUK_USE_UNION_INITIALIZERS +#if defined(DUK_F_C99) +#define DUK_USE_UNION_INITIALIZERS +#endif + +#define DUK_USE_FLEX_ZEROSIZE +#define DUK_USE_PACK_DUMMY_MEMBER +#elif defined(DUK_F_BCC) +/* --- Bruce's C compiler --- */ +#undef DUK_USE_BRANCH_HINTS + +#if defined(DUK_F_CPP) +#define DUK_USE_COMPILER_STRING "bcc++" +#else +#define DUK_USE_COMPILER_STRING "bcc" +#endif + +/* Most portable */ +#undef DUK_USE_VARIADIC_MACROS + +/* Most portable, wastes space */ +#undef DUK_USE_UNION_INITIALIZERS + +/* Most portable, wastes space */ +#define DUK_USE_FLEX_ONESIZE + +/* Most portable, potentially wastes space */ +#define DUK_USE_PACK_DUMMY_MEMBER + +/* BCC, assume we're on x86. */ +#if !defined(DUK_USE_BYTEORDER) +#define DUK_USE_BYTEORDER 1 +#endif +#else +/* --- Generic --- */ +#undef DUK_USE_BRANCH_HINTS + +#if defined(DUK_F_CPP) +#define DUK_USE_COMPILER_STRING "generic-c++" +#else +#define DUK_USE_COMPILER_STRING "generic" +#endif + +#undef DUK_USE_VARIADIC_MACROS +#if defined(DUK_F_C99) || defined(DUK_F_CPP11) +#define DUK_USE_VARIADIC_MACROS +#endif + +/* C++ doesn't have standard designated union initializers ({ .foo = 1 }). */ +#undef DUK_USE_UNION_INITIALIZERS +#if defined(DUK_F_C99) +#define DUK_USE_UNION_INITIALIZERS +#endif + +/* Most portable, wastes space */ +#define DUK_USE_FLEX_ONESIZE + +/* Most portable, potentially wastes space */ +#define DUK_USE_PACK_DUMMY_MEMBER +#endif /* autodetect compiler */ + +/* uclibc */ +#if defined(__UCLIBC__) +#define DUK_F_UCLIBC +#endif + +/* + * Wrapper typedefs and constants for integer types, also sanity check types. + * + * C99 typedefs are quite good but not always available, and we want to avoid + * forcibly redefining the C99 typedefs. So, there are Duktape wrappers for + * all C99 typedefs and Duktape code should only use these typedefs. Type + * detection when C99 is not supported is best effort and may end up detecting + * some types incorrectly. + * + * Pointer sizes are a portability problem: pointers to different types may + * have a different size and function pointers are very difficult to manage + * portably. + * + * http://en.wikipedia.org/wiki/C_data_types#Fixed-width_integer_types + * + * Note: there's an interesting corner case when trying to define minimum + * signed integer value constants which leads to the current workaround of + * defining e.g. -0x80000000 as (-0x7fffffffL - 1L). See doc/code-issues.txt + * for a longer discussion. + * + * Note: avoid typecasts and computations in macro integer constants as they + * can then no longer be used in macro relational expressions (such as + * #if DUK_SIZE_MAX < 0xffffffffUL). There is internal code which relies on + * being able to compare DUK_SIZE_MAX against a limit. + */ + +/* XXX: add feature options to force basic types from outside? */ + +#if !defined(INT_MAX) +#error INT_MAX not defined +#endif + +/* Check that architecture is two's complement, standard C allows e.g. + * INT_MIN to be -2**31+1 (instead of -2**31). + */ +#if defined(INT_MAX) && defined(INT_MIN) +#if INT_MAX != -(INT_MIN + 1) +#error platform does not seem complement of two +#endif +#else +#error cannot check complement of two +#endif + +/* Pointer size determination based on __WORDSIZE or architecture when + * that's not available. + */ +#if defined(DUK_F_X86) || defined(DUK_F_X32) || \ + defined(DUK_F_M68K) || defined(DUK_F_PPC32) || \ + defined(DUK_F_BCC) || \ + (defined(__WORDSIZE) && (__WORDSIZE == 32)) || \ + ((defined(DUK_F_OLD_SOLARIS) || defined(DUK_F_AIX) || \ + defined(DUK_F_HPUX)) && defined(_ILP32)) || \ + defined(DUK_F_ARM32) +#define DUK_F_32BIT_PTRS +#elif defined(DUK_F_X64) || \ + (defined(__WORDSIZE) && (__WORDSIZE == 64)) || \ + ((defined(DUK_F_OLD_SOLARIS) || defined(DUK_F_AIX) || \ + defined(DUK_F_HPUX)) && defined(_LP64)) || \ + defined(DUK_F_ARM64) +#define DUK_F_64BIT_PTRS +#else +/* not sure, not needed with C99 anyway */ +#endif + +/* Intermediate define for 'have inttypes.h' */ +#undef DUK_F_HAVE_INTTYPES +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !(defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC)) +/* vbcc + AmigaOS has C99 but no inttypes.h */ +#define DUK_F_HAVE_INTTYPES +#elif defined(__cplusplus) && (__cplusplus >= 201103L) +/* C++11 apparently ratified stdint.h */ +#define DUK_F_HAVE_INTTYPES +#endif + +/* Basic integer typedefs and limits, preferably from inttypes.h, otherwise + * through automatic detection. + */ +#if defined(DUK_F_HAVE_INTTYPES) +/* C99 or compatible */ + +#define DUK_F_HAVE_64BIT +#include <inttypes.h> + +typedef uint8_t duk_uint8_t; +typedef int8_t duk_int8_t; +typedef uint16_t duk_uint16_t; +typedef int16_t duk_int16_t; +typedef uint32_t duk_uint32_t; +typedef int32_t duk_int32_t; +typedef uint64_t duk_uint64_t; +typedef int64_t duk_int64_t; +typedef uint_least8_t duk_uint_least8_t; +typedef int_least8_t duk_int_least8_t; +typedef uint_least16_t duk_uint_least16_t; +typedef int_least16_t duk_int_least16_t; +typedef uint_least32_t duk_uint_least32_t; +typedef int_least32_t duk_int_least32_t; +typedef uint_least64_t duk_uint_least64_t; +typedef int_least64_t duk_int_least64_t; +typedef uint_fast8_t duk_uint_fast8_t; +typedef int_fast8_t duk_int_fast8_t; +typedef uint_fast16_t duk_uint_fast16_t; +typedef int_fast16_t duk_int_fast16_t; +typedef uint_fast32_t duk_uint_fast32_t; +typedef int_fast32_t duk_int_fast32_t; +typedef uint_fast64_t duk_uint_fast64_t; +typedef int_fast64_t duk_int_fast64_t; +typedef uintptr_t duk_uintptr_t; +typedef intptr_t duk_intptr_t; +typedef uintmax_t duk_uintmax_t; +typedef intmax_t duk_intmax_t; + +#define DUK_UINT8_MIN 0 +#define DUK_UINT8_MAX UINT8_MAX +#define DUK_INT8_MIN INT8_MIN +#define DUK_INT8_MAX INT8_MAX +#define DUK_UINT_LEAST8_MIN 0 +#define DUK_UINT_LEAST8_MAX UINT_LEAST8_MAX +#define DUK_INT_LEAST8_MIN INT_LEAST8_MIN +#define DUK_INT_LEAST8_MAX INT_LEAST8_MAX +#define DUK_UINT_FAST8_MIN 0 +#define DUK_UINT_FAST8_MAX UINT_FAST8_MAX +#define DUK_INT_FAST8_MIN INT_FAST8_MIN +#define DUK_INT_FAST8_MAX INT_FAST8_MAX +#define DUK_UINT16_MIN 0 +#define DUK_UINT16_MAX UINT16_MAX +#define DUK_INT16_MIN INT16_MIN +#define DUK_INT16_MAX INT16_MAX +#define DUK_UINT_LEAST16_MIN 0 +#define DUK_UINT_LEAST16_MAX UINT_LEAST16_MAX +#define DUK_INT_LEAST16_MIN INT_LEAST16_MIN +#define DUK_INT_LEAST16_MAX INT_LEAST16_MAX +#define DUK_UINT_FAST16_MIN 0 +#define DUK_UINT_FAST16_MAX UINT_FAST16_MAX +#define DUK_INT_FAST16_MIN INT_FAST16_MIN +#define DUK_INT_FAST16_MAX INT_FAST16_MAX +#define DUK_UINT32_MIN 0 +#define DUK_UINT32_MAX UINT32_MAX +#define DUK_INT32_MIN INT32_MIN +#define DUK_INT32_MAX INT32_MAX +#define DUK_UINT_LEAST32_MIN 0 +#define DUK_UINT_LEAST32_MAX UINT_LEAST32_MAX +#define DUK_INT_LEAST32_MIN INT_LEAST32_MIN +#define DUK_INT_LEAST32_MAX INT_LEAST32_MAX +#define DUK_UINT_FAST32_MIN 0 +#define DUK_UINT_FAST32_MAX UINT_FAST32_MAX +#define DUK_INT_FAST32_MIN INT_FAST32_MIN +#define DUK_INT_FAST32_MAX INT_FAST32_MAX +#define DUK_UINT64_MIN 0 +#define DUK_UINT64_MAX UINT64_MAX +#define DUK_INT64_MIN INT64_MIN +#define DUK_INT64_MAX INT64_MAX +#define DUK_UINT_LEAST64_MIN 0 +#define DUK_UINT_LEAST64_MAX UINT_LEAST64_MAX +#define DUK_INT_LEAST64_MIN INT_LEAST64_MIN +#define DUK_INT_LEAST64_MAX INT_LEAST64_MAX +#define DUK_UINT_FAST64_MIN 0 +#define DUK_UINT_FAST64_MAX UINT_FAST64_MAX +#define DUK_INT_FAST64_MIN INT_FAST64_MIN +#define DUK_INT_FAST64_MAX INT_FAST64_MAX + +#define DUK_UINTPTR_MIN 0 +#define DUK_UINTPTR_MAX UINTPTR_MAX +#define DUK_INTPTR_MIN INTPTR_MIN +#define DUK_INTPTR_MAX INTPTR_MAX + +#define DUK_UINTMAX_MIN 0 +#define DUK_UINTMAX_MAX UINTMAX_MAX +#define DUK_INTMAX_MIN INTMAX_MIN +#define DUK_INTMAX_MAX INTMAX_MAX + +#define DUK_SIZE_MIN 0 +#define DUK_SIZE_MAX SIZE_MAX +#undef DUK_SIZE_MAX_COMPUTED + +#else /* C99 types */ + +/* When C99 types are not available, we use heuristic detection to get + * the basic 8, 16, 32, and (possibly) 64 bit types. The fast/least + * types are then assumed to be exactly the same for now: these could + * be improved per platform but C99 types are very often now available. + * 64-bit types are not available on all platforms; this is OK at least + * on 32-bit platforms. + * + * This detection code is necessarily a bit hacky and can provide typedefs + * and defines that won't work correctly on some exotic platform. + */ + +#if (defined(CHAR_BIT) && (CHAR_BIT == 8)) || \ + (defined(UCHAR_MAX) && (UCHAR_MAX == 255)) +typedef unsigned char duk_uint8_t; +typedef signed char duk_int8_t; +#else +#error cannot detect 8-bit type +#endif + +#if defined(USHRT_MAX) && (USHRT_MAX == 65535UL) +typedef unsigned short duk_uint16_t; +typedef signed short duk_int16_t; +#elif defined(UINT_MAX) && (UINT_MAX == 65535UL) +/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */ +typedef unsigned int duk_uint16_t; +typedef signed int duk_int16_t; +#else +#error cannot detect 16-bit type +#endif + +#if defined(UINT_MAX) && (UINT_MAX == 4294967295UL) +typedef unsigned int duk_uint32_t; +typedef signed int duk_int32_t; +#elif defined(ULONG_MAX) && (ULONG_MAX == 4294967295UL) +/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */ +typedef unsigned long duk_uint32_t; +typedef signed long duk_int32_t; +#else +#error cannot detect 32-bit type +#endif + +/* 64-bit type detection is a bit tricky. + * + * ULLONG_MAX is a standard define. __LONG_LONG_MAX__ and __ULONG_LONG_MAX__ + * are used by at least GCC (even if system headers don't provide ULLONG_MAX). + * Some GCC variants may provide __LONG_LONG_MAX__ but not __ULONG_LONG_MAX__. + * + * ULL / LL constants are rejected / warned about by some compilers, even if + * the compiler has a 64-bit type and the compiler/system headers provide an + * unsupported constant (ULL/LL)! Try to avoid using ULL / LL constants. + * As a side effect we can only check that e.g. ULONG_MAX is larger than 32 + * bits but can't be sure it is exactly 64 bits. Self tests will catch such + * cases. + */ +#undef DUK_F_HAVE_64BIT +#if !defined(DUK_F_HAVE_64BIT) && defined(ULONG_MAX) +#if (ULONG_MAX > 4294967295UL) +#define DUK_F_HAVE_64BIT +typedef unsigned long duk_uint64_t; +typedef signed long duk_int64_t; +#endif +#endif +#if !defined(DUK_F_HAVE_64BIT) && defined(ULLONG_MAX) +#if (ULLONG_MAX > 4294967295UL) +#define DUK_F_HAVE_64BIT +typedef unsigned long long duk_uint64_t; +typedef signed long long duk_int64_t; +#endif +#endif +#if !defined(DUK_F_HAVE_64BIT) && defined(__ULONG_LONG_MAX__) +#if (__ULONG_LONG_MAX__ > 4294967295UL) +#define DUK_F_HAVE_64BIT +typedef unsigned long long duk_uint64_t; +typedef signed long long duk_int64_t; +#endif +#endif +#if !defined(DUK_F_HAVE_64BIT) && defined(__LONG_LONG_MAX__) +#if (__LONG_LONG_MAX__ > 2147483647L) +#define DUK_F_HAVE_64BIT +typedef unsigned long long duk_uint64_t; +typedef signed long long duk_int64_t; +#endif +#endif +#if !defined(DUK_F_HAVE_64BIT) && defined(DUK_F_MINGW) +#define DUK_F_HAVE_64BIT +typedef unsigned long duk_uint64_t; +typedef signed long duk_int64_t; +#endif +#if !defined(DUK_F_HAVE_64BIT) && defined(DUK_F_MSVC) +#define DUK_F_HAVE_64BIT +typedef unsigned __int64 duk_uint64_t; +typedef signed __int64 duk_int64_t; +#endif +#if !defined(DUK_F_HAVE_64BIT) +/* cannot detect 64-bit type, not always needed so don't error */ +#endif + +typedef duk_uint8_t duk_uint_least8_t; +typedef duk_int8_t duk_int_least8_t; +typedef duk_uint16_t duk_uint_least16_t; +typedef duk_int16_t duk_int_least16_t; +typedef duk_uint32_t duk_uint_least32_t; +typedef duk_int32_t duk_int_least32_t; +typedef duk_uint8_t duk_uint_fast8_t; +typedef duk_int8_t duk_int_fast8_t; +typedef duk_uint16_t duk_uint_fast16_t; +typedef duk_int16_t duk_int_fast16_t; +typedef duk_uint32_t duk_uint_fast32_t; +typedef duk_int32_t duk_int_fast32_t; +#if defined(DUK_F_HAVE_64BIT) +typedef duk_uint64_t duk_uint_least64_t; +typedef duk_int64_t duk_int_least64_t; +typedef duk_uint64_t duk_uint_fast64_t; +typedef duk_int64_t duk_int_fast64_t; +#endif +#if defined(DUK_F_HAVE_64BIT) +typedef duk_uint64_t duk_uintmax_t; +typedef duk_int64_t duk_intmax_t; +#else +typedef duk_uint32_t duk_uintmax_t; +typedef duk_int32_t duk_intmax_t; +#endif + +/* Note: the funny looking computations for signed minimum 16-bit, 32-bit, and + * 64-bit values are intentional as the obvious forms (e.g. -0x80000000L) are + * -not- portable. See code-issues.txt for a detailed discussion. + */ +#define DUK_UINT8_MIN 0UL +#define DUK_UINT8_MAX 0xffUL +#define DUK_INT8_MIN (-0x80L) +#define DUK_INT8_MAX 0x7fL +#define DUK_UINT_LEAST8_MIN 0UL +#define DUK_UINT_LEAST8_MAX 0xffUL +#define DUK_INT_LEAST8_MIN (-0x80L) +#define DUK_INT_LEAST8_MAX 0x7fL +#define DUK_UINT_FAST8_MIN 0UL +#define DUK_UINT_FAST8_MAX 0xffUL +#define DUK_INT_FAST8_MIN (-0x80L) +#define DUK_INT_FAST8_MAX 0x7fL +#define DUK_UINT16_MIN 0UL +#define DUK_UINT16_MAX 0xffffUL +#define DUK_INT16_MIN (-0x7fffL - 1L) +#define DUK_INT16_MAX 0x7fffL +#define DUK_UINT_LEAST16_MIN 0UL +#define DUK_UINT_LEAST16_MAX 0xffffUL +#define DUK_INT_LEAST16_MIN (-0x7fffL - 1L) +#define DUK_INT_LEAST16_MAX 0x7fffL +#define DUK_UINT_FAST16_MIN 0UL +#define DUK_UINT_FAST16_MAX 0xffffUL +#define DUK_INT_FAST16_MIN (-0x7fffL - 1L) +#define DUK_INT_FAST16_MAX 0x7fffL +#define DUK_UINT32_MIN 0UL +#define DUK_UINT32_MAX 0xffffffffUL +#define DUK_INT32_MIN (-0x7fffffffL - 1L) +#define DUK_INT32_MAX 0x7fffffffL +#define DUK_UINT_LEAST32_MIN 0UL +#define DUK_UINT_LEAST32_MAX 0xffffffffUL +#define DUK_INT_LEAST32_MIN (-0x7fffffffL - 1L) +#define DUK_INT_LEAST32_MAX 0x7fffffffL +#define DUK_UINT_FAST32_MIN 0UL +#define DUK_UINT_FAST32_MAX 0xffffffffUL +#define DUK_INT_FAST32_MIN (-0x7fffffffL - 1L) +#define DUK_INT_FAST32_MAX 0x7fffffffL + +/* 64-bit constants. Since LL / ULL constants are not always available, + * use computed values. These values can't be used in preprocessor + * comparisons; flag them as such. + */ +#if defined(DUK_F_HAVE_64BIT) +#define DUK_UINT64_MIN ((duk_uint64_t) 0) +#define DUK_UINT64_MAX ((duk_uint64_t) -1) +#define DUK_INT64_MIN ((duk_int64_t) (~(DUK_UINT64_MAX >> 1))) +#define DUK_INT64_MAX ((duk_int64_t) (DUK_UINT64_MAX >> 1)) +#define DUK_UINT_LEAST64_MIN DUK_UINT64_MIN +#define DUK_UINT_LEAST64_MAX DUK_UINT64_MAX +#define DUK_INT_LEAST64_MIN DUK_INT64_MIN +#define DUK_INT_LEAST64_MAX DUK_INT64_MAX +#define DUK_UINT_FAST64_MIN DUK_UINT64_MIN +#define DUK_UINT_FAST64_MAX DUK_UINT64_MAX +#define DUK_INT_FAST64_MIN DUK_INT64_MIN +#define DUK_INT_FAST64_MAX DUK_INT64_MAX +#define DUK_UINT64_MIN_COMPUTED +#define DUK_UINT64_MAX_COMPUTED +#define DUK_INT64_MIN_COMPUTED +#define DUK_INT64_MAX_COMPUTED +#define DUK_UINT_LEAST64_MIN_COMPUTED +#define DUK_UINT_LEAST64_MAX_COMPUTED +#define DUK_INT_LEAST64_MIN_COMPUTED +#define DUK_INT_LEAST64_MAX_COMPUTED +#define DUK_UINT_FAST64_MIN_COMPUTED +#define DUK_UINT_FAST64_MAX_COMPUTED +#define DUK_INT_FAST64_MIN_COMPUTED +#define DUK_INT_FAST64_MAX_COMPUTED +#endif + +#if defined(DUK_F_HAVE_64BIT) +#define DUK_UINTMAX_MIN DUK_UINT64_MIN +#define DUK_UINTMAX_MAX DUK_UINT64_MAX +#define DUK_INTMAX_MIN DUK_INT64_MIN +#define DUK_INTMAX_MAX DUK_INT64_MAX +#define DUK_UINTMAX_MIN_COMPUTED +#define DUK_UINTMAX_MAX_COMPUTED +#define DUK_INTMAX_MIN_COMPUTED +#define DUK_INTMAX_MAX_COMPUTED +#else +#define DUK_UINTMAX_MIN 0UL +#define DUK_UINTMAX_MAX 0xffffffffUL +#define DUK_INTMAX_MIN (-0x7fffffffL - 1L) +#define DUK_INTMAX_MAX 0x7fffffffL +#endif + +/* This detection is not very reliable. */ +#if defined(DUK_F_32BIT_PTRS) +typedef duk_int32_t duk_intptr_t; +typedef duk_uint32_t duk_uintptr_t; +#define DUK_UINTPTR_MIN DUK_UINT32_MIN +#define DUK_UINTPTR_MAX DUK_UINT32_MAX +#define DUK_INTPTR_MIN DUK_INT32_MIN +#define DUK_INTPTR_MAX DUK_INT32_MAX +#elif defined(DUK_F_64BIT_PTRS) && defined(DUK_F_HAVE_64BIT) +typedef duk_int64_t duk_intptr_t; +typedef duk_uint64_t duk_uintptr_t; +#define DUK_UINTPTR_MIN DUK_UINT64_MIN +#define DUK_UINTPTR_MAX DUK_UINT64_MAX +#define DUK_INTPTR_MIN DUK_INT64_MIN +#define DUK_INTPTR_MAX DUK_INT64_MAX +#define DUK_UINTPTR_MIN_COMPUTED +#define DUK_UINTPTR_MAX_COMPUTED +#define DUK_INTPTR_MIN_COMPUTED +#define DUK_INTPTR_MAX_COMPUTED +#else +#error cannot determine intptr type +#endif + +/* SIZE_MAX may be missing so use an approximate value for it. */ +#undef DUK_SIZE_MAX_COMPUTED +#if !defined(SIZE_MAX) +#define DUK_SIZE_MAX_COMPUTED +#define SIZE_MAX ((size_t) (-1)) +#endif +#define DUK_SIZE_MIN 0 +#define DUK_SIZE_MAX SIZE_MAX + +#endif /* C99 types */ + +/* A few types are assumed to always exist. */ +typedef size_t duk_size_t; +typedef ptrdiff_t duk_ptrdiff_t; + +/* The best type for an "all around int" in Duktape internals is "at least + * 32 bit signed integer" which is most convenient. Same for unsigned type. + * Prefer 'int' when large enough, as it is almost always a convenient type. + */ +#if defined(UINT_MAX) && (UINT_MAX >= 0xffffffffUL) +typedef int duk_int_t; +typedef unsigned int duk_uint_t; +#define DUK_INT_MIN INT_MIN +#define DUK_INT_MAX INT_MAX +#define DUK_UINT_MIN 0 +#define DUK_UINT_MAX UINT_MAX +#else +typedef duk_int_fast32_t duk_int_t; +typedef duk_uint_fast32_t duk_uint_t; +#define DUK_INT_MIN DUK_INT_FAST32_MIN +#define DUK_INT_MAX DUK_INT_FAST32_MAX +#define DUK_UINT_MIN DUK_UINT_FAST32_MIN +#define DUK_UINT_MAX DUK_UINT_FAST32_MAX +#endif + +/* Same as 'duk_int_t' but guaranteed to be a 'fast' variant if this + * distinction matters for the CPU. These types are used mainly in the + * executor where it might really matter. + */ +typedef duk_int_fast32_t duk_int_fast_t; +typedef duk_uint_fast32_t duk_uint_fast_t; +#define DUK_INT_FAST_MIN DUK_INT_FAST32_MIN +#define DUK_INT_FAST_MAX DUK_INT_FAST32_MAX +#define DUK_UINT_FAST_MIN DUK_UINT_FAST32_MIN +#define DUK_UINT_FAST_MAX DUK_UINT_FAST32_MAX + +/* Small integers (16 bits or more) can fall back to the 'int' type, but + * have a typedef so they are marked "small" explicitly. + */ +typedef int duk_small_int_t; +typedef unsigned int duk_small_uint_t; +#define DUK_SMALL_INT_MIN INT_MIN +#define DUK_SMALL_INT_MAX INT_MAX +#define DUK_SMALL_UINT_MIN 0 +#define DUK_SMALL_UINT_MAX UINT_MAX + +/* Fast variants of small integers, again for really fast paths like the + * executor. + */ +typedef duk_int_fast16_t duk_small_int_fast_t; +typedef duk_uint_fast16_t duk_small_uint_fast_t; +#define DUK_SMALL_INT_FAST_MIN DUK_INT_FAST16_MIN +#define DUK_SMALL_INT_FAST_MAX DUK_INT_FAST16_MAX +#define DUK_SMALL_UINT_FAST_MIN DUK_UINT_FAST16_MIN +#define DUK_SMALL_UINT_FAST_MAX DUK_UINT_FAST16_MAX + +/* Boolean values are represented with the platform 'unsigned int'. */ +typedef duk_small_uint_t duk_bool_t; +#define DUK_BOOL_MIN DUK_SMALL_UINT_MIN +#define DUK_BOOL_MAX DUK_SMALL_UINT_MAX + +/* Index values must have at least 32-bit signed range. */ +typedef duk_int_t duk_idx_t; +#define DUK_IDX_MIN DUK_INT_MIN +#define DUK_IDX_MAX DUK_INT_MAX + +/* Unsigned index variant. */ +typedef duk_uint_t duk_uidx_t; +#define DUK_UIDX_MIN DUK_UINT_MIN +#define DUK_UIDX_MAX DUK_UINT_MAX + +/* Array index values, could be exact 32 bits. + * Currently no need for signed duk_arridx_t. + */ +typedef duk_uint_t duk_uarridx_t; +#define DUK_UARRIDX_MIN DUK_UINT_MIN +#define DUK_UARRIDX_MAX DUK_UINT_MAX + +/* Duktape/C function return value, platform int is enough for now to + * represent 0, 1, or negative error code. Must be compatible with + * assigning truth values (e.g. duk_ret_t rc = (foo == bar);). + */ +typedef duk_small_int_t duk_ret_t; +#define DUK_RET_MIN DUK_SMALL_INT_MIN +#define DUK_RET_MAX DUK_SMALL_INT_MAX + +/* Error codes are represented with platform int. High bits are used + * for flags and such, so 32 bits are needed. + */ +typedef duk_int_t duk_errcode_t; +#define DUK_ERRCODE_MIN DUK_INT_MIN +#define DUK_ERRCODE_MAX DUK_INT_MAX + +/* Codepoint type. Must be 32 bits or more because it is used also for + * internal codepoints. The type is signed because negative codepoints + * are used as internal markers (e.g. to mark EOF or missing argument). + * (X)UTF-8/CESU-8 encode/decode take and return an unsigned variant to + * ensure duk_uint32_t casts back and forth nicely. Almost everything + * else uses the signed one. + */ +typedef duk_int_t duk_codepoint_t; +typedef duk_uint_t duk_ucodepoint_t; +#define DUK_CODEPOINT_MIN DUK_INT_MIN +#define DUK_CODEPOINT_MAX DUK_INT_MAX +#define DUK_UCODEPOINT_MIN DUK_UINT_MIN +#define DUK_UCODEPOINT_MAX DUK_UINT_MAX + +/* IEEE float/double typedef. */ +typedef float duk_float_t; +typedef double duk_double_t; + +/* We're generally assuming that we're working on a platform with a 32-bit + * address space. If DUK_SIZE_MAX is a typecast value (which is necessary + * if SIZE_MAX is missing), the check must be avoided because the + * preprocessor can't do a comparison. + */ +#if !defined(DUK_SIZE_MAX) +#error DUK_SIZE_MAX is undefined, probably missing SIZE_MAX +#elif !defined(DUK_SIZE_MAX_COMPUTED) +#if DUK_SIZE_MAX < 0xffffffffUL +/* On some systems SIZE_MAX can be smaller than max unsigned 32-bit value + * which seems incorrect if size_t is (at least) an unsigned 32-bit type. + * However, it doesn't seem useful to error out compilation if this is the + * case. + */ +#endif +#endif + +/* Type used in public API declarations and user code. Typedef maps to + * 'struct duk_hthread' like the 'duk_hthread' typedef which is used + * exclusively in internals. + */ +typedef struct duk_hthread duk_context; + +/* Check whether we should use 64-bit integers or not. + * + * Quite incomplete now. Use 64-bit types if detected (C99 or other detection) + * unless they are known to be unreliable. For instance, 64-bit types are + * available on VBCC but seem to misbehave. + */ +#if defined(DUK_F_HAVE_64BIT) && !defined(DUK_F_VBCC) +#define DUK_USE_64BIT_OPS +#else +#undef DUK_USE_64BIT_OPS +#endif + +/* + * Fill-ins for platform, architecture, and compiler + */ + +/* An abort()-like primitive is needed by the default fatal error handler. */ +#if !defined(DUK_ABORT) +#define DUK_ABORT abort +#endif + +#if !defined(DUK_SETJMP) +#define DUK_JMPBUF_TYPE jmp_buf +#define DUK_SETJMP(jb) setjmp((jb)) +#define DUK_LONGJMP(jb) longjmp((jb), 1) +#endif + +#if 0 +/* sigsetjmp() alternative */ +#define DUK_JMPBUF_TYPE sigjmp_buf +#define DUK_SETJMP(jb) sigsetjmp((jb)) +#define DUK_LONGJMP(jb) siglongjmp((jb), 1) +#endif + +/* Special naming to avoid conflict with e.g. DUK_FREE() in duk_heap.h + * (which is unfortunately named). May sometimes need replacement, e.g. + * some compilers don't handle zero length or NULL correctly in realloc(). + */ +#if !defined(DUK_ANSI_MALLOC) +#define DUK_ANSI_MALLOC malloc +#endif +#if !defined(DUK_ANSI_REALLOC) +#define DUK_ANSI_REALLOC realloc +#endif +#if !defined(DUK_ANSI_CALLOC) +#define DUK_ANSI_CALLOC calloc +#endif +#if !defined(DUK_ANSI_FREE) +#define DUK_ANSI_FREE free +#endif + +/* ANSI C (various versions) and some implementations require that the + * pointer arguments to memset(), memcpy(), and memmove() be valid values + * even when byte size is 0 (even a NULL pointer is considered invalid in + * this context). Zero-size operations as such are allowed, as long as their + * pointer arguments point to a valid memory area. The DUK_MEMSET(), + * DUK_MEMCPY(), and DUK_MEMMOVE() macros require this same behavior, i.e.: + * (1) pointers must be valid and non-NULL, (2) zero size must otherwise be + * allowed. If these are not fulfilled, a macro wrapper is needed. + * + * http://stackoverflow.com/questions/5243012/is-it-guaranteed-to-be-safe-to-perform-memcpy0-0-0 + * http://lists.cs.uiuc.edu/pipermail/llvmdev/2007-October/011065.html + * + * Not sure what's the required behavior when a pointer points just past the + * end of a buffer, which often happens in practice (e.g. zero size memmoves). + * For example, if allocation size is 3, the following pointer would not + * technically point to a valid memory byte: + * + * <-- alloc --> + * | 0 | 1 | 2 | ..... + * ^-- p=3, points after last valid byte (2) + */ +#if !defined(DUK_MEMCPY) +#if defined(DUK_F_UCLIBC) +/* Old uclibcs have a broken memcpy so use memmove instead (this is overly wide + * now on purpose): http://lists.uclibc.org/pipermail/uclibc-cvs/2008-October/025511.html + */ +#define DUK_MEMCPY memmove +#else +#define DUK_MEMCPY memcpy +#endif +#endif +#if !defined(DUK_MEMMOVE) +#define DUK_MEMMOVE memmove +#endif +#if !defined(DUK_MEMCMP) +#define DUK_MEMCMP memcmp +#endif +#if !defined(DUK_MEMSET) +#define DUK_MEMSET memset +#endif +#if !defined(DUK_STRLEN) +#define DUK_STRLEN strlen +#endif +#if !defined(DUK_STRCMP) +#define DUK_STRCMP strcmp +#endif +#if !defined(DUK_STRNCMP) +#define DUK_STRNCMP strncmp +#endif +#if !defined(DUK_SPRINTF) +#define DUK_SPRINTF sprintf +#endif +#if !defined(DUK_SNPRINTF) +/* snprintf() is technically not part of C89 but usually available. */ +#define DUK_SNPRINTF snprintf +#endif +#if !defined(DUK_VSPRINTF) +#define DUK_VSPRINTF vsprintf +#endif +#if !defined(DUK_VSNPRINTF) +/* vsnprintf() is technically not part of C89 but usually available. */ +#define DUK_VSNPRINTF vsnprintf +#endif +#if !defined(DUK_SSCANF) +#define DUK_SSCANF sscanf +#endif +#if !defined(DUK_VSSCANF) +#define DUK_VSSCANF vsscanf +#endif +#if !defined(DUK_MEMZERO) +#define DUK_MEMZERO(p,n) DUK_MEMSET((p), 0, (n)) +#endif + +#if !defined(DUK_DOUBLE_INFINITY) +#undef DUK_USE_COMPUTED_INFINITY +#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION < 40600) +/* GCC older than 4.6: avoid overflow warnings related to using INFINITY */ +#define DUK_DOUBLE_INFINITY (__builtin_inf()) +#elif defined(INFINITY) +#define DUK_DOUBLE_INFINITY ((double) INFINITY) +#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC) && \ + !defined(DUK_F_OLD_SOLARIS) && !defined(DUK_F_AIX) +#define DUK_DOUBLE_INFINITY (1.0 / 0.0) +#else +/* In VBCC (1.0 / 0.0) results in a warning and 0.0 instead of infinity. + * Use a computed infinity (initialized when a heap is created at the + * latest). + */ +#define DUK_USE_COMPUTED_INFINITY +#define DUK_DOUBLE_INFINITY duk_computed_infinity +#endif +#endif + +#if !defined(DUK_DOUBLE_NAN) +#undef DUK_USE_COMPUTED_NAN +#if defined(NAN) +#define DUK_DOUBLE_NAN NAN +#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC) && \ + !defined(DUK_F_OLD_SOLARIS) && !defined(DUK_F_AIX) +#define DUK_DOUBLE_NAN (0.0 / 0.0) +#else +/* In VBCC (0.0 / 0.0) results in a warning and 0.0 instead of NaN. + * In MSVC (VS2010 Express) (0.0 / 0.0) results in a compile error. + * Use a computed NaN (initialized when a heap is created at the + * latest). + */ +#define DUK_USE_COMPUTED_NAN +#define DUK_DOUBLE_NAN duk_computed_nan +#endif +#endif + +/* Many platforms are missing fpclassify() and friends, so use replacements + * if necessary. The replacement constants (FP_NAN etc) can be anything but + * match Linux constants now. + */ +#undef DUK_USE_REPL_FPCLASSIFY +#undef DUK_USE_REPL_SIGNBIT +#undef DUK_USE_REPL_ISFINITE +#undef DUK_USE_REPL_ISNAN +#undef DUK_USE_REPL_ISINF + +/* Complex condition broken into separate parts. */ +#undef DUK_F_USE_REPL_ALL +#if !(defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO) && \ + defined(FP_SUBNORMAL) && defined(FP_NORMAL)) +/* Missing some obvious constants. */ +#define DUK_F_USE_REPL_ALL +#elif defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC) +/* VBCC is missing the built-ins even in C99 mode (perhaps a header issue). */ +#define DUK_F_USE_REPL_ALL +#elif defined(DUK_F_AMIGAOS) && defined(DUK_F_M68K) +/* AmigaOS + M68K seems to have math issues even when using GCC cross + * compilation. Use replacements for all AmigaOS versions on M68K + * regardless of compiler. + */ +#define DUK_F_USE_REPL_ALL +#elif defined(DUK_F_FREEBSD) && defined(DUK_F_CLANG) +/* Placeholder fix for (detection is wider than necessary): + * http://llvm.org/bugs/show_bug.cgi?id=17788 + */ +#define DUK_F_USE_REPL_ALL +#elif defined(DUK_F_UCLIBC) +/* At least some uclibc versions have broken floating point math. For + * example, fpclassify() can incorrectly classify certain NaN formats. + * To be safe, use replacements. + */ +#define DUK_F_USE_REPL_ALL +#elif defined(DUK_F_AIX) +/* Older versions may be missing isnan(), etc. */ +#define DUK_F_USE_REPL_ALL +#endif + +#if defined(DUK_F_USE_REPL_ALL) +#define DUK_USE_REPL_FPCLASSIFY +#define DUK_USE_REPL_SIGNBIT +#define DUK_USE_REPL_ISFINITE +#define DUK_USE_REPL_ISNAN +#define DUK_USE_REPL_ISINF +#define DUK_FPCLASSIFY duk_repl_fpclassify +#define DUK_SIGNBIT duk_repl_signbit +#define DUK_ISFINITE duk_repl_isfinite +#define DUK_ISNAN duk_repl_isnan +#define DUK_ISINF duk_repl_isinf +#define DUK_FP_NAN 0 +#define DUK_FP_INFINITE 1 +#define DUK_FP_ZERO 2 +#define DUK_FP_SUBNORMAL 3 +#define DUK_FP_NORMAL 4 +#else +#define DUK_FPCLASSIFY fpclassify +#define DUK_SIGNBIT signbit +#define DUK_ISFINITE isfinite +#define DUK_ISNAN isnan +#define DUK_ISINF isinf +#define DUK_FP_NAN FP_NAN +#define DUK_FP_INFINITE FP_INFINITE +#define DUK_FP_ZERO FP_ZERO +#define DUK_FP_SUBNORMAL FP_SUBNORMAL +#define DUK_FP_NORMAL FP_NORMAL +#endif + +#if defined(DUK_F_USE_REPL_ALL) +#undef DUK_F_USE_REPL_ALL +#endif + +/* These functions don't currently need replacement but are wrapped for + * completeness. Because these are used as function pointers, they need + * to be defined as concrete C functions (not macros). + */ +#if !defined(DUK_FABS) +#define DUK_FABS fabs +#endif +#if !defined(DUK_FLOOR) +#define DUK_FLOOR floor +#endif +#if !defined(DUK_CEIL) +#define DUK_CEIL ceil +#endif +#if !defined(DUK_FMOD) +#define DUK_FMOD fmod +#endif +#if !defined(DUK_POW) +#define DUK_POW pow +#endif +#if !defined(DUK_ACOS) +#define DUK_ACOS acos +#endif +#if !defined(DUK_ASIN) +#define DUK_ASIN asin +#endif +#if !defined(DUK_ATAN) +#define DUK_ATAN atan +#endif +#if !defined(DUK_ATAN2) +#define DUK_ATAN2 atan2 +#endif +#if !defined(DUK_SIN) +#define DUK_SIN sin +#endif +#if !defined(DUK_COS) +#define DUK_COS cos +#endif +#if !defined(DUK_TAN) +#define DUK_TAN tan +#endif +#if !defined(DUK_EXP) +#define DUK_EXP exp +#endif +#if !defined(DUK_LOG) +#define DUK_LOG log +#endif +#if !defined(DUK_SQRT) +#define DUK_SQRT sqrt +#endif + +/* The functions below exist only in C99/C++11 or later and need a workaround + * for platforms that don't include them. MSVC isn't detected as C99, but + * these functions also exist in MSVC 2013 and later so include a clause for + * that too. Android doesn't have log2; disable all of these for Android. + */ +#if (defined(DUK_F_C99) || defined(DUK_F_CPP11) || (defined(_MSC_VER) && (_MSC_VER >= 1800))) && \ + !defined(DUK_F_ANDROID) && !defined(DUK_F_MINT) +#if !defined(DUK_CBRT) +#define DUK_CBRT cbrt +#endif +#if !defined(DUK_LOG2) +#define DUK_LOG2 log2 +#endif +#if !defined(DUK_LOG10) +#define DUK_LOG10 log10 +#endif +#if !defined(DUK_TRUNC) +#define DUK_TRUNC trunc +#endif +#endif /* DUK_F_C99 etc */ + +/* NetBSD 6.0 x86 (at least) has a few problems with pow() semantics, + * see test-bug-netbsd-math-pow.js. MinGW has similar (but different) + * issues, see test-bug-mingw-math-issues.js. Enable pow() workarounds + * for these targets. + */ +#undef DUK_USE_POW_WORKAROUNDS +#if defined(DUK_F_NETBSD) || defined(DUK_F_MINGW) +#define DUK_USE_POW_WORKAROUNDS +#endif + +/* Similar workarounds for atan2() semantics issues. MinGW issues are + * documented in test-bug-mingw-math-issues.js. + */ +#undef DUK_USE_ATAN2_WORKAROUNDS +#if defined(DUK_F_MINGW) +#define DUK_USE_ATAN2_WORKAROUNDS +#endif + +/* Rely as little as possible on compiler behavior for NaN comparison, + * signed zero handling, etc. Currently never activated but may be needed + * for broken compilers. + */ +#undef DUK_USE_PARANOID_MATH + +/* There was a curious bug where test-bi-date-canceling.js would fail e.g. + * on 64-bit Ubuntu, gcc-4.8.1, -m32, and no -std=c99. Some date computations + * using doubles would be optimized which then broke some corner case tests. + * The problem goes away by adding 'volatile' to the datetime computations. + * Not sure what the actual triggering conditions are, but using this on + * non-C99 systems solves the known issues and has relatively little cost + * on other platforms. + */ +#undef DUK_USE_PARANOID_DATE_COMPUTATION +#if !defined(DUK_F_C99) +#define DUK_USE_PARANOID_DATE_COMPUTATION +#endif + +/* + * Byte order and double memory layout detection + * + * Endianness detection is a major portability hassle because the macros + * and headers are not standardized. There's even variance across UNIX + * platforms. Even with "standard" headers, details like underscore count + * varies between platforms, e.g. both __BYTE_ORDER and _BYTE_ORDER are used + * (Crossbridge has a single underscore, for instance). + * + * The checks below are structured with this in mind: several approaches are + * used, and at the end we check if any of them worked. This allows generic + * approaches to be tried first, and platform/compiler specific hacks tried + * last. As a last resort, the user can force a specific endianness, as it's + * not likely that automatic detection will work on the most exotic platforms. + * + * Duktape supports little and big endian machines. There's also support + * for a hybrid used by some ARM machines where integers are little endian + * but IEEE double values use a mixed order (12345678 -> 43218765). This + * byte order for doubles is referred to as "mixed endian". + */ + +/* GCC and Clang provide endianness defines as built-in predefines, with + * leading and trailing double underscores (e.g. __BYTE_ORDER__). See + * output of "make gccpredefs" and "make clangpredefs". Clang doesn't + * seem to provide __FLOAT_WORD_ORDER__; assume not mixed endian for clang. + * http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html + */ +#if !defined(DUK_USE_BYTEORDER) && defined(__BYTE_ORDER__) +#if defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#define DUK_USE_BYTEORDER 1 +#elif defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__) +#define DUK_USE_BYTEORDER 2 +#elif !defined(__FLOAT_WORD_ORDER__) +/* Float word order not known, assume not a hybrid. */ +#define DUK_USE_BYTEORDER 1 +#else +/* Byte order is little endian but cannot determine IEEE double word order. */ +#endif /* float word order */ +#elif defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__) +#define DUK_USE_BYTEORDER 3 +#elif !defined(__FLOAT_WORD_ORDER__) +/* Float word order not known, assume not a hybrid. */ +#define DUK_USE_BYTEORDER 3 +#else +/* Byte order is big endian but cannot determine IEEE double word order. */ +#endif /* float word order */ +#else +/* Cannot determine byte order; __ORDER_PDP_ENDIAN__ is related to 32-bit + * integer ordering and is not relevant. + */ +#endif /* integer byte order */ +#endif /* !defined(DUK_USE_BYTEORDER) && defined(__BYTE_ORDER__) */ + +/* More or less standard endianness predefines provided by header files. + * The ARM hybrid case is detected by assuming that __FLOAT_WORD_ORDER + * will be big endian, see: http://lists.mysql.com/internals/443. + * On some platforms some defines may be present with an empty value which + * causes comparisons to fail: https://github.com/svaarala/duktape/issues/453. + */ +#if !defined(DUK_USE_BYTEORDER) +#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) || \ + defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && (_BYTE_ORDER == _LITTLE_ENDIAN) || \ + defined(__LITTLE_ENDIAN__) +#if defined(__FLOAT_WORD_ORDER) && defined(__LITTLE_ENDIAN) && (__FLOAT_WORD_ORDER == __LITTLE_ENDIAN) || \ + defined(_FLOAT_WORD_ORDER) && defined(_LITTLE_ENDIAN) && (_FLOAT_WORD_ORDER == _LITTLE_ENDIAN) +#define DUK_USE_BYTEORDER 1 +#elif defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \ + defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN) +#define DUK_USE_BYTEORDER 2 +#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER) +/* Float word order not known, assume not a hybrid. */ +#define DUK_USE_BYTEORDER 1 +#else +/* Byte order is little endian but cannot determine IEEE double word order. */ +#endif /* float word order */ +#elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) || \ + defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && (_BYTE_ORDER == _BIG_ENDIAN) || \ + defined(__BIG_ENDIAN__) +#if defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \ + defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN) +#define DUK_USE_BYTEORDER 3 +#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER) +/* Float word order not known, assume not a hybrid. */ +#define DUK_USE_BYTEORDER 3 +#else +/* Byte order is big endian but cannot determine IEEE double word order. */ +#endif /* float word order */ +#else +/* Cannot determine byte order. */ +#endif /* integer byte order */ +#endif /* !defined(DUK_USE_BYTEORDER) */ + +/* QNX gcc cross compiler seems to define e.g. __LITTLEENDIAN__ or __BIGENDIAN__: + * $ /opt/qnx650/host/linux/x86/usr/bin/i486-pc-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian + * 67:#define __LITTLEENDIAN__ 1 + * $ /opt/qnx650/host/linux/x86/usr/bin/mips-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian + * 81:#define __BIGENDIAN__ 1 + * $ /opt/qnx650/host/linux/x86/usr/bin/arm-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian + * 70:#define __LITTLEENDIAN__ 1 + */ +#if !defined(DUK_USE_BYTEORDER) +#if defined(__LITTLEENDIAN__) +#define DUK_USE_BYTEORDER 1 +#elif defined(__BIGENDIAN__) +#define DUK_USE_BYTEORDER 3 +#endif +#endif + +/* + * Alignment requirement and support for unaligned accesses + * + * Assume unaligned accesses are not supported unless specifically allowed + * in the target platform. Some platforms may support unaligned accesses + * but alignment to 4 or 8 may still be desirable. + */ + +/* If not provided, use safe default for alignment. */ +#if !defined(DUK_USE_ALIGN_BY) +#define DUK_USE_ALIGN_BY 8 +#endif + +/* Compiler specific hackery needed to force struct size to match aligment, + * see e.g. duk_hbuffer.h. + * + * http://stackoverflow.com/questions/11130109/c-struct-size-alignment + * http://stackoverflow.com/questions/10951039/specifying-64-bit-alignment + */ +#if !(defined(DUK_USE_PACK_MSVC_PRAGMA) || defined(DUK_USE_PACK_GCC_ATTR) || \ + defined(DUK_USE_PACK_CLANG_ATTR) || defined(DUK_USE_PACK_DUMMY_MEMBER)) +#define DUK_USE_PACK_DUMMY_MEMBER +#endif + +#if !defined(DUK_VA_COPY) +/* We need va_copy() which is defined in C99 / C++11, so an awkward + * replacement is needed for pre-C99 / pre-C++11 environments. This + * will quite likely need portability hacks for some non-C99 + * environments. + */ +#if defined(DUK_F_C99) || defined(DUK_F_CPP11) +/* C99 / C++11 and above: rely on va_copy() which is required. + * Omit parenthesis on macro right side on purpose to minimize differences + * to direct use. + */ +#define DUK_VA_COPY(dest,src) va_copy(dest,src) +#else +/* Pre-C99: va_list type is implementation dependent. This replacement + * assumes it is a plain value so that a simple assignment will work. + * This is not the case on all platforms (it may be a single-array element, + * for instance). + */ +#define DUK_VA_COPY(dest,src) do { (dest) = (src); } while (0) +#endif +#endif + +#if !defined(DUK_MACRO_STRINGIFY) +/* Macro hackery to convert e.g. __LINE__ to a string without formatting, + * see: http://stackoverflow.com/questions/240353/convert-a-preprocessor-token-to-a-string + */ +#define DUK_MACRO_STRINGIFY_HELPER(x) #x +#define DUK_MACRO_STRINGIFY(x) DUK_MACRO_STRINGIFY_HELPER(x) +#endif + +#if !defined(DUK_CAUSE_SEGFAULT) +/* This can be used for testing; valgrind will then indicate the C call stack + * leading to the call site. + */ +#define DUK_CAUSE_SEGFAULT() do { *((volatile duk_uint32_t *) NULL) = (duk_uint32_t) 0xdeadbeefUL; } while (0) +#endif +#if !defined(DUK_UNREF) +/* Macro for suppressing warnings for potentially unreferenced variables. + * The variables can be actually unreferenced or unreferenced in some + * specific cases only; for instance, if a variable is only debug printed, + * it is unreferenced when debug printing is disabled. May cause warnings + * for volatile arguments. + */ +#define DUK_UNREF(x) do { (void) (x); } while (0) +#endif +#if !defined(DUK_NORETURN) +#define DUK_NORETURN(decl) decl +#endif +#if !defined(DUK_UNREACHABLE) +/* Don't know how to declare unreachable point, so don't do it; this + * may cause some spurious compilation warnings (e.g. "variable used + * uninitialized"). + */ +#define DUK_UNREACHABLE() do { } while (0) +#endif +#if !defined(DUK_LOSE_CONST) +/* Convert any input pointer into a "void *", losing a const qualifier. + * This is not fully portable because casting through duk_uintptr_t may + * not work on all architectures (e.g. those with long, segmented pointers). + */ +#define DUK_LOSE_CONST(src) ((void *) (duk_uintptr_t) (src)) +#endif + +#if !defined(DUK_LIKELY) +#define DUK_LIKELY(x) (x) +#endif +#if !defined(DUK_UNLIKELY) +#define DUK_UNLIKELY(x) (x) +#endif +#if !defined(DUK_UNPREDICTABLE) +#define DUK_UNPREDICTABLE(x) (x) +#endif + +#if !defined(DUK_NOINLINE) +#define DUK_NOINLINE /*nop*/ +#endif +#if !defined(DUK_INLINE) +#define DUK_INLINE /*nop*/ +#endif +#if !defined(DUK_ALWAYS_INLINE) +#define DUK_ALWAYS_INLINE /*nop*/ +#endif + +#if !defined(DUK_HOT) +#define DUK_HOT /*nop*/ +#endif +#if !defined(DUK_COLD) +#define DUK_COLD /*nop*/ +#endif + +#if !defined(DUK_EXTERNAL_DECL) +#define DUK_EXTERNAL_DECL extern +#endif +#if !defined(DUK_EXTERNAL) +#define DUK_EXTERNAL /*empty*/ +#endif +#if !defined(DUK_INTERNAL_DECL) +#if defined(DUK_SINGLE_FILE) +#define DUK_INTERNAL_DECL static +#else +#define DUK_INTERNAL_DECL extern +#endif +#endif +#if !defined(DUK_INTERNAL) +#if defined(DUK_SINGLE_FILE) +#define DUK_INTERNAL static +#else +#define DUK_INTERNAL /*empty*/ +#endif +#endif +#if !defined(DUK_LOCAL_DECL) +#define DUK_LOCAL_DECL static +#endif +#if !defined(DUK_LOCAL) +#define DUK_LOCAL static +#endif + +#if !defined(DUK_FILE_MACRO) +#define DUK_FILE_MACRO __FILE__ +#endif +#if !defined(DUK_LINE_MACRO) +#define DUK_LINE_MACRO __LINE__ +#endif +#if !defined(DUK_FUNC_MACRO) +#if defined(DUK_F_C99) || defined(DUK_F_CPP11) +#define DUK_FUNC_MACRO __func__ +#elif defined(__FUNCTION__) +#define DUK_FUNC_MACRO __FUNCTION__ +#else +#define DUK_FUNC_MACRO "unknown" +#endif +#endif + +#if !defined(DUK_BSWAP32) +#define DUK_BSWAP32(x) \ + ((((duk_uint32_t) (x)) >> 24) | \ + ((((duk_uint32_t) (x)) >> 8) & 0xff00UL) | \ + ((((duk_uint32_t) (x)) << 8) & 0xff0000UL) | \ + (((duk_uint32_t) (x)) << 24)) +#endif +#if !defined(DUK_BSWAP16) +#define DUK_BSWAP16(x) \ + ((duk_uint16_t) (x) >> 8) | \ + ((duk_uint16_t) (x) << 8) +#endif + +/* DUK_USE_VARIADIC_MACROS: required from compilers, so no fill-in. */ +/* DUK_USE_UNION_INITIALIZERS: required from compilers, so no fill-in. */ + +#if !(defined(DUK_USE_FLEX_C99) || defined(DUK_USE_FLEX_ZEROSIZE) || defined(DUK_USE_FLEX_ONESIZE)) +#if defined(DUK_F_C99) +#define DUK_USE_FLEX_C99 +#else +#define DUK_USE_FLEX_ZEROSIZE /* Not standard but common enough */ +#endif +#endif + +#if !(defined(DUK_USE_PACK_GCC_ATTR) || defined(DUK_USE_PACK_CLANG_ATTR) || \ + defined(DUK_USE_PACK_MSVC_PRAGMA) || defined(DUK_USE_PACK_DUMMY_MEMBER)) +#define DUK_USE_PACK_DUMMY_MEMBER +#endif + +#if 0 /* not defined by default */ +#undef DUK_USE_GCC_PRAGMAS +#endif + +#if !defined(DUK_U64_CONSTANT) +#define DUK_U64_CONSTANT(x) x##ULL +#endif +#if !defined(DUK_I64_CONSTANT) +#define DUK_I64_CONSTANT(x) x##LL +#endif + +/* Workaround for GH-323: avoid inlining control when compiling from + * multiple sources, as it causes compiler portability trouble. + */ +#if !defined(DUK_SINGLE_FILE) +#undef DUK_NOINLINE +#undef DUK_INLINE +#undef DUK_ALWAYS_INLINE +#define DUK_NOINLINE /*nop*/ +#define DUK_INLINE /*nop*/ +#define DUK_ALWAYS_INLINE /*nop*/ +#endif + +/* + * Check whether or not a packed duk_tval representation is possible. + * What's basically required is that pointers are 32-bit values + * (sizeof(void *) == 4). Best effort check, not always accurate. + * If guess goes wrong, crashes may result; self tests also verify + * the guess. + */ + +/* Explicit marker needed; may be 'defined', 'undefined, 'or 'not provided'. */ +#if !defined(DUK_F_PACKED_TVAL_PROVIDED) +#undef DUK_F_PACKED_TVAL_POSSIBLE + +/* Strict C99 case: DUK_UINTPTR_MAX (= UINTPTR_MAX) should be very reliable */ +#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_UINTPTR_MAX) +#if (DUK_UINTPTR_MAX <= 0xffffffffUL) +#define DUK_F_PACKED_TVAL_POSSIBLE +#endif +#endif + +/* Non-C99 case, still relying on DUK_UINTPTR_MAX, as long as it is not a computed value */ +#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_UINTPTR_MAX) && !defined(DUK_UINTPTR_MAX_COMPUTED) +#if (DUK_UINTPTR_MAX <= 0xffffffffUL) +#define DUK_F_PACKED_TVAL_POSSIBLE +#endif +#endif + +/* DUK_SIZE_MAX (= SIZE_MAX) is often reliable */ +#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_SIZE_MAX) && !defined(DUK_SIZE_MAX_COMPUTED) +#if (DUK_SIZE_MAX <= 0xffffffffUL) +#define DUK_F_PACKED_TVAL_POSSIBLE +#endif +#endif + +#undef DUK_USE_PACKED_TVAL +#if defined(DUK_F_PACKED_TVAL_POSSIBLE) +#define DUK_USE_PACKED_TVAL +#endif + +#undef DUK_F_PACKED_TVAL_POSSIBLE +#endif /* DUK_F_PACKED_TVAL_PROVIDED */ +/* Object property allocation layout has implications for memory and code + * footprint and generated code size/speed. The best layout also depends + * on whether the platform has alignment requirements or benefits from + * having mostly aligned accesses. + */ +#undef DUK_USE_HOBJECT_LAYOUT_1 +#undef DUK_USE_HOBJECT_LAYOUT_2 +#undef DUK_USE_HOBJECT_LAYOUT_3 +#if (DUK_USE_ALIGN_BY == 1) +/* On platforms without any alignment issues, layout 1 is preferable + * because it compiles to slightly less code and provides direct access + * to property keys. + */ +#define DUK_USE_HOBJECT_LAYOUT_1 +#else +/* On other platforms use layout 2, which requires some padding but + * is a bit more natural than layout 3 in ordering the entries. Layout + * 3 is currently not used. + */ +#define DUK_USE_HOBJECT_LAYOUT_2 +#endif + +/* GCC/clang inaccurate math would break compliance and probably duk_tval, + * so refuse to compile. Relax this if -ffast-math is tested to work. + */ +#if defined(__FAST_MATH__) +#error __FAST_MATH__ defined, refusing to compile +#endif + +/* + * Autogenerated defaults + */ + +#define DUK_USE_ARRAY_BUILTIN +#define DUK_USE_ARRAY_FASTPATH +#define DUK_USE_ARRAY_PROP_FASTPATH +#undef DUK_USE_ASSERTIONS +#define DUK_USE_AUGMENT_ERROR_CREATE +#define DUK_USE_AUGMENT_ERROR_THROW +#define DUK_USE_AVOID_PLATFORM_FUNCPTRS +#define DUK_USE_BASE64_FASTPATH +#define DUK_USE_BOOLEAN_BUILTIN +#define DUK_USE_BUFFEROBJECT_SUPPORT +#undef DUK_USE_BUFLEN16 +#define DUK_USE_BYTECODE_DUMP_SUPPORT +#define DUK_USE_CACHE_ACTIVATION +#define DUK_USE_CACHE_CATCHER +#define DUK_USE_CALLSTACK_LIMIT 10000 +#define DUK_USE_COMMONJS_MODULES +#define DUK_USE_COMPILER_RECLIMIT 2500 +#define DUK_USE_COROUTINE_SUPPORT +#undef DUK_USE_CPP_EXCEPTIONS +#undef DUK_USE_DATAPTR16 +#undef DUK_USE_DATAPTR_DEC16 +#undef DUK_USE_DATAPTR_ENC16 +#define DUK_USE_DATE_BUILTIN +#undef DUK_USE_DATE_FORMAT_STRING +#undef DUK_USE_DATE_GET_LOCAL_TZOFFSET +#undef DUK_USE_DATE_GET_NOW +#undef DUK_USE_DATE_PARSE_STRING +#undef DUK_USE_DATE_PRS_GETDATE +#undef DUK_USE_DEBUG +#undef DUK_USE_DEBUGGER_DUMPHEAP +#undef DUK_USE_DEBUGGER_INSPECT +#undef DUK_USE_DEBUGGER_PAUSE_UNCAUGHT +#undef DUK_USE_DEBUGGER_SUPPORT +#define DUK_USE_DEBUGGER_THROW_NOTIFY +#undef DUK_USE_DEBUGGER_TRANSPORT_TORTURE +#define DUK_USE_DEBUG_BUFSIZE 65536L +#define DUK_USE_DEBUG_LEVEL 0 +#undef DUK_USE_DEBUG_WRITE +#define DUK_USE_DOUBLE_LINKED_HEAP +#define DUK_USE_DUKTAPE_BUILTIN +#define DUK_USE_ENCODING_BUILTINS +#define DUK_USE_ERRCREATE +#define DUK_USE_ERRTHROW +#define DUK_USE_ES6 +#define DUK_USE_ES6_OBJECT_PROTO_PROPERTY +#define DUK_USE_ES6_OBJECT_SETPROTOTYPEOF +#define DUK_USE_ES6_PROXY +#define DUK_USE_ES6_REGEXP_SYNTAX +#define DUK_USE_ES6_UNICODE_ESCAPE +#define DUK_USE_ES7 +#define DUK_USE_ES7_EXP_OPERATOR +#define DUK_USE_ES8 +#define DUK_USE_ES9 +#define DUK_USE_ESBC_LIMITS +#define DUK_USE_ESBC_MAX_BYTES 2147418112L +#define DUK_USE_ESBC_MAX_LINENUMBER 2147418112L +#undef DUK_USE_EXEC_FUN_LOCAL +#undef DUK_USE_EXEC_INDIRECT_BOUND_CHECK +#undef DUK_USE_EXEC_PREFER_SIZE +#define DUK_USE_EXEC_REGCONST_OPTIMIZE +#undef DUK_USE_EXEC_TIMEOUT_CHECK +#undef DUK_USE_EXPLICIT_NULL_INIT +#undef DUK_USE_EXTSTR_FREE +#undef DUK_USE_EXTSTR_INTERN_CHECK +#undef DUK_USE_FASTINT +#define DUK_USE_FAST_REFCOUNT_DEFAULT +#undef DUK_USE_FATAL_HANDLER +#define DUK_USE_FATAL_MAXLEN 128 +#define DUK_USE_FINALIZER_SUPPORT +#undef DUK_USE_FINALIZER_TORTURE +#undef DUK_USE_FUNCPTR16 +#undef DUK_USE_FUNCPTR_DEC16 +#undef DUK_USE_FUNCPTR_ENC16 +#define DUK_USE_FUNCTION_BUILTIN +#define DUK_USE_FUNC_FILENAME_PROPERTY +#define DUK_USE_FUNC_NAME_PROPERTY +#undef DUK_USE_GC_TORTURE +#undef DUK_USE_GET_MONOTONIC_TIME +#undef DUK_USE_GET_RANDOM_DOUBLE +#undef DUK_USE_GLOBAL_BINDING +#define DUK_USE_GLOBAL_BUILTIN +#undef DUK_USE_HEAPPTR16 +#undef DUK_USE_HEAPPTR_DEC16 +#undef DUK_USE_HEAPPTR_ENC16 +#define DUK_USE_HEX_FASTPATH +#define DUK_USE_HOBJECT_ARRAY_ABANDON_LIMIT 2 +#define DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT 9 +#define DUK_USE_HOBJECT_ARRAY_MINGROW_ADD 16 +#define DUK_USE_HOBJECT_ARRAY_MINGROW_DIVISOR 8 +#define DUK_USE_HOBJECT_ENTRY_MINGROW_ADD 16 +#define DUK_USE_HOBJECT_ENTRY_MINGROW_DIVISOR 8 +#define DUK_USE_HOBJECT_HASH_PART +#define DUK_USE_HOBJECT_HASH_PROP_LIMIT 8 +#define DUK_USE_HSTRING_ARRIDX +#define DUK_USE_HSTRING_CLEN +#undef DUK_USE_HSTRING_EXTDATA +#define DUK_USE_HSTRING_LAZY_CLEN +#define DUK_USE_HTML_COMMENTS +#define DUK_USE_IDCHAR_FASTPATH +#undef DUK_USE_INJECT_HEAP_ALLOC_ERROR +#undef DUK_USE_INTERRUPT_COUNTER +#undef DUK_USE_INTERRUPT_DEBUG_FIXUP +#define DUK_USE_JC +#define DUK_USE_JSON_BUILTIN +#define DUK_USE_JSON_DECNUMBER_FASTPATH +#define DUK_USE_JSON_DECSTRING_FASTPATH +#define DUK_USE_JSON_DEC_RECLIMIT 1000 +#define DUK_USE_JSON_EATWHITE_FASTPATH +#define DUK_USE_JSON_ENC_RECLIMIT 1000 +#define DUK_USE_JSON_QUOTESTRING_FASTPATH +#undef DUK_USE_JSON_STRINGIFY_FASTPATH +#define DUK_USE_JSON_SUPPORT +#define DUK_USE_JX +#define DUK_USE_LEXER_SLIDING_WINDOW +#undef DUK_USE_LIGHTFUNC_BUILTINS +#define DUK_USE_MARK_AND_SWEEP_RECLIMIT 256 +#define DUK_USE_MATH_BUILTIN +#define DUK_USE_NATIVE_CALL_RECLIMIT 1000 +#define DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER +#define DUK_USE_NONSTD_ARRAY_MAP_TRAILER +#define DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT +#undef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY +#undef DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY +#define DUK_USE_NONSTD_FUNC_STMT +#define DUK_USE_NONSTD_GETTER_KEY_ARGUMENT +#define DUK_USE_NONSTD_JSON_ESC_U2028_U2029 +#define DUK_USE_NONSTD_SETTER_KEY_ARGUMENT +#define DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT +#define DUK_USE_NUMBER_BUILTIN +#define DUK_USE_OBJECT_BUILTIN +#undef DUK_USE_OBJSIZES16 +#undef DUK_USE_PARANOID_ERRORS +#define DUK_USE_PC2LINE +#define DUK_USE_PERFORMANCE_BUILTIN +#undef DUK_USE_PREFER_SIZE +#undef DUK_USE_PROMISE_BUILTIN +#define DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS +#undef DUK_USE_REFCOUNT16 +#define DUK_USE_REFCOUNT32 +#define DUK_USE_REFERENCE_COUNTING +#define DUK_USE_REFLECT_BUILTIN +#define DUK_USE_REGEXP_CANON_BITMAP +#undef DUK_USE_REGEXP_CANON_WORKAROUND +#define DUK_USE_REGEXP_COMPILER_RECLIMIT 10000 +#define DUK_USE_REGEXP_EXECUTOR_RECLIMIT 10000 +#define DUK_USE_REGEXP_SUPPORT +#undef DUK_USE_ROM_GLOBAL_CLONE +#undef DUK_USE_ROM_GLOBAL_INHERIT +#undef DUK_USE_ROM_OBJECTS +#define DUK_USE_ROM_PTRCOMP_FIRST 63488L +#undef DUK_USE_ROM_STRINGS +#define DUK_USE_SECTION_B +#undef DUK_USE_SELF_TESTS +#define DUK_USE_SHEBANG_COMMENTS +#undef DUK_USE_SHUFFLE_TORTURE +#define DUK_USE_SOURCE_NONBMP +#undef DUK_USE_STRHASH16 +#undef DUK_USE_STRHASH_DENSE +#define DUK_USE_STRHASH_SKIP_SHIFT 5 +#define DUK_USE_STRICT_DECL +#undef DUK_USE_STRICT_UTF8_SOURCE +#define DUK_USE_STRING_BUILTIN +#undef DUK_USE_STRLEN16 +#define DUK_USE_STRTAB_GROW_LIMIT 17 +#define DUK_USE_STRTAB_MAXSIZE 268435456L +#define DUK_USE_STRTAB_MINSIZE 1024 +#undef DUK_USE_STRTAB_PTRCOMP +#define DUK_USE_STRTAB_RESIZE_CHECK_MASK 255 +#define DUK_USE_STRTAB_SHRINK_LIMIT 6 +#undef DUK_USE_STRTAB_TORTURE +#undef DUK_USE_SYMBOL_BUILTIN +#define DUK_USE_TAILCALL +#define DUK_USE_TARGET_INFO "unknown" +#define DUK_USE_TRACEBACKS +#define DUK_USE_TRACEBACK_DEPTH 10 +#define DUK_USE_USER_DECLARE() /* no user declarations */ +#define DUK_USE_VALSTACK_GROW_SHIFT 2 +#define DUK_USE_VALSTACK_LIMIT 1000000L +#define DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT 2 +#define DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT 4 +#undef DUK_USE_VALSTACK_UNSAFE +#define DUK_USE_VERBOSE_ERRORS +#define DUK_USE_VERBOSE_EXECUTOR_ERRORS +#define DUK_USE_VOLUNTARY_GC +#define DUK_USE_ZERO_BUFFER_DATA + +/* + * You may add overriding #define/#undef directives below for + * customization. You of course cannot un-#include or un-typedef + * anything; these require direct changes above. + */ + +/* __OVERRIDE_DEFINES__ */ + +/* + * Date provider selection + * + * User may define DUK_USE_DATE_GET_NOW() etc directly, in which case we'll + * rely on an external provider. If this is not done, revert to previous + * behavior and use Unix/Windows built-in provider. + */ + +#if defined(DUK_COMPILING_DUKTAPE) + +#if defined(DUK_USE_DATE_GET_NOW) +/* External provider already defined. */ +#elif defined(DUK_USE_DATE_NOW_GETTIMEOFDAY) +#define DUK_USE_DATE_GET_NOW(ctx) duk_bi_date_get_now_gettimeofday() +#elif defined(DUK_USE_DATE_NOW_TIME) +#define DUK_USE_DATE_GET_NOW(ctx) duk_bi_date_get_now_time() +#elif defined(DUK_USE_DATE_NOW_WINDOWS) +#define DUK_USE_DATE_GET_NOW(ctx) duk_bi_date_get_now_windows() +#elif defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS) +#define DUK_USE_DATE_GET_NOW(ctx) duk_bi_date_get_now_windows_subms() +#else +#error no provider for DUK_USE_DATE_GET_NOW() +#endif + +#if defined(DUK_USE_DATE_GET_LOCAL_TZOFFSET) +/* External provider already defined. */ +#elif defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S) || defined(DUK_USE_DATE_TZO_GMTIME) +#define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d) duk_bi_date_get_local_tzoffset_gmtime((d)) +#elif defined(DUK_USE_DATE_TZO_WINDOWS) +#define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d) duk_bi_date_get_local_tzoffset_windows((d)) +#elif defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST) +#define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d) duk_bi_date_get_local_tzoffset_windows_no_dst((d)) +#else +#error no provider for DUK_USE_DATE_GET_LOCAL_TZOFFSET() +#endif + +#if defined(DUK_USE_DATE_PARSE_STRING) +/* External provider already defined. */ +#elif defined(DUK_USE_DATE_PRS_STRPTIME) +#define DUK_USE_DATE_PARSE_STRING(ctx,str) duk_bi_date_parse_string_strptime((ctx), (str)) +#elif defined(DUK_USE_DATE_PRS_GETDATE) +#define DUK_USE_DATE_PARSE_STRING(ctx,str) duk_bi_date_parse_string_getdate((ctx), (str)) +#else +/* No provider for DUK_USE_DATE_PARSE_STRING(), fall back to ISO 8601 only. */ +#endif + +#if defined(DUK_USE_DATE_FORMAT_STRING) +/* External provider already defined. */ +#elif defined(DUK_USE_DATE_FMT_STRFTIME) +#define DUK_USE_DATE_FORMAT_STRING(ctx,parts,tzoffset,flags) \ + duk_bi_date_format_parts_strftime((ctx), (parts), (tzoffset), (flags)) +#else +/* No provider for DUK_USE_DATE_FORMAT_STRING(), fall back to ISO 8601 only. */ +#endif + +#if defined(DUK_USE_GET_MONOTONIC_TIME) +/* External provider already defined. */ +#elif defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME) +#define DUK_USE_GET_MONOTONIC_TIME(ctx) duk_bi_date_get_monotonic_time_clock_gettime() +#elif defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC) +#define DUK_USE_GET_MONOTONIC_TIME(ctx) duk_bi_date_get_monotonic_time_windows_qpc() +#else +/* No provider for DUK_USE_GET_MONOTONIC_TIME(), fall back to DUK_USE_DATE_GET_NOW(). */ +#endif + +#endif /* DUK_COMPILING_DUKTAPE */ + +/* + * Checks for legacy feature options (DUK_OPT_xxx) + */ + +#if defined(DUK_OPT_ASSERTIONS) +#error unsupported legacy feature option DUK_OPT_ASSERTIONS used +#endif +#if defined(DUK_OPT_BUFFEROBJECT_SUPPORT) +#error unsupported legacy feature option DUK_OPT_BUFFEROBJECT_SUPPORT used +#endif +#if defined(DUK_OPT_BUFLEN16) +#error unsupported legacy feature option DUK_OPT_BUFLEN16 used +#endif +#if defined(DUK_OPT_DATAPTR16) +#error unsupported legacy feature option DUK_OPT_DATAPTR16 used +#endif +#if defined(DUK_OPT_DATAPTR_DEC16) +#error unsupported legacy feature option DUK_OPT_DATAPTR_DEC16 used +#endif +#if defined(DUK_OPT_DATAPTR_ENC16) +#error unsupported legacy feature option DUK_OPT_DATAPTR_ENC16 used +#endif +#if defined(DUK_OPT_DDDPRINT) +#error unsupported legacy feature option DUK_OPT_DDDPRINT used +#endif +#if defined(DUK_OPT_DDPRINT) +#error unsupported legacy feature option DUK_OPT_DDPRINT used +#endif +#if defined(DUK_OPT_DEBUG) +#error unsupported legacy feature option DUK_OPT_DEBUG used +#endif +#if defined(DUK_OPT_DEBUGGER_DUMPHEAP) +#error unsupported legacy feature option DUK_OPT_DEBUGGER_DUMPHEAP used +#endif +#if defined(DUK_OPT_DEBUGGER_FWD_LOGGING) +#error unsupported legacy feature option DUK_OPT_DEBUGGER_FWD_LOGGING used +#endif +#if defined(DUK_OPT_DEBUGGER_FWD_PRINTALERT) +#error unsupported legacy feature option DUK_OPT_DEBUGGER_FWD_PRINTALERT used +#endif +#if defined(DUK_OPT_DEBUGGER_SUPPORT) +#error unsupported legacy feature option DUK_OPT_DEBUGGER_SUPPORT used +#endif +#if defined(DUK_OPT_DEBUGGER_TRANSPORT_TORTURE) +#error unsupported legacy feature option DUK_OPT_DEBUGGER_TRANSPORT_TORTURE used +#endif +#if defined(DUK_OPT_DEBUG_BUFSIZE) +#error unsupported legacy feature option DUK_OPT_DEBUG_BUFSIZE used +#endif +#if defined(DUK_OPT_DECLARE) +#error unsupported legacy feature option DUK_OPT_DECLARE used +#endif +#if defined(DUK_OPT_DEEP_C_STACK) +#error unsupported legacy feature option DUK_OPT_DEEP_C_STACK used +#endif +#if defined(DUK_OPT_DLL_BUILD) +#error unsupported legacy feature option DUK_OPT_DLL_BUILD used +#endif +#if defined(DUK_OPT_DPRINT) +#error unsupported legacy feature option DUK_OPT_DPRINT used +#endif +#if defined(DUK_OPT_DPRINT_COLORS) +#error unsupported legacy feature option DUK_OPT_DPRINT_COLORS used +#endif +#if defined(DUK_OPT_DPRINT_RDTSC) +#error unsupported legacy feature option DUK_OPT_DPRINT_RDTSC used +#endif +#if defined(DUK_OPT_EXEC_TIMEOUT_CHECK) +#error unsupported legacy feature option DUK_OPT_EXEC_TIMEOUT_CHECK used +#endif +#if defined(DUK_OPT_EXTERNAL_STRINGS) +#error unsupported legacy feature option DUK_OPT_EXTERNAL_STRINGS used +#endif +#if defined(DUK_OPT_EXTSTR_FREE) +#error unsupported legacy feature option DUK_OPT_EXTSTR_FREE used +#endif +#if defined(DUK_OPT_EXTSTR_INTERN_CHECK) +#error unsupported legacy feature option DUK_OPT_EXTSTR_INTERN_CHECK used +#endif +#if defined(DUK_OPT_FASTINT) +#error unsupported legacy feature option DUK_OPT_FASTINT used +#endif +#if defined(DUK_OPT_FORCE_ALIGN) +#error unsupported legacy feature option DUK_OPT_FORCE_ALIGN used +#endif +#if defined(DUK_OPT_FORCE_BYTEORDER) +#error unsupported legacy feature option DUK_OPT_FORCE_BYTEORDER used +#endif +#if defined(DUK_OPT_FUNCPTR16) +#error unsupported legacy feature option DUK_OPT_FUNCPTR16 used +#endif +#if defined(DUK_OPT_FUNCPTR_DEC16) +#error unsupported legacy feature option DUK_OPT_FUNCPTR_DEC16 used +#endif +#if defined(DUK_OPT_FUNCPTR_ENC16) +#error unsupported legacy feature option DUK_OPT_FUNCPTR_ENC16 used +#endif +#if defined(DUK_OPT_FUNC_NONSTD_CALLER_PROPERTY) +#error unsupported legacy feature option DUK_OPT_FUNC_NONSTD_CALLER_PROPERTY used +#endif +#if defined(DUK_OPT_FUNC_NONSTD_SOURCE_PROPERTY) +#error unsupported legacy feature option DUK_OPT_FUNC_NONSTD_SOURCE_PROPERTY used +#endif +#if defined(DUK_OPT_GC_TORTURE) +#error unsupported legacy feature option DUK_OPT_GC_TORTURE used +#endif +#if defined(DUK_OPT_HAVE_CUSTOM_H) +#error unsupported legacy feature option DUK_OPT_HAVE_CUSTOM_H used +#endif +#if defined(DUK_OPT_HEAPPTR16) +#error unsupported legacy feature option DUK_OPT_HEAPPTR16 used +#endif +#if defined(DUK_OPT_HEAPPTR_DEC16) +#error unsupported legacy feature option DUK_OPT_HEAPPTR_DEC16 used +#endif +#if defined(DUK_OPT_HEAPPTR_ENC16) +#error unsupported legacy feature option DUK_OPT_HEAPPTR_ENC16 used +#endif +#if defined(DUK_OPT_INTERRUPT_COUNTER) +#error unsupported legacy feature option DUK_OPT_INTERRUPT_COUNTER used +#endif +#if defined(DUK_OPT_JSON_STRINGIFY_FASTPATH) +#error unsupported legacy feature option DUK_OPT_JSON_STRINGIFY_FASTPATH used +#endif +#if defined(DUK_OPT_LIGHTFUNC_BUILTINS) +#error unsupported legacy feature option DUK_OPT_LIGHTFUNC_BUILTINS used +#endif +#if defined(DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY) +#error unsupported legacy feature option DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY used +#endif +#if defined(DUK_OPT_NONSTD_FUNC_SOURCE_PROPERTY) +#error unsupported legacy feature option DUK_OPT_NONSTD_FUNC_SOURCE_PROPERTY used +#endif +#if defined(DUK_OPT_NO_ARRAY_SPLICE_NONSTD_DELCOUNT) +#error unsupported legacy feature option DUK_OPT_NO_ARRAY_SPLICE_NONSTD_DELCOUNT used +#endif +#if defined(DUK_OPT_NO_AUGMENT_ERRORS) +#error unsupported legacy feature option DUK_OPT_NO_AUGMENT_ERRORS used +#endif +#if defined(DUK_OPT_NO_BROWSER_LIKE) +#error unsupported legacy feature option DUK_OPT_NO_BROWSER_LIKE used +#endif +#if defined(DUK_OPT_NO_BUFFEROBJECT_SUPPORT) +#error unsupported legacy feature option DUK_OPT_NO_BUFFEROBJECT_SUPPORT used +#endif +#if defined(DUK_OPT_NO_BYTECODE_DUMP_SUPPORT) +#error unsupported legacy feature option DUK_OPT_NO_BYTECODE_DUMP_SUPPORT used +#endif +#if defined(DUK_OPT_NO_COMMONJS_MODULES) +#error unsupported legacy feature option DUK_OPT_NO_COMMONJS_MODULES used +#endif +#if defined(DUK_OPT_NO_ES6_OBJECT_PROTO_PROPERTY) +#error unsupported legacy feature option DUK_OPT_NO_ES6_OBJECT_PROTO_PROPERTY used +#endif +#if defined(DUK_OPT_NO_ES6_OBJECT_SETPROTOTYPEOF) +#error unsupported legacy feature option DUK_OPT_NO_ES6_OBJECT_SETPROTOTYPEOF used +#endif +#if defined(DUK_OPT_NO_ES6_PROXY) +#error unsupported legacy feature option DUK_OPT_NO_ES6_PROXY used +#endif +#if defined(DUK_OPT_NO_FILE_IO) +#error unsupported legacy feature option DUK_OPT_NO_FILE_IO used +#endif +#if defined(DUK_OPT_NO_FUNC_STMT) +#error unsupported legacy feature option DUK_OPT_NO_FUNC_STMT used +#endif +#if defined(DUK_OPT_NO_JC) +#error unsupported legacy feature option DUK_OPT_NO_JC used +#endif +#if defined(DUK_OPT_NO_JSONC) +#error unsupported legacy feature option DUK_OPT_NO_JSONC used +#endif +#if defined(DUK_OPT_NO_JSONX) +#error unsupported legacy feature option DUK_OPT_NO_JSONX used +#endif +#if defined(DUK_OPT_NO_JX) +#error unsupported legacy feature option DUK_OPT_NO_JX used +#endif +#if defined(DUK_OPT_NO_MARK_AND_SWEEP) +#error unsupported legacy feature option DUK_OPT_NO_MARK_AND_SWEEP used +#endif +#if defined(DUK_OPT_NO_MS_STRINGTABLE_RESIZE) +#error unsupported legacy feature option DUK_OPT_NO_MS_STRINGTABLE_RESIZE used +#endif +#if defined(DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT) +#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT used +#endif +#if defined(DUK_OPT_NO_NONSTD_ARRAY_CONCAT_TRAILER) +#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ARRAY_CONCAT_TRAILER used +#endif +#if defined(DUK_OPT_NO_NONSTD_ARRAY_MAP_TRAILER) +#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ARRAY_MAP_TRAILER used +#endif +#if defined(DUK_OPT_NO_NONSTD_ARRAY_SPLICE_DELCOUNT) +#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ARRAY_SPLICE_DELCOUNT used +#endif +#if defined(DUK_OPT_NO_NONSTD_FUNC_STMT) +#error unsupported legacy feature option DUK_OPT_NO_NONSTD_FUNC_STMT used +#endif +#if defined(DUK_OPT_NO_NONSTD_JSON_ESC_U2028_U2029) +#error unsupported legacy feature option DUK_OPT_NO_NONSTD_JSON_ESC_U2028_U2029 used +#endif +#if defined(DUK_OPT_NO_NONSTD_STRING_FROMCHARCODE_32BIT) +#error unsupported legacy feature option DUK_OPT_NO_NONSTD_STRING_FROMCHARCODE_32BIT used +#endif +#if defined(DUK_OPT_NO_OBJECT_ES6_PROTO_PROPERTY) +#error unsupported legacy feature option DUK_OPT_NO_OBJECT_ES6_PROTO_PROPERTY used +#endif +#if defined(DUK_OPT_NO_OBJECT_ES6_SETPROTOTYPEOF) +#error unsupported legacy feature option DUK_OPT_NO_OBJECT_ES6_SETPROTOTYPEOF used +#endif +#if defined(DUK_OPT_NO_OCTAL_SUPPORT) +#error unsupported legacy feature option DUK_OPT_NO_OCTAL_SUPPORT used +#endif +#if defined(DUK_OPT_NO_PACKED_TVAL) +#error unsupported legacy feature option DUK_OPT_NO_PACKED_TVAL used +#endif +#if defined(DUK_OPT_NO_PC2LINE) +#error unsupported legacy feature option DUK_OPT_NO_PC2LINE used +#endif +#if defined(DUK_OPT_NO_REFERENCE_COUNTING) +#error unsupported legacy feature option DUK_OPT_NO_REFERENCE_COUNTING used +#endif +#if defined(DUK_OPT_NO_REGEXP_SUPPORT) +#error unsupported legacy feature option DUK_OPT_NO_REGEXP_SUPPORT used +#endif +#if defined(DUK_OPT_NO_SECTION_B) +#error unsupported legacy feature option DUK_OPT_NO_SECTION_B used +#endif +#if defined(DUK_OPT_NO_SOURCE_NONBMP) +#error unsupported legacy feature option DUK_OPT_NO_SOURCE_NONBMP used +#endif +#if defined(DUK_OPT_NO_STRICT_DECL) +#error unsupported legacy feature option DUK_OPT_NO_STRICT_DECL used +#endif +#if defined(DUK_OPT_NO_TRACEBACKS) +#error unsupported legacy feature option DUK_OPT_NO_TRACEBACKS used +#endif +#if defined(DUK_OPT_NO_VERBOSE_ERRORS) +#error unsupported legacy feature option DUK_OPT_NO_VERBOSE_ERRORS used +#endif +#if defined(DUK_OPT_NO_VOLUNTARY_GC) +#error unsupported legacy feature option DUK_OPT_NO_VOLUNTARY_GC used +#endif +#if defined(DUK_OPT_NO_ZERO_BUFFER_DATA) +#error unsupported legacy feature option DUK_OPT_NO_ZERO_BUFFER_DATA used +#endif +#if defined(DUK_OPT_OBJSIZES16) +#error unsupported legacy feature option DUK_OPT_OBJSIZES16 used +#endif +#if defined(DUK_OPT_PANIC_HANDLER) +#error unsupported legacy feature option DUK_OPT_PANIC_HANDLER used +#endif +#if defined(DUK_OPT_REFCOUNT16) +#error unsupported legacy feature option DUK_OPT_REFCOUNT16 used +#endif +#if defined(DUK_OPT_SEGFAULT_ON_PANIC) +#error unsupported legacy feature option DUK_OPT_SEGFAULT_ON_PANIC used +#endif +#if defined(DUK_OPT_SELF_TESTS) +#error unsupported legacy feature option DUK_OPT_SELF_TESTS used +#endif +#if defined(DUK_OPT_SETJMP) +#error unsupported legacy feature option DUK_OPT_SETJMP used +#endif +#if defined(DUK_OPT_SHUFFLE_TORTURE) +#error unsupported legacy feature option DUK_OPT_SHUFFLE_TORTURE used +#endif +#if defined(DUK_OPT_SIGSETJMP) +#error unsupported legacy feature option DUK_OPT_SIGSETJMP used +#endif +#if defined(DUK_OPT_STRHASH16) +#error unsupported legacy feature option DUK_OPT_STRHASH16 used +#endif +#if defined(DUK_OPT_STRICT_UTF8_SOURCE) +#error unsupported legacy feature option DUK_OPT_STRICT_UTF8_SOURCE used +#endif +#if defined(DUK_OPT_STRLEN16) +#error unsupported legacy feature option DUK_OPT_STRLEN16 used +#endif +#if defined(DUK_OPT_STRTAB_CHAIN) +#error unsupported legacy feature option DUK_OPT_STRTAB_CHAIN used +#endif +#if defined(DUK_OPT_STRTAB_CHAIN_SIZE) +#error unsupported legacy feature option DUK_OPT_STRTAB_CHAIN_SIZE used +#endif +#if defined(DUK_OPT_TARGET_INFO) +#error unsupported legacy feature option DUK_OPT_TARGET_INFO used +#endif +#if defined(DUK_OPT_TRACEBACK_DEPTH) +#error unsupported legacy feature option DUK_OPT_TRACEBACK_DEPTH used +#endif +#if defined(DUK_OPT_UNDERSCORE_SETJMP) +#error unsupported legacy feature option DUK_OPT_UNDERSCORE_SETJMP used +#endif +#if defined(DUK_OPT_USER_INITJS) +#error unsupported legacy feature option DUK_OPT_USER_INITJS used +#endif + +/* + * Checks for config option consistency (DUK_USE_xxx) + */ + +#if defined(DUK_USE_32BIT_PTRS) +#error unsupported config option used (option has been removed): DUK_USE_32BIT_PTRS +#endif +#if defined(DUK_USE_ALIGN_4) +#error unsupported config option used (option has been removed): DUK_USE_ALIGN_4 +#endif +#if defined(DUK_USE_ALIGN_8) +#error unsupported config option used (option has been removed): DUK_USE_ALIGN_8 +#endif +#if defined(DUK_USE_BROWSER_LIKE) +#error unsupported config option used (option has been removed): DUK_USE_BROWSER_LIKE +#endif +#if defined(DUK_USE_BUILTIN_INITJS) +#error unsupported config option used (option has been removed): DUK_USE_BUILTIN_INITJS +#endif +#if defined(DUK_USE_BYTEORDER_FORCED) +#error unsupported config option used (option has been removed): DUK_USE_BYTEORDER_FORCED +#endif +#if defined(DUK_USE_DATAPTR_DEC16) && !defined(DUK_USE_DATAPTR16) +#error config option DUK_USE_DATAPTR_DEC16 requires option DUK_USE_DATAPTR16 (which is missing) +#endif +#if defined(DUK_USE_DATAPTR_ENC16) && !defined(DUK_USE_DATAPTR16) +#error config option DUK_USE_DATAPTR_ENC16 requires option DUK_USE_DATAPTR16 (which is missing) +#endif +#if defined(DUK_USE_DDDPRINT) +#error unsupported config option used (option has been removed): DUK_USE_DDDPRINT +#endif +#if defined(DUK_USE_DDPRINT) +#error unsupported config option used (option has been removed): DUK_USE_DDPRINT +#endif +#if defined(DUK_USE_DEBUGGER_FWD_LOGGING) +#error unsupported config option used (option has been removed): DUK_USE_DEBUGGER_FWD_LOGGING +#endif +#if defined(DUK_USE_DEBUGGER_FWD_PRINTALERT) +#error unsupported config option used (option has been removed): DUK_USE_DEBUGGER_FWD_PRINTALERT +#endif +#if defined(DUK_USE_DEBUGGER_SUPPORT) && !defined(DUK_USE_INTERRUPT_COUNTER) +#error config option DUK_USE_DEBUGGER_SUPPORT requires option DUK_USE_INTERRUPT_COUNTER (which is missing) +#endif +#if defined(DUK_USE_DEEP_C_STACK) +#error unsupported config option used (option has been removed): DUK_USE_DEEP_C_STACK +#endif +#if defined(DUK_USE_DOUBLE_BE) +#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_BE +#endif +#if defined(DUK_USE_DOUBLE_BE) && defined(DUK_USE_DOUBLE_LE) +#error config option DUK_USE_DOUBLE_BE conflicts with option DUK_USE_DOUBLE_LE (which is also defined) +#endif +#if defined(DUK_USE_DOUBLE_BE) && defined(DUK_USE_DOUBLE_ME) +#error config option DUK_USE_DOUBLE_BE conflicts with option DUK_USE_DOUBLE_ME (which is also defined) +#endif +#if defined(DUK_USE_DOUBLE_LE) +#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_LE +#endif +#if defined(DUK_USE_DOUBLE_LE) && defined(DUK_USE_DOUBLE_BE) +#error config option DUK_USE_DOUBLE_LE conflicts with option DUK_USE_DOUBLE_BE (which is also defined) +#endif +#if defined(DUK_USE_DOUBLE_LE) && defined(DUK_USE_DOUBLE_ME) +#error config option DUK_USE_DOUBLE_LE conflicts with option DUK_USE_DOUBLE_ME (which is also defined) +#endif +#if defined(DUK_USE_DOUBLE_ME) +#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_ME +#endif +#if defined(DUK_USE_DOUBLE_ME) && defined(DUK_USE_DOUBLE_LE) +#error config option DUK_USE_DOUBLE_ME conflicts with option DUK_USE_DOUBLE_LE (which is also defined) +#endif +#if defined(DUK_USE_DOUBLE_ME) && defined(DUK_USE_DOUBLE_BE) +#error config option DUK_USE_DOUBLE_ME conflicts with option DUK_USE_DOUBLE_BE (which is also defined) +#endif +#if defined(DUK_USE_DPRINT) +#error unsupported config option used (option has been removed): DUK_USE_DPRINT +#endif +#if defined(DUK_USE_DPRINT) && !defined(DUK_USE_DEBUG) +#error config option DUK_USE_DPRINT requires option DUK_USE_DEBUG (which is missing) +#endif +#if defined(DUK_USE_DPRINT_COLORS) +#error unsupported config option used (option has been removed): DUK_USE_DPRINT_COLORS +#endif +#if defined(DUK_USE_DPRINT_RDTSC) +#error unsupported config option used (option has been removed): DUK_USE_DPRINT_RDTSC +#endif +#if defined(DUK_USE_ES6_REGEXP_BRACES) +#error unsupported config option used (option has been removed): DUK_USE_ES6_REGEXP_BRACES +#endif +#if defined(DUK_USE_ESBC_MAX_BYTES) && !defined(DUK_USE_ESBC_LIMITS) +#error config option DUK_USE_ESBC_MAX_BYTES requires option DUK_USE_ESBC_LIMITS (which is missing) +#endif +#if defined(DUK_USE_ESBC_MAX_LINENUMBER) && !defined(DUK_USE_ESBC_LIMITS) +#error config option DUK_USE_ESBC_MAX_LINENUMBER requires option DUK_USE_ESBC_LIMITS (which is missing) +#endif +#if defined(DUK_USE_EXEC_TIMEOUT_CHECK) && !defined(DUK_USE_INTERRUPT_COUNTER) +#error config option DUK_USE_EXEC_TIMEOUT_CHECK requires option DUK_USE_INTERRUPT_COUNTER (which is missing) +#endif +#if defined(DUK_USE_EXTSTR_FREE) && !defined(DUK_USE_HSTRING_EXTDATA) +#error config option DUK_USE_EXTSTR_FREE requires option DUK_USE_HSTRING_EXTDATA (which is missing) +#endif +#if defined(DUK_USE_EXTSTR_INTERN_CHECK) && !defined(DUK_USE_HSTRING_EXTDATA) +#error config option DUK_USE_EXTSTR_INTERN_CHECK requires option DUK_USE_HSTRING_EXTDATA (which is missing) +#endif +#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_64BIT_OPS) +#error config option DUK_USE_FASTINT requires option DUK_USE_64BIT_OPS (which is missing) +#endif +#if defined(DUK_USE_FILE_IO) +#error unsupported config option used (option has been removed): DUK_USE_FILE_IO +#endif +#if defined(DUK_USE_FULL_TVAL) +#error unsupported config option used (option has been removed): DUK_USE_FULL_TVAL +#endif +#if defined(DUK_USE_FUNCPTR_DEC16) && !defined(DUK_USE_FUNCPTR16) +#error config option DUK_USE_FUNCPTR_DEC16 requires option DUK_USE_FUNCPTR16 (which is missing) +#endif +#if defined(DUK_USE_FUNCPTR_ENC16) && !defined(DUK_USE_FUNCPTR16) +#error config option DUK_USE_FUNCPTR_ENC16 requires option DUK_USE_FUNCPTR16 (which is missing) +#endif +#if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS) +#error unsupported config option used (option has been removed): DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS +#endif +#if defined(DUK_USE_HEAPPTR16) && defined(DUK_USE_DEBUG) +#error config option DUK_USE_HEAPPTR16 conflicts with option DUK_USE_DEBUG (which is also defined) +#endif +#if defined(DUK_USE_HEAPPTR_DEC16) && !defined(DUK_USE_HEAPPTR16) +#error config option DUK_USE_HEAPPTR_DEC16 requires option DUK_USE_HEAPPTR16 (which is missing) +#endif +#if defined(DUK_USE_HEAPPTR_ENC16) && !defined(DUK_USE_HEAPPTR16) +#error config option DUK_USE_HEAPPTR_ENC16 requires option DUK_USE_HEAPPTR16 (which is missing) +#endif +#if defined(DUK_USE_INTEGER_BE) +#error unsupported config option used (option has been removed): DUK_USE_INTEGER_BE +#endif +#if defined(DUK_USE_INTEGER_BE) && defined(DUK_USE_INTEGER_LE) +#error config option DUK_USE_INTEGER_BE conflicts with option DUK_USE_INTEGER_LE (which is also defined) +#endif +#if defined(DUK_USE_INTEGER_BE) && defined(DUK_USE_INTEGER_ME) +#error config option DUK_USE_INTEGER_BE conflicts with option DUK_USE_INTEGER_ME (which is also defined) +#endif +#if defined(DUK_USE_INTEGER_LE) +#error unsupported config option used (option has been removed): DUK_USE_INTEGER_LE +#endif +#if defined(DUK_USE_INTEGER_LE) && defined(DUK_USE_INTEGER_BE) +#error config option DUK_USE_INTEGER_LE conflicts with option DUK_USE_INTEGER_BE (which is also defined) +#endif +#if defined(DUK_USE_INTEGER_LE) && defined(DUK_USE_INTEGER_ME) +#error config option DUK_USE_INTEGER_LE conflicts with option DUK_USE_INTEGER_ME (which is also defined) +#endif +#if defined(DUK_USE_INTEGER_ME) +#error unsupported config option used (option has been removed): DUK_USE_INTEGER_ME +#endif +#if defined(DUK_USE_INTEGER_ME) && defined(DUK_USE_INTEGER_LE) +#error config option DUK_USE_INTEGER_ME conflicts with option DUK_USE_INTEGER_LE (which is also defined) +#endif +#if defined(DUK_USE_INTEGER_ME) && defined(DUK_USE_INTEGER_BE) +#error config option DUK_USE_INTEGER_ME conflicts with option DUK_USE_INTEGER_BE (which is also defined) +#endif +#if defined(DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE) +#error unsupported config option used (option has been removed): DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE +#endif +#if defined(DUK_USE_MARK_AND_SWEEP) +#error unsupported config option used (option has been removed): DUK_USE_MARK_AND_SWEEP +#endif +#if defined(DUK_USE_MATH_FMAX) +#error unsupported config option used (option has been removed): DUK_USE_MATH_FMAX +#endif +#if defined(DUK_USE_MATH_FMIN) +#error unsupported config option used (option has been removed): DUK_USE_MATH_FMIN +#endif +#if defined(DUK_USE_MATH_ROUND) +#error unsupported config option used (option has been removed): DUK_USE_MATH_ROUND +#endif +#if defined(DUK_USE_MS_STRINGTABLE_RESIZE) +#error unsupported config option used (option has been removed): DUK_USE_MS_STRINGTABLE_RESIZE +#endif +#if defined(DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE) +#error unsupported config option used (option has been removed): DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE +#endif +#if defined(DUK_USE_NO_DOUBLE_ALIASING_SELFTEST) +#error unsupported config option used (option has been removed): DUK_USE_NO_DOUBLE_ALIASING_SELFTEST +#endif +#if defined(DUK_USE_OCTAL_SUPPORT) +#error unsupported config option used (option has been removed): DUK_USE_OCTAL_SUPPORT +#endif +#if defined(DUK_USE_PACKED_TVAL_POSSIBLE) +#error unsupported config option used (option has been removed): DUK_USE_PACKED_TVAL_POSSIBLE +#endif +#if defined(DUK_USE_PANIC_ABORT) +#error unsupported config option used (option has been removed): DUK_USE_PANIC_ABORT +#endif +#if defined(DUK_USE_PANIC_EXIT) +#error unsupported config option used (option has been removed): DUK_USE_PANIC_EXIT +#endif +#if defined(DUK_USE_PANIC_HANDLER) +#error unsupported config option used (option has been removed): DUK_USE_PANIC_HANDLER +#endif +#if defined(DUK_USE_PANIC_SEGFAULT) +#error unsupported config option used (option has been removed): DUK_USE_PANIC_SEGFAULT +#endif +#if defined(DUK_USE_POW_NETBSD_WORKAROUND) +#error unsupported config option used (option has been removed): DUK_USE_POW_NETBSD_WORKAROUND +#endif +#if defined(DUK_USE_RDTSC) +#error unsupported config option used (option has been removed): DUK_USE_RDTSC +#endif +#if defined(DUK_USE_REFZERO_FINALIZER_TORTURE) +#error unsupported config option used (option has been removed): DUK_USE_REFZERO_FINALIZER_TORTURE +#endif +#if defined(DUK_USE_ROM_GLOBAL_CLONE) && !defined(DUK_USE_ROM_STRINGS) +#error config option DUK_USE_ROM_GLOBAL_CLONE requires option DUK_USE_ROM_STRINGS (which is missing) +#endif +#if defined(DUK_USE_ROM_GLOBAL_CLONE) && !defined(DUK_USE_ROM_OBJECTS) +#error config option DUK_USE_ROM_GLOBAL_CLONE requires option DUK_USE_ROM_OBJECTS (which is missing) +#endif +#if defined(DUK_USE_ROM_GLOBAL_CLONE) && defined(DUK_USE_ROM_GLOBAL_INHERIT) +#error config option DUK_USE_ROM_GLOBAL_CLONE conflicts with option DUK_USE_ROM_GLOBAL_INHERIT (which is also defined) +#endif +#if defined(DUK_USE_ROM_GLOBAL_INHERIT) && !defined(DUK_USE_ROM_STRINGS) +#error config option DUK_USE_ROM_GLOBAL_INHERIT requires option DUK_USE_ROM_STRINGS (which is missing) +#endif +#if defined(DUK_USE_ROM_GLOBAL_INHERIT) && !defined(DUK_USE_ROM_OBJECTS) +#error config option DUK_USE_ROM_GLOBAL_INHERIT requires option DUK_USE_ROM_OBJECTS (which is missing) +#endif +#if defined(DUK_USE_ROM_GLOBAL_INHERIT) && defined(DUK_USE_ROM_GLOBAL_CLONE) +#error config option DUK_USE_ROM_GLOBAL_INHERIT conflicts with option DUK_USE_ROM_GLOBAL_CLONE (which is also defined) +#endif +#if defined(DUK_USE_ROM_OBJECTS) && !defined(DUK_USE_ROM_STRINGS) +#error config option DUK_USE_ROM_OBJECTS requires option DUK_USE_ROM_STRINGS (which is missing) +#endif +#if defined(DUK_USE_ROM_STRINGS) && !defined(DUK_USE_ROM_OBJECTS) +#error config option DUK_USE_ROM_STRINGS requires option DUK_USE_ROM_OBJECTS (which is missing) +#endif +#if defined(DUK_USE_SETJMP) +#error unsupported config option used (option has been removed): DUK_USE_SETJMP +#endif +#if defined(DUK_USE_SIGSETJMP) +#error unsupported config option used (option has been removed): DUK_USE_SIGSETJMP +#endif +#if defined(DUK_USE_STRTAB_CHAIN) +#error unsupported config option used (option has been removed): DUK_USE_STRTAB_CHAIN +#endif +#if defined(DUK_USE_STRTAB_CHAIN_SIZE) +#error unsupported config option used (option has been removed): DUK_USE_STRTAB_CHAIN_SIZE +#endif +#if defined(DUK_USE_STRTAB_CHAIN_SIZE) && !defined(DUK_USE_STRTAB_CHAIN) +#error config option DUK_USE_STRTAB_CHAIN_SIZE requires option DUK_USE_STRTAB_CHAIN (which is missing) +#endif +#if defined(DUK_USE_STRTAB_PROBE) +#error unsupported config option used (option has been removed): DUK_USE_STRTAB_PROBE +#endif +#if defined(DUK_USE_STRTAB_PTRCOMP) && !defined(DUK_USE_HEAPPTR16) +#error config option DUK_USE_STRTAB_PTRCOMP requires option DUK_USE_HEAPPTR16 (which is missing) +#endif +#if defined(DUK_USE_TAILCALL) && defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY) +#error config option DUK_USE_TAILCALL conflicts with option DUK_USE_NONSTD_FUNC_CALLER_PROPERTY (which is also defined) +#endif +#if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE) +#error unsupported config option used (option has been removed): DUK_USE_UNALIGNED_ACCESSES_POSSIBLE +#endif +#if defined(DUK_USE_UNDERSCORE_SETJMP) +#error unsupported config option used (option has been removed): DUK_USE_UNDERSCORE_SETJMP +#endif +#if defined(DUK_USE_USER_INITJS) +#error unsupported config option used (option has been removed): DUK_USE_USER_INITJS +#endif + +#if defined(DUK_USE_CPP_EXCEPTIONS) && !defined(__cplusplus) +#error DUK_USE_CPP_EXCEPTIONS enabled but not compiling with a C++ compiler +#endif + +/* + * Convert DUK_USE_BYTEORDER, from whatever source, into currently used + * internal defines. If detection failed, #error out. + */ + +#if defined(DUK_USE_BYTEORDER) +#if (DUK_USE_BYTEORDER == 1) +#define DUK_USE_INTEGER_LE +#define DUK_USE_DOUBLE_LE +#elif (DUK_USE_BYTEORDER == 2) +#define DUK_USE_INTEGER_LE /* integer endianness is little on purpose */ +#define DUK_USE_DOUBLE_ME +#elif (DUK_USE_BYTEORDER == 3) +#define DUK_USE_INTEGER_BE +#define DUK_USE_DOUBLE_BE +#else +#error unsupported: byte order invalid +#endif /* byte order */ +#else +#error unsupported: byte order detection failed +#endif /* defined(DUK_USE_BYTEORDER) */ + +#endif /* DUK_CONFIG_H_INCLUDED */
A
src/litestorepkg/vendor/duktape/duktape.c
@@ -0,0 +1,95142 @@
+/* + * Single source autogenerated distributable for Duktape 2.2.1. + * + * Git commit 25420e773c5fbc50d5b46bf487fc45717e35b94f (v2.2.1). + * Git branch v2.2-maintenance. + * + * See Duktape AUTHORS.rst and LICENSE.txt for copyright and + * licensing information. + */ + +/* LICENSE.txt */ +/* +* =============== +* Duktape license +* =============== +* +* (http://opensource.org/licenses/MIT) +* +* Copyright (c) 2013-2017 by Duktape authors (see AUTHORS.rst) +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +/* AUTHORS.rst */ +/* +* =============== +* Duktape authors +* =============== +* +* Copyright +* ========= +* +* Duktape copyrights are held by its authors. Each author has a copyright +* to their contribution, and agrees to irrevocably license the contribution +* under the Duktape ``LICENSE.txt``. +* +* Authors +* ======= +* +* Please include an e-mail address, a link to your GitHub profile, or something +* similar to allow your contribution to be identified accurately. +* +* The following people have contributed code, website contents, or Wiki contents, +* and agreed to irrevocably license their contributions under the Duktape +* ``LICENSE.txt`` (in order of appearance): +* +* * Sami Vaarala <sami.vaarala@iki.fi> +* * Niki Dobrev +* * Andreas \u00d6man <andreas@lonelycoder.com> +* * L\u00e1szl\u00f3 Lang\u00f3 <llango.u-szeged@partner.samsung.com> +* * Legimet <legimet.calc@gmail.com> +* * Karl Skomski <karl@skomski.com> +* * Bruce Pascoe <fatcerberus1@gmail.com> +* * Ren\u00e9 Hollander <rene@rene8888.at> +* * Julien Hamaide (https://github.com/crazyjul) +* * Sebastian G\u00f6tte (https://github.com/jaseg) +* * Tomasz Magulski (https://github.com/magul) +* * \D. Bohdan (https://github.com/dbohdan) +* * Ond\u0159ej Jirman (https://github.com/megous) +* * Sa\u00fal Ibarra Corretg\u00e9 <saghul@gmail.com> +* * Jeremy HU <huxingyi@msn.com> +* * Ole Andr\u00e9 Vadla Ravn\u00e5s (https://github.com/oleavr) +* * Harold Brenes (https://github.com/harold-b) +* * Oliver Crow (https://github.com/ocrow) +* * Jakub Ch\u0142api\u0144ski (https://github.com/jchlapinski) +* * Brett Vickers (https://github.com/beevik) +* * Dominik Okwieka (https://github.com/okitec) +* * Remko Tron\u00e7on (https://el-tramo.be) +* * Romero Malaquias (rbsm@ic.ufal.br) +* * Michael Drake <michael.drake@codethink.co.uk> +* * Steven Don (https://github.com/shdon) +* * Simon Stone (https://github.com/sstone1) +* * \J. McC. (https://github.com/jmhmccr) +* +* Other contributions +* =================== +* +* The following people have contributed something other than code (e.g. reported +* bugs, provided ideas, etc; roughly in order of appearance): +* +* * Greg Burns +* * Anthony Rabine +* * Carlos Costa +* * Aur\u00e9lien Bouilland +* * Preet Desai (Pris Matic) +* * judofyr (http://www.reddit.com/user/judofyr) +* * Jason Woofenden +* * Micha\u0142 Przyby\u015b +* * Anthony Howe +* * Conrad Pankoff +* * Jim Schimpf +* * Rajaran Gaunker (https://github.com/zimbabao) +* * Andreas \u00d6man +* * Doug Sanden +* * Josh Engebretson (https://github.com/JoshEngebretson) +* * Remo Eichenberger (https://github.com/remoe) +* * Mamod Mehyar (https://github.com/mamod) +* * David Demelier (https://github.com/markand) +* * Tim Caswell (https://github.com/creationix) +* * Mitchell Blank Jr (https://github.com/mitchblank) +* * https://github.com/yushli +* * Seo Sanghyeon (https://github.com/sanxiyn) +* * Han ChoongWoo (https://github.com/tunz) +* * Joshua Peek (https://github.com/josh) +* * Bruce E. Pascoe (https://github.com/fatcerberus) +* * https://github.com/Kelledin +* * https://github.com/sstruchtrup +* * Michael Drake (https://github.com/tlsa) +* * https://github.com/chris-y +* * Laurent Zubiaur (https://github.com/lzubiaur) +* * Neil Kolban (https://github.com/nkolban) +* +* If you are accidentally missing from this list, send me an e-mail +* (``sami.vaarala@iki.fi``) and I'll fix the omission. +*/ + +#line 1 "duk_replacements.c" +/* + * Replacements for missing platform functions. + * + * Unlike the originals, fpclassify() and signbit() replacements don't + * work on any floating point types, only doubles. The C typing here + * mimics the standard prototypes. + */ + +/* #include duk_internal.h */ +#line 1 "duk_internal.h" +/* + * Top-level include file to be used for all (internal) source files. + * + * Source files should not include individual header files, as they + * have not been designed to be individually included. + */ + +#if !defined(DUK_INTERNAL_H_INCLUDED) +#define DUK_INTERNAL_H_INCLUDED + +/* + * The 'duktape.h' header provides the public API, but also handles all + * compiler and platform specific feature detection, Duktape feature + * resolution, inclusion of system headers, etc. These have been merged + * because the public API is also dependent on e.g. detecting appropriate + * C types which is quite platform/compiler specific especially for a non-C99 + * build. The public API is also dependent on the resolved feature set. + * + * Some actions taken by the merged header (such as including system headers) + * are not appropriate for building a user application. The define + * DUK_COMPILING_DUKTAPE allows the merged header to skip/include some + * sections depending on what is being built. + */ + +#define DUK_COMPILING_DUKTAPE +#include "duktape.h" + +/* + * User declarations, e.g. prototypes for user functions used by Duktape + * macros. + */ + +DUK_USE_USER_DECLARE() + +/* + * Duktape includes (other than duk_features.h) + * + * The header files expect to be included in an order which satisfies header + * dependencies correctly (the headers themselves don't include any other + * includes). Forward declarations are used to break circular struct/typedef + * dependencies. + */ + +/* #include duk_dblunion.h */ +#line 1 "duk_dblunion.h" +/* + * Union to access IEEE double memory representation, indexes for double + * memory representation, and some macros for double manipulation. + * + * Also used by packed duk_tval. Use a union for bit manipulation to + * minimize aliasing issues in practice. The C99 standard does not + * guarantee that this should work, but it's a very widely supported + * practice for low level manipulation. + * + * IEEE double format summary: + * + * seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff + * A B C D E F G H + * + * s sign bit + * eee... exponent field + * fff... fraction + * + * See http://en.wikipedia.org/wiki/Double_precision_floating-point_format. + * + * NaNs are represented as exponent 0x7ff and mantissa != 0. The NaN is a + * signaling NaN when the highest bit of the mantissa is zero, and a quiet + * NaN when the highest bit is set. + * + * At least three memory layouts are relevant here: + * + * A B C D E F G H Big endian (e.g. 68k) DUK_USE_DOUBLE_BE + * H G F E D C B A Little endian (e.g. x86) DUK_USE_DOUBLE_LE + * D C B A H G F E Mixed/cross endian (e.g. ARM) DUK_USE_DOUBLE_ME + * + * ARM is a special case: ARM double values are in mixed/cross endian + * format while ARM duk_uint64_t values are in standard little endian + * format (H G F E D C B A). When a double is read as a duk_uint64_t + * from memory, the register will contain the (logical) value + * E F G H A B C D. This requires some special handling below. + * + * Indexes of various types (8-bit, 16-bit, 32-bit) in memory relative to + * the logical (big endian) order: + * + * byte order duk_uint8_t duk_uint16_t duk_uint32_t + * BE 01234567 0123 01 + * LE 76543210 3210 10 + * ME (ARM) 32107654 1032 01 + * + * Some processors may alter NaN values in a floating point load+store. + * For instance, on X86 a FLD + FSTP may convert a signaling NaN to a + * quiet one. This is catastrophic when NaN space is used in packed + * duk_tval values. See: misc/clang_aliasing.c. + */ + +#if !defined(DUK_DBLUNION_H_INCLUDED) +#define DUK_DBLUNION_H_INCLUDED + +/* + * Union for accessing double parts, also serves as packed duk_tval + */ + +union duk_double_union { + double d; + float f[2]; +#if defined(DUK_USE_64BIT_OPS) + duk_uint64_t ull[1]; +#endif + duk_uint32_t ui[2]; + duk_uint16_t us[4]; + duk_uint8_t uc[8]; +#if defined(DUK_USE_PACKED_TVAL) + void *vp[2]; /* used by packed duk_tval, assumes sizeof(void *) == 4 */ +#endif +}; + +typedef union duk_double_union duk_double_union; + +/* + * Indexes of various types with respect to big endian (logical) layout + */ + +#if defined(DUK_USE_DOUBLE_LE) +#if defined(DUK_USE_64BIT_OPS) +#define DUK_DBL_IDX_ULL0 0 +#endif +#define DUK_DBL_IDX_UI0 1 +#define DUK_DBL_IDX_UI1 0 +#define DUK_DBL_IDX_US0 3 +#define DUK_DBL_IDX_US1 2 +#define DUK_DBL_IDX_US2 1 +#define DUK_DBL_IDX_US3 0 +#define DUK_DBL_IDX_UC0 7 +#define DUK_DBL_IDX_UC1 6 +#define DUK_DBL_IDX_UC2 5 +#define DUK_DBL_IDX_UC3 4 +#define DUK_DBL_IDX_UC4 3 +#define DUK_DBL_IDX_UC5 2 +#define DUK_DBL_IDX_UC6 1 +#define DUK_DBL_IDX_UC7 0 +#define DUK_DBL_IDX_VP0 DUK_DBL_IDX_UI0 /* packed tval */ +#define DUK_DBL_IDX_VP1 DUK_DBL_IDX_UI1 /* packed tval */ +#elif defined(DUK_USE_DOUBLE_BE) +#if defined(DUK_USE_64BIT_OPS) +#define DUK_DBL_IDX_ULL0 0 +#endif +#define DUK_DBL_IDX_UI0 0 +#define DUK_DBL_IDX_UI1 1 +#define DUK_DBL_IDX_US0 0 +#define DUK_DBL_IDX_US1 1 +#define DUK_DBL_IDX_US2 2 +#define DUK_DBL_IDX_US3 3 +#define DUK_DBL_IDX_UC0 0 +#define DUK_DBL_IDX_UC1 1 +#define DUK_DBL_IDX_UC2 2 +#define DUK_DBL_IDX_UC3 3 +#define DUK_DBL_IDX_UC4 4 +#define DUK_DBL_IDX_UC5 5 +#define DUK_DBL_IDX_UC6 6 +#define DUK_DBL_IDX_UC7 7 +#define DUK_DBL_IDX_VP0 DUK_DBL_IDX_UI0 /* packed tval */ +#define DUK_DBL_IDX_VP1 DUK_DBL_IDX_UI1 /* packed tval */ +#elif defined(DUK_USE_DOUBLE_ME) +#if defined(DUK_USE_64BIT_OPS) +#define DUK_DBL_IDX_ULL0 0 /* not directly applicable, byte order differs from a double */ +#endif +#define DUK_DBL_IDX_UI0 0 +#define DUK_DBL_IDX_UI1 1 +#define DUK_DBL_IDX_US0 1 +#define DUK_DBL_IDX_US1 0 +#define DUK_DBL_IDX_US2 3 +#define DUK_DBL_IDX_US3 2 +#define DUK_DBL_IDX_UC0 3 +#define DUK_DBL_IDX_UC1 2 +#define DUK_DBL_IDX_UC2 1 +#define DUK_DBL_IDX_UC3 0 +#define DUK_DBL_IDX_UC4 7 +#define DUK_DBL_IDX_UC5 6 +#define DUK_DBL_IDX_UC6 5 +#define DUK_DBL_IDX_UC7 4 +#define DUK_DBL_IDX_VP0 DUK_DBL_IDX_UI0 /* packed tval */ +#define DUK_DBL_IDX_VP1 DUK_DBL_IDX_UI1 /* packed tval */ +#else +#error internal error +#endif + +/* + * Helper macros for reading/writing memory representation parts, used + * by duk_numconv.c and duk_tval.h. + */ + +#define DUK_DBLUNION_SET_DOUBLE(u,v) do { \ + (u)->d = (v); \ + } while (0) + +#define DUK_DBLUNION_SET_HIGH32(u,v) do { \ + (u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \ + } while (0) + +#if defined(DUK_USE_64BIT_OPS) +#if defined(DUK_USE_DOUBLE_ME) +#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v) do { \ + (u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \ + } while (0) +#else +#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v) do { \ + (u)->ull[DUK_DBL_IDX_ULL0] = ((duk_uint64_t) (v)) << 32; \ + } while (0) +#endif +#else /* DUK_USE_64BIT_OPS */ +#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v) do { \ + (u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \ + (u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0; \ + } while (0) +#endif /* DUK_USE_64BIT_OPS */ + +#define DUK_DBLUNION_SET_LOW32(u,v) do { \ + (u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \ + } while (0) + +#define DUK_DBLUNION_GET_DOUBLE(u) ((u)->d) +#define DUK_DBLUNION_GET_HIGH32(u) ((u)->ui[DUK_DBL_IDX_UI0]) +#define DUK_DBLUNION_GET_LOW32(u) ((u)->ui[DUK_DBL_IDX_UI1]) + +#if defined(DUK_USE_64BIT_OPS) +#if defined(DUK_USE_DOUBLE_ME) +#define DUK_DBLUNION_SET_UINT64(u,v) do { \ + (u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) ((v) >> 32); \ + (u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \ + } while (0) +#define DUK_DBLUNION_GET_UINT64(u) \ + ((((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI0]) << 32) | \ + ((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI1])) +#else +#define DUK_DBLUNION_SET_UINT64(u,v) do { \ + (u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \ + } while (0) +#define DUK_DBLUNION_GET_UINT64(u) ((u)->ull[DUK_DBL_IDX_ULL0]) +#endif +#define DUK_DBLUNION_SET_INT64(u,v) DUK_DBLUNION_SET_UINT64((u), (duk_uint64_t) (v)) +#define DUK_DBLUNION_GET_INT64(u) ((duk_int64_t) DUK_DBLUNION_GET_UINT64((u))) +#endif /* DUK_USE_64BIT_OPS */ + +/* + * Double NaN manipulation macros related to NaN normalization needed when + * using the packed duk_tval representation. NaN normalization is necessary + * to keep double values compatible with the duk_tval format. + * + * When packed duk_tval is used, the NaN space is used to store pointers + * and other tagged values in addition to NaNs. Actual NaNs are normalized + * to a specific quiet NaN. The macros below are used by the implementation + * to check and normalize NaN values when they might be created. The macros + * are essentially NOPs when the non-packed duk_tval representation is used. + * + * A FULL check is exact and checks all bits. A NOTFULL check is used by + * the packed duk_tval and works correctly for all NaNs except those that + * begin with 0x7ff0. Since the 'normalized NaN' values used with packed + * duk_tval begin with 0x7ff8, the partial check is reliable when packed + * duk_tval is used. The 0x7ff8 prefix means the normalized NaN will be a + * quiet NaN regardless of its remaining lower bits. + * + * The ME variant below is specifically for ARM byte order, which has the + * feature that while doubles have a mixed byte order (32107654), unsigned + * long long values has a little endian byte order (76543210). When writing + * a logical double value through a ULL pointer, the 32-bit words need to be + * swapped; hence the #if defined()s below for ULL writes with DUK_USE_DOUBLE_ME. + * This is not full ARM support but suffices for some environments. + */ + +#if defined(DUK_USE_64BIT_OPS) +#if defined(DUK_USE_DOUBLE_ME) +/* Macros for 64-bit ops + mixed endian doubles. */ +#define DUK__DBLUNION_SET_NAN_FULL(u) do { \ + (u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x000000007ff80000); \ + } while (0) +#define DUK__DBLUNION_IS_NAN_FULL(u) \ + ((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000)) && \ + ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0xffffffff000fffff)) != 0)) +#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \ + ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff80000)) +#define DUK__DBLUNION_IS_ANYINF(u) \ + (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x000000007ff00000)) +#define DUK__DBLUNION_IS_POSINF(u) \ + ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff00000)) +#define DUK__DBLUNION_IS_NEGINF(u) \ + ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x00000000fff00000)) +#define DUK__DBLUNION_IS_ANYZERO(u) \ + (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x0000000000000000)) +#define DUK__DBLUNION_IS_POSZERO(u) \ + ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000)) +#define DUK__DBLUNION_IS_NEGZERO(u) \ + ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000080000000)) +#else +/* Macros for 64-bit ops + big/little endian doubles. */ +#define DUK__DBLUNION_SET_NAN_FULL(u) do { \ + (u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x7ff8000000000000); \ + } while (0) +#define DUK__DBLUNION_IS_NAN_FULL(u) \ + ((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000)) && \ + ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0x000fffffffffffff)) != 0)) +#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \ + ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff8000000000000)) +#define DUK__DBLUNION_IS_ANYINF(u) \ + (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x7ff0000000000000)) +#define DUK__DBLUNION_IS_POSINF(u) \ + ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff0000000000000)) +#define DUK__DBLUNION_IS_NEGINF(u) \ + ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0xfff0000000000000)) +#define DUK__DBLUNION_IS_ANYZERO(u) \ + (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x0000000000000000)) +#define DUK__DBLUNION_IS_POSZERO(u) \ + ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000)) +#define DUK__DBLUNION_IS_NEGZERO(u) \ + ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x8000000000000000)) +#endif +#else /* DUK_USE_64BIT_OPS */ +/* Macros for no 64-bit ops, any endianness. */ +#define DUK__DBLUNION_SET_NAN_FULL(u) do { \ + (u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) 0x7ff80000UL; \ + (u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0x00000000UL; \ + } while (0) +#define DUK__DBLUNION_IS_NAN_FULL(u) \ + ((((u)->ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL) && \ + (((u)->ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) != 0 || \ + (u)->ui[DUK_DBL_IDX_UI1] != 0)) +#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \ + (((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff80000UL) && \ + ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL)) +#define DUK__DBLUNION_IS_ANYINF(u) \ + ((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x7ff00000UL) && \ + ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL)) +#define DUK__DBLUNION_IS_POSINF(u) \ + (((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff00000UL) && \ + ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL)) +#define DUK__DBLUNION_IS_NEGINF(u) \ + (((u)->ui[DUK_DBL_IDX_UI0] == 0xfff00000UL) && \ + ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL)) +#define DUK__DBLUNION_IS_ANYZERO(u) \ + ((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x00000000UL) && \ + ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL)) +#define DUK__DBLUNION_IS_POSZERO(u) \ + (((u)->ui[DUK_DBL_IDX_UI0] == 0x00000000UL) && \ + ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL)) +#define DUK__DBLUNION_IS_NEGZERO(u) \ + (((u)->ui[DUK_DBL_IDX_UI0] == 0x80000000UL) && \ + ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL)) +#endif /* DUK_USE_64BIT_OPS */ + +#define DUK__DBLUNION_SET_NAN_NOTFULL(u) do { \ + (u)->us[DUK_DBL_IDX_US0] = 0x7ff8UL; \ + } while (0) + +#define DUK__DBLUNION_IS_NAN_NOTFULL(u) \ + /* E == 0x7ff, topmost four bits of F != 0 => assume NaN */ \ + ((((u)->us[DUK_DBL_IDX_US0] & 0x7ff0UL) == 0x7ff0UL) && \ + (((u)->us[DUK_DBL_IDX_US0] & 0x000fUL) != 0x0000UL)) + +#define DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL(u) \ + /* E == 0x7ff, F == 8 => normalized NaN */ \ + ((u)->us[DUK_DBL_IDX_US0] == 0x7ff8UL) + +#define DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL(u) do { \ + if (DUK__DBLUNION_IS_NAN_FULL((u))) { \ + DUK__DBLUNION_SET_NAN_FULL((u)); \ + } \ + } while (0) + +#define DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL(u) do { \ + if (DUK__DBLUNION_IS_NAN_NOTFULL((u))) { \ + DUK__DBLUNION_SET_NAN_NOTFULL((u)); \ + } \ + } while (0) + +/* Concrete macros for NaN handling used by the implementation internals. + * Chosen so that they match the duk_tval representation: with a packed + * duk_tval, ensure NaNs are properly normalized; with a non-packed duk_tval + * these are essentially NOPs. + */ + +#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 +#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)) +#define DUK_DBLUNION_SET_NAN(d) DUK__DBLUNION_SET_NAN_NOTFULL((d)) +#endif +#define DUK_DBLUNION_IS_NORMALIZED(u) \ + (!DUK_DBLUNION_IS_NAN((u)) || /* either not a NaN */ \ + DUK_DBLUNION_IS_NORMALIZED_NAN((u))) /* or is a normalized NaN */ +#else /* DUK_USE_PACKED_TVAL */ +#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u) /* nop: no need to normalize */ +#define DUK_DBLUNION_IS_NAN(u) DUK__DBLUNION_IS_NAN_FULL((u)) /* (DUK_ISNAN((u)->d)) */ +#define DUK_DBLUNION_IS_NORMALIZED_NAN(u) DUK__DBLUNION_IS_NAN_FULL((u)) /* (DUK_ISNAN((u)->d)) */ +#define DUK_DBLUNION_IS_NORMALIZED(u) 1 /* all doubles are considered normalized */ +#define DUK_DBLUNION_SET_NAN(u) do { \ + /* in non-packed representation we don't care about which NaN is used */ \ + (u)->d = DUK_DOUBLE_NAN; \ + } while (0) +#endif /* DUK_USE_PACKED_TVAL */ + +#define DUK_DBLUNION_IS_ANYINF(u) DUK__DBLUNION_IS_ANYINF((u)) +#define DUK_DBLUNION_IS_POSINF(u) DUK__DBLUNION_IS_POSINF((u)) +#define DUK_DBLUNION_IS_NEGINF(u) DUK__DBLUNION_IS_NEGINF((u)) + +#define DUK_DBLUNION_IS_ANYZERO(u) DUK__DBLUNION_IS_ANYZERO((u)) +#define DUK_DBLUNION_IS_POSZERO(u) DUK__DBLUNION_IS_POSZERO((u)) +#define DUK_DBLUNION_IS_NEGZERO(u) DUK__DBLUNION_IS_NEGZERO((u)) + +/* XXX: native 64-bit byteswaps when available */ + +/* 64-bit byteswap, same operation independent of target endianness. */ +#define DUK_DBLUNION_BSWAP64(u) do { \ + duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \ + duk__bswaptmp1 = (u)->ui[0]; \ + duk__bswaptmp2 = (u)->ui[1]; \ + duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \ + duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \ + (u)->ui[0] = duk__bswaptmp2; \ + (u)->ui[1] = duk__bswaptmp1; \ + } while (0) + +/* Byteswap an IEEE double in the duk_double_union from host to network + * order. For a big endian target this is a no-op. + */ +#if defined(DUK_USE_DOUBLE_LE) +#define DUK_DBLUNION_DOUBLE_HTON(u) do { \ + duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \ + duk__bswaptmp1 = (u)->ui[0]; \ + duk__bswaptmp2 = (u)->ui[1]; \ + duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \ + duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \ + (u)->ui[0] = duk__bswaptmp2; \ + (u)->ui[1] = duk__bswaptmp1; \ + } while (0) +#elif defined(DUK_USE_DOUBLE_ME) +#define DUK_DBLUNION_DOUBLE_HTON(u) do { \ + duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \ + duk__bswaptmp1 = (u)->ui[0]; \ + duk__bswaptmp2 = (u)->ui[1]; \ + duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \ + duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \ + (u)->ui[0] = duk__bswaptmp1; \ + (u)->ui[1] = duk__bswaptmp2; \ + } while (0) +#elif defined(DUK_USE_DOUBLE_BE) +#define DUK_DBLUNION_DOUBLE_HTON(u) do { } while (0) +#else +#error internal error, double endianness insane +#endif + +/* Reverse operation is the same. */ +#define DUK_DBLUNION_DOUBLE_NTOH(u) DUK_DBLUNION_DOUBLE_HTON((u)) + +/* Some sign bit helpers. */ +#if defined(DUK_USE_64BIT_OPS) +#define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000)) != 0) +#define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] >> 63U)) +#else +#define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] & 0x80000000UL) != 0) +#define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] >> 31U)) +#endif + +#endif /* DUK_DBLUNION_H_INCLUDED */ +/* #include duk_replacements.h */ +#line 1 "duk_replacements.h" +#if !defined(DUK_REPLACEMENTS_H_INCLUDED) +#define DUK_REPLACEMENTS_H_INCLUDED + +#if !defined(DUK_SINGLE_FILE) +#if defined(DUK_USE_COMPUTED_INFINITY) +DUK_INTERNAL_DECL double duk_computed_infinity; +#endif +#if defined(DUK_USE_COMPUTED_NAN) +DUK_INTERNAL_DECL double duk_computed_nan; +#endif +#endif /* !DUK_SINGLE_FILE */ + +#if defined(DUK_USE_REPL_FPCLASSIFY) +DUK_INTERNAL_DECL int duk_repl_fpclassify(double x); +#endif +#if defined(DUK_USE_REPL_SIGNBIT) +DUK_INTERNAL_DECL int duk_repl_signbit(double x); +#endif +#if defined(DUK_USE_REPL_ISFINITE) +DUK_INTERNAL_DECL int duk_repl_isfinite(double x); +#endif +#if defined(DUK_USE_REPL_ISNAN) +DUK_INTERNAL_DECL int duk_repl_isnan(double x); +#endif +#if defined(DUK_USE_REPL_ISINF) +DUK_INTERNAL_DECL int duk_repl_isinf(double x); +#endif + +#endif /* DUK_REPLACEMENTS_H_INCLUDED */ +/* #include duk_jmpbuf.h */ +#line 1 "duk_jmpbuf.h" +/* + * Wrapper for jmp_buf. + * + * This is used because jmp_buf is an array type for backward compatibility. + * Wrapping jmp_buf in a struct makes pointer references, sizeof, etc, + * behave more intuitively. + * + * http://en.wikipedia.org/wiki/Setjmp.h#Member_types + */ + +#if !defined(DUK_JMPBUF_H_INCLUDED) +#define DUK_JMPBUF_H_INCLUDED + +#if defined(DUK_USE_CPP_EXCEPTIONS) +struct duk_jmpbuf { + duk_small_int_t dummy; /* unused */ +}; +#else +struct duk_jmpbuf { + DUK_JMPBUF_TYPE jb; +}; +#endif + +#endif /* DUK_JMPBUF_H_INCLUDED */ +/* #include duk_exception.h */ +#line 1 "duk_exception.h" +/* + * Exception for Duktape internal throws when C++ exceptions are used + * for long control transfers. + * + * Doesn't inherit from any exception base class to minimize the chance + * that user code would accidentally catch this exception. + */ + +#if !defined(DUK_EXCEPTION_H_INCLUDED) +#define DUK_EXCEPTION_H_INCLUDED + +#if defined(DUK_USE_CPP_EXCEPTIONS) +class duk_internal_exception { + /* intentionally empty */ +}; +#endif + +#endif /* DUK_EXCEPTION_H_INCLUDED */ +/* #include duk_forwdecl.h */ +#line 1 "duk_forwdecl.h" +/* + * Forward declarations for all Duktape structures. + */ + +#if !defined(DUK_FORWDECL_H_INCLUDED) +#define DUK_FORWDECL_H_INCLUDED + +/* + * Forward declarations + */ + +#if defined(DUK_USE_CPP_EXCEPTIONS) +class duk_internal_exception; +#else +struct duk_jmpbuf; +#endif + +/* duk_tval intentionally skipped */ +struct duk_heaphdr; +struct duk_heaphdr_string; +struct duk_harray; +struct duk_hstring; +struct duk_hstring_external; +struct duk_hobject; +struct duk_hcompfunc; +struct duk_hnatfunc; +struct duk_hboundfunc; +struct duk_hthread; +struct duk_hbufobj; +struct duk_hdecenv; +struct duk_hobjenv; +struct duk_hproxy; +struct duk_hbuffer; +struct duk_hbuffer_fixed; +struct duk_hbuffer_dynamic; +struct duk_hbuffer_external; + +struct duk_propaccessor; +union duk_propvalue; +struct duk_propdesc; + +struct duk_heap; +struct duk_breakpoint; + +struct duk_activation; +struct duk_catcher; +struct duk_strcache; +struct duk_ljstate; +struct duk_strtab_entry; + +#if defined(DUK_USE_DEBUG) +struct duk_fixedbuffer; +#endif + +struct duk_bitdecoder_ctx; +struct duk_bitencoder_ctx; +struct duk_bufwriter_ctx; + +struct duk_token; +struct duk_re_token; +struct duk_lexer_point; +struct duk_lexer_ctx; +struct duk_lexer_codepoint; + +struct duk_compiler_instr; +struct duk_compiler_func; +struct duk_compiler_ctx; + +struct duk_re_matcher_ctx; +struct duk_re_compiler_ctx; + +#if defined(DUK_USE_CPP_EXCEPTIONS) +/* no typedef */ +#else +typedef struct duk_jmpbuf duk_jmpbuf; +#endif + +/* duk_tval intentionally skipped */ +typedef struct duk_heaphdr duk_heaphdr; +typedef struct duk_heaphdr_string duk_heaphdr_string; +typedef struct duk_harray duk_harray; +typedef struct duk_hstring duk_hstring; +typedef struct duk_hstring_external duk_hstring_external; +typedef struct duk_hobject duk_hobject; +typedef struct duk_hcompfunc duk_hcompfunc; +typedef struct duk_hnatfunc duk_hnatfunc; +typedef struct duk_hboundfunc duk_hboundfunc; +typedef struct duk_hthread duk_hthread; +typedef struct duk_hbufobj duk_hbufobj; +typedef struct duk_hdecenv duk_hdecenv; +typedef struct duk_hobjenv duk_hobjenv; +typedef struct duk_hproxy duk_hproxy; +typedef struct duk_hbuffer duk_hbuffer; +typedef struct duk_hbuffer_fixed duk_hbuffer_fixed; +typedef struct duk_hbuffer_dynamic duk_hbuffer_dynamic; +typedef struct duk_hbuffer_external duk_hbuffer_external; + +typedef struct duk_propaccessor duk_propaccessor; +typedef union duk_propvalue duk_propvalue; +typedef struct duk_propdesc duk_propdesc; + +typedef struct duk_heap duk_heap; +typedef struct duk_breakpoint duk_breakpoint; + +typedef struct duk_activation duk_activation; +typedef struct duk_catcher duk_catcher; +typedef struct duk_strcache duk_strcache; +typedef struct duk_ljstate duk_ljstate; +typedef struct duk_strtab_entry duk_strtab_entry; + +#if defined(DUK_USE_DEBUG) +typedef struct duk_fixedbuffer duk_fixedbuffer; +#endif + +typedef struct duk_bitdecoder_ctx duk_bitdecoder_ctx; +typedef struct duk_bitencoder_ctx duk_bitencoder_ctx; +typedef struct duk_bufwriter_ctx duk_bufwriter_ctx; + +typedef struct duk_token duk_token; +typedef struct duk_re_token duk_re_token; +typedef struct duk_lexer_point duk_lexer_point; +typedef struct duk_lexer_ctx duk_lexer_ctx; +typedef struct duk_lexer_codepoint duk_lexer_codepoint; + +typedef struct duk_compiler_instr duk_compiler_instr; +typedef struct duk_compiler_func duk_compiler_func; +typedef struct duk_compiler_ctx duk_compiler_ctx; + +typedef struct duk_re_matcher_ctx duk_re_matcher_ctx; +typedef struct duk_re_compiler_ctx duk_re_compiler_ctx; + +#endif /* DUK_FORWDECL_H_INCLUDED */ +/* #include duk_tval.h */ +#line 1 "duk_tval.h" +/* + * Tagged type definition (duk_tval) and accessor macros. + * + * Access all fields through the accessor macros, as the representation + * is quite tricky. + * + * There are two packed type alternatives: an 8-byte representation + * based on an IEEE double (preferred for compactness), and a 12-byte + * representation (portability). The latter is needed also in e.g. + * 64-bit environments (it usually pads to 16 bytes per value). + * + * Selecting the tagged type format involves many trade-offs (memory + * use, size and performance of generated code, portability, etc). + * + * NB: because macro arguments are often expressions, macros should + * avoid evaluating their argument more than once. + */ + +#if !defined(DUK_TVAL_H_INCLUDED) +#define DUK_TVAL_H_INCLUDED + +/* sanity */ +#if !defined(DUK_USE_DOUBLE_LE) && !defined(DUK_USE_DOUBLE_ME) && !defined(DUK_USE_DOUBLE_BE) +#error unsupported: cannot determine byte order variant +#endif + +#if defined(DUK_USE_PACKED_TVAL) +/* ======================================================================== */ + +/* + * Packed 8-byte representation + */ + +/* use duk_double_union as duk_tval directly */ +typedef union duk_double_union duk_tval; +typedef struct { + duk_uint16_t a; + duk_uint16_t b; + duk_uint16_t c; + duk_uint16_t d; +} duk_tval_unused; + +/* tags */ +#define DUK_TAG_NORMALIZED_NAN 0x7ff8UL /* the NaN variant we use */ +/* avoid tag 0xfff0, no risk of confusion with negative infinity */ +#define DUK_TAG_MIN 0xfff1UL +#if defined(DUK_USE_FASTINT) +#define DUK_TAG_FASTINT 0xfff1UL /* embed: integer value */ +#endif +#define DUK_TAG_UNUSED 0xfff2UL /* marker; not actual tagged value */ +#define DUK_TAG_UNDEFINED 0xfff3UL /* embed: nothing */ +#define DUK_TAG_NULL 0xfff4UL /* embed: nothing */ +#define DUK_TAG_BOOLEAN 0xfff5UL /* embed: 0 or 1 (false or true) */ +/* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */ +#define DUK_TAG_POINTER 0xfff6UL /* embed: void ptr */ +#define DUK_TAG_LIGHTFUNC 0xfff7UL /* embed: func ptr */ +#define DUK_TAG_STRING 0xfff8UL /* embed: duk_hstring ptr */ +#define DUK_TAG_OBJECT 0xfff9UL /* embed: duk_hobject ptr */ +#define DUK_TAG_BUFFER 0xfffaUL /* embed: duk_hbuffer ptr */ +#define DUK_TAG_MAX 0xfffaUL + +/* for convenience */ +#define DUK_XTAG_BOOLEAN_FALSE 0xfff50000UL +#define DUK_XTAG_BOOLEAN_TRUE 0xfff50001UL + +#define DUK_TVAL_IS_VALID_TAG(tv) \ + (DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN) + +/* DUK_TVAL_UNUSED initializer for duk_tval_unused, works for any endianness. */ +#define DUK_TVAL_UNUSED_INITIALIZER() \ + { DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED } + +/* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */ +#if defined(DUK_USE_64BIT_OPS) +#if defined(DUK_USE_DOUBLE_ME) +#define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag) do { \ + (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \ + } while (0) +#else +#define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag) do { \ + (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \ + } while (0) +#endif +#else /* DUK_USE_64BIT_OPS */ +#define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \ + duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \ + } while (0) +#endif /* DUK_USE_64BIT_OPS */ + +#if defined(DUK_USE_64BIT_OPS) +/* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */ +#if defined(DUK_USE_DOUBLE_ME) +#define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \ + (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \ + ((duk_uint64_t) (flags)) | \ + (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \ + } while (0) +#else +#define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \ + (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \ + (((duk_uint64_t) (flags)) << 32) | \ + ((duk_uint64_t) (duk_uint32_t) (fp)); \ + } while (0) +#endif +#else /* DUK_USE_64BIT_OPS */ +#define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \ + duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \ + } while (0) +#endif /* DUK_USE_64BIT_OPS */ + +#if defined(DUK_USE_FASTINT) +/* Note: masking is done for 'i' to deal with negative numbers correctly */ +#if defined(DUK_USE_DOUBLE_ME) +#define DUK__TVAL_SET_I48(tv,i) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \ + duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \ + } while (0) +#define DUK__TVAL_SET_U32(tv,i) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \ + duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \ + } while (0) +#else +#define DUK__TVAL_SET_I48(tv,i) do { \ + (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & DUK_U64_CONSTANT(0x0000ffffffffffff)); \ + } while (0) +#define DUK__TVAL_SET_U32(tv,i) do { \ + (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \ + } while (0) +#endif + +/* This needs to go through a cast because sign extension is needed. */ +#define DUK__TVAL_SET_I32(tv,i) do { \ + duk_int64_t duk__tmp = (duk_int64_t) (i); \ + DUK_TVAL_SET_I48((tv), duk__tmp); \ + } while (0) + +/* XXX: Clumsy sign extend and masking of 16 topmost bits. */ +#if defined(DUK_USE_DOUBLE_ME) +#define DUK__TVAL_GET_FASTINT(tv) (((duk_int64_t) ((((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI0]) << 32) | ((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI1]))) << 16 >> 16) +#else +#define DUK__TVAL_GET_FASTINT(tv) ((((duk_int64_t) (tv)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16) +#endif +#define DUK__TVAL_GET_FASTINT_U32(tv) ((tv)->ui[DUK_DBL_IDX_UI1]) +#define DUK__TVAL_GET_FASTINT_I32(tv) ((duk_int32_t) (tv)->ui[DUK_DBL_IDX_UI1]) +#endif /* DUK_USE_FASTINT */ + +#define DUK_TVAL_SET_UNDEFINED(tv) do { \ + (tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \ + } while (0) +#define DUK_TVAL_SET_UNUSED(tv) do { \ + (tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \ + } while (0) +#define DUK_TVAL_SET_NULL(tv) do { \ + (tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \ + } while (0) + +#define DUK_TVAL_SET_BOOLEAN(tv,val) DUK_DBLUNION_SET_HIGH32((tv), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val))) + +#define DUK_TVAL_SET_NAN(tv) DUK_DBLUNION_SET_NAN_FULL((tv)) + +/* Assumes that caller has normalized NaNs, otherwise trouble ahead. */ +#if defined(DUK_USE_FASTINT) +#define DUK_TVAL_SET_DOUBLE(tv,d) do { \ + duk_double_t duk__dblval; \ + duk__dblval = (d); \ + DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \ + DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \ + } while (0) +#define DUK_TVAL_SET_I48(tv,i) DUK__TVAL_SET_I48((tv), (i)) +#define DUK_TVAL_SET_I32(tv,i) DUK__TVAL_SET_I32((tv), (i)) +#define DUK_TVAL_SET_U32(tv,i) DUK__TVAL_SET_U32((tv), (i)) +#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) duk_tval_set_number_chkfast_fast((tv), (d)) +#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) duk_tval_set_number_chkfast_slow((tv), (d)) +#define DUK_TVAL_SET_NUMBER(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d)) +#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { \ + duk_tval *duk__tv; \ + duk_double_t duk__d; \ + duk__tv = (tv); \ + if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \ + duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \ + DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \ + } \ + } while (0) +#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { \ + duk_tval *duk__tv; \ + duk_double_t duk__d; \ + duk__tv = (tv); \ + if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \ + duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \ + DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \ + } \ + } while (0) +#else /* DUK_USE_FASTINT */ +#define DUK_TVAL_SET_DOUBLE(tv,d) do { \ + duk_double_t duk__dblval; \ + duk__dblval = (d); \ + DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \ + DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \ + } while (0) +#define DUK_TVAL_SET_I48(tv,i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i)) /* XXX: fast int-to-double */ +#define DUK_TVAL_SET_I32(tv,i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i)) +#define DUK_TVAL_SET_U32(tv,i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i)) +#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d)) +#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d)) +#define DUK_TVAL_SET_NUMBER(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d)) +#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { } while (0) +#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { } while (0) +#endif /* DUK_USE_FASTINT */ + +#define DUK_TVAL_SET_FASTINT(tv,i) DUK_TVAL_SET_I48((tv), (i)) /* alias */ + +#define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags) DUK__TVAL_SET_LIGHTFUNC((tv), (fp), (flags)) +#define DUK_TVAL_SET_STRING(tv,h) DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_STRING) +#define DUK_TVAL_SET_OBJECT(tv,h) DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_OBJECT) +#define DUK_TVAL_SET_BUFFER(tv,h) DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_BUFFER) +#define DUK_TVAL_SET_POINTER(tv,p) DUK__TVAL_SET_TAGGEDPOINTER((tv), (p), DUK_TAG_POINTER) + +#define DUK_TVAL_SET_TVAL(tv,x) do { *(tv) = *(x); } while (0) + +/* getters */ +#define DUK_TVAL_GET_BOOLEAN(tv) ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US1]) +#if defined(DUK_USE_FASTINT) +#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->d) +#define DUK_TVAL_GET_FASTINT(tv) DUK__TVAL_GET_FASTINT((tv)) +#define DUK_TVAL_GET_FASTINT_U32(tv) DUK__TVAL_GET_FASTINT_U32((tv)) +#define DUK_TVAL_GET_FASTINT_I32(tv) DUK__TVAL_GET_FASTINT_I32((tv)) +#define DUK_TVAL_GET_NUMBER(tv) duk_tval_get_number_packed((tv)) +#else +#define DUK_TVAL_GET_NUMBER(tv) ((tv)->d) +#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->d) +#endif +#define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags) do { \ + (out_flags) = (tv)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \ + (out_fp) = (duk_c_function) (tv)->ui[DUK_DBL_IDX_UI1]; \ + } while (0) +#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((duk_c_function) ((tv)->ui[DUK_DBL_IDX_UI1])) +#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv) (((duk_small_uint_t) (tv)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL) +#define DUK_TVAL_GET_STRING(tv) ((duk_hstring *) (tv)->vp[DUK_DBL_IDX_VP1]) +#define DUK_TVAL_GET_OBJECT(tv) ((duk_hobject *) (tv)->vp[DUK_DBL_IDX_VP1]) +#define DUK_TVAL_GET_BUFFER(tv) ((duk_hbuffer *) (tv)->vp[DUK_DBL_IDX_VP1]) +#define DUK_TVAL_GET_POINTER(tv) ((void *) (tv)->vp[DUK_DBL_IDX_VP1]) +#define DUK_TVAL_GET_HEAPHDR(tv) ((duk_heaphdr *) (tv)->vp[DUK_DBL_IDX_VP1]) + +/* decoding */ +#define DUK_TVAL_GET_TAG(tv) ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US0]) + +#define DUK_TVAL_IS_UNDEFINED(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNDEFINED) +#define DUK_TVAL_IS_UNUSED(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNUSED) +#define DUK_TVAL_IS_NULL(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_NULL) +#define DUK_TVAL_IS_BOOLEAN(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BOOLEAN) +#define DUK_TVAL_IS_BOOLEAN_TRUE(tv) ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE) +#define DUK_TVAL_IS_BOOLEAN_FALSE(tv) ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE) +#define DUK_TVAL_IS_LIGHTFUNC(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_LIGHTFUNC) +#define DUK_TVAL_IS_STRING(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_STRING) +#define DUK_TVAL_IS_OBJECT(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_OBJECT) +#define DUK_TVAL_IS_BUFFER(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BUFFER) +#define DUK_TVAL_IS_POINTER(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_POINTER) +#if defined(DUK_USE_FASTINT) +/* 0xfff0 is -Infinity */ +#define DUK_TVAL_IS_DOUBLE(tv) (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL) +#define DUK_TVAL_IS_FASTINT(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_FASTINT) +#define DUK_TVAL_IS_NUMBER(tv) (DUK_TVAL_GET_TAG((tv)) <= 0xfff1UL) +#else +#define DUK_TVAL_IS_NUMBER(tv) (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL) +#define DUK_TVAL_IS_DOUBLE(tv) DUK_TVAL_IS_NUMBER((tv)) +#endif + +/* This is performance critical because it appears in every DECREF. */ +#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) (DUK_TVAL_GET_TAG((tv)) >= DUK_TAG_STRING) + +#if defined(DUK_USE_FASTINT) +DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv); +#endif + +#else /* DUK_USE_PACKED_TVAL */ +/* ======================================================================== */ + +/* + * Portable 12-byte representation + */ + +/* Note: not initializing all bytes is normally not an issue: Duktape won't + * read or use the uninitialized bytes so valgrind won't issue warnings. + * In some special cases a harmless valgrind warning may be issued though. + * For example, the DumpHeap debugger command writes out a compiled function's + * 'data' area as is, including any uninitialized bytes, which causes a + * valgrind warning. + */ + +typedef struct duk_tval_struct duk_tval; + +struct duk_tval_struct { + duk_small_uint_t t; + duk_small_uint_t v_extra; + union { + duk_double_t d; + duk_small_int_t i; +#if defined(DUK_USE_FASTINT) + duk_int64_t fi; /* if present, forces 16-byte duk_tval */ +#endif + void *voidptr; + duk_hstring *hstring; + duk_hobject *hobject; + duk_hcompfunc *hcompfunc; + duk_hnatfunc *hnatfunc; + duk_hthread *hthread; + duk_hbuffer *hbuffer; + duk_heaphdr *heaphdr; + duk_c_function lightfunc; + } v; +}; + +typedef struct { + duk_small_uint_t t; + duk_small_uint_t v_extra; + /* The rest of the fields don't matter except for debug dumps and such + * for which a partial initializer may trigger out-ot-bounds memory + * reads. Include a double field which is usually as large or larger + * than pointers (not always however). + */ + duk_double_t d; +} duk_tval_unused; + +#define DUK_TVAL_UNUSED_INITIALIZER() \ + { DUK_TAG_UNUSED, 0, 0.0 } + +#define DUK_TAG_MIN 0 +#define DUK_TAG_NUMBER 0 /* DUK_TAG_NUMBER only defined for non-packed duk_tval */ +#if defined(DUK_USE_FASTINT) +#define DUK_TAG_FASTINT 1 +#endif +#define DUK_TAG_UNDEFINED 2 +#define DUK_TAG_NULL 3 +#define DUK_TAG_BOOLEAN 4 +#define DUK_TAG_POINTER 5 +#define DUK_TAG_LIGHTFUNC 6 +#define DUK_TAG_UNUSED 7 /* marker; not actual tagged type */ +#define DUK_TAG_STRING 8 /* first heap allocated, match bit boundary */ +#define DUK_TAG_OBJECT 9 +#define DUK_TAG_BUFFER 10 +#define DUK_TAG_MAX 10 + +#define DUK_TVAL_IS_VALID_TAG(tv) \ + (DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN) + +/* DUK_TAG_NUMBER is intentionally first, as it is the default clause in code + * to support the 8-byte representation. Further, it is a non-heap-allocated + * type so it should come before DUK_TAG_STRING. Finally, it should not break + * the tag value ranges covered by case-clauses in a switch-case. + */ + +/* setters */ +#define DUK_TVAL_SET_UNDEFINED(tv) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->t = DUK_TAG_UNDEFINED; \ + } while (0) + +#define DUK_TVAL_SET_UNUSED(tv) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->t = DUK_TAG_UNUSED; \ + } while (0) + +#define DUK_TVAL_SET_NULL(tv) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->t = DUK_TAG_NULL; \ + } while (0) + +#define DUK_TVAL_SET_BOOLEAN(tv,val) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->t = DUK_TAG_BOOLEAN; \ + duk__tv->v.i = (duk_small_int_t) (val); \ + } while (0) + +#if defined(DUK_USE_FASTINT) +#define DUK_TVAL_SET_DOUBLE(tv,val) do { \ + duk_tval *duk__tv; \ + duk_double_t duk__dblval; \ + duk__dblval = (val); \ + DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \ + duk__tv = (tv); \ + duk__tv->t = DUK_TAG_NUMBER; \ + duk__tv->v.d = duk__dblval; \ + } while (0) +#define DUK_TVAL_SET_I48(tv,val) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->t = DUK_TAG_FASTINT; \ + duk__tv->v.fi = (val); \ + } while (0) +#define DUK_TVAL_SET_U32(tv,val) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->t = DUK_TAG_FASTINT; \ + duk__tv->v.fi = (duk_int64_t) (val); \ + } while (0) +#define DUK_TVAL_SET_I32(tv,val) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->t = DUK_TAG_FASTINT; \ + duk__tv->v.fi = (duk_int64_t) (val); \ + } while (0) +#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \ + duk_tval_set_number_chkfast_fast((tv), (d)) +#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \ + duk_tval_set_number_chkfast_slow((tv), (d)) +#define DUK_TVAL_SET_NUMBER(tv,val) \ + DUK_TVAL_SET_DOUBLE((tv), (val)) +#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { \ + duk_tval *duk__tv; \ + duk_double_t duk__d; \ + duk__tv = (tv); \ + if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \ + duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \ + DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \ + } \ + } while (0) +#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { \ + duk_tval *duk__tv; \ + duk_double_t duk__d; \ + duk__tv = (tv); \ + if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \ + duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \ + DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \ + } \ + } while (0) +#else /* DUK_USE_FASTINT */ +#define DUK_TVAL_SET_DOUBLE(tv,d) \ + DUK_TVAL_SET_NUMBER((tv), (d)) +#define DUK_TVAL_SET_I48(tv,val) \ + DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val)) /* XXX: fast int-to-double */ +#define DUK_TVAL_SET_U32(tv,val) \ + DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val)) +#define DUK_TVAL_SET_I32(tv,val) \ + DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val)) +#define DUK_TVAL_SET_NUMBER(tv,val) do { \ + duk_tval *duk__tv; \ + duk_double_t duk__dblval; \ + duk__dblval = (val); \ + DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \ + duk__tv = (tv); \ + duk__tv->t = DUK_TAG_NUMBER; \ + duk__tv->v.d = duk__dblval; \ + } while (0) +#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \ + DUK_TVAL_SET_NUMBER((tv), (d)) +#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \ + DUK_TVAL_SET_NUMBER((tv), (d)) +#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { } while (0) +#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { } while (0) +#endif /* DUK_USE_FASTINT */ + +#define DUK_TVAL_SET_FASTINT(tv,i) \ + DUK_TVAL_SET_I48((tv), (i)) /* alias */ + +#define DUK_TVAL_SET_POINTER(tv,hptr) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->t = DUK_TAG_POINTER; \ + duk__tv->v.voidptr = (hptr); \ + } while (0) + +#define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->t = DUK_TAG_LIGHTFUNC; \ + duk__tv->v_extra = (flags); \ + duk__tv->v.lightfunc = (duk_c_function) (fp); \ + } while (0) + +#define DUK_TVAL_SET_STRING(tv,hptr) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->t = DUK_TAG_STRING; \ + duk__tv->v.hstring = (hptr); \ + } while (0) + +#define DUK_TVAL_SET_OBJECT(tv,hptr) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->t = DUK_TAG_OBJECT; \ + duk__tv->v.hobject = (hptr); \ + } while (0) + +#define DUK_TVAL_SET_BUFFER(tv,hptr) do { \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->t = DUK_TAG_BUFFER; \ + duk__tv->v.hbuffer = (hptr); \ + } while (0) + +#define DUK_TVAL_SET_NAN(tv) do { \ + /* in non-packed representation we don't care about which NaN is used */ \ + duk_tval *duk__tv; \ + duk__tv = (tv); \ + duk__tv->t = DUK_TAG_NUMBER; \ + duk__tv->v.d = DUK_DOUBLE_NAN; \ + } while (0) + +#define DUK_TVAL_SET_TVAL(tv,x) do { *(tv) = *(x); } while (0) + +/* getters */ +#define DUK_TVAL_GET_BOOLEAN(tv) ((duk_small_uint_t) (tv)->v.i) +#if defined(DUK_USE_FASTINT) +#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d) +#define DUK_TVAL_GET_FASTINT(tv) ((tv)->v.fi) +#define DUK_TVAL_GET_FASTINT_U32(tv) ((duk_uint32_t) ((tv)->v.fi)) +#define DUK_TVAL_GET_FASTINT_I32(tv) ((duk_int32_t) ((tv)->v.fi)) +#if 0 +#define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? \ + (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \ + DUK_TVAL_GET_DOUBLE((tv))) +#define DUK_TVAL_GET_NUMBER(tv) duk_tval_get_number_unpacked((tv)) +#else +/* This seems reasonable overall. */ +#define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? \ + duk_tval_get_number_unpacked_fastint((tv)) : \ + DUK_TVAL_GET_DOUBLE((tv))) +#endif +#else +#define DUK_TVAL_GET_NUMBER(tv) ((tv)->v.d) +#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d) +#endif /* DUK_USE_FASTINT */ +#define DUK_TVAL_GET_POINTER(tv) ((tv)->v.voidptr) +#define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags) do { \ + (out_flags) = (duk_uint32_t) (tv)->v_extra; \ + (out_fp) = (tv)->v.lightfunc; \ + } while (0) +#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc) +#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv) ((duk_small_uint_t) ((tv)->v_extra)) +#define DUK_TVAL_GET_STRING(tv) ((tv)->v.hstring) +#define DUK_TVAL_GET_OBJECT(tv) ((tv)->v.hobject) +#define DUK_TVAL_GET_BUFFER(tv) ((tv)->v.hbuffer) +#define DUK_TVAL_GET_HEAPHDR(tv) ((tv)->v.heaphdr) + +/* decoding */ +#define DUK_TVAL_GET_TAG(tv) ((tv)->t) +#define DUK_TVAL_IS_UNDEFINED(tv) ((tv)->t == DUK_TAG_UNDEFINED) +#define DUK_TVAL_IS_UNUSED(tv) ((tv)->t == DUK_TAG_UNUSED) +#define DUK_TVAL_IS_NULL(tv) ((tv)->t == DUK_TAG_NULL) +#define DUK_TVAL_IS_BOOLEAN(tv) ((tv)->t == DUK_TAG_BOOLEAN) +#define DUK_TVAL_IS_BOOLEAN_TRUE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0)) +#define DUK_TVAL_IS_BOOLEAN_FALSE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0)) +#if defined(DUK_USE_FASTINT) +#define DUK_TVAL_IS_DOUBLE(tv) ((tv)->t == DUK_TAG_NUMBER) +#define DUK_TVAL_IS_FASTINT(tv) ((tv)->t == DUK_TAG_FASTINT) +#define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK_TAG_NUMBER || \ + (tv)->t == DUK_TAG_FASTINT) +#else +#define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK_TAG_NUMBER) +#define DUK_TVAL_IS_DOUBLE(tv) DUK_TVAL_IS_NUMBER((tv)) +#endif /* DUK_USE_FASTINT */ +#define DUK_TVAL_IS_POINTER(tv) ((tv)->t == DUK_TAG_POINTER) +#define DUK_TVAL_IS_LIGHTFUNC(tv) ((tv)->t == DUK_TAG_LIGHTFUNC) +#define DUK_TVAL_IS_STRING(tv) ((tv)->t == DUK_TAG_STRING) +#define DUK_TVAL_IS_OBJECT(tv) ((tv)->t == DUK_TAG_OBJECT) +#define DUK_TVAL_IS_BUFFER(tv) ((tv)->t == DUK_TAG_BUFFER) + +/* This is performance critical because it's needed for every DECREF. + * Take advantage of the fact that the first heap allocated tag is 8, + * so that bit 3 is set for all heap allocated tags (and never set for + * non-heap-allocated tags). + */ +#if 0 +#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t >= DUK_TAG_STRING) +#endif +#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t & 0x08) + +#if defined(DUK_USE_FASTINT) +#if 0 +DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv); +#endif +DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv); +#endif + +#endif /* DUK_USE_PACKED_TVAL */ + +/* + * Convenience (independent of representation) + */ + +#define DUK_TVAL_SET_BOOLEAN_TRUE(tv) DUK_TVAL_SET_BOOLEAN((tv), 1) +#define DUK_TVAL_SET_BOOLEAN_FALSE(tv) DUK_TVAL_SET_BOOLEAN((tv), 0) + +#define DUK_TVAL_STRING_IS_SYMBOL(tv) \ + DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING((tv))) + +/* Lightfunc flags packing and unpacking. */ +/* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss##. + * Avoid signed shifts due to portability limitations. + */ +#define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \ + ((duk_int32_t) (duk_int8_t) (((duk_uint16_t) (lf_flags)) >> 8)) +#define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \ + (((lf_flags) >> 4) & 0x0fU) +#define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \ + ((lf_flags) & 0x0fU) +#define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \ + ((((duk_small_uint_t) (magic)) & 0xffU) << 8) | ((length) << 4) | (nargs) + +#define DUK_LFUNC_NARGS_VARARGS 0x0f /* varargs marker */ +#define DUK_LFUNC_NARGS_MIN 0x00 +#define DUK_LFUNC_NARGS_MAX 0x0e /* max, excl. varargs marker */ +#define DUK_LFUNC_LENGTH_MIN 0x00 +#define DUK_LFUNC_LENGTH_MAX 0x0f +#define DUK_LFUNC_MAGIC_MIN (-0x80) +#define DUK_LFUNC_MAGIC_MAX 0x7f + +/* fastint constants etc */ +#if defined(DUK_USE_FASTINT) +#define DUK_FASTINT_MIN (DUK_I64_CONSTANT(-0x800000000000)) +#define DUK_FASTINT_MAX (DUK_I64_CONSTANT(0x7fffffffffff)) +#define DUK_FASTINT_BITS 48 + +DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x); +DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x); +#endif + +#endif /* DUK_TVAL_H_INCLUDED */ +/* #include duk_builtins.h */ +#line 1 "duk_builtins.h" +/* + * Automatically generated by genbuiltins.py, do not edit! + */ + +#if !defined(DUK_BUILTINS_H_INCLUDED) +#define DUK_BUILTINS_H_INCLUDED + +#if defined(DUK_USE_ROM_STRINGS) +#error ROM support not enabled, rerun configure.py with --rom-support +#else /* DUK_USE_ROM_STRINGS */ +#define DUK_STRIDX_UC_UNDEFINED 0 /* 'Undefined' */ +#define DUK_HEAP_STRING_UC_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_UNDEFINED) +#define DUK_HTHREAD_STRING_UC_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_UNDEFINED) +#define DUK_STRIDX_UC_NULL 1 /* 'Null' */ +#define DUK_HEAP_STRING_UC_NULL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NULL) +#define DUK_HTHREAD_STRING_UC_NULL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NULL) +#define DUK_STRIDX_UC_SYMBOL 2 /* 'Symbol' */ +#define DUK_HEAP_STRING_UC_SYMBOL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_SYMBOL) +#define DUK_HTHREAD_STRING_UC_SYMBOL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_SYMBOL) +#define DUK_STRIDX_UC_ARGUMENTS 3 /* 'Arguments' */ +#define DUK_HEAP_STRING_UC_ARGUMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARGUMENTS) +#define DUK_HTHREAD_STRING_UC_ARGUMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARGUMENTS) +#define DUK_STRIDX_UC_OBJECT 4 /* 'Object' */ +#define DUK_HEAP_STRING_UC_OBJECT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_OBJECT) +#define DUK_HTHREAD_STRING_UC_OBJECT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_OBJECT) +#define DUK_STRIDX_UC_FUNCTION 5 /* 'Function' */ +#define DUK_HEAP_STRING_UC_FUNCTION(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_FUNCTION) +#define DUK_HTHREAD_STRING_UC_FUNCTION(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_FUNCTION) +#define DUK_STRIDX_ARRAY 6 /* 'Array' */ +#define DUK_HEAP_STRING_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY) +#define DUK_HTHREAD_STRING_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY) +#define DUK_STRIDX_UC_STRING 7 /* 'String' */ +#define DUK_HEAP_STRING_UC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_STRING) +#define DUK_HTHREAD_STRING_UC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_STRING) +#define DUK_STRIDX_UC_BOOLEAN 8 /* 'Boolean' */ +#define DUK_HEAP_STRING_UC_BOOLEAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BOOLEAN) +#define DUK_HTHREAD_STRING_UC_BOOLEAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BOOLEAN) +#define DUK_STRIDX_UC_NUMBER 9 /* 'Number' */ +#define DUK_HEAP_STRING_UC_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NUMBER) +#define DUK_HTHREAD_STRING_UC_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NUMBER) +#define DUK_STRIDX_DATE 10 /* 'Date' */ +#define DUK_HEAP_STRING_DATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATE) +#define DUK_HTHREAD_STRING_DATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATE) +#define DUK_STRIDX_REG_EXP 11 /* 'RegExp' */ +#define DUK_HEAP_STRING_REG_EXP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REG_EXP) +#define DUK_HTHREAD_STRING_REG_EXP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REG_EXP) +#define DUK_STRIDX_UC_ERROR 12 /* 'Error' */ +#define DUK_HEAP_STRING_UC_ERROR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ERROR) +#define DUK_HTHREAD_STRING_UC_ERROR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ERROR) +#define DUK_STRIDX_MATH 13 /* 'Math' */ +#define DUK_HEAP_STRING_MATH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MATH) +#define DUK_HTHREAD_STRING_MATH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MATH) +#define DUK_STRIDX_JSON 14 /* 'JSON' */ +#define DUK_HEAP_STRING_JSON(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON) +#define DUK_HTHREAD_STRING_JSON(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON) +#define DUK_STRIDX_EMPTY_STRING 15 /* '' */ +#define DUK_HEAP_STRING_EMPTY_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING) +#define DUK_HTHREAD_STRING_EMPTY_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING) +#define DUK_STRIDX_ARRAY_BUFFER 16 /* 'ArrayBuffer' */ +#define DUK_HEAP_STRING_ARRAY_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER) +#define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER) +#define DUK_STRIDX_DATA_VIEW 17 /* 'DataView' */ +#define DUK_HEAP_STRING_DATA_VIEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW) +#define DUK_HTHREAD_STRING_DATA_VIEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW) +#define DUK_STRIDX_INT8_ARRAY 18 /* 'Int8Array' */ +#define DUK_HEAP_STRING_INT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY) +#define DUK_HTHREAD_STRING_INT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY) +#define DUK_STRIDX_UINT8_ARRAY 19 /* 'Uint8Array' */ +#define DUK_HEAP_STRING_UINT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY) +#define DUK_HTHREAD_STRING_UINT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY) +#define DUK_STRIDX_UINT8_CLAMPED_ARRAY 20 /* 'Uint8ClampedArray' */ +#define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY) +#define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY) +#define DUK_STRIDX_INT16_ARRAY 21 /* 'Int16Array' */ +#define DUK_HEAP_STRING_INT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY) +#define DUK_HTHREAD_STRING_INT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY) +#define DUK_STRIDX_UINT16_ARRAY 22 /* 'Uint16Array' */ +#define DUK_HEAP_STRING_UINT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY) +#define DUK_HTHREAD_STRING_UINT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY) +#define DUK_STRIDX_INT32_ARRAY 23 /* 'Int32Array' */ +#define DUK_HEAP_STRING_INT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY) +#define DUK_HTHREAD_STRING_INT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY) +#define DUK_STRIDX_UINT32_ARRAY 24 /* 'Uint32Array' */ +#define DUK_HEAP_STRING_UINT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY) +#define DUK_HTHREAD_STRING_UINT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY) +#define DUK_STRIDX_FLOAT32_ARRAY 25 /* 'Float32Array' */ +#define DUK_HEAP_STRING_FLOAT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY) +#define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY) +#define DUK_STRIDX_FLOAT64_ARRAY 26 /* 'Float64Array' */ +#define DUK_HEAP_STRING_FLOAT64_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY) +#define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY) +#define DUK_STRIDX_GLOBAL 27 /* 'global' */ +#define DUK_HEAP_STRING_GLOBAL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL) +#define DUK_HTHREAD_STRING_GLOBAL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GLOBAL) +#define DUK_STRIDX_OBJ_ENV 28 /* 'ObjEnv' */ +#define DUK_HEAP_STRING_OBJ_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV) +#define DUK_HTHREAD_STRING_OBJ_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV) +#define DUK_STRIDX_DEC_ENV 29 /* 'DecEnv' */ +#define DUK_HEAP_STRING_DEC_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV) +#define DUK_HTHREAD_STRING_DEC_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV) +#define DUK_STRIDX_UC_BUFFER 30 /* 'Buffer' */ +#define DUK_HEAP_STRING_UC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER) +#define DUK_HTHREAD_STRING_UC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER) +#define DUK_STRIDX_UC_POINTER 31 /* 'Pointer' */ +#define DUK_HEAP_STRING_UC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER) +#define DUK_HTHREAD_STRING_UC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER) +#define DUK_STRIDX_UC_THREAD 32 /* 'Thread' */ +#define DUK_HEAP_STRING_UC_THREAD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_THREAD) +#define DUK_HTHREAD_STRING_UC_THREAD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD) +#define DUK_STRIDX_EVAL 33 /* 'eval' */ +#define DUK_HEAP_STRING_EVAL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EVAL) +#define DUK_HTHREAD_STRING_EVAL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EVAL) +#define DUK_STRIDX_VALUE 34 /* 'value' */ +#define DUK_HEAP_STRING_VALUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE) +#define DUK_HTHREAD_STRING_VALUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE) +#define DUK_STRIDX_WRITABLE 35 /* 'writable' */ +#define DUK_HEAP_STRING_WRITABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITABLE) +#define DUK_HTHREAD_STRING_WRITABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITABLE) +#define DUK_STRIDX_CONFIGURABLE 36 /* 'configurable' */ +#define DUK_HEAP_STRING_CONFIGURABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONFIGURABLE) +#define DUK_HTHREAD_STRING_CONFIGURABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONFIGURABLE) +#define DUK_STRIDX_ENUMERABLE 37 /* 'enumerable' */ +#define DUK_HEAP_STRING_ENUMERABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERABLE) +#define DUK_HTHREAD_STRING_ENUMERABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERABLE) +#define DUK_STRIDX_JOIN 38 /* 'join' */ +#define DUK_HEAP_STRING_JOIN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JOIN) +#define DUK_HTHREAD_STRING_JOIN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JOIN) +#define DUK_STRIDX_TO_LOCALE_STRING 39 /* 'toLocaleString' */ +#define DUK_HEAP_STRING_TO_LOCALE_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOCALE_STRING) +#define DUK_HTHREAD_STRING_TO_LOCALE_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOCALE_STRING) +#define DUK_STRIDX_VALUE_OF 40 /* 'valueOf' */ +#define DUK_HEAP_STRING_VALUE_OF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE_OF) +#define DUK_HTHREAD_STRING_VALUE_OF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE_OF) +#define DUK_STRIDX_TO_UTC_STRING 41 /* 'toUTCString' */ +#define DUK_HEAP_STRING_TO_UTC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_UTC_STRING) +#define DUK_HTHREAD_STRING_TO_UTC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_UTC_STRING) +#define DUK_STRIDX_TO_ISO_STRING 42 /* 'toISOString' */ +#define DUK_HEAP_STRING_TO_ISO_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_ISO_STRING) +#define DUK_HTHREAD_STRING_TO_ISO_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_ISO_STRING) +#define DUK_STRIDX_TO_GMT_STRING 43 /* 'toGMTString' */ +#define DUK_HEAP_STRING_TO_GMT_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_GMT_STRING) +#define DUK_HTHREAD_STRING_TO_GMT_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_GMT_STRING) +#define DUK_STRIDX_SOURCE 44 /* 'source' */ +#define DUK_HEAP_STRING_SOURCE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SOURCE) +#define DUK_HTHREAD_STRING_SOURCE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SOURCE) +#define DUK_STRIDX_IGNORE_CASE 45 /* 'ignoreCase' */ +#define DUK_HEAP_STRING_IGNORE_CASE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IGNORE_CASE) +#define DUK_HTHREAD_STRING_IGNORE_CASE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IGNORE_CASE) +#define DUK_STRIDX_MULTILINE 46 /* 'multiline' */ +#define DUK_HEAP_STRING_MULTILINE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MULTILINE) +#define DUK_HTHREAD_STRING_MULTILINE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MULTILINE) +#define DUK_STRIDX_LAST_INDEX 47 /* 'lastIndex' */ +#define DUK_HEAP_STRING_LAST_INDEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LAST_INDEX) +#define DUK_HTHREAD_STRING_LAST_INDEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LAST_INDEX) +#define DUK_STRIDX_FLAGS 48 /* 'flags' */ +#define DUK_HEAP_STRING_FLAGS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLAGS) +#define DUK_HTHREAD_STRING_FLAGS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLAGS) +#define DUK_STRIDX_INDEX 49 /* 'index' */ +#define DUK_HEAP_STRING_INDEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INDEX) +#define DUK_HTHREAD_STRING_INDEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INDEX) +#define DUK_STRIDX_PROTOTYPE 50 /* 'prototype' */ +#define DUK_HEAP_STRING_PROTOTYPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTOTYPE) +#define DUK_HTHREAD_STRING_PROTOTYPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTOTYPE) +#define DUK_STRIDX_CONSTRUCTOR 51 /* 'constructor' */ +#define DUK_HEAP_STRING_CONSTRUCTOR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCTOR) +#define DUK_HTHREAD_STRING_CONSTRUCTOR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCTOR) +#define DUK_STRIDX_MESSAGE 52 /* 'message' */ +#define DUK_HEAP_STRING_MESSAGE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MESSAGE) +#define DUK_HTHREAD_STRING_MESSAGE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MESSAGE) +#define DUK_STRIDX_LC_BOOLEAN 53 /* 'boolean' */ +#define DUK_HEAP_STRING_LC_BOOLEAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BOOLEAN) +#define DUK_HTHREAD_STRING_LC_BOOLEAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BOOLEAN) +#define DUK_STRIDX_LC_NUMBER 54 /* 'number' */ +#define DUK_HEAP_STRING_LC_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NUMBER) +#define DUK_HTHREAD_STRING_LC_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NUMBER) +#define DUK_STRIDX_LC_STRING 55 /* 'string' */ +#define DUK_HEAP_STRING_LC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_STRING) +#define DUK_HTHREAD_STRING_LC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_STRING) +#define DUK_STRIDX_LC_SYMBOL 56 /* 'symbol' */ +#define DUK_HEAP_STRING_LC_SYMBOL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_SYMBOL) +#define DUK_HTHREAD_STRING_LC_SYMBOL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_SYMBOL) +#define DUK_STRIDX_LC_OBJECT 57 /* 'object' */ +#define DUK_HEAP_STRING_LC_OBJECT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_OBJECT) +#define DUK_HTHREAD_STRING_LC_OBJECT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_OBJECT) +#define DUK_STRIDX_LC_UNDEFINED 58 /* 'undefined' */ +#define DUK_HEAP_STRING_LC_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_UNDEFINED) +#define DUK_HTHREAD_STRING_LC_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_UNDEFINED) +#define DUK_STRIDX_NAN 59 /* 'NaN' */ +#define DUK_HEAP_STRING_NAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAN) +#define DUK_HTHREAD_STRING_NAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAN) +#define DUK_STRIDX_INFINITY 60 /* 'Infinity' */ +#define DUK_HEAP_STRING_INFINITY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INFINITY) +#define DUK_HTHREAD_STRING_INFINITY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INFINITY) +#define DUK_STRIDX_MINUS_INFINITY 61 /* '-Infinity' */ +#define DUK_HEAP_STRING_MINUS_INFINITY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_INFINITY) +#define DUK_HTHREAD_STRING_MINUS_INFINITY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_INFINITY) +#define DUK_STRIDX_MINUS_ZERO 62 /* '-0' */ +#define DUK_HEAP_STRING_MINUS_ZERO(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_ZERO) +#define DUK_HTHREAD_STRING_MINUS_ZERO(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_ZERO) +#define DUK_STRIDX_COMMA 63 /* ',' */ +#define DUK_HEAP_STRING_COMMA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMMA) +#define DUK_HTHREAD_STRING_COMMA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMMA) +#define DUK_STRIDX_NEWLINE_4SPACE 64 /* '\n ' */ +#define DUK_HEAP_STRING_NEWLINE_4SPACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEWLINE_4SPACE) +#define DUK_HTHREAD_STRING_NEWLINE_4SPACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEWLINE_4SPACE) +#define DUK_STRIDX_BRACKETED_ELLIPSIS 65 /* '[...]' */ +#define DUK_HEAP_STRING_BRACKETED_ELLIPSIS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BRACKETED_ELLIPSIS) +#define DUK_HTHREAD_STRING_BRACKETED_ELLIPSIS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BRACKETED_ELLIPSIS) +#define DUK_STRIDX_INVALID_DATE 66 /* 'Invalid Date' */ +#define DUK_HEAP_STRING_INVALID_DATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INVALID_DATE) +#define DUK_HTHREAD_STRING_INVALID_DATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INVALID_DATE) +#define DUK_STRIDX_LC_ARGUMENTS 67 /* 'arguments' */ +#define DUK_HEAP_STRING_LC_ARGUMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ARGUMENTS) +#define DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ARGUMENTS) +#define DUK_STRIDX_CALLEE 68 /* 'callee' */ +#define DUK_HEAP_STRING_CALLEE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLEE) +#define DUK_HTHREAD_STRING_CALLEE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLEE) +#define DUK_STRIDX_CALLER 69 /* 'caller' */ +#define DUK_HEAP_STRING_CALLER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLER) +#define DUK_HTHREAD_STRING_CALLER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLER) +#define DUK_STRIDX_APPLY 70 /* 'apply' */ +#define DUK_HEAP_STRING_APPLY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_APPLY) +#define DUK_HTHREAD_STRING_APPLY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_APPLY) +#define DUK_STRIDX_CONSTRUCT 71 /* 'construct' */ +#define DUK_HEAP_STRING_CONSTRUCT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCT) +#define DUK_HTHREAD_STRING_CONSTRUCT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCT) +#define DUK_STRIDX_DELETE_PROPERTY 72 /* 'deleteProperty' */ +#define DUK_HEAP_STRING_DELETE_PROPERTY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE_PROPERTY) +#define DUK_HTHREAD_STRING_DELETE_PROPERTY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE_PROPERTY) +#define DUK_STRIDX_GET 73 /* 'get' */ +#define DUK_HEAP_STRING_GET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET) +#define DUK_HTHREAD_STRING_GET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET) +#define DUK_STRIDX_HAS 74 /* 'has' */ +#define DUK_HEAP_STRING_HAS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HAS) +#define DUK_HTHREAD_STRING_HAS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HAS) +#define DUK_STRIDX_OWN_KEYS 75 /* 'ownKeys' */ +#define DUK_HEAP_STRING_OWN_KEYS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OWN_KEYS) +#define DUK_HTHREAD_STRING_OWN_KEYS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OWN_KEYS) +#define DUK_STRIDX_SET_PROTOTYPE_OF 76 /* 'setPrototypeOf' */ +#define DUK_HEAP_STRING_SET_PROTOTYPE_OF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_PROTOTYPE_OF) +#define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_PROTOTYPE_OF) +#define DUK_STRIDX___PROTO__ 77 /* '__proto__' */ +#define DUK_HEAP_STRING___PROTO__(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX___PROTO__) +#define DUK_HTHREAD_STRING___PROTO__(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX___PROTO__) +#define DUK_STRIDX_TO_STRING 78 /* 'toString' */ +#define DUK_HEAP_STRING_TO_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_STRING) +#define DUK_HTHREAD_STRING_TO_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_STRING) +#define DUK_STRIDX_TO_JSON 79 /* 'toJSON' */ +#define DUK_HEAP_STRING_TO_JSON(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_JSON) +#define DUK_HTHREAD_STRING_TO_JSON(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_JSON) +#define DUK_STRIDX_TYPE 80 /* 'type' */ +#define DUK_HEAP_STRING_TYPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE) +#define DUK_HTHREAD_STRING_TYPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE) +#define DUK_STRIDX_DATA 81 /* 'data' */ +#define DUK_HEAP_STRING_DATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA) +#define DUK_HTHREAD_STRING_DATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA) +#define DUK_STRIDX_LENGTH 82 /* 'length' */ +#define DUK_HEAP_STRING_LENGTH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH) +#define DUK_HTHREAD_STRING_LENGTH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH) +#define DUK_STRIDX_SET 83 /* 'set' */ +#define DUK_HEAP_STRING_SET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET) +#define DUK_HTHREAD_STRING_SET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET) +#define DUK_STRIDX_STACK 84 /* 'stack' */ +#define DUK_HEAP_STRING_STACK(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK) +#define DUK_HTHREAD_STRING_STACK(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK) +#define DUK_STRIDX_PC 85 /* 'pc' */ +#define DUK_HEAP_STRING_PC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC) +#define DUK_HTHREAD_STRING_PC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC) +#define DUK_STRIDX_LINE_NUMBER 86 /* 'lineNumber' */ +#define DUK_HEAP_STRING_LINE_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER) +#define DUK_HTHREAD_STRING_LINE_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER) +#define DUK_STRIDX_INT_TRACEDATA 87 /* '\x82Tracedata' */ +#define DUK_HEAP_STRING_INT_TRACEDATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA) +#define DUK_HTHREAD_STRING_INT_TRACEDATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA) +#define DUK_STRIDX_NAME 88 /* 'name' */ +#define DUK_HEAP_STRING_NAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME) +#define DUK_HTHREAD_STRING_NAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME) +#define DUK_STRIDX_FILE_NAME 89 /* 'fileName' */ +#define DUK_HEAP_STRING_FILE_NAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME) +#define DUK_HTHREAD_STRING_FILE_NAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME) +#define DUK_STRIDX_LC_POINTER 90 /* 'pointer' */ +#define DUK_HEAP_STRING_LC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER) +#define DUK_HTHREAD_STRING_LC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER) +#define DUK_STRIDX_INT_TARGET 91 /* '\x82Target' */ +#define DUK_HEAP_STRING_INT_TARGET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET) +#define DUK_HTHREAD_STRING_INT_TARGET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET) +#define DUK_STRIDX_INT_NEXT 92 /* '\x82Next' */ +#define DUK_HEAP_STRING_INT_NEXT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT) +#define DUK_HTHREAD_STRING_INT_NEXT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT) +#define DUK_STRIDX_INT_BYTECODE 93 /* '\x82Bytecode' */ +#define DUK_HEAP_STRING_INT_BYTECODE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE) +#define DUK_HTHREAD_STRING_INT_BYTECODE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE) +#define DUK_STRIDX_INT_FORMALS 94 /* '\x82Formals' */ +#define DUK_HEAP_STRING_INT_FORMALS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS) +#define DUK_HTHREAD_STRING_INT_FORMALS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS) +#define DUK_STRIDX_INT_VARMAP 95 /* '\x82Varmap' */ +#define DUK_HEAP_STRING_INT_VARMAP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP) +#define DUK_HTHREAD_STRING_INT_VARMAP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP) +#define DUK_STRIDX_INT_SOURCE 96 /* '\x82Source' */ +#define DUK_HEAP_STRING_INT_SOURCE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE) +#define DUK_HTHREAD_STRING_INT_SOURCE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE) +#define DUK_STRIDX_INT_PC2LINE 97 /* '\x82Pc2line' */ +#define DUK_HEAP_STRING_INT_PC2LINE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE) +#define DUK_HTHREAD_STRING_INT_PC2LINE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE) +#define DUK_STRIDX_INT_MAP 98 /* '\x82Map' */ +#define DUK_HEAP_STRING_INT_MAP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP) +#define DUK_HTHREAD_STRING_INT_MAP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP) +#define DUK_STRIDX_INT_VARENV 99 /* '\x82Varenv' */ +#define DUK_HEAP_STRING_INT_VARENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV) +#define DUK_HTHREAD_STRING_INT_VARENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV) +#define DUK_STRIDX_INT_FINALIZER 100 /* '\x82Finalizer' */ +#define DUK_HEAP_STRING_INT_FINALIZER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER) +#define DUK_HTHREAD_STRING_INT_FINALIZER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER) +#define DUK_STRIDX_INT_VALUE 101 /* '\x82Value' */ +#define DUK_HEAP_STRING_INT_VALUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE) +#define DUK_HTHREAD_STRING_INT_VALUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE) +#define DUK_STRIDX_COMPILE 102 /* 'compile' */ +#define DUK_HEAP_STRING_COMPILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE) +#define DUK_HTHREAD_STRING_COMPILE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE) +#define DUK_STRIDX_INPUT 103 /* 'input' */ +#define DUK_HEAP_STRING_INPUT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT) +#define DUK_HTHREAD_STRING_INPUT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT) +#define DUK_STRIDX_ERR_CREATE 104 /* 'errCreate' */ +#define DUK_HEAP_STRING_ERR_CREATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE) +#define DUK_HTHREAD_STRING_ERR_CREATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE) +#define DUK_STRIDX_ERR_THROW 105 /* 'errThrow' */ +#define DUK_HEAP_STRING_ERR_THROW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW) +#define DUK_HTHREAD_STRING_ERR_THROW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW) +#define DUK_STRIDX_ENV 106 /* 'env' */ +#define DUK_HEAP_STRING_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV) +#define DUK_HTHREAD_STRING_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV) +#define DUK_STRIDX_HEX 107 /* 'hex' */ +#define DUK_HEAP_STRING_HEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX) +#define DUK_HTHREAD_STRING_HEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX) +#define DUK_STRIDX_BASE64 108 /* 'base64' */ +#define DUK_HEAP_STRING_BASE64(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64) +#define DUK_HTHREAD_STRING_BASE64(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64) +#define DUK_STRIDX_JX 109 /* 'jx' */ +#define DUK_HEAP_STRING_JX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX) +#define DUK_HTHREAD_STRING_JX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX) +#define DUK_STRIDX_JC 110 /* 'jc' */ +#define DUK_HEAP_STRING_JC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC) +#define DUK_HTHREAD_STRING_JC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC) +#define DUK_STRIDX_JSON_EXT_UNDEFINED 111 /* '{"_undef":true}' */ +#define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED) +#define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED) +#define DUK_STRIDX_JSON_EXT_NAN 112 /* '{"_nan":true}' */ +#define DUK_HEAP_STRING_JSON_EXT_NAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN) +#define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN) +#define DUK_STRIDX_JSON_EXT_POSINF 113 /* '{"_inf":true}' */ +#define DUK_HEAP_STRING_JSON_EXT_POSINF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF) +#define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF) +#define DUK_STRIDX_JSON_EXT_NEGINF 114 /* '{"_ninf":true}' */ +#define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF) +#define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF) +#define DUK_STRIDX_JSON_EXT_FUNCTION1 115 /* '{"_func":true}' */ +#define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1) +#define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1) +#define DUK_STRIDX_JSON_EXT_FUNCTION2 116 /* '{_func:true}' */ +#define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2) +#define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2) +#define DUK_STRIDX_BREAK 117 /* 'break' */ +#define DUK_HEAP_STRING_BREAK(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK) +#define DUK_HTHREAD_STRING_BREAK(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK) +#define DUK_STRIDX_CASE 118 /* 'case' */ +#define DUK_HEAP_STRING_CASE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE) +#define DUK_HTHREAD_STRING_CASE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE) +#define DUK_STRIDX_CATCH 119 /* 'catch' */ +#define DUK_HEAP_STRING_CATCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH) +#define DUK_HTHREAD_STRING_CATCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH) +#define DUK_STRIDX_CONTINUE 120 /* 'continue' */ +#define DUK_HEAP_STRING_CONTINUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE) +#define DUK_HTHREAD_STRING_CONTINUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE) +#define DUK_STRIDX_DEBUGGER 121 /* 'debugger' */ +#define DUK_HEAP_STRING_DEBUGGER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER) +#define DUK_HTHREAD_STRING_DEBUGGER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER) +#define DUK_STRIDX_DEFAULT 122 /* 'default' */ +#define DUK_HEAP_STRING_DEFAULT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT) +#define DUK_HTHREAD_STRING_DEFAULT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT) +#define DUK_STRIDX_DELETE 123 /* 'delete' */ +#define DUK_HEAP_STRING_DELETE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE) +#define DUK_HTHREAD_STRING_DELETE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE) +#define DUK_STRIDX_DO 124 /* 'do' */ +#define DUK_HEAP_STRING_DO(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO) +#define DUK_HTHREAD_STRING_DO(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO) +#define DUK_STRIDX_ELSE 125 /* 'else' */ +#define DUK_HEAP_STRING_ELSE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE) +#define DUK_HTHREAD_STRING_ELSE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE) +#define DUK_STRIDX_FINALLY 126 /* 'finally' */ +#define DUK_HEAP_STRING_FINALLY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY) +#define DUK_HTHREAD_STRING_FINALLY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY) +#define DUK_STRIDX_FOR 127 /* 'for' */ +#define DUK_HEAP_STRING_FOR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR) +#define DUK_HTHREAD_STRING_FOR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR) +#define DUK_STRIDX_LC_FUNCTION 128 /* 'function' */ +#define DUK_HEAP_STRING_LC_FUNCTION(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION) +#define DUK_HTHREAD_STRING_LC_FUNCTION(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION) +#define DUK_STRIDX_IF 129 /* 'if' */ +#define DUK_HEAP_STRING_IF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF) +#define DUK_HTHREAD_STRING_IF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF) +#define DUK_STRIDX_IN 130 /* 'in' */ +#define DUK_HEAP_STRING_IN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN) +#define DUK_HTHREAD_STRING_IN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN) +#define DUK_STRIDX_INSTANCEOF 131 /* 'instanceof' */ +#define DUK_HEAP_STRING_INSTANCEOF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF) +#define DUK_HTHREAD_STRING_INSTANCEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF) +#define DUK_STRIDX_NEW 132 /* 'new' */ +#define DUK_HEAP_STRING_NEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW) +#define DUK_HTHREAD_STRING_NEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW) +#define DUK_STRIDX_RETURN 133 /* 'return' */ +#define DUK_HEAP_STRING_RETURN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN) +#define DUK_HTHREAD_STRING_RETURN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN) +#define DUK_STRIDX_SWITCH 134 /* 'switch' */ +#define DUK_HEAP_STRING_SWITCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH) +#define DUK_HTHREAD_STRING_SWITCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH) +#define DUK_STRIDX_THIS 135 /* 'this' */ +#define DUK_HEAP_STRING_THIS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS) +#define DUK_HTHREAD_STRING_THIS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS) +#define DUK_STRIDX_THROW 136 /* 'throw' */ +#define DUK_HEAP_STRING_THROW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW) +#define DUK_HTHREAD_STRING_THROW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW) +#define DUK_STRIDX_TRY 137 /* 'try' */ +#define DUK_HEAP_STRING_TRY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY) +#define DUK_HTHREAD_STRING_TRY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY) +#define DUK_STRIDX_TYPEOF 138 /* 'typeof' */ +#define DUK_HEAP_STRING_TYPEOF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF) +#define DUK_HTHREAD_STRING_TYPEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF) +#define DUK_STRIDX_VAR 139 /* 'var' */ +#define DUK_HEAP_STRING_VAR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR) +#define DUK_HTHREAD_STRING_VAR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR) +#define DUK_STRIDX_CONST 140 /* 'const' */ +#define DUK_HEAP_STRING_CONST(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST) +#define DUK_HTHREAD_STRING_CONST(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST) +#define DUK_STRIDX_VOID 141 /* 'void' */ +#define DUK_HEAP_STRING_VOID(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID) +#define DUK_HTHREAD_STRING_VOID(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID) +#define DUK_STRIDX_WHILE 142 /* 'while' */ +#define DUK_HEAP_STRING_WHILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE) +#define DUK_HTHREAD_STRING_WHILE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE) +#define DUK_STRIDX_WITH 143 /* 'with' */ +#define DUK_HEAP_STRING_WITH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH) +#define DUK_HTHREAD_STRING_WITH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH) +#define DUK_STRIDX_CLASS 144 /* 'class' */ +#define DUK_HEAP_STRING_CLASS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS) +#define DUK_HTHREAD_STRING_CLASS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS) +#define DUK_STRIDX_ENUM 145 /* 'enum' */ +#define DUK_HEAP_STRING_ENUM(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM) +#define DUK_HTHREAD_STRING_ENUM(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM) +#define DUK_STRIDX_EXPORT 146 /* 'export' */ +#define DUK_HEAP_STRING_EXPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT) +#define DUK_HTHREAD_STRING_EXPORT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT) +#define DUK_STRIDX_EXTENDS 147 /* 'extends' */ +#define DUK_HEAP_STRING_EXTENDS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS) +#define DUK_HTHREAD_STRING_EXTENDS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS) +#define DUK_STRIDX_IMPORT 148 /* 'import' */ +#define DUK_HEAP_STRING_IMPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT) +#define DUK_HTHREAD_STRING_IMPORT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT) +#define DUK_STRIDX_SUPER 149 /* 'super' */ +#define DUK_HEAP_STRING_SUPER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER) +#define DUK_HTHREAD_STRING_SUPER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER) +#define DUK_STRIDX_LC_NULL 150 /* 'null' */ +#define DUK_HEAP_STRING_LC_NULL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL) +#define DUK_HTHREAD_STRING_LC_NULL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL) +#define DUK_STRIDX_TRUE 151 /* 'true' */ +#define DUK_HEAP_STRING_TRUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE) +#define DUK_HTHREAD_STRING_TRUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE) +#define DUK_STRIDX_FALSE 152 /* 'false' */ +#define DUK_HEAP_STRING_FALSE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE) +#define DUK_HTHREAD_STRING_FALSE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE) +#define DUK_STRIDX_IMPLEMENTS 153 /* 'implements' */ +#define DUK_HEAP_STRING_IMPLEMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS) +#define DUK_HTHREAD_STRING_IMPLEMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS) +#define DUK_STRIDX_INTERFACE 154 /* 'interface' */ +#define DUK_HEAP_STRING_INTERFACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE) +#define DUK_HTHREAD_STRING_INTERFACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE) +#define DUK_STRIDX_LET 155 /* 'let' */ +#define DUK_HEAP_STRING_LET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET) +#define DUK_HTHREAD_STRING_LET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET) +#define DUK_STRIDX_PACKAGE 156 /* 'package' */ +#define DUK_HEAP_STRING_PACKAGE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE) +#define DUK_HTHREAD_STRING_PACKAGE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE) +#define DUK_STRIDX_PRIVATE 157 /* 'private' */ +#define DUK_HEAP_STRING_PRIVATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE) +#define DUK_HTHREAD_STRING_PRIVATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE) +#define DUK_STRIDX_PROTECTED 158 /* 'protected' */ +#define DUK_HEAP_STRING_PROTECTED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED) +#define DUK_HTHREAD_STRING_PROTECTED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED) +#define DUK_STRIDX_PUBLIC 159 /* 'public' */ +#define DUK_HEAP_STRING_PUBLIC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC) +#define DUK_HTHREAD_STRING_PUBLIC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC) +#define DUK_STRIDX_STATIC 160 /* 'static' */ +#define DUK_HEAP_STRING_STATIC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC) +#define DUK_HTHREAD_STRING_STATIC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC) +#define DUK_STRIDX_YIELD 161 /* 'yield' */ +#define DUK_HEAP_STRING_YIELD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD) +#define DUK_HTHREAD_STRING_YIELD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD) + +#define DUK_HEAP_NUM_STRINGS 162 +#define DUK_STRIDX_START_RESERVED 117 +#define DUK_STRIDX_START_STRICT_RESERVED 153 +#define DUK_STRIDX_END_RESERVED 162 /* exclusive endpoint */ + +/* To convert a heap stridx to a token number, subtract + * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED. + */ +#if !defined(DUK_SINGLE_FILE) +DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[892]; +#endif /* !DUK_SINGLE_FILE */ +#define DUK_STRDATA_MAX_STRLEN 17 +#define DUK_STRDATA_DATA_LENGTH 892 +#endif /* DUK_USE_ROM_STRINGS */ + +#if defined(DUK_USE_ROM_OBJECTS) +#error RAM support not enabled, rerun configure.py with --ram-support +#else /* DUK_USE_ROM_OBJECTS */ +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_function_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_number_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_escape(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_assign(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_length(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_name(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_code_point(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_repeat(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_includes(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_tostring(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_flags(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_clz32(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_hypot(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_imul(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_max(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_min(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_random(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_sign(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_parse(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_yield(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_resume(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_current(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_apply(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_construct(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_delete_property(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_get(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_has(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_set(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_buffer_getter(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_set(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_allocplain(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_plainof(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_performance_now(duk_context *ctx); +#if !defined(DUK_SINGLE_FILE) +DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[176]; +#endif /* !DUK_SINGLE_FILE */ +#define DUK_BIDX_GLOBAL 0 +#define DUK_BIDX_GLOBAL_ENV 1 +#define DUK_BIDX_OBJECT_CONSTRUCTOR 2 +#define DUK_BIDX_OBJECT_PROTOTYPE 3 +#define DUK_BIDX_FUNCTION_CONSTRUCTOR 4 +#define DUK_BIDX_FUNCTION_PROTOTYPE 5 +#define DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE 6 +#define DUK_BIDX_ARRAY_CONSTRUCTOR 7 +#define DUK_BIDX_ARRAY_PROTOTYPE 8 +#define DUK_BIDX_STRING_CONSTRUCTOR 9 +#define DUK_BIDX_STRING_PROTOTYPE 10 +#define DUK_BIDX_BOOLEAN_CONSTRUCTOR 11 +#define DUK_BIDX_BOOLEAN_PROTOTYPE 12 +#define DUK_BIDX_NUMBER_CONSTRUCTOR 13 +#define DUK_BIDX_NUMBER_PROTOTYPE 14 +#define DUK_BIDX_DATE_CONSTRUCTOR 15 +#define DUK_BIDX_DATE_PROTOTYPE 16 +#define DUK_BIDX_REGEXP_CONSTRUCTOR 17 +#define DUK_BIDX_REGEXP_PROTOTYPE 18 +#define DUK_BIDX_ERROR_CONSTRUCTOR 19 +#define DUK_BIDX_ERROR_PROTOTYPE 20 +#define DUK_BIDX_EVAL_ERROR_CONSTRUCTOR 21 +#define DUK_BIDX_EVAL_ERROR_PROTOTYPE 22 +#define DUK_BIDX_RANGE_ERROR_CONSTRUCTOR 23 +#define DUK_BIDX_RANGE_ERROR_PROTOTYPE 24 +#define DUK_BIDX_REFERENCE_ERROR_CONSTRUCTOR 25 +#define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE 26 +#define DUK_BIDX_SYNTAX_ERROR_CONSTRUCTOR 27 +#define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE 28 +#define DUK_BIDX_TYPE_ERROR_CONSTRUCTOR 29 +#define DUK_BIDX_TYPE_ERROR_PROTOTYPE 30 +#define DUK_BIDX_URI_ERROR_CONSTRUCTOR 31 +#define DUK_BIDX_URI_ERROR_PROTOTYPE 32 +#define DUK_BIDX_TYPE_ERROR_THROWER 33 +#define DUK_BIDX_DUKTAPE 34 +#define DUK_BIDX_THREAD_PROTOTYPE 35 +#define DUK_BIDX_POINTER_PROTOTYPE 36 +#define DUK_BIDX_DOUBLE_ERROR 37 +#define DUK_BIDX_SYMBOL_PROTOTYPE 38 +#define DUK_BIDX_ARRAYBUFFER_PROTOTYPE 39 +#define DUK_BIDX_DATAVIEW_PROTOTYPE 40 +#define DUK_BIDX_INT8ARRAY_PROTOTYPE 41 +#define DUK_BIDX_UINT8ARRAY_PROTOTYPE 42 +#define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE 43 +#define DUK_BIDX_INT16ARRAY_PROTOTYPE 44 +#define DUK_BIDX_UINT16ARRAY_PROTOTYPE 45 +#define DUK_BIDX_INT32ARRAY_PROTOTYPE 46 +#define DUK_BIDX_UINT32ARRAY_PROTOTYPE 47 +#define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE 48 +#define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE 49 +#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE 50 +#define DUK_NUM_BUILTINS 51 +#define DUK_NUM_BIDX_BUILTINS 51 +#define DUK_NUM_ALL_BUILTINS 76 +#if defined(DUK_USE_DOUBLE_LE) +#if !defined(DUK_SINGLE_FILE) +DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3972]; +#endif /* !DUK_SINGLE_FILE */ +#define DUK_BUILTINS_DATA_LENGTH 3972 +#elif defined(DUK_USE_DOUBLE_BE) +#if !defined(DUK_SINGLE_FILE) +DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3972]; +#endif /* !DUK_SINGLE_FILE */ +#define DUK_BUILTINS_DATA_LENGTH 3972 +#elif defined(DUK_USE_DOUBLE_ME) +#if !defined(DUK_SINGLE_FILE) +DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3972]; +#endif /* !DUK_SINGLE_FILE */ +#define DUK_BUILTINS_DATA_LENGTH 3972 +#else +#error invalid endianness defines +#endif +#endif /* DUK_USE_ROM_OBJECTS */ +#endif /* DUK_BUILTINS_H_INCLUDED */ +#line 51 "duk_internal.h" + +/* #include duk_util.h */ +#line 1 "duk_util.h" +/* + * Utilities + */ + +#if !defined(DUK_UTIL_H_INCLUDED) +#define DUK_UTIL_H_INCLUDED + +#if defined(DUK_USE_GET_RANDOM_DOUBLE) +#define DUK_UTIL_GET_RANDOM_DOUBLE(thr) DUK_USE_GET_RANDOM_DOUBLE((thr)->heap_udata) +#else +#define DUK_UTIL_GET_RANDOM_DOUBLE(thr) duk_util_tinyrandom_get_double(thr) +#endif + +/* + * Some useful constants + */ + +#define DUK_DOUBLE_2TO32 4294967296.0 +#define DUK_DOUBLE_2TO31 2147483648.0 +#define DUK_DOUBLE_LOG2E 1.4426950408889634 +#define DUK_DOUBLE_LOG10E 0.4342944819032518 + +/* + * Endian conversion + */ + +#if defined(DUK_USE_INTEGER_LE) +#define DUK_HTON32(x) DUK_BSWAP32((x)) +#define DUK_NTOH32(x) DUK_BSWAP32((x)) +#define DUK_HTON16(x) DUK_BSWAP16((x)) +#define DUK_NTOH16(x) DUK_BSWAP16((x)) +#elif defined(DUK_USE_INTEGER_BE) +#define DUK_HTON32(x) (x) +#define DUK_NTOH32(x) (x) +#define DUK_HTON16(x) (x) +#define DUK_NTOH16(x) (x) +#else +#error internal error, endianness defines broken +#endif + +/* + * Bitstream decoder + */ + +struct duk_bitdecoder_ctx { + const duk_uint8_t *data; + duk_size_t offset; + duk_size_t length; + duk_uint32_t currval; + duk_small_int_t currbits; +}; + +#define DUK_BD_BITPACKED_STRING_MAXLEN 256 + +/* + * Bitstream encoder + */ + +struct duk_bitencoder_ctx { + duk_uint8_t *data; + duk_size_t offset; + duk_size_t length; + duk_uint32_t currval; + duk_small_int_t currbits; + duk_small_int_t truncated; +}; + +/* + * Raw write/read macros for big endian, unaligned basic values. + * Caller ensures there's enough space. The macros update the pointer + * argument automatically on resizes. The idiom seems a bit odd, but + * leads to compact code. + */ + +#define DUK_RAW_WRITE_U8(ptr,val) do { \ + *(ptr)++ = (duk_uint8_t) (val); \ + } while (0) +#define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be(&(ptr), (duk_uint16_t) (val)) +#define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be(&(ptr), (duk_uint32_t) (val)) +#define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be(&(ptr), (duk_double_t) (val)) +#define DUK_RAW_WRITE_XUTF8(ptr,val) do { \ + /* 'ptr' is evaluated both as LHS and RHS. */ \ + duk_uint8_t *duk__ptr; \ + duk_small_int_t duk__len; \ + duk__ptr = (duk_uint8_t *) (ptr); \ + duk__len = duk_unicode_encode_xutf8((duk_ucodepoint_t) (val), duk__ptr); \ + duk__ptr += duk__len; \ + (ptr) = duk__ptr; \ + } while (0) +#define DUK_RAW_WRITE_CESU8(ptr,val) do { \ + /* 'ptr' is evaluated both as LHS and RHS. */ \ + duk_uint8_t *duk__ptr; \ + duk_small_int_t duk__len; \ + duk__ptr = (duk_uint8_t *) (ptr); \ + duk__len = duk_unicode_encode_cesu8((duk_ucodepoint_t) (val), duk__ptr); \ + duk__ptr += duk__len; \ + (ptr) = duk__ptr; \ + } while (0) + +#define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)++)) +#define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be(&(ptr)); +#define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be(&(ptr)); +#define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be(&(ptr)); + +/* + * Buffer writer (dynamic buffer only) + * + * Helper for writing to a dynamic buffer with a concept of a "slack" area + * to reduce resizes. You can ensure there is enough space beforehand and + * then write for a while without further checks, relying on a stable data + * pointer. Slack handling is automatic so call sites only indicate how + * much data they need right now. + * + * There are several ways to write using bufwriter. The best approach + * depends mainly on how much performance matters over code footprint. + * The key issues are (1) ensuring there is space and (2) keeping the + * pointers consistent. Fast code should ensure space for multiple writes + * with one ensure call. Fastest inner loop code can temporarily borrow + * the 'p' pointer but must write it back eventually. + * + * Be careful to ensure all macro arguments (other than static pointers like + * 'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if + * necessary (if that's not possible, there should be a note near the macro). + * Buffer write arguments often contain arithmetic etc so this is + * particularly important here. + */ + +/* XXX: Migrate bufwriter and other read/write helpers to its own header? */ + +struct duk_bufwriter_ctx { + duk_uint8_t *p; + duk_uint8_t *p_base; + duk_uint8_t *p_limit; + duk_hbuffer_dynamic *buf; +}; + +#if defined(DUK_USE_PREFER_SIZE) +#define DUK_BW_SLACK_ADD 64 +#define DUK_BW_SLACK_SHIFT 4 /* 2^4 -> 1/16 = 6.25% slack */ +#else +#define DUK_BW_SLACK_ADD 64 +#define DUK_BW_SLACK_SHIFT 2 /* 2^2 -> 1/4 = 25% slack */ +#endif + +/* Initialization and finalization (compaction), converting to other types. */ + +#define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \ + duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \ + } while (0) +#define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \ + duk_bw_init((thr), (bw_ctx), (buf)); \ + } while (0) +#define DUK_BW_COMPACT(thr,bw_ctx) do { \ + /* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \ + duk_bw_compact((thr), (bw_ctx)); \ + } while (0) +#define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \ + duk_push_lstring((thr), \ + (const char *) (bw_ctx)->p_base, \ + (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \ + } while (0) +/* Pointers may be NULL for a while when 'buf' size is zero and before any + * ENSURE calls have been made. Once an ENSURE has been made, the pointers + * are required to be non-NULL so that it's always valid to use memcpy() and + * memmove(), even for zero size. + */ +#define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx) \ + DUK_ASSERT_EXPR((bw_ctx) != NULL && \ + (bw_ctx)->buf != NULL && \ + ((DUK_HBUFFER_DYNAMIC_GET_SIZE((bw_ctx)->buf) == 0) || \ + ((bw_ctx)->p != NULL && \ + (bw_ctx)->p_base != NULL && \ + (bw_ctx)->p_limit != NULL && \ + (bw_ctx)->p_limit >= (bw_ctx)->p_base && \ + (bw_ctx)->p >= (bw_ctx)->p_base && \ + (bw_ctx)->p <= (bw_ctx)->p_limit))) +#define DUK_BW_ASSERT_VALID(thr,bw_ctx) do { \ + DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)); \ + } while (0) + +/* Working with the pointer and current size. */ + +#define DUK_BW_GET_PTR(thr,bw_ctx) \ + ((bw_ctx)->p) +#define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \ + (bw_ctx)->p = (ptr); \ + } while (0) +#define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \ + (bw_ctx)->p += (delta); \ + } while (0) +#define DUK_BW_GET_BASEPTR(thr,bw_ctx) \ + ((bw_ctx)->p_base) +#define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \ + ((bw_ctx)->p_limit) +#define DUK_BW_GET_SIZE(thr,bw_ctx) \ + ((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)) +#define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \ + DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \ + (bw_ctx)->p = (bw_ctx)->p_base + (sz); \ + } while (0) +#define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \ + /* Reset to zero size, keep current limit. */ \ + (bw_ctx)->p = (bw_ctx)->p_base; \ + } while (0) +#define DUK_BW_GET_BUFFER(thr,bw_ctx) \ + ((bw_ctx)->buf) + +/* Ensuring (reserving) space. */ + +#define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \ + duk_size_t duk__sz, duk__space; \ + DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \ + duk__sz = (sz); \ + duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \ + if (duk__space < duk__sz) { \ + (void) duk_bw_resize((thr), (bw_ctx), duk__sz); \ + } \ + } while (0) +/* NOTE: Multiple evaluation of 'ptr' in this macro. */ +/* XXX: Rework to use an always-inline function? */ +#define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \ + (((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \ + (ptr) : \ + ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz)))) +#define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \ + DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p) +#define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \ + (DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \ + DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz))) +#define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \ + DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \ + } while (0) + +/* Miscellaneous. */ + +#define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \ + (bw_ctx)->p = (ptr); \ + duk_bw_compact((thr), (bw_ctx)); \ + } while (0) + +/* Fast write calls which assume you control the slack beforehand. + * Multibyte write variants exist and use a temporary write pointer + * because byte writes alias with anything: with a stored pointer + * explicit pointer load/stores get generated (e.g. gcc -Os). + */ + +#define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \ + *(bw_ctx)->p++ = (duk_uint8_t) (val); \ + } while (0) +#define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \ + duk_uint8_t *duk__p; \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \ + duk__p = (bw_ctx)->p; \ + *duk__p++ = (duk_uint8_t) (val1); \ + *duk__p++ = (duk_uint8_t) (val2); \ + (bw_ctx)->p = duk__p; \ + } while (0) +#define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \ + duk_uint8_t *duk__p; \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \ + duk__p = (bw_ctx)->p; \ + *duk__p++ = (duk_uint8_t) (val1); \ + *duk__p++ = (duk_uint8_t) (val2); \ + *duk__p++ = (duk_uint8_t) (val3); \ + (bw_ctx)->p = duk__p; \ + } while (0) +#define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \ + duk_uint8_t *duk__p; \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \ + duk__p = (bw_ctx)->p; \ + *duk__p++ = (duk_uint8_t) (val1); \ + *duk__p++ = (duk_uint8_t) (val2); \ + *duk__p++ = (duk_uint8_t) (val3); \ + *duk__p++ = (duk_uint8_t) (val4); \ + (bw_ctx)->p = duk__p; \ + } while (0) +#define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \ + duk_uint8_t *duk__p; \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \ + duk__p = (bw_ctx)->p; \ + *duk__p++ = (duk_uint8_t) (val1); \ + *duk__p++ = (duk_uint8_t) (val2); \ + *duk__p++ = (duk_uint8_t) (val3); \ + *duk__p++ = (duk_uint8_t) (val4); \ + *duk__p++ = (duk_uint8_t) (val5); \ + (bw_ctx)->p = duk__p; \ + } while (0) +#define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \ + duk_uint8_t *duk__p; \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \ + duk__p = (bw_ctx)->p; \ + *duk__p++ = (duk_uint8_t) (val1); \ + *duk__p++ = (duk_uint8_t) (val2); \ + *duk__p++ = (duk_uint8_t) (val3); \ + *duk__p++ = (duk_uint8_t) (val4); \ + *duk__p++ = (duk_uint8_t) (val5); \ + *duk__p++ = (duk_uint8_t) (val6); \ + (bw_ctx)->p = duk__p; \ + } while (0) +#define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \ + duk_ucodepoint_t duk__cp; \ + duk_small_int_t duk__enc_len; \ + duk__cp = (duk_ucodepoint_t) (cp); \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \ + duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \ + (bw_ctx)->p += duk__enc_len; \ + } while (0) +#define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \ + duk_ucodepoint_t duk__cp; \ + duk_small_int_t duk__enc_len; \ + duk__cp = (duk_ucodepoint_t) (cp); \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \ + duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \ + (bw_ctx)->p += duk__enc_len; \ + } while (0) +/* XXX: add temporary duk__p pointer here too; sharing */ +#define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \ + const void *duk__valptr; \ + duk_size_t duk__valsz; \ + duk__valptr = (const void *) (valptr); \ + duk__valsz = (duk_size_t) (valsz); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \ + (bw_ctx)->p += duk__valsz; \ + } while (0) +#define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \ + const duk_uint8_t *duk__val; \ + duk_size_t duk__val_len; \ + duk__val = (const duk_uint8_t *) (val); \ + duk__val_len = DUK_STRLEN((const char *) duk__val); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) + +/* Append bytes from a slice already in the buffer. */ +#define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \ + duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len)) + +/* Insert bytes in the middle of the buffer from an external buffer. */ +#define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \ + duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len)) + +/* Insert bytes in the middle of the buffer from a slice already + * in the buffer. Source offset is interpreted "before" the operation. + */ +#define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \ + duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len)) + +/* Insert a reserved area somewhere in the buffer; caller fills it. + * Evaluates to a (duk_uint_t *) pointing to the start of the reserved + * area for convenience. + */ +#define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \ + duk_bw_insert_raw_area((thr), (bw), (off), (len)) + +/* Remove a slice from inside buffer. */ +#define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \ + duk_bw_remove_raw_slice((thr), (bw), (off), (len)) + +/* Safe write calls which will ensure space first. */ + +#define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), 1); \ + DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \ + } while (0) +#define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), 2); \ + DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \ + } while (0) +#define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), 3); \ + DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \ + } while (0) +#define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), 4); \ + DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \ + } while (0) +#define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), 5); \ + DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \ + } while (0) +#define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), 6); \ + DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \ + } while (0) +#define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \ + DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \ + } while (0) +#define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \ + DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \ + } while (0) +/* XXX: add temporary duk__p pointer here too; sharing */ +#define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \ + const void *duk__valptr; \ + duk_size_t duk__valsz; \ + duk__valptr = (const void *) (valptr); \ + duk__valsz = (duk_size_t) (valsz); \ + DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \ + (bw_ctx)->p += duk__valsz; \ + } while (0) +#define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \ + const duk_uint8_t *duk__val; \ + duk_size_t duk__val_len; \ + duk__val = (const duk_uint8_t *) (val); \ + duk__val_len = DUK_STRLEN((const char *) duk__val); \ + DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \ + DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \ + DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \ + DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \ + DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) + +#define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \ + duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len)) +#define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \ + duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len)) +#define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \ + duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len)) +#define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \ + /* Evaluates to (duk_uint8_t *) pointing to start of area. */ \ + duk_bw_insert_ensure_area((thr), (bw), (off), (len)) +#define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \ + /* No difference between raw/ensure because the buffer shrinks. */ \ + DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len)) + +/* + * Externs and prototypes + */ + +#if !defined(DUK_SINGLE_FILE) +DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36]; +DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16]; +DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256]; +#if defined(DUK_USE_HEX_FASTPATH) +DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256]; +DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256]; +#endif +#if defined(DUK_USE_BASE64_FASTPATH) +DUK_INTERNAL_DECL const duk_uint8_t duk_base64_enctab[64]; +DUK_INTERNAL_DECL const duk_int8_t duk_base64_dectab[256]; +#endif +#endif /* !DUK_SINGLE_FILE */ + +/* Note: assumes that duk_util_probe_steps size is 32 */ +#if defined(DUK_USE_HOBJECT_HASH_PART) +#if !defined(DUK_SINGLE_FILE) +DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32]; +#endif /* !DUK_SINGLE_FILE */ +#endif + +#if defined(DUK_USE_STRHASH_DENSE) +DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed); +#endif + +DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits); +DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx); +DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value); +DUK_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged_signed(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value); +DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx); +DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out); + +DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits); +DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx); + +#if !defined(DUK_USE_GET_RANDOM_DOUBLE) +DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr); +#endif + +DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf); +DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size); +DUK_INTERNAL_DECL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz); +DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx); +DUK_INTERNAL_DECL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len); +DUK_INTERNAL_DECL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len); +DUK_INTERNAL_DECL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len); +DUK_INTERNAL_DECL void duk_bw_insert_ensure_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len); +DUK_INTERNAL_DECL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len); +DUK_INTERNAL_DECL void duk_bw_insert_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len); +DUK_INTERNAL_DECL duk_uint8_t *duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len); +DUK_INTERNAL_DECL duk_uint8_t *duk_bw_insert_ensure_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len); +DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len); +/* No duk_bw_remove_ensure_slice(), functionality would be identical. */ + +DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p); +DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p); +DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(duk_uint8_t **p); +DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val); +DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val); +DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val); + +#if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */ +DUK_INTERNAL_DECL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len); +#endif + +DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival); +DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival); +DUK_INTERNAL_DECL duk_bool_t duk_double_is_anyinf(duk_double_t x); +DUK_INTERNAL_DECL duk_bool_t duk_double_is_posinf(duk_double_t x); +DUK_INTERNAL_DECL duk_bool_t duk_double_is_neginf(duk_double_t x); +DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan(duk_double_t x); +DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x); +DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x); +DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x); +DUK_INTERNAL_DECL duk_small_uint_t duk_double_signbit(duk_double_t x); +DUK_INTERNAL_DECL duk_double_t duk_double_trunc_towards_zero(duk_double_t x); +DUK_INTERNAL_DECL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y); +DUK_INTERNAL_DECL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y); +DUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y); + +#endif /* DUK_UTIL_H_INCLUDED */ +/* #include duk_strings.h */ +#line 1 "duk_strings.h" +/* + * Shared string macros. + * + * Using shared macros helps minimize strings data size because it's easy + * to check if an existing string could be used. String constants don't + * need to be all defined here; defining a string here makes sense if there's + * a high chance the string could be reused. Also, using macros allows + * a call site express the exact string needed, but the macro may map to an + * approximate string to reduce unique string count. Macros can also be + * more easily tuned for low memory targets than #if defined()s throughout + * the code base. + * + * Because format strings behave differently in the call site (they need to + * be followed by format arguments), they use a special prefix DUK_STR_FMT_. + * + * On some compilers using explicit shared strings is preferable; on others + * it may be better to use straight literals because the compiler will combine + * them anyway, and such strings won't end up unnecessarily in a symbol table. + */ + +#if !defined(DUK_ERRMSG_H_INCLUDED) +#define DUK_ERRMSG_H_INCLUDED + +/* Mostly API and built-in method related */ +#define DUK_STR_INTERNAL_ERROR "internal error" +#define DUK_STR_UNSUPPORTED "unsupported" +#define DUK_STR_INVALID_COUNT "invalid count" +#define DUK_STR_INVALID_ARGS "invalid args" +#define DUK_STR_INVALID_STATE "invalid state" +#define DUK_STR_INVALID_INPUT "invalid input" +#define DUK_STR_INVALID_LENGTH "invalid length" +#define DUK_STR_NOT_CONSTRUCTABLE "not constructable" +#define DUK_STR_CONSTRUCT_ONLY "constructor requires 'new'" +#define DUK_STR_NOT_CALLABLE "not callable" +#define DUK_STR_NOT_EXTENSIBLE "not extensible" +#define DUK_STR_NOT_WRITABLE "not writable" +#define DUK_STR_NOT_CONFIGURABLE "not configurable" +#define DUK_STR_INVALID_CONTEXT "invalid context" +#define DUK_STR_INVALID_INDEX "invalid args" +#define DUK_STR_PUSH_BEYOND_ALLOC_STACK "cannot push beyond allocated stack" +#define DUK_STR_NOT_UNDEFINED "unexpected type" +#define DUK_STR_NOT_NULL "unexpected type" +#define DUK_STR_NOT_BOOLEAN "unexpected type" +#define DUK_STR_NOT_NUMBER "unexpected type" +#define DUK_STR_NOT_STRING "unexpected type" +#define DUK_STR_NOT_OBJECT "unexpected type" +#define DUK_STR_NOT_POINTER "unexpected type" +#define DUK_STR_NOT_BUFFER "not buffer" /* still in use with verbose messages */ +#define DUK_STR_UNEXPECTED_TYPE "unexpected type" +#define DUK_STR_NOT_THREAD "unexpected type" +#define DUK_STR_NOT_COMPFUNC "unexpected type" +#define DUK_STR_NOT_NATFUNC "unexpected type" +#define DUK_STR_NOT_C_FUNCTION "unexpected type" +#define DUK_STR_NOT_FUNCTION "unexpected type" +#define DUK_STR_NOT_REGEXP "unexpected type" +#define DUK_STR_TOPRIMITIVE_FAILED "coercion to primitive failed" +#define DUK_STR_NUMBER_OUTSIDE_RANGE "number outside range" +#define DUK_STR_NOT_OBJECT_COERCIBLE "not object coercible" +#define DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL "cannot number coerce Symbol" +#define DUK_STR_CANNOT_STRING_COERCE_SYMBOL "cannot string coerce Symbol" +#define DUK_STR_STRING_TOO_LONG "string too long" +#define DUK_STR_BUFFER_TOO_LONG "buffer too long" +#define DUK_STR_ALLOC_FAILED "alloc failed" +#define DUK_STR_WRONG_BUFFER_TYPE "wrong buffer type" +#define DUK_STR_BASE64_ENCODE_FAILED "base64 encode failed" +#define DUK_STR_SOURCE_DECODE_FAILED "source decode failed" +#define DUK_STR_UTF8_DECODE_FAILED "utf-8 decode failed" +#define DUK_STR_BASE64_DECODE_FAILED "base64 decode failed" +#define DUK_STR_HEX_DECODE_FAILED "hex decode failed" +#define DUK_STR_INVALID_BYTECODE "invalid bytecode" +#define DUK_STR_NO_SOURCECODE "no sourcecode" +#define DUK_STR_RESULT_TOO_LONG "result too long" +#define DUK_STR_INVALID_CFUNC_RC "invalid C function rc" +#define DUK_STR_INVALID_INSTANCEOF_RVAL "invalid instanceof rval" +#define DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO "instanceof rval has no .prototype" + +/* 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" + +/* Object property access */ +#define DUK_STR_INVALID_BASE "invalid base value" +#define DUK_STR_STRICT_CALLER_READ "cannot read strict 'caller'" +#define DUK_STR_PROXY_REJECTED "proxy rejected" +#define DUK_STR_INVALID_ARRAY_LENGTH "invalid array length" +#define DUK_STR_SETTER_UNDEFINED "setter undefined" +#define DUK_STR_INVALID_DESCRIPTOR "invalid descriptor" + +/* Proxy */ +#define DUK_STR_PROXY_REVOKED "proxy revoked" +#define DUK_STR_INVALID_TRAP_RESULT "invalid trap result" + +/* Variables */ + +/* Lexer */ +#define DUK_STR_INVALID_ESCAPE "invalid escape" +#define DUK_STR_UNTERMINATED_STRING "unterminated string" +#define DUK_STR_UNTERMINATED_COMMENT "unterminated comment" +#define DUK_STR_UNTERMINATED_REGEXP "unterminated regexp" +#define DUK_STR_TOKEN_LIMIT "token limit" +#define DUK_STR_REGEXP_SUPPORT_DISABLED "regexp support disabled" +#define DUK_STR_INVALID_NUMBER_LITERAL "invalid number literal" +#define DUK_STR_INVALID_TOKEN "invalid token" + +/* Compiler */ +#define DUK_STR_PARSE_ERROR "parse error" +#define DUK_STR_DUPLICATE_LABEL "duplicate label" +#define DUK_STR_INVALID_LABEL "invalid label" +#define DUK_STR_INVALID_ARRAY_LITERAL "invalid array literal" +#define DUK_STR_INVALID_OBJECT_LITERAL "invalid object literal" +#define DUK_STR_INVALID_VAR_DECLARATION "invalid variable declaration" +#define DUK_STR_CANNOT_DELETE_IDENTIFIER "cannot delete identifier" +#define DUK_STR_INVALID_EXPRESSION "invalid expression" +#define DUK_STR_INVALID_LVALUE "invalid lvalue" +#define DUK_STR_INVALID_NEWTARGET "invalid new.target" +#define DUK_STR_EXPECTED_IDENTIFIER "expected identifier" +#define DUK_STR_EMPTY_EXPR_NOT_ALLOWED "empty expression not allowed" +#define DUK_STR_INVALID_FOR "invalid for statement" +#define DUK_STR_INVALID_SWITCH "invalid switch statement" +#define DUK_STR_INVALID_BREAK_CONT_LABEL "invalid break/continue label" +#define DUK_STR_INVALID_RETURN "invalid return" +#define DUK_STR_INVALID_TRY "invalid try" +#define DUK_STR_INVALID_THROW "invalid throw" +#define DUK_STR_WITH_IN_STRICT_MODE "with in strict mode" +#define DUK_STR_FUNC_STMT_NOT_ALLOWED "function statement not allowed" +#define DUK_STR_UNTERMINATED_STMT "unterminated statement" +#define DUK_STR_INVALID_ARG_NAME "invalid argument name" +#define DUK_STR_INVALID_FUNC_NAME "invalid function name" +#define DUK_STR_INVALID_GETSET_NAME "invalid getter/setter name" +#define DUK_STR_FUNC_NAME_REQUIRED "function name required" + +/* RegExp */ +#define DUK_STR_INVALID_QUANTIFIER "invalid regexp quantifier" +#define DUK_STR_INVALID_QUANTIFIER_NO_ATOM "quantifier without preceding atom" +#define DUK_STR_INVALID_QUANTIFIER_VALUES "quantifier values invalid (qmin > qmax)" +#define DUK_STR_QUANTIFIER_TOO_MANY_COPIES "quantifier requires too many atom copies" +#define DUK_STR_UNEXPECTED_CLOSING_PAREN "unexpected closing parenthesis" +#define DUK_STR_UNEXPECTED_END_OF_PATTERN "unexpected end of pattern" +#define DUK_STR_UNEXPECTED_REGEXP_TOKEN "unexpected token in regexp" +#define DUK_STR_INVALID_REGEXP_FLAGS "invalid regexp flags" +#define DUK_STR_INVALID_REGEXP_ESCAPE "invalid regexp escape" +#define DUK_STR_INVALID_BACKREFS "invalid backreference(s)" +#define DUK_STR_INVALID_REGEXP_CHARACTER "invalid regexp character" +#define DUK_STR_INVALID_REGEXP_GROUP "invalid regexp group" +#define DUK_STR_UNTERMINATED_CHARCLASS "unterminated character class" +#define DUK_STR_INVALID_RANGE "invalid range" + +/* Limits */ +#define DUK_STR_VALSTACK_LIMIT "valstack limit" +#define DUK_STR_CALLSTACK_LIMIT "callstack limit" +#define DUK_STR_PROTOTYPE_CHAIN_LIMIT "prototype chain limit" +#define DUK_STR_BOUND_CHAIN_LIMIT "function call bound chain limit" +#define DUK_STR_C_CALLSTACK_LIMIT "C call stack depth limit" +#define DUK_STR_COMPILER_RECURSION_LIMIT "compiler recursion limit" +#define DUK_STR_BYTECODE_LIMIT "bytecode limit" +#define DUK_STR_REG_LIMIT "register limit" +#define DUK_STR_TEMP_LIMIT "temp limit" +#define DUK_STR_CONST_LIMIT "const limit" +#define DUK_STR_FUNC_LIMIT "function limit" +#define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT "regexp compiler recursion limit" +#define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT "regexp executor recursion limit" +#define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT "regexp step limit" + +#endif /* DUK_ERRMSG_H_INCLUDED */ +/* #include duk_js_bytecode.h */ +#line 1 "duk_js_bytecode.h" +/* + * Ecmascript bytecode + */ + +#if !defined(DUK_JS_BYTECODE_H_INCLUDED) +#define DUK_JS_BYTECODE_H_INCLUDED + +/* + * Bytecode instruction layout + * =========================== + * + * Instructions are unsigned 32-bit integers divided as follows: + * + * !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! ! + * !1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0! + * +-----------------------------------------------+---------------+ + * ! C ! B ! A ! OP ! + * +-----------------------------------------------+---------------+ + * + * OP (8 bits): opcode (DUK_OP_*), access should be fastest + * consecutive opcodes allocated when opcode needs flags + * A (8 bits): typically a target register number + * B (8 bits): typically first source register/constant number + * C (8 bits): typically second source register/constant number + * + * Some instructions combine BC or ABC together for larger parameter values. + * Signed integers (e.g. jump offsets) are encoded as unsigned, with an + * opcode specific bias. + * + * Some opcodes have flags which are handled by allocating consecutive + * opcodes to make space for 1-N flags. Flags can also be e.g. in the 'A' + * field when there's room for the specific opcode. + * + * For example, if three flags were needed, they could be allocated from + * the opcode field as follows: + * + * !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! ! + * !1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0! + * +-----------------------------------------------+---------------+ + * ! C ! B ! A ! OP !Z!Y!X! + * +-----------------------------------------------+---------------+ + * + * Some opcodes accept a reg/const argument which is handled by allocating + * flags in the OP field, see DUK_BC_ISREG() and DUK_BC_ISCONST(). The + * following convention is shared by most opcodes, so that the compiler + * can handle reg/const flagging without opcode specific code paths: + * + * !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! ! + * !1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0! + * +-----------------------------------------------+---------------+ + * ! C ! B ! A ! OP !Y!X! + * +-----------------------------------------------+---------------+ + * + * X 1=B is const, 0=B is reg + * Y 1=C is const, 0=C is reg + * + * In effect OP, OP + 1, OP + 2, and OP + 3 are allocated from the + * 8-bit opcode space for a single logical opcode. The base opcode + * number should be divisible by 4. If the opcode is called 'FOO' + * the following opcode constants would be defined: + * + * DUK_OP_FOO 100 // base opcode number + * DUK_OP_FOO_RR 100 // FOO, B=reg, C=reg + * DUK_OP_FOO_CR 101 // FOO, B=const, C=reg + * DUK_OP_FOO_RC 102 // FOO, B=reg, C=const + * DUK_OP_FOO_CC 103 // FOO, B=const, C=const + * + * If only B or C is a reg/const, the unused opcode combinations can be + * used for other opcodes (which take no reg/const argument). However, + * such opcode values are initially reserved, at least while opcode space + * is available. For example, if 'BAR' uses B for a register field and + * C is a reg/const: + * + * DUK_OP_BAR 116 // base opcode number + * DUK_OP_BAR_RR 116 // BAR, B=reg, C=reg + * DUK_OP_BAR_CR_UNUSED 117 // unused, could be repurposed + * DUK_OP_BAR_RC 118 // BAR, B=reg, C=const + * DUK_OP_BAR_CC_UNUSED 119 // unused, could be repurposed + * + * Macro naming is a bit misleading, e.g. "ABC" in macro name but the + * field layout is concretely "CBA" in the register. + */ + +typedef duk_uint32_t duk_instr_t; + +#define DUK_BC_SHIFT_OP 0 +#define DUK_BC_SHIFT_A 8 +#define DUK_BC_SHIFT_B 16 +#define DUK_BC_SHIFT_C 24 +#define DUK_BC_SHIFT_BC DUK_BC_SHIFT_B +#define DUK_BC_SHIFT_ABC DUK_BC_SHIFT_A + +#define DUK_BC_UNSHIFTED_MASK_OP 0xffUL +#define DUK_BC_UNSHIFTED_MASK_A 0xffUL +#define DUK_BC_UNSHIFTED_MASK_B 0xffUL +#define DUK_BC_UNSHIFTED_MASK_C 0xffUL +#define DUK_BC_UNSHIFTED_MASK_BC 0xffffUL +#define DUK_BC_UNSHIFTED_MASK_ABC 0xffffffUL + +#define DUK_BC_SHIFTED_MASK_OP (DUK_BC_UNSHIFTED_MASK_OP << DUK_BC_SHIFT_OP) +#define DUK_BC_SHIFTED_MASK_A (DUK_BC_UNSHIFTED_MASK_A << DUK_BC_SHIFT_A) +#define DUK_BC_SHIFTED_MASK_B (DUK_BC_UNSHIFTED_MASK_B << DUK_BC_SHIFT_B) +#define DUK_BC_SHIFTED_MASK_C (DUK_BC_UNSHIFTED_MASK_C << DUK_BC_SHIFT_C) +#define DUK_BC_SHIFTED_MASK_BC (DUK_BC_UNSHIFTED_MASK_BC << DUK_BC_SHIFT_BC) +#define DUK_BC_SHIFTED_MASK_ABC (DUK_BC_UNSHIFTED_MASK_ABC << DUK_BC_SHIFT_ABC) + +#define DUK_DEC_OP(x) ((x) & 0xffUL) +#define DUK_DEC_A(x) (((x) >> 8) & 0xffUL) +#define DUK_DEC_B(x) (((x) >> 16) & 0xffUL) +#define DUK_DEC_C(x) (((x) >> 24) & 0xffUL) +#define DUK_DEC_BC(x) (((x) >> 16) & 0xffffUL) +#define DUK_DEC_ABC(x) (((x) >> 8) & 0xffffffUL) + +#define DUK_ENC_OP(op) ((duk_instr_t) (op)) +#define DUK_ENC_OP_ABC(op,abc) ((duk_instr_t) ( \ + (((duk_instr_t) (abc)) << 8) | \ + ((duk_instr_t) (op)) \ + )) +#define DUK_ENC_OP_A_BC(op,a,bc) ((duk_instr_t) ( \ + (((duk_instr_t) (bc)) << 16) | \ + (((duk_instr_t) (a)) << 8) | \ + ((duk_instr_t) (op)) \ + )) +#define DUK_ENC_OP_A_B_C(op,a,b,c) ((duk_instr_t) ( \ + (((duk_instr_t) (c)) << 24) | \ + (((duk_instr_t) (b)) << 16) | \ + (((duk_instr_t) (a)) << 8) | \ + ((duk_instr_t) (op)) \ + )) +#define DUK_ENC_OP_A_B(op,a,b) DUK_ENC_OP_A_B_C((op),(a),(b),0) +#define DUK_ENC_OP_A(op,a) DUK_ENC_OP_A_B_C((op),(a),0,0) +#define DUK_ENC_OP_BC(op,bc) DUK_ENC_OP_A_BC((op),0,(bc)) + +/* Get opcode base value with B/C reg/const flags cleared. */ +#define DUK_BC_NOREGCONST_OP(op) ((op) & 0xfc) + +/* Constants should be signed so that signed arithmetic involving them + * won't cause values to be coerced accidentally to unsigned. + */ +#define DUK_BC_OP_MIN 0 +#define DUK_BC_OP_MAX 0xffL +#define DUK_BC_A_MIN 0 +#define DUK_BC_A_MAX 0xffL +#define DUK_BC_B_MIN 0 +#define DUK_BC_B_MAX 0xffL +#define DUK_BC_C_MIN 0 +#define DUK_BC_C_MAX 0xffL +#define DUK_BC_BC_MIN 0 +#define DUK_BC_BC_MAX 0xffffL +#define DUK_BC_ABC_MIN 0 +#define DUK_BC_ABC_MAX 0xffffffL + +/* Masks for B/C reg/const indicator in opcode field. */ +#define DUK_BC_REGCONST_B (0x01UL) +#define DUK_BC_REGCONST_C (0x02UL) + +/* Misc. masks for opcode field. */ +#define DUK_BC_INCDECP_FLAG_DEC (0x04UL) +#define DUK_BC_INCDECP_FLAG_POST (0x08UL) + +/* Opcodes. */ +#define DUK_OP_LDREG 0 +#define DUK_OP_STREG 1 +#define DUK_OP_JUMP 2 +#define DUK_OP_LDCONST 3 +#define DUK_OP_LDINT 4 +#define DUK_OP_LDINTX 5 +#define DUK_OP_LDTHIS 6 +#define DUK_OP_LDUNDEF 7 +#define DUK_OP_LDNULL 8 +#define DUK_OP_LDTRUE 9 +#define DUK_OP_LDFALSE 10 +#define DUK_OP_GETVAR 11 +#define DUK_OP_BNOT 12 +#define DUK_OP_LNOT 13 +#define DUK_OP_UNM 14 +#define DUK_OP_UNP 15 +#define DUK_OP_EQ 16 +#define DUK_OP_EQ_RR 16 +#define DUK_OP_EQ_CR 17 +#define DUK_OP_EQ_RC 18 +#define DUK_OP_EQ_CC 19 +#define DUK_OP_NEQ 20 +#define DUK_OP_NEQ_RR 20 +#define DUK_OP_NEQ_CR 21 +#define DUK_OP_NEQ_RC 22 +#define DUK_OP_NEQ_CC 23 +#define DUK_OP_SEQ 24 +#define DUK_OP_SEQ_RR 24 +#define DUK_OP_SEQ_CR 25 +#define DUK_OP_SEQ_RC 26 +#define DUK_OP_SEQ_CC 27 +#define DUK_OP_SNEQ 28 +#define DUK_OP_SNEQ_RR 28 +#define DUK_OP_SNEQ_CR 29 +#define DUK_OP_SNEQ_RC 30 +#define DUK_OP_SNEQ_CC 31 +#define DUK_OP_GT 32 +#define DUK_OP_GT_RR 32 +#define DUK_OP_GT_CR 33 +#define DUK_OP_GT_RC 34 +#define DUK_OP_GT_CC 35 +#define DUK_OP_GE 36 +#define DUK_OP_GE_RR 36 +#define DUK_OP_GE_CR 37 +#define DUK_OP_GE_RC 38 +#define DUK_OP_GE_CC 39 +#define DUK_OP_LT 40 +#define DUK_OP_LT_RR 40 +#define DUK_OP_LT_CR 41 +#define DUK_OP_LT_RC 42 +#define DUK_OP_LT_CC 43 +#define DUK_OP_LE 44 +#define DUK_OP_LE_RR 44 +#define DUK_OP_LE_CR 45 +#define DUK_OP_LE_RC 46 +#define DUK_OP_LE_CC 47 +#define DUK_OP_IFTRUE 48 +#define DUK_OP_IFTRUE_R 48 +#define DUK_OP_IFTRUE_C 49 +#define DUK_OP_IFFALSE 50 +#define DUK_OP_IFFALSE_R 50 +#define DUK_OP_IFFALSE_C 51 +#define DUK_OP_ADD 52 +#define DUK_OP_ADD_RR 52 +#define DUK_OP_ADD_CR 53 +#define DUK_OP_ADD_RC 54 +#define DUK_OP_ADD_CC 55 +#define DUK_OP_SUB 56 +#define DUK_OP_SUB_RR 56 +#define DUK_OP_SUB_CR 57 +#define DUK_OP_SUB_RC 58 +#define DUK_OP_SUB_CC 59 +#define DUK_OP_MUL 60 +#define DUK_OP_MUL_RR 60 +#define DUK_OP_MUL_CR 61 +#define DUK_OP_MUL_RC 62 +#define DUK_OP_MUL_CC 63 +#define DUK_OP_DIV 64 +#define DUK_OP_DIV_RR 64 +#define DUK_OP_DIV_CR 65 +#define DUK_OP_DIV_RC 66 +#define DUK_OP_DIV_CC 67 +#define DUK_OP_MOD 68 +#define DUK_OP_MOD_RR 68 +#define DUK_OP_MOD_CR 69 +#define DUK_OP_MOD_RC 70 +#define DUK_OP_MOD_CC 71 +#define DUK_OP_EXP 72 +#define DUK_OP_EXP_RR 72 +#define DUK_OP_EXP_CR 73 +#define DUK_OP_EXP_RC 74 +#define DUK_OP_EXP_CC 75 +#define DUK_OP_BAND 76 +#define DUK_OP_BAND_RR 76 +#define DUK_OP_BAND_CR 77 +#define DUK_OP_BAND_RC 78 +#define DUK_OP_BAND_CC 79 +#define DUK_OP_BOR 80 +#define DUK_OP_BOR_RR 80 +#define DUK_OP_BOR_CR 81 +#define DUK_OP_BOR_RC 82 +#define DUK_OP_BOR_CC 83 +#define DUK_OP_BXOR 84 +#define DUK_OP_BXOR_RR 84 +#define DUK_OP_BXOR_CR 85 +#define DUK_OP_BXOR_RC 86 +#define DUK_OP_BXOR_CC 87 +#define DUK_OP_BASL 88 +#define DUK_OP_BASL_RR 88 +#define DUK_OP_BASL_CR 89 +#define DUK_OP_BASL_RC 90 +#define DUK_OP_BASL_CC 91 +#define DUK_OP_BLSR 92 +#define DUK_OP_BLSR_RR 92 +#define DUK_OP_BLSR_CR 93 +#define DUK_OP_BLSR_RC 94 +#define DUK_OP_BLSR_CC 95 +#define DUK_OP_BASR 96 +#define DUK_OP_BASR_RR 96 +#define DUK_OP_BASR_CR 97 +#define DUK_OP_BASR_RC 98 +#define DUK_OP_BASR_CC 99 +#define DUK_OP_INSTOF 100 +#define DUK_OP_INSTOF_RR 100 +#define DUK_OP_INSTOF_CR 101 +#define DUK_OP_INSTOF_RC 102 +#define DUK_OP_INSTOF_CC 103 +#define DUK_OP_IN 104 +#define DUK_OP_IN_RR 104 +#define DUK_OP_IN_CR 105 +#define DUK_OP_IN_RC 106 +#define DUK_OP_IN_CC 107 +#define DUK_OP_GETPROP 108 +#define DUK_OP_GETPROP_RR 108 +#define DUK_OP_GETPROP_CR 109 +#define DUK_OP_GETPROP_RC 110 +#define DUK_OP_GETPROP_CC 111 +#define DUK_OP_PUTPROP 112 +#define DUK_OP_PUTPROP_RR 112 +#define DUK_OP_PUTPROP_CR 113 +#define DUK_OP_PUTPROP_RC 114 +#define DUK_OP_PUTPROP_CC 115 +#define DUK_OP_DELPROP 116 +#define DUK_OP_DELPROP_RR 116 +#define DUK_OP_DELPROP_CR_UNUSED 117 /* unused now */ +#define DUK_OP_DELPROP_RC 118 +#define DUK_OP_DELPROP_CC_UNUSED 119 /* unused now */ +#define DUK_OP_PREINCR 120 /* pre/post opcode values have constraints, */ +#define DUK_OP_PREDECR 121 /* see duk_js_executor.c and duk_js_compiler.c. */ +#define DUK_OP_POSTINCR 122 +#define DUK_OP_POSTDECR 123 +#define DUK_OP_PREINCV 124 +#define DUK_OP_PREDECV 125 +#define DUK_OP_POSTINCV 126 +#define DUK_OP_POSTDECV 127 +#define DUK_OP_PREINCP 128 /* pre/post inc/dec prop opcodes have constraints */ +#define DUK_OP_PREINCP_RR 128 +#define DUK_OP_PREINCP_CR 129 +#define DUK_OP_PREINCP_RC 130 +#define DUK_OP_PREINCP_CC 131 +#define DUK_OP_PREDECP 132 +#define DUK_OP_PREDECP_RR 132 +#define DUK_OP_PREDECP_CR 133 +#define DUK_OP_PREDECP_RC 134 +#define DUK_OP_PREDECP_CC 135 +#define DUK_OP_POSTINCP 136 +#define DUK_OP_POSTINCP_RR 136 +#define DUK_OP_POSTINCP_CR 137 +#define DUK_OP_POSTINCP_RC 138 +#define DUK_OP_POSTINCP_CC 139 +#define DUK_OP_POSTDECP 140 +#define DUK_OP_POSTDECP_RR 140 +#define DUK_OP_POSTDECP_CR 141 +#define DUK_OP_POSTDECP_RC 142 +#define DUK_OP_POSTDECP_CC 143 +#define DUK_OP_DECLVAR 144 +#define DUK_OP_DECLVAR_RR 144 +#define DUK_OP_DECLVAR_CR 145 +#define DUK_OP_DECLVAR_RC 146 +#define DUK_OP_DECLVAR_CC 147 +#define DUK_OP_REGEXP 148 +#define DUK_OP_REGEXP_RR 148 +#define DUK_OP_REGEXP_CR 149 +#define DUK_OP_REGEXP_RC 150 +#define DUK_OP_REGEXP_CC 151 +#define DUK_OP_CLOSURE 152 +#define DUK_OP_TYPEOF 153 +#define DUK_OP_TYPEOFID 154 +#define DUK_OP_PUTVAR 155 +#define DUK_OP_DELVAR 156 +#define DUK_OP_RETREG 157 +#define DUK_OP_RETUNDEF 158 +#define DUK_OP_RETCONST 159 +#define DUK_OP_RETCONSTN 160 /* return const without incref (e.g. number) */ +#define DUK_OP_LABEL 161 +#define DUK_OP_ENDLABEL 162 +#define DUK_OP_BREAK 163 +#define DUK_OP_CONTINUE 164 +#define DUK_OP_TRYCATCH 165 +#define DUK_OP_ENDTRY 166 +#define DUK_OP_ENDCATCH 167 +#define DUK_OP_ENDFIN 168 +#define DUK_OP_THROW 169 +#define DUK_OP_INVLHS 170 +#define DUK_OP_CSREG 171 +#define DUK_OP_CSVAR 172 +#define DUK_OP_CSVAR_RR 172 +#define DUK_OP_CSVAR_CR 173 +#define DUK_OP_CSVAR_RC 174 +#define DUK_OP_CSVAR_CC 175 +#define DUK_OP_CALL0 176 /* DUK_OP_CALL0 & 0x0F must be zero. */ +#define DUK_OP_CALL1 177 +#define DUK_OP_CALL2 178 +#define DUK_OP_CALL3 179 +#define DUK_OP_CALL4 180 +#define DUK_OP_CALL5 181 +#define DUK_OP_CALL6 182 +#define DUK_OP_CALL7 183 +#define DUK_OP_CALL8 184 +#define DUK_OP_CALL9 185 +#define DUK_OP_CALL10 186 +#define DUK_OP_CALL11 187 +#define DUK_OP_CALL12 188 +#define DUK_OP_CALL13 189 +#define DUK_OP_CALL14 190 +#define DUK_OP_CALL15 191 +#define DUK_OP_NEWOBJ 192 +#define DUK_OP_NEWARR 193 +#define DUK_OP_MPUTOBJ 194 +#define DUK_OP_MPUTOBJI 195 +#define DUK_OP_INITSET 196 +#define DUK_OP_INITGET 197 +#define DUK_OP_MPUTARR 198 +#define DUK_OP_MPUTARRI 199 +#define DUK_OP_SETALEN 200 +#define DUK_OP_INITENUM 201 +#define DUK_OP_NEXTENUM 202 +#define DUK_OP_NEWTARGET 203 +#define DUK_OP_DEBUGGER 204 +#define DUK_OP_NOP 205 +#define DUK_OP_INVALID 206 +#define DUK_OP_UNUSED207 207 +#define DUK_OP_GETPROPC 208 +#define DUK_OP_GETPROPC_RR 208 +#define DUK_OP_GETPROPC_CR 209 +#define DUK_OP_GETPROPC_RC 210 +#define DUK_OP_GETPROPC_CC 211 +#define DUK_OP_UNUSED212 212 +#define DUK_OP_UNUSED213 213 +#define DUK_OP_UNUSED214 214 +#define DUK_OP_UNUSED215 215 +#define DUK_OP_UNUSED216 216 +#define DUK_OP_UNUSED217 217 +#define DUK_OP_UNUSED218 218 +#define DUK_OP_UNUSED219 219 +#define DUK_OP_UNUSED220 220 +#define DUK_OP_UNUSED221 221 +#define DUK_OP_UNUSED222 222 +#define DUK_OP_UNUSED223 223 +#define DUK_OP_UNUSED224 224 +#define DUK_OP_UNUSED225 225 +#define DUK_OP_UNUSED226 226 +#define DUK_OP_UNUSED227 227 +#define DUK_OP_UNUSED228 228 +#define DUK_OP_UNUSED229 229 +#define DUK_OP_UNUSED230 230 +#define DUK_OP_UNUSED231 231 +#define DUK_OP_UNUSED232 232 +#define DUK_OP_UNUSED233 233 +#define DUK_OP_UNUSED234 234 +#define DUK_OP_UNUSED235 235 +#define DUK_OP_UNUSED236 236 +#define DUK_OP_UNUSED237 237 +#define DUK_OP_UNUSED238 238 +#define DUK_OP_UNUSED239 239 +#define DUK_OP_UNUSED240 240 +#define DUK_OP_UNUSED241 241 +#define DUK_OP_UNUSED242 242 +#define DUK_OP_UNUSED243 243 +#define DUK_OP_UNUSED244 244 +#define DUK_OP_UNUSED245 245 +#define DUK_OP_UNUSED246 246 +#define DUK_OP_UNUSED247 247 +#define DUK_OP_UNUSED248 248 +#define DUK_OP_UNUSED249 249 +#define DUK_OP_UNUSED250 250 +#define DUK_OP_UNUSED251 251 +#define DUK_OP_UNUSED252 252 +#define DUK_OP_UNUSED253 253 +#define DUK_OP_UNUSED254 254 +#define DUK_OP_UNUSED255 255 +#define DUK_OP_NONE 256 /* dummy value used as marker (doesn't fit in 8-bit field) */ + +/* XXX: Allocate flags from opcode field? Would take 16 opcode slots + * but avoids shuffling in more cases. Maybe not worth it. + */ +/* DUK_OP_TRYCATCH flags in A. */ +#define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH (1U << 0) +#define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY (1U << 1) +#define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING (1U << 2) +#define DUK_BC_TRYCATCH_FLAG_WITH_BINDING (1U << 3) + +/* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags + * (DUK_PROPDESC_FLAG_XXX). + */ +#define DUK_BC_DECLVAR_FLAG_FUNC_DECL (1U << 4) /* function declaration */ + +/* DUK_OP_CALLn flags, part of opcode field. Three lowest bits must match + * DUK_CALL_FLAG_xxx directly. + */ +#define DUK_BC_CALL_FLAG_TAILCALL (1U << 0) +#define DUK_BC_CALL_FLAG_CONSTRUCT (1U << 1) +#define DUK_BC_CALL_FLAG_CALLED_AS_EVAL (1U << 2) +#define DUK_BC_CALL_FLAG_INDIRECT (1U << 3) + +/* Misc constants and helper macros. */ +#define DUK_BC_LDINT_BIAS (1L << 15) +#define DUK_BC_LDINTX_SHIFT 16 +#define DUK_BC_JUMP_BIAS (1L << 23) + +#endif /* DUK_JS_BYTECODE_H_INCLUDED */ +/* #include duk_lexer.h */ +#line 1 "duk_lexer.h" +/* + * Lexer defines. + */ + +#if !defined(DUK_LEXER_H_INCLUDED) +#define DUK_LEXER_H_INCLUDED + +typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct); + +/* + * A token is interpreted as any possible production of InputElementDiv + * and InputElementRegExp, see E5 Section 7 in its entirety. Note that + * the E5 "Token" production does not cover all actual tokens of the + * language (which is explicitly stated in the specification, Section 7.5). + * Null and boolean literals are defined as part of both ReservedWord + * (E5 Section 7.6.1) and Literal (E5 Section 7.8) productions. Here, + * null and boolean values have literal tokens, and are not reserved + * words. + * + * Decimal literal negative/positive sign is -not- part of DUK_TOK_NUMBER. + * The number tokens always have a non-negative value. The unary minus + * operator in "-1.0" is optimized during compilation to yield a single + * negative constant. + * + * Token numbering is free except that reserved words are required to be + * in a continuous range and in a particular order. See genstrings.py. + */ + +#define DUK_LEXER_INITCTX(ctx) duk_lexer_initctx((ctx)) + +#define DUK_LEXER_SETPOINT(ctx,pt) duk_lexer_setpoint((ctx), (pt)) + +#define DUK_LEXER_GETPOINT(ctx,pt) duk_lexer_getpoint((ctx), (pt)) + +/* Currently 6 characters of lookup are actually needed (duk_lexer.c). */ +#define DUK_LEXER_WINDOW_SIZE 6 +#if defined(DUK_USE_LEXER_SLIDING_WINDOW) +#define DUK_LEXER_BUFFER_SIZE 64 +#endif + +#define DUK_TOK_MINVAL 0 + +/* returned after EOF (infinite amount) */ +#define DUK_TOK_EOF 0 + +/* identifier names (E5 Section 7.6) */ +#define DUK_TOK_IDENTIFIER 1 + +/* reserved words: keywords */ +#define DUK_TOK_START_RESERVED 2 +#define DUK_TOK_BREAK 2 +#define DUK_TOK_CASE 3 +#define DUK_TOK_CATCH 4 +#define DUK_TOK_CONTINUE 5 +#define DUK_TOK_DEBUGGER 6 +#define DUK_TOK_DEFAULT 7 +#define DUK_TOK_DELETE 8 +#define DUK_TOK_DO 9 +#define DUK_TOK_ELSE 10 +#define DUK_TOK_FINALLY 11 +#define DUK_TOK_FOR 12 +#define DUK_TOK_FUNCTION 13 +#define DUK_TOK_IF 14 +#define DUK_TOK_IN 15 +#define DUK_TOK_INSTANCEOF 16 +#define DUK_TOK_NEW 17 +#define DUK_TOK_RETURN 18 +#define DUK_TOK_SWITCH 19 +#define DUK_TOK_THIS 20 +#define DUK_TOK_THROW 21 +#define DUK_TOK_TRY 22 +#define DUK_TOK_TYPEOF 23 +#define DUK_TOK_VAR 24 +#define DUK_TOK_CONST 25 +#define DUK_TOK_VOID 26 +#define DUK_TOK_WHILE 27 +#define DUK_TOK_WITH 28 + +/* reserved words: future reserved words */ +#define DUK_TOK_CLASS 29 +#define DUK_TOK_ENUM 30 +#define DUK_TOK_EXPORT 31 +#define DUK_TOK_EXTENDS 32 +#define DUK_TOK_IMPORT 33 +#define DUK_TOK_SUPER 34 + +/* "null", "true", and "false" are always reserved words. + * Note that "get" and "set" are not! + */ +#define DUK_TOK_NULL 35 +#define DUK_TOK_TRUE 36 +#define DUK_TOK_FALSE 37 + +/* reserved words: additional future reserved words in strict mode */ +#define DUK_TOK_START_STRICT_RESERVED 38 /* inclusive */ +#define DUK_TOK_IMPLEMENTS 38 +#define DUK_TOK_INTERFACE 39 +#define DUK_TOK_LET 40 +#define DUK_TOK_PACKAGE 41 +#define DUK_TOK_PRIVATE 42 +#define DUK_TOK_PROTECTED 43 +#define DUK_TOK_PUBLIC 44 +#define DUK_TOK_STATIC 45 +#define DUK_TOK_YIELD 46 + +#define DUK_TOK_END_RESERVED 47 /* exclusive */ + +/* "get" and "set" are tokens but NOT ReservedWords. They are currently + * parsed and identifiers and these defines are actually now unused. + */ +#define DUK_TOK_GET 47 +#define DUK_TOK_SET 48 + +/* punctuators (unlike the spec, also includes "/" and "/=") */ +#define DUK_TOK_LCURLY 49 +#define DUK_TOK_RCURLY 50 +#define DUK_TOK_LBRACKET 51 +#define DUK_TOK_RBRACKET 52 +#define DUK_TOK_LPAREN 53 +#define DUK_TOK_RPAREN 54 +#define DUK_TOK_PERIOD 55 +#define DUK_TOK_SEMICOLON 56 +#define DUK_TOK_COMMA 57 +#define DUK_TOK_LT 58 +#define DUK_TOK_GT 59 +#define DUK_TOK_LE 60 +#define DUK_TOK_GE 61 +#define DUK_TOK_EQ 62 +#define DUK_TOK_NEQ 63 +#define DUK_TOK_SEQ 64 +#define DUK_TOK_SNEQ 65 +#define DUK_TOK_ADD 66 +#define DUK_TOK_SUB 67 +#define DUK_TOK_MUL 68 +#define DUK_TOK_DIV 69 +#define DUK_TOK_MOD 70 +#define DUK_TOK_EXP 71 +#define DUK_TOK_INCREMENT 72 +#define DUK_TOK_DECREMENT 73 +#define DUK_TOK_ALSHIFT 74 /* named "arithmetic" because result is signed */ +#define DUK_TOK_ARSHIFT 75 +#define DUK_TOK_RSHIFT 76 +#define DUK_TOK_BAND 77 +#define DUK_TOK_BOR 78 +#define DUK_TOK_BXOR 79 +#define DUK_TOK_LNOT 80 +#define DUK_TOK_BNOT 81 +#define DUK_TOK_LAND 82 +#define DUK_TOK_LOR 83 +#define DUK_TOK_QUESTION 84 +#define DUK_TOK_COLON 85 +#define DUK_TOK_EQUALSIGN 86 +#define DUK_TOK_ADD_EQ 87 +#define DUK_TOK_SUB_EQ 88 +#define DUK_TOK_MUL_EQ 89 +#define DUK_TOK_DIV_EQ 90 +#define DUK_TOK_MOD_EQ 91 +#define DUK_TOK_EXP_EQ 92 +#define DUK_TOK_ALSHIFT_EQ 93 +#define DUK_TOK_ARSHIFT_EQ 94 +#define DUK_TOK_RSHIFT_EQ 95 +#define DUK_TOK_BAND_EQ 96 +#define DUK_TOK_BOR_EQ 97 +#define DUK_TOK_BXOR_EQ 98 + +/* literals (E5 Section 7.8), except null, true, false, which are treated + * like reserved words (above). + */ +#define DUK_TOK_NUMBER 99 +#define DUK_TOK_STRING 100 +#define DUK_TOK_REGEXP 101 + +#define DUK_TOK_MAXVAL 101 /* inclusive */ + +#define DUK_TOK_INVALID DUK_SMALL_UINT_MAX + +/* Convert heap string index to a token (reserved words) */ +#define DUK_STRIDX_TO_TOK(x) ((x) - DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED) + +/* Sanity check */ +#if (DUK_TOK_MAXVAL > 255) +#error DUK_TOK_MAXVAL too large, code assumes it fits into 8 bits +#endif + +/* Sanity checks for string and token defines */ +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_BREAK) != DUK_TOK_BREAK) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CASE) != DUK_TOK_CASE) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CATCH) != DUK_TOK_CATCH) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONTINUE) != DUK_TOK_CONTINUE) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEBUGGER) != DUK_TOK_DEBUGGER) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEFAULT) != DUK_TOK_DEFAULT) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DELETE) != DUK_TOK_DELETE) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DO) != DUK_TOK_DO) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ELSE) != DUK_TOK_ELSE) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FINALLY) != DUK_TOK_FINALLY) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FOR) != DUK_TOK_FOR) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_FUNCTION) != DUK_TOK_FUNCTION) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IF) != DUK_TOK_IF) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IN) != DUK_TOK_IN) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INSTANCEOF) != DUK_TOK_INSTANCEOF) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_NEW) != DUK_TOK_NEW) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_RETURN) != DUK_TOK_RETURN) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SWITCH) != DUK_TOK_SWITCH) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THIS) != DUK_TOK_THIS) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THROW) != DUK_TOK_THROW) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRY) != DUK_TOK_TRY) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TYPEOF) != DUK_TOK_TYPEOF) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VAR) != DUK_TOK_VAR) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VOID) != DUK_TOK_VOID) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WHILE) != DUK_TOK_WHILE) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WITH) != DUK_TOK_WITH) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CLASS) != DUK_TOK_CLASS) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONST) != DUK_TOK_CONST) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ENUM) != DUK_TOK_ENUM) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXPORT) != DUK_TOK_EXPORT) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXTENDS) != DUK_TOK_EXTENDS) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPORT) != DUK_TOK_IMPORT) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SUPER) != DUK_TOK_SUPER) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_NULL) != DUK_TOK_NULL) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRUE) != DUK_TOK_TRUE) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FALSE) != DUK_TOK_FALSE) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPLEMENTS) != DUK_TOK_IMPLEMENTS) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INTERFACE) != DUK_TOK_INTERFACE) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LET) != DUK_TOK_LET) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PACKAGE) != DUK_TOK_PACKAGE) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PRIVATE) != DUK_TOK_PRIVATE) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PROTECTED) != DUK_TOK_PROTECTED) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PUBLIC) != DUK_TOK_PUBLIC) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_STATIC) != DUK_TOK_STATIC) +#error mismatch in token defines +#endif +#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_YIELD) != DUK_TOK_YIELD) +#error mismatch in token defines +#endif + +/* Regexp tokens */ +#define DUK_RETOK_EOF 0 +#define DUK_RETOK_DISJUNCTION 1 +#define DUK_RETOK_QUANTIFIER 2 +#define DUK_RETOK_ASSERT_START 3 +#define DUK_RETOK_ASSERT_END 4 +#define DUK_RETOK_ASSERT_WORD_BOUNDARY 5 +#define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY 6 +#define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD 7 +#define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD 8 +#define DUK_RETOK_ATOM_PERIOD 9 +#define DUK_RETOK_ATOM_CHAR 10 +#define DUK_RETOK_ATOM_DIGIT 11 /* assumptions in regexp compiler */ +#define DUK_RETOK_ATOM_NOT_DIGIT 12 /* -""- */ +#define DUK_RETOK_ATOM_WHITE 13 /* -""- */ +#define DUK_RETOK_ATOM_NOT_WHITE 14 /* -""- */ +#define DUK_RETOK_ATOM_WORD_CHAR 15 /* -""- */ +#define DUK_RETOK_ATOM_NOT_WORD_CHAR 16 /* -""- */ +#define DUK_RETOK_ATOM_BACKREFERENCE 17 +#define DUK_RETOK_ATOM_START_CAPTURE_GROUP 18 +#define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP 19 +#define DUK_RETOK_ATOM_START_CHARCLASS 20 +#define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED 21 +#define DUK_RETOK_ATOM_END_GROUP 22 + +/* Constants for duk_lexer_ctx.buf. */ +#define DUK_LEXER_TEMP_BUF_LIMIT 256 + +/* A token value. Can be memcpy()'d, but note that slot1/slot2 values are on the valstack. + * Some fields (like num, str1, str2) are only valid for specific token types and may have + * stale values otherwise. + */ +struct duk_token { + duk_small_uint_t t; /* token type (with reserved word identification) */ + duk_small_uint_t t_nores; /* token type (with reserved words as DUK_TOK_IDENTIFER) */ + duk_double_t num; /* numeric value of token */ + duk_hstring *str1; /* string 1 of token (borrowed, stored to ctx->slot1_idx) */ + duk_hstring *str2; /* string 2 of token (borrowed, stored to ctx->slot2_idx) */ + duk_size_t start_offset; /* start byte offset of token in lexer input */ + duk_int_t start_line; /* start line of token (first char) */ + duk_int_t num_escapes; /* number of escapes and line continuations (for directive prologue) */ + duk_bool_t lineterm; /* token was preceded by a lineterm */ + duk_bool_t allow_auto_semi; /* token allows automatic semicolon insertion (eof or preceded by newline) */ +}; + +#define DUK_RE_QUANTIFIER_INFINITE ((duk_uint32_t) 0xffffffffUL) + +/* A regexp token value. */ +struct duk_re_token { + duk_small_uint_t t; /* token type */ + duk_small_uint_t greedy; + duk_uint32_t num; /* numeric value (character, count) */ + duk_uint32_t qmin; + duk_uint32_t qmax; +}; + +/* A structure for 'snapshotting' a point for rewinding */ +struct duk_lexer_point { + duk_size_t offset; + duk_int_t line; +}; + +/* Lexer codepoint with additional info like offset/line number */ +struct duk_lexer_codepoint { + duk_codepoint_t codepoint; + duk_size_t offset; + duk_int_t line; +}; + +/* Lexer context. Same context is used for Ecmascript and Regexp parsing. */ +struct duk_lexer_ctx { +#if defined(DUK_USE_LEXER_SLIDING_WINDOW) + duk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */ + duk_lexer_codepoint buffer[DUK_LEXER_BUFFER_SIZE]; +#else + duk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */ +#endif + + duk_hthread *thr; /* thread; minimizes argument passing */ + + const duk_uint8_t *input; /* input string (may be a user pointer) */ + duk_size_t input_length; /* input byte length */ + duk_size_t input_offset; /* input offset for window leading edge (not window[0]) */ + duk_int_t input_line; /* input linenumber at input_offset (not window[0]), init to 1 */ + + duk_idx_t slot1_idx; /* valstack slot for 1st token value */ + duk_idx_t slot2_idx; /* valstack slot for 2nd token value */ + duk_idx_t buf_idx; /* valstack slot for temp buffer */ + duk_hbuffer_dynamic *buf; /* temp accumulation buffer */ + duk_bufwriter_ctx bw; /* bufwriter for temp accumulation */ + + duk_int_t token_count; /* number of tokens parsed */ + duk_int_t token_limit; /* maximum token count before error (sanity backstop) */ + + duk_small_uint_t flags; /* lexer flags, use compiler flag defines for now */ +}; + +/* + * Prototypes + */ + +DUK_INTERNAL_DECL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx); + +DUK_INTERNAL_DECL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt); +DUK_INTERNAL_DECL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt); + +DUK_INTERNAL_DECL +void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx, + duk_token *out_token, + duk_bool_t strict_mode, + duk_bool_t regexp_mode); +#if defined(DUK_USE_REGEXP_SUPPORT) +DUK_INTERNAL_DECL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token); +DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata); +#endif /* DUK_USE_REGEXP_SUPPORT */ + +#endif /* DUK_LEXER_H_INCLUDED */ +/* #include duk_js_compiler.h */ +#line 1 "duk_js_compiler.h" +/* + * Ecmascript compiler. + */ + +#if !defined(DUK_JS_COMPILER_H_INCLUDED) +#define DUK_JS_COMPILER_H_INCLUDED + +/* ecmascript compiler limits */ +#define DUK_COMPILER_TOKEN_LIMIT 100000000L /* 1e8: protects against deeply nested inner functions */ + +/* maximum loopcount for peephole optimization */ +#define DUK_COMPILER_PEEPHOLE_MAXITER 3 + +/* maximum bytecode length in instructions */ +#define DUK_COMPILER_MAX_BYTECODE_LENGTH (256L * 1024L * 1024L) /* 1 GB */ + +/* + * Compiler intermediate values + * + * Intermediate values describe either plain values (e.g. strings or + * numbers) or binary operations which have not yet been coerced into + * either a left-hand-side or right-hand-side role (e.g. object property). + */ + +#define DUK_IVAL_NONE 0 /* no value */ +#define DUK_IVAL_PLAIN 1 /* register, constant, or value */ +#define DUK_IVAL_ARITH 2 /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */ +#define DUK_IVAL_PROP 3 /* property access */ +#define DUK_IVAL_VAR 4 /* variable access */ + +#define DUK_ISPEC_NONE 0 /* no value */ +#define DUK_ISPEC_VALUE 1 /* value resides in 'valstack_idx' */ +#define DUK_ISPEC_REGCONST 2 /* value resides in a register or constant */ + +/* Bit mask which indicates that a regconst is a constant instead of a register. + * Chosen so that when a regconst is cast to duk_int32_t, all consts are + * negative values. + */ +#define DUK_REGCONST_CONST_MARKER DUK_INT32_MIN /* = -0x80000000 */ + +/* Type to represent a reg/const reference during compilation, with <0 + * indicating a constant. Some call sites also use -1 to indicate 'none'. + */ +typedef duk_int32_t duk_regconst_t; + +typedef struct { + duk_small_uint_t t; /* DUK_ISPEC_XXX */ + duk_regconst_t regconst; + duk_idx_t valstack_idx; /* always set; points to a reserved valstack slot */ +} duk_ispec; + +typedef struct { + /* + * PLAIN: x1 + * ARITH: x1 <op> x2 + * PROP: x1.x2 + * VAR: x1 (name) + */ + + /* XXX: can be optimized for smaller footprint esp. on 32-bit environments */ + duk_small_uint_t t; /* DUK_IVAL_XXX */ + duk_small_uint_t op; /* bytecode opcode for binary ops */ + duk_ispec x1; + duk_ispec x2; +} duk_ivalue; + +/* + * Bytecode instruction representation during compilation + * + * Contains the actual instruction and (optionally) debug info. + */ + +struct duk_compiler_instr { + duk_instr_t ins; +#if defined(DUK_USE_PC2LINE) + duk_uint32_t line; +#endif +}; + +/* + * Compiler state + */ + +#define DUK_LABEL_FLAG_ALLOW_BREAK (1U << 0) +#define DUK_LABEL_FLAG_ALLOW_CONTINUE (1U << 1) + +#define DUK_DECL_TYPE_VAR 0 +#define DUK_DECL_TYPE_FUNC 1 + +/* XXX: optimize to 16 bytes */ +typedef struct { + duk_small_uint_t flags; + duk_int_t label_id; /* numeric label_id (-1 reserved as marker) */ + duk_hstring *h_label; /* borrowed label name */ + duk_int_t catch_depth; /* catch depth at point of definition */ + duk_int_t pc_label; /* pc of label statement: + * pc+1: break jump site + * pc+2: continue jump site + */ + + /* Fast jumps (which avoid longjmp) jump directly to the jump sites + * which are always known even while the iteration/switch statement + * is still being parsed. A final peephole pass "straightens out" + * the jumps. + */ +} duk_labelinfo; + +/* Compiling state of one function, eventually converted to duk_hcompfunc */ +struct duk_compiler_func { + /* These pointers are at the start of the struct so that they pack + * nicely. Mixing pointers and integer values is bad on some + * platforms (e.g. if int is 32 bits and pointers are 64 bits). + */ + + duk_bufwriter_ctx bw_code; /* bufwriter for code */ + + duk_hstring *h_name; /* function name (borrowed reference), ends up in _name */ + /* h_code: held in bw_code */ + duk_hobject *h_consts; /* array */ + duk_hobject *h_funcs; /* array of function templates: [func1, offset1, line1, func2, offset2, line2] + * offset/line points to closing brace to allow skipping on pass 2 + */ + duk_hobject *h_decls; /* array of declarations: [ name1, val1, name2, val2, ... ] + * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars) + * record function and variable declarations in pass 1 + */ + duk_hobject *h_labelnames; /* array of active label names */ + duk_hbuffer_dynamic *h_labelinfos; /* C array of duk_labelinfo */ + duk_hobject *h_argnames; /* array of formal argument names (-> _Formals) */ + duk_hobject *h_varmap; /* variable map for pass 2 (identifier -> register number or null (unmapped)) */ + + /* Value stack indices for tracking objects. */ + /* code_idx: not needed */ + duk_idx_t consts_idx; + duk_idx_t funcs_idx; + duk_idx_t decls_idx; + duk_idx_t labelnames_idx; + duk_idx_t labelinfos_idx; + duk_idx_t argnames_idx; + duk_idx_t varmap_idx; + + /* Temp reg handling. */ + duk_regconst_t temp_first; /* first register that is a temporary (below: variables) */ + duk_regconst_t temp_next; /* next temporary register to allocate */ + duk_regconst_t temp_max; /* highest value of temp_reg (temp_max - 1 is highest used reg) */ + + /* Shuffle registers if large number of regs/consts. */ + duk_regconst_t shuffle1; + duk_regconst_t shuffle2; + duk_regconst_t shuffle3; + + /* Stats for current expression being parsed. */ + duk_int_t nud_count; + duk_int_t led_count; + duk_int_t paren_level; /* parenthesis count, 0 = top level */ + duk_bool_t expr_lhs; /* expression is left-hand-side compatible */ + duk_bool_t allow_in; /* current paren level allows 'in' token */ + + /* Misc. */ + duk_int_t stmt_next; /* statement id allocation (running counter) */ + duk_int_t label_next; /* label id allocation (running counter) */ + duk_int_t catch_depth; /* catch stack depth */ + duk_int_t with_depth; /* with stack depth (affects identifier lookups) */ + duk_int_t fnum_next; /* inner function numbering */ + duk_int_t num_formals; /* number of formal arguments */ + duk_regconst_t reg_stmt_value; /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */ +#if defined(DUK_USE_DEBUGGER_SUPPORT) + duk_int_t min_line; /* XXX: typing (duk_hcompfunc has duk_uint32_t) */ + duk_int_t max_line; +#endif + + /* Status booleans. */ + duk_uint8_t is_function; /* is an actual function (not global/eval code) */ + duk_uint8_t is_eval; /* is eval code */ + duk_uint8_t is_global; /* is global code */ + duk_uint8_t is_namebinding; /* needs a name binding */ + duk_uint8_t is_constructable; /* result is constructable */ + duk_uint8_t is_setget; /* is a setter/getter */ + duk_uint8_t is_strict; /* function is strict */ + duk_uint8_t is_notail; /* function must not be tail called */ + duk_uint8_t in_directive_prologue; /* parsing in "directive prologue", recognize directives */ + duk_uint8_t in_scanning; /* parsing in "scanning" phase (first pass) */ + duk_uint8_t may_direct_eval; /* function may call direct eval */ + duk_uint8_t id_access_arguments; /* function refers to 'arguments' identifier */ + duk_uint8_t id_access_slow; /* function makes one or more slow path accesses that won't match own static variables */ + duk_uint8_t id_access_slow_own; /* function makes one or more slow path accesses that may match own static variables */ + duk_uint8_t is_arguments_shadowed; /* argument/function declaration shadows 'arguments' */ + duk_uint8_t needs_shuffle; /* function needs shuffle registers */ + duk_uint8_t reject_regexp_in_adv; /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */ +}; + +struct duk_compiler_ctx { + duk_hthread *thr; + + /* filename being compiled (ends up in functions' '_filename' property) */ + duk_hstring *h_filename; /* borrowed reference */ + + /* lexing (tokenization) state (contains two valstack slot indices) */ + duk_lexer_ctx lex; + + /* current and previous token for parsing */ + duk_token prev_token; + duk_token curr_token; + duk_idx_t tok11_idx; /* curr_token slot1 (matches 'lex' slot1_idx) */ + duk_idx_t tok12_idx; /* curr_token slot2 (matches 'lex' slot2_idx) */ + duk_idx_t tok21_idx; /* prev_token slot1 */ + duk_idx_t tok22_idx; /* prev_token slot2 */ + + /* recursion limit */ + duk_int_t recursion_depth; + duk_int_t recursion_limit; + + /* code emission temporary */ + duk_int_t emit_jumpslot_pc; + + /* current function being compiled (embedded instead of pointer for more compact access) */ + duk_compiler_func curr_func; +}; + +/* + * Prototypes + */ + +DUK_INTERNAL_DECL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags); + +#endif /* DUK_JS_COMPILER_H_INCLUDED */ +/* #include duk_regexp.h */ +#line 1 "duk_regexp.h" +/* + * Regular expression structs, constants, and bytecode defines. + */ + +#if !defined(DUK_REGEXP_H_INCLUDED) +#define DUK_REGEXP_H_INCLUDED + +/* maximum bytecode copies for {n,m} quantifiers */ +#define DUK_RE_MAX_ATOM_COPIES 1000 + +/* regexp compilation limits */ +#define DUK_RE_COMPILE_TOKEN_LIMIT 100000000L /* 1e8 */ + +/* regexp execution limits */ +#define DUK_RE_EXECUTE_STEPS_LIMIT 1000000000L /* 1e9 */ + +/* regexp opcodes */ +#define DUK_REOP_MATCH 1 +#define DUK_REOP_CHAR 2 +#define DUK_REOP_PERIOD 3 +#define DUK_REOP_RANGES 4 +#define DUK_REOP_INVRANGES 5 +#define DUK_REOP_JUMP 6 +#define DUK_REOP_SPLIT1 7 +#define DUK_REOP_SPLIT2 8 +#define DUK_REOP_SQMINIMAL 9 +#define DUK_REOP_SQGREEDY 10 +#define DUK_REOP_SAVE 11 +#define DUK_REOP_WIPERANGE 12 +#define DUK_REOP_LOOKPOS 13 +#define DUK_REOP_LOOKNEG 14 +#define DUK_REOP_BACKREFERENCE 15 +#define DUK_REOP_ASSERT_START 16 +#define DUK_REOP_ASSERT_END 17 +#define DUK_REOP_ASSERT_WORD_BOUNDARY 18 +#define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY 19 + +/* flags */ +#define DUK_RE_FLAG_GLOBAL (1U << 0) +#define DUK_RE_FLAG_IGNORE_CASE (1U << 1) +#define DUK_RE_FLAG_MULTILINE (1U << 2) + +struct duk_re_matcher_ctx { + duk_hthread *thr; + + duk_uint32_t re_flags; + const duk_uint8_t *input; + const duk_uint8_t *input_end; + const duk_uint8_t *bytecode; + const duk_uint8_t *bytecode_end; + const duk_uint8_t **saved; /* allocated from valstack (fixed buffer) */ + duk_uint32_t nsaved; + duk_uint32_t recursion_depth; + duk_uint32_t recursion_limit; + duk_uint32_t steps_count; + duk_uint32_t steps_limit; +}; + +struct duk_re_compiler_ctx { + duk_hthread *thr; + + duk_uint32_t re_flags; + duk_lexer_ctx lex; + duk_re_token curr_token; + duk_bufwriter_ctx bw; + duk_uint32_t captures; /* highest capture number emitted so far (used as: ++captures) */ + duk_uint32_t highest_backref; + duk_uint32_t recursion_depth; + duk_uint32_t recursion_limit; + duk_uint32_t nranges; /* internal temporary value, used for char classes */ +}; + +/* + * Prototypes + */ + +#if defined(DUK_USE_REGEXP_SUPPORT) +DUK_INTERNAL_DECL void duk_regexp_compile(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_regexp_create_instance(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_regexp_match(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr); /* hacky helper for String.prototype.split() */ +#endif + +#endif /* DUK_REGEXP_H_INCLUDED */ +/* #include duk_heaphdr.h */ +#line 1 "duk_heaphdr.h" +/* + * Heap header definition and assorted macros, including ref counting. + * Access all fields through the accessor macros. + */ + +#if !defined(DUK_HEAPHDR_H_INCLUDED) +#define DUK_HEAPHDR_H_INCLUDED + +/* + * Common heap header + * + * All heap objects share the same flags and refcount fields. Objects other + * than strings also need to have a single or double linked list pointers + * for insertion into the "heap allocated" list. Strings have single linked + * list pointers for string table chaining. + * + * Technically, 'h_refcount' must be wide enough to guarantee that it cannot + * wrap; otherwise objects might be freed incorrectly after wrapping. The + * default refcount field is 32 bits even on 64-bit systems: while that's in + * theory incorrect, the Duktape heap needs to be larger than 64GB for the + * count to actually wrap (assuming 16-byte duk_tvals). This is very unlikely + * to ever be an issue, but if it is, disabling DUK_USE_REFCOUNT32 causes + * Duktape to use size_t for refcounts which should always be safe. + * + * Heap header size on 32-bit platforms: 8 bytes without reference counting, + * 16 bytes with reference counting. + * + * Note that 'raw' macros such as DUK_HEAPHDR_GET_REFCOUNT() are not + * defined without DUK_USE_REFERENCE_COUNTING, so caller must #if defined() + * around them. + */ + +/* XXX: macro for shared header fields (avoids some padding issues) */ + +struct duk_heaphdr { + duk_uint32_t h_flags; + +#if defined(DUK_USE_REFERENCE_COUNTING) +#if defined(DUK_USE_ASSERTIONS) + /* When assertions enabled, used by mark-and-sweep for refcount + * validation. Largest reasonable type; also detects overflows. + */ + duk_size_t h_assert_refcount; +#endif +#if defined(DUK_USE_REFCOUNT16) + duk_uint16_t h_refcount; +#elif defined(DUK_USE_REFCOUNT32) + duk_uint32_t h_refcount; +#else + duk_size_t h_refcount; +#endif +#endif /* DUK_USE_REFERENCE_COUNTING */ + +#if defined(DUK_USE_HEAPPTR16) + duk_uint16_t h_next16; +#else + duk_heaphdr *h_next; +#endif + +#if defined(DUK_USE_DOUBLE_LINKED_HEAP) + /* refcounting requires direct heap frees, which in turn requires a dual linked heap */ +#if defined(DUK_USE_HEAPPTR16) + duk_uint16_t h_prev16; +#else + duk_heaphdr *h_prev; +#endif +#endif + + /* When DUK_USE_HEAPPTR16 (and DUK_USE_REFCOUNT16) is in use, the + * struct won't align nicely to 4 bytes. This 16-bit extra field + * is added to make the alignment clean; the field can be used by + * heap objects when 16-bit packing is used. This field is now + * conditional to DUK_USE_HEAPPTR16 only, but it is intended to be + * used with DUK_USE_REFCOUNT16 and DUK_USE_DOUBLE_LINKED_HEAP; + * this only matter to low memory environments anyway. + */ +#if defined(DUK_USE_HEAPPTR16) + duk_uint16_t h_extra16; +#endif +}; + +struct duk_heaphdr_string { + /* 16 bits would be enough for shared heaphdr flags and duk_hstring + * flags. The initial parts of duk_heaphdr_string and duk_heaphdr + * must match so changing the flags field size here would be quite + * awkward. However, to minimize struct size, we can pack at least + * 16 bits of duk_hstring data into the flags field. + */ + duk_uint32_t h_flags; + +#if defined(DUK_USE_REFERENCE_COUNTING) +#if defined(DUK_USE_ASSERTIONS) + /* When assertions enabled, used by mark-and-sweep for refcount + * validation. Largest reasonable type; also detects overflows. + */ + duk_size_t h_assert_refcount; +#endif +#if defined(DUK_USE_REFCOUNT16) + duk_uint16_t h_refcount; + duk_uint16_t h_strextra16; /* round out to 8 bytes */ +#elif defined(DUK_USE_REFCOUNT32) + duk_uint32_t h_refcount; +#else + duk_size_t h_refcount; +#endif +#else + duk_uint16_t h_strextra16; +#endif /* DUK_USE_REFERENCE_COUNTING */ + + duk_hstring *h_next; + /* No 'h_prev' pointer for strings. */ +}; + +#define DUK_HEAPHDR_FLAGS_TYPE_MASK 0x00000003UL +#define DUK_HEAPHDR_FLAGS_FLAG_MASK (~DUK_HEAPHDR_FLAGS_TYPE_MASK) + + /* 2 bits for heap type */ +#define DUK_HEAPHDR_FLAGS_HEAP_START 2 /* 5 heap flags */ +#define DUK_HEAPHDR_FLAGS_USER_START 7 /* 25 user flags */ + +#define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_HEAP_START + (n)) +#define DUK_HEAPHDR_USER_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_USER_START + (n)) +#define DUK_HEAPHDR_HEAP_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n))) +#define DUK_HEAPHDR_USER_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n))) + +#define DUK_HEAPHDR_FLAG_REACHABLE DUK_HEAPHDR_HEAP_FLAG(0) /* mark-and-sweep: reachable */ +#define DUK_HEAPHDR_FLAG_TEMPROOT DUK_HEAPHDR_HEAP_FLAG(1) /* mark-and-sweep: children not processed */ +#define DUK_HEAPHDR_FLAG_FINALIZABLE DUK_HEAPHDR_HEAP_FLAG(2) /* mark-and-sweep: finalizable (on current pass) */ +#define DUK_HEAPHDR_FLAG_FINALIZED DUK_HEAPHDR_HEAP_FLAG(3) /* mark-and-sweep: finalized (on previous pass) */ +#define DUK_HEAPHDR_FLAG_READONLY DUK_HEAPHDR_HEAP_FLAG(4) /* read-only object, in code section */ + +#define DUK_HTYPE_MIN 0 +#define DUK_HTYPE_STRING 0 +#define DUK_HTYPE_OBJECT 1 +#define DUK_HTYPE_BUFFER 2 +#define DUK_HTYPE_MAX 2 + +#if defined(DUK_USE_HEAPPTR16) +#define DUK_HEAPHDR_GET_NEXT(heap,h) \ + ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16)) +#define DUK_HEAPHDR_SET_NEXT(heap,h,val) do { \ + (h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \ + } while (0) +#else +#define DUK_HEAPHDR_GET_NEXT(heap,h) ((h)->h_next) +#define DUK_HEAPHDR_SET_NEXT(heap,h,val) do { \ + (h)->h_next = (val); \ + } while (0) +#endif + +#if defined(DUK_USE_DOUBLE_LINKED_HEAP) +#if defined(DUK_USE_HEAPPTR16) +#define DUK_HEAPHDR_GET_PREV(heap,h) \ + ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16)) +#define DUK_HEAPHDR_SET_PREV(heap,h,val) do { \ + (h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \ + } while (0) +#else +#define DUK_HEAPHDR_GET_PREV(heap,h) ((h)->h_prev) +#define DUK_HEAPHDR_SET_PREV(heap,h,val) do { \ + (h)->h_prev = (val); \ + } while (0) +#endif +#endif + +#if defined(DUK_USE_REFERENCE_COUNTING) +#define DUK_HEAPHDR_GET_REFCOUNT(h) ((h)->h_refcount) +#define DUK_HEAPHDR_SET_REFCOUNT(h,val) do { \ + (h)->h_refcount = (val); \ + DUK_ASSERT((h)->h_refcount == (val)); /* No truncation. */ \ + } while (0) +#define DUK_HEAPHDR_PREINC_REFCOUNT(h) (++(h)->h_refcount) /* result: updated refcount */ +#define DUK_HEAPHDR_PREDEC_REFCOUNT(h) (--(h)->h_refcount) /* result: updated refcount */ +#else +/* refcount macros not defined without refcounting, caller must #if defined() now */ +#endif /* DUK_USE_REFERENCE_COUNTING */ + +/* + * Note: type is treated as a field separate from flags, so some masking is + * involved in the macros below. + */ + +#define DUK_HEAPHDR_GET_FLAGS_RAW(h) ((h)->h_flags) +#define DUK_HEAPHDR_SET_FLAGS_RAW(h,val) do { \ + (h)->h_flags = (val); } \ + } +#define DUK_HEAPHDR_GET_FLAGS(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK) +#define DUK_HEAPHDR_SET_FLAGS(h,val) do { \ + (h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \ + } while (0) +#define DUK_HEAPHDR_GET_TYPE(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK) +#define DUK_HEAPHDR_SET_TYPE(h,val) do { \ + (h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_TYPE_MASK)) | (val); \ + } while (0) + +/* Comparison for type >= DUK_HTYPE_MIN skipped; because DUK_HTYPE_MIN is zero + * and the comparison is unsigned, it's always true and generates warnings. + */ +#define DUK_HEAPHDR_HTYPE_VALID(h) ( \ + DUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX \ + ) + +#define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h,tval,fval) do { \ + (h)->h_flags = ((tval) & DUK_HEAPHDR_FLAGS_TYPE_MASK) | \ + ((fval) & DUK_HEAPHDR_FLAGS_FLAG_MASK); \ + } while (0) + +#define DUK_HEAPHDR_SET_FLAG_BITS(h,bits) do { \ + DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \ + (h)->h_flags |= (bits); \ + } while (0) + +#define DUK_HEAPHDR_CLEAR_FLAG_BITS(h,bits) do { \ + DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \ + (h)->h_flags &= ~((bits)); \ + } while (0) + +#define DUK_HEAPHDR_CHECK_FLAG_BITS(h,bits) (((h)->h_flags & (bits)) != 0) + +#define DUK_HEAPHDR_SET_REACHABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE) +#define DUK_HEAPHDR_CLEAR_REACHABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE) +#define DUK_HEAPHDR_HAS_REACHABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE) + +#define DUK_HEAPHDR_SET_TEMPROOT(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT) +#define DUK_HEAPHDR_CLEAR_TEMPROOT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT) +#define DUK_HEAPHDR_HAS_TEMPROOT(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT) + +#define DUK_HEAPHDR_SET_FINALIZABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE) +#define DUK_HEAPHDR_CLEAR_FINALIZABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE) +#define DUK_HEAPHDR_HAS_FINALIZABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE) + +#define DUK_HEAPHDR_SET_FINALIZED(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED) +#define DUK_HEAPHDR_CLEAR_FINALIZED(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED) +#define DUK_HEAPHDR_HAS_FINALIZED(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED) + +#define DUK_HEAPHDR_SET_READONLY(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY) +#define DUK_HEAPHDR_CLEAR_READONLY(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY) +#define DUK_HEAPHDR_HAS_READONLY(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY) + +/* get or set a range of flags; m=first bit number, n=number of bits */ +#define DUK_HEAPHDR_GET_FLAG_RANGE(h,m,n) (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL)) + +#define DUK_HEAPHDR_SET_FLAG_RANGE(h,m,n,v) do { \ + (h)->h_flags = \ + ((h)->h_flags & (~(((1UL << (n)) - 1UL) << (m)))) \ + | ((v) << (m)); \ + } while (0) + +/* init pointer fields to null */ +#if defined(DUK_USE_DOUBLE_LINKED_HEAP) +#define DUK_HEAPHDR_INIT_NULLS(h) do { \ + DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \ + DUK_HEAPHDR_SET_PREV((h), (void *) NULL); \ + } while (0) +#else +#define DUK_HEAPHDR_INIT_NULLS(h) do { \ + DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \ + } while (0) +#endif + +#define DUK_HEAPHDR_STRING_INIT_NULLS(h) do { \ + (h)->h_next = NULL; \ + } while (0) + +/* + * Type tests + */ + +/* Take advantage of the fact that for DUK_HTYPE_xxx numbers the lowest bit + * is only set for DUK_HTYPE_OBJECT (= 1). + */ +#if 0 +#define DUK_HEAPHDR_IS_OBJECT(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_OBJECT) +#endif +#define DUK_HEAPHDR_IS_OBJECT(h) ((h)->h_flags & 0x01UL) +#define DUK_HEAPHDR_IS_STRING(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_STRING) +#define DUK_HEAPHDR_IS_BUFFER(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_BUFFER) + +/* + * Assert helpers + */ + +/* Check that prev/next links are consistent: if e.g. h->prev is != NULL, + * h->prev->next should point back to h. + */ +#if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_ASSERTIONS) +#define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do { \ + if ((h) != NULL) { \ + duk_heaphdr *h__prev, *h__next; \ + h__prev = DUK_HEAPHDR_GET_PREV((heap), (h)); \ + h__next = DUK_HEAPHDR_GET_NEXT((heap), (h)); \ + DUK_ASSERT(h__prev == NULL || (DUK_HEAPHDR_GET_NEXT((heap), h__prev) == (h))); \ + DUK_ASSERT(h__next == NULL || (DUK_HEAPHDR_GET_PREV((heap), h__next) == (h))); \ + } \ + } while (0) +#else +#define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do {} while (0) +#endif + +#define DUK_ASSERT_HEAPHDR_VALID(h) do { \ + DUK_ASSERT((h) != NULL); \ + DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID((h))); \ + } while (0) + +#endif /* DUK_HEAPHDR_H_INCLUDED */ +/* #include duk_refcount.h */ +#line 1 "duk_refcount.h" +/* + * Reference counting helper macros. The macros take a thread argument + * and must thus always be executed in a specific thread context. The + * thread argument is not really needed anymore: DECREF can operate with + * a heap pointer only, and INCREF needs neither. + */ + +#if !defined(DUK_REFCOUNT_H_INCLUDED) +#define DUK_REFCOUNT_H_INCLUDED + +#if defined(DUK_USE_REFERENCE_COUNTING) + +#if defined(DUK_USE_ROM_OBJECTS) +/* With ROM objects "needs refcount update" is true when the value is + * heap allocated and is not a ROM object. + */ +/* XXX: double evaluation for 'tv' argument. */ +#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) \ + (DUK_TVAL_IS_HEAP_ALLOCATED((tv)) && !DUK_HEAPHDR_HAS_READONLY(DUK_TVAL_GET_HEAPHDR((tv)))) +#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) (!DUK_HEAPHDR_HAS_READONLY((h))) +#else /* DUK_USE_ROM_OBJECTS */ +/* Without ROM objects "needs refcount update" == is heap allocated. */ +#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) DUK_TVAL_IS_HEAP_ALLOCATED((tv)) +#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) 1 +#endif /* DUK_USE_ROM_OBJECTS */ + +/* Fast variants, inline refcount operations except for refzero handling. + * Can be used explicitly when speed is always more important than size. + * For a good compiler and a single file build, these are basically the + * same as a forced inline. + */ +#define DUK_TVAL_INCREF_FAST(thr,tv) do { \ + duk_tval *duk__tv = (tv); \ + DUK_ASSERT(duk__tv != NULL); \ + if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \ + duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \ + DUK_ASSERT(duk__h != NULL); \ + DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \ + DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \ + DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0); /* No wrapping. */ \ + } \ + } while (0) +#define DUK_TVAL_DECREF_FAST(thr,tv) do { \ + duk_tval *duk__tv = (tv); \ + DUK_ASSERT(duk__tv != NULL); \ + if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \ + duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \ + DUK_ASSERT(duk__h != NULL); \ + DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \ + DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \ + if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \ + duk_heaphdr_refzero((thr), duk__h); \ + } \ + } \ + } while (0) +#define DUK_TVAL_DECREF_NORZ_FAST(thr,tv) do { \ + duk_tval *duk__tv = (tv); \ + DUK_ASSERT(duk__tv != NULL); \ + if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \ + duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \ + DUK_ASSERT(duk__h != NULL); \ + DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \ + DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \ + if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \ + duk_heaphdr_refzero_norz((thr), duk__h); \ + } \ + } \ + } while (0) +#define DUK_HEAPHDR_INCREF_FAST(thr,h) do { \ + duk_heaphdr *duk__h = (duk_heaphdr *) (h); \ + DUK_ASSERT(duk__h != NULL); \ + DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \ + if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \ + DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \ + DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0); /* No wrapping. */ \ + } \ + } while (0) +#define DUK_HEAPHDR_DECREF_FAST_RAW(thr,h,rzcall,rzcast) do { \ + duk_heaphdr *duk__h = (duk_heaphdr *) (h); \ + DUK_ASSERT(duk__h != NULL); \ + DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \ + DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \ + if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \ + if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \ + (rzcall)((thr), (rzcast) duk__h); \ + } \ + } \ + } while (0) +#define DUK_HEAPHDR_DECREF_FAST(thr,h) \ + DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *) +#define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h) \ + DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *) + +/* Slow variants, call to a helper to reduce code size. + * Can be used explicitly when size is always more important than speed. + */ +#define DUK_TVAL_INCREF_SLOW(thr,tv) do { duk_tval_incref((tv)); } while (0) +#define DUK_TVAL_DECREF_SLOW(thr,tv) do { duk_tval_decref((thr), (tv)); } while (0) +#define DUK_TVAL_DECREF_NORZ_SLOW(thr,tv) do { duk_tval_decref_norz((thr), (tv)); } while (0) +#define DUK_HEAPHDR_INCREF_SLOW(thr,h) do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0) +#define DUK_HEAPHDR_DECREF_SLOW(thr,h) do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0) +#define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h) do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0) +#define DUK_HSTRING_INCREF_SLOW(thr,h) do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0) +#define DUK_HSTRING_DECREF_SLOW(thr,h) do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0) +#define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h) do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0) +#define DUK_HBUFFER_INCREF_SLOW(thr,h) do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0) +#define DUK_HBUFFER_DECREF_SLOW(thr,h) do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0) +#define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h) do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0) +#define DUK_HOBJECT_INCREF_SLOW(thr,h) do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0) +#define DUK_HOBJECT_DECREF_SLOW(thr,h) do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0) +#define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h) do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0) + +/* Default variants. Selection depends on speed/size preference. + * Concretely: with gcc 4.8.1 -Os x64 the difference in final binary + * is about +1kB for _FAST variants. + */ +#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT) +/* XXX: It would be nice to specialize for specific duk_hobject subtypes + * but current refzero queue handling prevents that. + */ +#define DUK_TVAL_INCREF(thr,tv) DUK_TVAL_INCREF_FAST((thr),(tv)) +#define DUK_TVAL_DECREF(thr,tv) DUK_TVAL_DECREF_FAST((thr),(tv)) +#define DUK_TVAL_DECREF_NORZ(thr,tv) DUK_TVAL_DECREF_NORZ_FAST((thr),(tv)) +#define DUK_HEAPHDR_INCREF(thr,h) DUK_HEAPHDR_INCREF_FAST((thr),(h)) +#define DUK_HEAPHDR_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *) +#define DUK_HEAPHDR_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *) +#define DUK_HSTRING_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h)) +#define DUK_HSTRING_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *) +#define DUK_HSTRING_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *) /* no 'norz' variant */ +#define DUK_HOBJECT_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h)) +#define DUK_HOBJECT_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *) +#define DUK_HOBJECT_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *) +#define DUK_HBUFFER_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h)) +#define DUK_HBUFFER_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *) +#define DUK_HBUFFER_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *) /* no 'norz' variant */ +#define DUK_HCOMPFUNC_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj) +#define DUK_HCOMPFUNC_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *) +#define DUK_HCOMPFUNC_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *) +#define DUK_HNATFUNC_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj) +#define DUK_HNATFUNC_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *) +#define DUK_HNATFUNC_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *) +#define DUK_HBUFOBJ_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj) +#define DUK_HBUFOBJ_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *) +#define DUK_HBUFOBJ_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *) +#define DUK_HTHREAD_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj) +#define DUK_HTHREAD_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *) +#define DUK_HTHREAD_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *) +#else +#define DUK_TVAL_INCREF(thr,tv) DUK_TVAL_INCREF_SLOW((thr),(tv)) +#define DUK_TVAL_DECREF(thr,tv) DUK_TVAL_DECREF_SLOW((thr),(tv)) +#define DUK_TVAL_DECREF_NORZ(thr,tv) DUK_TVAL_DECREF_NORZ_SLOW((thr),(tv)) +#define DUK_HEAPHDR_INCREF(thr,h) DUK_HEAPHDR_INCREF_SLOW((thr),(h)) +#define DUK_HEAPHDR_DECREF(thr,h) DUK_HEAPHDR_DECREF_SLOW((thr),(h)) +#define DUK_HEAPHDR_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_NORZ_SLOW((thr),(h)) +#define DUK_HSTRING_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h)) +#define DUK_HSTRING_DECREF(thr,h) DUK_HSTRING_DECREF_SLOW((thr),(h)) +#define DUK_HSTRING_DECREF_NORZ(thr,h) DUK_HSTRING_DECREF_NORZ_SLOW((thr),(h)) +#define DUK_HOBJECT_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h)) +#define DUK_HOBJECT_DECREF(thr,h) DUK_HOBJECT_DECREF_SLOW((thr),(h)) +#define DUK_HOBJECT_DECREF_NORZ(thr,h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(h)) +#define DUK_HBUFFER_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h)) +#define DUK_HBUFFER_DECREF(thr,h) DUK_HBUFFER_DECREF_SLOW((thr),(h)) +#define DUK_HBUFFER_DECREF_NORZ(thr,h) DUK_HBUFFER_DECREF_NORZ_SLOW((thr),(h)) +#define DUK_HCOMPFUNC_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj) +#define DUK_HCOMPFUNC_DECREF(thr,h) DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj) +#define DUK_HCOMPFUNC_DECREF_NORZ(thr,h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj) +#define DUK_HNATFUNC_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj) +#define DUK_HNATFUNC_DECREF(thr,h) DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj) +#define DUK_HNATFUNC_DECREF_NORZ(thr,h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj) +#define DUK_HBUFOBJ_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj) +#define DUK_HBUFOBJ_DECREF(thr,h) DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj) +#define DUK_HBUFOB_DECREF_NORZ(thr,h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj) +#define DUK_HTHREAD_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj) +#define DUK_HTHREAD_DECREF(thr,h) DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj) +#define DUK_HTHREAD_DECREF_NORZ(thr,h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj) +#endif + +/* Convenience for some situations; the above macros don't allow NULLs + * for performance reasons. Macros cover only actually needed cases. + */ +#define DUK_HEAPHDR_INCREF_ALLOWNULL(thr,h) do { \ + if ((h) != NULL) { \ + DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \ + } \ + } while (0) +#define DUK_HEAPHDR_DECREF_ALLOWNULL(thr,h) do { \ + if ((h) != NULL) { \ + DUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \ + } \ + } while (0) +#define DUK_HEAPHDR_DECREF_NORZ_ALLOWNULL(thr,h) do { \ + if ((h) != NULL) { \ + DUK_HEAPHDR_DECREF_NORZ((thr), (duk_heaphdr *) (h)); \ + } \ + } while (0) +#define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do { \ + if ((h) != NULL) { \ + DUK_HOBJECT_INCREF((thr), (h)); \ + } \ + } while (0) +#define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do { \ + if ((h) != NULL) { \ + DUK_HOBJECT_DECREF((thr), (h)); \ + } \ + } while (0) +#define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h) do { \ + if ((h) != NULL) { \ + DUK_HOBJECT_DECREF_NORZ((thr), (h)); \ + } \ + } while (0) +#define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h) do { \ + if ((h) != NULL) { \ + DUK_HBUFFER_INCREF((thr), (h)); \ + } \ + } while (0) +#define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h) do { \ + if ((h) != NULL) { \ + DUK_HBUFFER_DECREF((thr), (h)); \ + } \ + } while (0) +#define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h) do { \ + if ((h) != NULL) { \ + DUK_HBUFFER_DECREF_NORZ((thr), (h)); \ + } \ + } while (0) +#define DUK_HTHREAD_INCREF_ALLOWNULL(thr,h) do { \ + if ((h) != NULL) { \ + DUK_HTHREAD_INCREF((thr), (h)); \ + } \ + } while (0) +#define DUK_HTHREAD_DECREF_ALLOWNULL(thr,h) do { \ + if ((h) != NULL) { \ + DUK_HTHREAD_DECREF((thr), (h)); \ + } \ + } while (0) +#define DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr,h) do { \ + if ((h) != NULL) { \ + DUK_HTHREAD_DECREF_NORZ((thr), (h)); \ + } \ + } while (0) + +/* Called after one or more DECREF NORZ calls to handle pending side effects. + * At present DECREF NORZ does freeing inline but doesn't execute finalizers, + * so these macros check for pending finalizers and execute them. The FAST + * variant is performance critical. + */ +#if defined(DUK_USE_FINALIZER_SUPPORT) +#define DUK_REFZERO_CHECK_FAST(thr) do { \ + duk_refzero_check_fast((thr)); \ + } while (0) +#define DUK_REFZERO_CHECK_SLOW(thr) do { \ + duk_refzero_check_slow((thr)); \ + } while (0) +#else /* DUK_USE_FINALIZER_SUPPORT */ +#define DUK_REFZERO_CHECK_FAST(thr) do { } while (0) +#define DUK_REFZERO_CHECK_SLOW(thr) do { } while (0) +#endif /* DUK_USE_FINALIZER_SUPPORT */ + +/* + * Macros to set a duk_tval and update refcount of the target (decref the + * old value and incref the new value if necessary). This is both performance + * and footprint critical; any changes made should be measured for size/speed. + */ + +#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_UNDEFINED(tv__dst); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) + +#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0(thr,tvptr_dst) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_UNDEFINED(tv__dst); \ + DUK_TVAL_DECREF_NORZ((thr), &tv__tmp); \ + } while (0) + +#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_UNUSED(tv__dst); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) + +#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_NULL(tv__dst); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) + +#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) + +#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) +#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) +#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) +#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_NAN(tv__dst); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) +#if defined(DUK_USE_FASTINT) +#define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_I48(tv__dst, (newval)); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) +#define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_I32(tv__dst, (newval)); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) +#define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_U32(tv__dst, (newval)); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) +#else +#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \ + DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval)) +#endif /* DUK_USE_FASTINT */ + +#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) + +#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_STRING(tv__dst, (newval)); \ + DUK_HSTRING_INCREF((thr), (newval)); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) + +#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \ + DUK_HOBJECT_INCREF((thr), (newval)); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) + +#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \ + DUK_HBUFFER_INCREF((thr), (newval)); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) + +#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_POINTER(tv__dst, (newval)); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) + +/* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups, + * etc, so it's very important for performance. Measure when changing. + * + * NOTE: the source and destination duk_tval pointers may be the same, and + * the macros MUST deal with that correctly. + */ + +/* Original idiom used, minimal code size. */ +#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \ + duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \ + tv__dst = (tvptr_dst); tv__src = (tvptr_src); \ + DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ + DUK_TVAL_SET_TVAL(tv__dst, tv__src); \ + DUK_TVAL_INCREF((thr), tv__src); \ + DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ + } while (0) + +/* Faster alternative: avoid making a temporary copy of tvptr_dst and use + * fast incref/decref macros. + */ +#define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \ + duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \ + tv__dst = (tvptr_dst); tv__src = (tvptr_src); \ + DUK_TVAL_INCREF_FAST((thr), tv__src); \ + if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv__dst)) { \ + h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \ + DUK_ASSERT(h__obj != NULL); \ + DUK_TVAL_SET_TVAL(tv__dst, tv__src); \ + DUK_HEAPHDR_DECREF_FAST((thr), h__obj); /* side effects */ \ + } else { \ + DUK_TVAL_SET_TVAL(tv__dst, tv__src); \ + } \ + } while (0) + +/* XXX: no optimized variants yet */ +#define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0 +#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0 +#define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0 +#define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0 +#define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0 +#define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0 +#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0 +#define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0 +#define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0 +#if defined(DUK_USE_FASTINT) +#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_I48_UPDREF_ALT0 +#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_I32_UPDREF_ALT0 +#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_U32_UPDREF_ALT0 +#else +#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast int-to-double */ +#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF +#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF +#endif /* DUK_USE_FASTINT */ +#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_I48_UPDREF /* convenience */ +#define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0 +#define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0 +#define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0 +#define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0 +#define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0 + +#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT) +/* Optimized for speed. */ +#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT1 +#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT1 +#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0 +#else +/* Optimized for size. */ +#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0 +#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0 +#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0 +#endif + +#else /* DUK_USE_REFERENCE_COUNTING */ + +#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) 0 +#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) 0 + +#define DUK_TVAL_INCREF_FAST(thr,v) do {} while (0) /* nop */ +#define DUK_TVAL_DECREF_FAST(thr,v) do {} while (0) /* nop */ +#define DUK_TVAL_DECREF_NORZ_FAST(thr,v) do {} while (0) /* nop */ +#define DUK_TVAL_INCREF_SLOW(thr,v) do {} while (0) /* nop */ +#define DUK_TVAL_DECREF_SLOW(thr,v) do {} while (0) /* nop */ +#define DUK_TVAL_DECREF_NORZ_SLOW(thr,v) do {} while (0) /* nop */ +#define DUK_TVAL_INCREF(thr,v) do {} while (0) /* nop */ +#define DUK_TVAL_DECREF(thr,v) do {} while (0) /* nop */ +#define DUK_TVAL_DECREF_NORZ(thr,v) do {} while (0) /* nop */ +#define DUK_HEAPHDR_INCREF_FAST(thr,h) do {} while (0) /* nop */ +#define DUK_HEAPHDR_DECREF_FAST(thr,h) do {} while (0) /* nop */ +#define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h) do {} while (0) /* nop */ +#define DUK_HEAPHDR_INCREF_SLOW(thr,h) do {} while (0) /* nop */ +#define DUK_HEAPHDR_DECREF_SLOW(thr,h) do {} while (0) /* nop */ +#define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h) do {} while (0) /* nop */ +#define DUK_HEAPHDR_INCREF(thr,h) do {} while (0) /* nop */ +#define DUK_HEAPHDR_DECREF(thr,h) do {} while (0) /* nop */ +#define DUK_HEAPHDR_DECREF_NORZ(thr,h) do {} while (0) /* nop */ +#define DUK_HSTRING_INCREF_FAST(thr,h) do {} while (0) /* nop */ +#define DUK_HSTRING_DECREF_FAST(thr,h) do {} while (0) /* nop */ +#define DUK_HSTRING_DECREF_NORZ_FAST(thr,h) do {} while (0) /* nop */ +#define DUK_HSTRING_INCREF_SLOW(thr,h) do {} while (0) /* nop */ +#define DUK_HSTRING_DECREF_SLOW(thr,h) do {} while (0) /* nop */ +#define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h) do {} while (0) /* nop */ +#define DUK_HSTRING_INCREF(thr,h) do {} while (0) /* nop */ +#define DUK_HSTRING_DECREF(thr,h) do {} while (0) /* nop */ +#define DUK_HSTRING_DECREF_NORZ(thr,h) do {} while (0) /* nop */ +#define DUK_HOBJECT_INCREF_FAST(thr,h) do {} while (0) /* nop */ +#define DUK_HOBJECT_DECREF_FAST(thr,h) do {} while (0) /* nop */ +#define DUK_HOBJECT_DECREF_NORZ_FAST(thr,h) do {} while (0) /* nop */ +#define DUK_HOBJECT_INCREF_SLOW(thr,h) do {} while (0) /* nop */ +#define DUK_HOBJECT_DECREF_SLOW(thr,h) do {} while (0) /* nop */ +#define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h) do {} while (0) /* nop */ +#define DUK_HOBJECT_INCREF(thr,h) do {} while (0) /* nop */ +#define DUK_HOBJECT_DECREF(thr,h) do {} while (0) /* nop */ +#define DUK_HOBJECT_DECREF_NORZ(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFFER_INCREF_FAST(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFFER_DECREF_FAST(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFFER_DECREF_NORZ_FAST(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFFER_INCREF_SLOW(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFFER_DECREF_SLOW(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFFER_INCREF(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFFER_DECREF(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFFER_DECREF_NORZ(thr,h) do {} while (0) /* nop */ + +#define DUK_HCOMPFUNC_INCREF(thr,h) do {} while (0) /* nop */ +#define DUK_HCOMPFUNC_DECREF(thr,h) do {} while (0) /* nop */ +#define DUK_HCOMPFUNC_DECREF_NORZ(thr,h) do {} while (0) /* nop */ +#define DUK_HNATFUNC_INCREF(thr,h) do {} while (0) /* nop */ +#define DUK_HNATFUNC_DECREF(thr,h) do {} while (0) /* nop */ +#define DUK_HNATFUNC_DECREF_NORZ(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFOBJ_INCREF(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFOBJ_DECREF(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFOBJ_DECREF_NORZ(thr,h) do {} while (0) /* nop */ +#define DUK_HTHREAD_INCREF(thr,h) do {} while (0) /* nop */ +#define DUK_HTHREAD_DECREF(thr,h) do {} while (0) /* nop */ +#define DUK_HTHREAD_DECREF_NORZ(thr,h) do {} while (0) /* nop */ +#define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do {} while (0) /* nop */ +#define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do {} while (0) /* nop */ +#define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h) do {} while (0) /* nop */ + +#define DUK_REFZERO_CHECK_FAST(thr) do {} while (0) /* nop */ +#define DUK_REFZERO_CHECK_SLOW(thr) do {} while (0) /* nop */ + +#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_UNDEFINED(tv__dst); \ + DUK_UNREF((thr)); \ + } while (0) + +#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_UNUSED(tv__dst); \ + DUK_UNREF((thr)); \ + } while (0) + +#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_NULL(tv__dst); \ + DUK_UNREF((thr)); \ + } while (0) + +#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \ + DUK_UNREF((thr)); \ + } while (0) + +#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \ + DUK_UNREF((thr)); \ + } while (0) +#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \ + DUK_UNREF((thr)); \ + } while (0) +#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \ + DUK_UNREF((thr)); \ + } while (0) +#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_NAN(tv__dst); \ + DUK_UNREF((thr)); \ + } while (0) +#if defined(DUK_USE_FASTINT) +#define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_I48(tv__dst, (newval)); \ + DUK_UNREF((thr)); \ + } while (0) +#define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_I32(tv__dst, (newval)); \ + DUK_UNREF((thr)); \ + } while (0) +#define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_U32(tv__dst, (newval)); \ + DUK_UNREF((thr)); \ + } while (0) +#else +#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \ + DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval)) +#endif /* DUK_USE_FASTINT */ + +#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \ + DUK_UNREF((thr)); \ + } while (0) + +#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_STRING(tv__dst, (newval)); \ + DUK_UNREF((thr)); \ + } while (0) + +#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \ + DUK_UNREF((thr)); \ + } while (0) + +#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \ + DUK_UNREF((thr)); \ + } while (0) + +#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ + duk_tval *tv__dst; tv__dst = (tvptr_dst); \ + DUK_TVAL_SET_POINTER(tv__dst, (newval)); \ + DUK_UNREF((thr)); \ + } while (0) + +#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \ + duk_tval *tv__dst, *tv__src; \ + tv__dst = (tvptr_dst); tv__src = (tvptr_src); \ + DUK_TVAL_SET_TVAL(tv__dst, tv__src); \ + DUK_UNREF((thr)); \ + } while (0) + +#define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0 +#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0 +#define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0 +#define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0 +#define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0 +#define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0 +#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0 +#define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0 +#define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0 +#if defined(DUK_USE_FASTINT) +#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_I48_UPDREF_ALT0 +#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_I32_UPDREF_ALT0 +#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_U32_UPDREF_ALT0 +#else +#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast-int-to-double */ +#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF +#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF +#endif /* DUK_USE_FASTINT */ +#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_I48_UPDREF /* convenience */ +#define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0 +#define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0 +#define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0 +#define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0 +#define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0 + +#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0 +#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0 +#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0 + +#endif /* DUK_USE_REFERENCE_COUNTING */ + +/* + * Some convenience macros that don't have optimized implementations now. + */ + +#define DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr,tv_dst,tv_src) do { \ + duk_hthread *duk__thr = (thr); \ + duk_tval *duk__dst = (tv_dst); \ + duk_tval *duk__src = (tv_src); \ + DUK_UNREF(duk__thr); \ + DUK_TVAL_DECREF_NORZ(thr, duk__dst); \ + DUK_TVAL_SET_TVAL(duk__dst, duk__src); \ + DUK_TVAL_INCREF(thr, duk__dst); \ + } while (0) + +#define DUK_TVAL_SET_U32_UPDREF_NORZ(thr,tv_dst,val) do { \ + duk_hthread *duk__thr = (thr); \ + duk_tval *duk__dst = (tv_dst); \ + duk_uint32_t duk__val = (duk_uint32_t) (val); \ + DUK_UNREF(duk__thr); \ + DUK_TVAL_DECREF_NORZ(thr, duk__dst); \ + DUK_TVAL_SET_U32(duk__dst, duk__val); \ + } while (0) + +/* + * Prototypes + */ + +#if defined(DUK_USE_REFERENCE_COUNTING) +#if defined(DUK_USE_FINALIZER_SUPPORT) +DUK_INTERNAL_DECL void duk_refzero_check_slow(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_refzero_check_fast(duk_hthread *thr); +#endif +DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr); +DUK_INTERNAL_DECL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h); +#if 0 /* Not needed: fast path handles inline; slow path uses duk_heaphdr_decref() which is needed anyway. */ +DUK_INTERNAL_DECL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h); +DUK_INTERNAL_DECL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h); +DUK_INTERNAL_DECL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h); +DUK_INTERNAL_DECL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h); +DUK_INTERNAL_DECL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h); +DUK_INTERNAL_DECL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h); +#endif +DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h); +DUK_INTERNAL_DECL void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h); +#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT) +DUK_INTERNAL_DECL void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h); /* no 'norz' variant */ +DUK_INTERNAL_DECL void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h); /* no 'norz' variant */ +DUK_INTERNAL_DECL void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h); +DUK_INTERNAL_DECL void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h); +#else +DUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv); +DUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv); +DUK_INTERNAL_DECL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv); +DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h); +DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h); +DUK_INTERNAL_DECL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h); +#endif +#else /* DUK_USE_REFERENCE_COUNTING */ +/* no refcounting */ +#endif /* DUK_USE_REFERENCE_COUNTING */ + +#endif /* DUK_REFCOUNT_H_INCLUDED */ +/* #include duk_api_internal.h */ +#line 1 "duk_api_internal.h" +/* + * Internal API calls which have (stack and other) semantics similar + * to the public API. + */ + +#if !defined(DUK_API_INTERNAL_H_INCLUDED) +#define DUK_API_INTERNAL_H_INCLUDED + +#define DUK_INTERNAL_SYMBOL(x) ("\x82" x) + +/* duk_push_sprintf constants */ +#define DUK_PUSH_SPRINTF_INITIAL_SIZE 256L +#define DUK_PUSH_SPRINTF_SANITY_LIMIT (1L * 1024L * 1024L * 1024L) + +/* Flag ORed to err_code to indicate __FILE__ / __LINE__ is not + * blamed as source of error for error fileName / lineNumber. + */ +#define DUK_ERRCODE_FLAG_NOBLAME_FILELINE (1L << 24) + +/* Current convention is to use duk_size_t for value stack sizes and global indices, + * and duk_idx_t for local frame indices. + */ +DUK_INTERNAL_DECL void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes); +DUK_INTERNAL_DECL duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes); +DUK_INTERNAL_DECL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug); + +DUK_INTERNAL_DECL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count); + +DUK_INTERNAL_DECL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count); + +DUK_INTERNAL_DECL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start); + +DUK_INTERNAL_DECL void duk_dup_0(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_dup_1(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_dup_2(duk_hthread *thr); +/* duk_dup_m1() would be same as duk_dup_top() */ +DUK_INTERNAL_DECL void duk_dup_m2(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_dup_m3(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_dup_m4(duk_hthread *thr); + +DUK_INTERNAL_DECL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL void duk_remove_m2(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count); +DUK_INTERNAL_DECL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count); + +DUK_INTERNAL_DECL duk_int_t duk_get_type_tval(duk_tval *tv); +DUK_INTERNAL_DECL duk_uint_t duk_get_type_mask_tval(duk_tval *tv); + +#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS) +DUK_INTERNAL_DECL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx); +#endif +DUK_INTERNAL_DECL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx); + +DUK_INTERNAL_DECL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_tval *duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL void duk_push_tval(duk_hthread *thr, duk_tval *tv); + +/* Push the current 'this' binding; throw TypeError if binding is not object + * coercible (CheckObjectCoercible). + */ +DUK_INTERNAL_DECL void duk_push_this_check_object_coercible(duk_hthread *thr); + +/* duk_push_this() + CheckObjectCoercible() + duk_to_object() */ +DUK_INTERNAL_DECL duk_hobject *duk_push_this_coercible_to_object(duk_hthread *thr); + +/* duk_push_this() + CheckObjectCoercible() + duk_to_string() */ +DUK_INTERNAL_DECL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr); + +DUK_INTERNAL_DECL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i); + +/* Get a borrowed duk_tval pointer to the current 'this' binding. Caller must + * make sure there's an active callstack entry. Note that the returned pointer + * is unstable with regards to side effects. + */ +DUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr); + +/* XXX: add fastint support? */ +#define duk_push_u64(thr,val) \ + duk_push_number((thr), (duk_double_t) (val)) +#define duk_push_i64(thr,val) \ + duk_push_number((thr), (duk_double_t) (val)) + +/* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */ +#define duk_push_u32(thr,val) \ + duk_push_uint((thr), (duk_uint_t) (val)) +#define duk_push_i32(thr,val) \ + duk_push_int((thr), (duk_int_t) (val)) + +/* sometimes stack and array indices need to go on the stack */ +#define duk_push_idx(thr,val) \ + duk_push_int((thr), (duk_int_t) (val)) +#define duk_push_uarridx(thr,val) \ + duk_push_uint((thr), (duk_uint_t) (val)) +#define duk_push_size_t(thr,val) \ + duk_push_uint((thr), (duk_uint_t) (val)) /* XXX: assumed to fit for now */ + +DUK_INTERNAL_DECL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx); + +DUK_INTERNAL_DECL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv); + +DUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hobject *duk_get_hobject(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hbuffer *duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx); + +DUK_INTERNAL_DECL void *duk_get_buffer_data_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_len, duk_bool_t throw_flag, duk_bool_t *out_isbuffer); + +DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum); + +DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask); +DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask); +DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask); +#define duk_require_hobject_promote_lfunc(thr,idx) \ + duk_require_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC) +#define duk_get_hobject_promote_lfunc(thr,idx) \ + duk_get_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC) + +#if 0 /*unused*/ +DUK_INTERNAL_DECL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx); +#endif + +DUK_INTERNAL_DECL duk_hstring *duk_known_hstring(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hobject *duk_known_hobject(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hbuffer *duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hcompfunc *duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hnatfunc *duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx); + +DUK_INTERNAL_DECL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv); + +DUK_INTERNAL_DECL duk_hstring *duk_to_hstring(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_m1(duk_hthread *thr); +DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx); + +DUK_INTERNAL_DECL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx); + +DUK_INTERNAL_DECL duk_double_t duk_to_number_m1(duk_hthread *thr); +DUK_INTERNAL_DECL duk_double_t duk_to_number_m2(duk_hthread *thr); + +#if defined(DUK_USE_DEBUGGER_SUPPORT) /* only needed by debugger for now */ +DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx); +#endif +DUK_INTERNAL_DECL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv); + +DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped); /* out_clamped=NULL, RangeError if outside range */ +DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval); +DUK_INTERNAL_DECL duk_int_t duk_to_int_check_range(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval); +#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) +DUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx); +#endif +DUK_INTERNAL_DECL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx); + +DUK_INTERNAL_DECL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL const char *duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len); +DUK_INTERNAL_DECL const char *duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx); + +DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum); + +DUK_INTERNAL_DECL void duk_push_hstring(duk_hthread *thr, duk_hstring *h); +DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx); +DUK_INTERNAL_DECL void duk_push_hstring_empty(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_push_hobject(duk_hthread *thr, duk_hobject *h); +DUK_INTERNAL_DECL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h); +#define duk_push_hthread(thr,h) \ + duk_push_hobject((thr), (duk_hobject *) (h)) +#define duk_push_hnatfunc(thr,h) \ + duk_push_hobject((thr), (duk_hobject *) (h)) +DUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx); +DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx); +DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto); +DUK_INTERNAL_DECL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr); +DUK_INTERNAL_DECL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs); +DUK_INTERNAL_DECL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs); + +/* XXX: duk_push_harray() and duk_push_hcompfunc() are inconsistent with + * duk_push_hobject() etc which don't create a new value. + */ +DUK_INTERNAL_DECL duk_harray *duk_push_harray(duk_hthread *thr); +DUK_INTERNAL_DECL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size); +DUK_INTERNAL_DECL duk_tval *duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size); + +DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz); +DUK_INTERNAL_DECL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags); +DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv); +DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv); +#if 0 /* not used yet */ +DUK_INTERNAL_DECL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h); +#endif +#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) +DUK_INTERNAL_DECL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx); +#endif + +DUK_INTERNAL_DECL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len); +DUK_INTERNAL_DECL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len); + +DUK_INTERNAL_DECL const char *duk_push_string_readable(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL const char *duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv); +DUK_INTERNAL_DECL const char *duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv); + +/* The duk_xxx_prop_stridx_short() variants expect their arguments to be short + * enough to be packed into a single 32-bit integer argument. Argument limits + * vary per call; typically 16 bits are assigned to the signed value stack index + * and the stridx. In practice these work well for footprint with constant + * arguments and such call sites are also easiest to verify to be correct. + */ + +DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [val] */ +DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args); +#define duk_get_prop_stridx_short(thr,obj_idx,stridx) \ + (DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \ + DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \ + duk_get_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx)))) +DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_boolean(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_bool_t *out_has_prop); /* [] -> [] */ + +DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [val] -> [] */ +DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args); +#define duk_put_prop_stridx_short(thr,obj_idx,stridx) \ + (DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \ + DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \ + duk_put_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx)))) + +DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [] */ +#if 0 /* Too few call sites to be useful. */ +DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args); +#define duk_del_prop_stridx_short(thr,obj_idx,stridx) \ + (DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \ + DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \ + duk_del_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx)))) +#endif +#define duk_del_prop_stridx_short(thr,obj_idx,stridx) \ + duk_del_prop_stridx((thr), (obj_idx), (stridx)) + +DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [] */ +#if 0 /* Too few call sites to be useful. */ +DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args); +#define duk_has_prop_stridx_short(thr,obj_idx,stridx) \ + (DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \ + DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \ + duk_has_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx)))) +#endif +#define duk_has_prop_stridx_short(thr,obj_idx,stridx) \ + duk_has_prop_stridx((thr), (obj_idx), (stridx)) + +DUK_INTERNAL_DECL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags); /* [key val] -> [] */ + +DUK_INTERNAL_DECL void duk_xdef_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx, duk_small_uint_t desc_flags); /* [val] -> [] */ + +/* XXX: Because stridx and desc_flags have a limited range, this call could + * always pack stridx and desc_flags into a single argument. + */ +DUK_INTERNAL_DECL void duk_xdef_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_uint_t desc_flags); /* [val] -> [] */ +DUK_INTERNAL_DECL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args); +#define duk_xdef_prop_stridx_short(thr,obj_idx,stridx,desc_flags) \ + (DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x80L && (duk_int_t) (obj_idx) <= 0x7fL), \ + DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \ + DUK_ASSERT_EXPR((duk_int_t) (desc_flags) >= 0 && (duk_int_t) (desc_flags) <= 0xffL), \ + duk_xdef_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 24) + (((duk_uint_t) (stridx)) << 8) + (duk_uint_t) (desc_flags))) + +#define duk_xdef_prop_wec(thr,obj_idx) \ + duk_xdef_prop((thr), (obj_idx), DUK_PROPDESC_FLAGS_WEC) +#define duk_xdef_prop_index_wec(thr,obj_idx,arr_idx) \ + duk_xdef_prop_index((thr), (obj_idx), (arr_idx), DUK_PROPDESC_FLAGS_WEC) +#define duk_xdef_prop_stridx_wec(thr,obj_idx,stridx) \ + duk_xdef_prop_stridx((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC) +#define duk_xdef_prop_stridx_short_wec(thr,obj_idx,stridx) \ + duk_xdef_prop_stridx_short((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC) + +#if 0 /*unused*/ +DUK_INTERNAL_DECL void duk_xdef_prop_stridx_builtin(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags); /* [] -> [] */ +#endif + +DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [] */ + +DUK_INTERNAL_DECL void duk_pack(duk_hthread *thr, duk_idx_t count); +DUK_INTERNAL_DECL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx); +#if 0 +DUK_INTERNAL_DECL void duk_unpack(duk_hthread *thr); +#endif + +DUK_INTERNAL_DECL void duk_require_constructor_call(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h); + +DUK_INTERNAL_DECL void duk_resolve_nonbound_function(duk_hthread *thr); + +DUK_INTERNAL_DECL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top); +DUK_INTERNAL_DECL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr); + +DUK_INTERNAL_DECL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count); +DUK_INTERNAL_DECL void duk_pop_unsafe(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_pop_2_unsafe(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_pop_3_unsafe(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count); +DUK_INTERNAL_DECL void duk_pop_nodecref_unsafe(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_pop_2_nodecref_unsafe(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_pop_3_nodecref_unsafe(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_pop_undefined(duk_hthread *thr); + +DUK_INTERNAL_DECL void duk_compact_m1(duk_hthread *thr); + +DUK_INTERNAL_DECL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze); + +DUK_INTERNAL_DECL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx); +DUK_INTERNAL_DECL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count); + +DUK_INTERNAL_DECL void duk_concat_2(duk_hthread *thr); + +DUK_INTERNAL_DECL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags); + +/* Raw internal valstack access macros: access is unsafe so call site + * must have a guarantee that the index is valid. When that is the case, + * using these macro results in faster and smaller code than duk_get_tval(). + * Both 'ctx' and 'idx' are evaluted multiple times, but only for asserts. + */ +#define DUK_ASSERT_VALID_NEGIDX(thr,idx) \ + (DUK_ASSERT_EXPR((duk_int_t) (idx) < 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx)))) +#define DUK_ASSERT_VALID_POSIDX(thr,idx) \ + (DUK_ASSERT_EXPR((duk_int_t) (idx) >= 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx)))) +#define DUK_GET_TVAL_NEGIDX(thr,idx) \ + (DUK_ASSERT_VALID_NEGIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_top + (idx)) +#define DUK_GET_TVAL_POSIDX(thr,idx) \ + (DUK_ASSERT_VALID_POSIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_bottom + (idx)) +#define DUK_GET_HOBJECT_NEGIDX(thr,idx) \ + (DUK_ASSERT_VALID_NEGIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_top + (idx))) +#define DUK_GET_HOBJECT_POSIDX(thr,idx) \ + (DUK_ASSERT_VALID_POSIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_bottom + (idx))) + +#define DUK_GET_THIS_TVAL_PTR(thr) \ + (DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \ + (thr)->valstack_bottom - 1) + +DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr); +DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr); +DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr); + +#endif /* DUK_API_INTERNAL_H_INCLUDED */ +/* #include duk_hstring.h */ +#line 1 "duk_hstring.h" +/* + * Heap string representation. + * + * Strings are byte sequences ordinarily stored in extended UTF-8 format, + * allowing values larger than the official UTF-8 range (used internally) + * and also allowing UTF-8 encoding of surrogate pairs (CESU-8 format). + * Strings may also be invalid UTF-8 altogether which is the case e.g. with + * strings used as internal property names and raw buffers converted to + * strings. In such cases the 'clen' field contains an inaccurate value. + * + * Ecmascript requires support for 32-bit long strings. However, since each + * 16-bit codepoint can take 3 bytes in CESU-8, this representation can only + * support about 1.4G codepoint long strings in extreme cases. This is not + * really a practical issue. + */ + +#if !defined(DUK_HSTRING_H_INCLUDED) +#define DUK_HSTRING_H_INCLUDED + +/* Impose a maximum string length for now. Restricted artificially to + * ensure adding a heap header length won't overflow size_t. The limit + * should be synchronized with DUK_HBUFFER_MAX_BYTELEN. + * + * E5.1 makes provisions to support strings longer than 4G characters. + * This limit should be eliminated on 64-bit platforms (and increased + * closer to maximum support on 32-bit platforms). + */ + +#if defined(DUK_USE_STRLEN16) +#define DUK_HSTRING_MAX_BYTELEN (0x0000ffffUL) +#else +#define DUK_HSTRING_MAX_BYTELEN (0x7fffffffUL) +#endif + +/* XXX: could add flags for "is valid CESU-8" (Ecmascript compatible strings), + * "is valid UTF-8", "is valid extended UTF-8" (internal strings are not, + * regexp bytecode is), and "contains non-BMP characters". These are not + * needed right now. + */ + +#define DUK_HSTRING_FLAG_ASCII DUK_HEAPHDR_USER_FLAG(0) /* string is ASCII, clen == blen */ +#define DUK_HSTRING_FLAG_ARRIDX DUK_HEAPHDR_USER_FLAG(1) /* string is a valid array index */ +#define DUK_HSTRING_FLAG_SYMBOL DUK_HEAPHDR_USER_FLAG(2) /* string is a symbol (invalid utf-8) */ +#define DUK_HSTRING_FLAG_HIDDEN DUK_HEAPHDR_USER_FLAG(3) /* string is a hidden symbol (implies symbol, Duktape 1.x internal string) */ +#define DUK_HSTRING_FLAG_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(4) /* string is a reserved word (non-strict) */ +#define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(5) /* string is a reserved word (strict) */ +#define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS DUK_HEAPHDR_USER_FLAG(6) /* string is 'eval' or 'arguments' */ +#define DUK_HSTRING_FLAG_EXTDATA DUK_HEAPHDR_USER_FLAG(7) /* string data is external (duk_hstring_external) */ + +#define DUK_HSTRING_HAS_ASCII(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII) +#define DUK_HSTRING_HAS_ARRIDX(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX) +#define DUK_HSTRING_HAS_SYMBOL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL) +#define DUK_HSTRING_HAS_HIDDEN(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN) +#define DUK_HSTRING_HAS_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD) +#define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD) +#define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS) +#define DUK_HSTRING_HAS_EXTDATA(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA) + +#define DUK_HSTRING_SET_ASCII(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII) +#define DUK_HSTRING_SET_ARRIDX(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX) +#define DUK_HSTRING_SET_SYMBOL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL) +#define DUK_HSTRING_SET_HIDDEN(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN) +#define DUK_HSTRING_SET_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD) +#define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD) +#define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS) +#define DUK_HSTRING_SET_EXTDATA(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA) + +#define DUK_HSTRING_CLEAR_ASCII(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII) +#define DUK_HSTRING_CLEAR_ARRIDX(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX) +#define DUK_HSTRING_CLEAR_SYMBOL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL) +#define DUK_HSTRING_CLEAR_HIDDEN(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN) +#define DUK_HSTRING_CLEAR_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD) +#define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD) +#define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS) +#define DUK_HSTRING_CLEAR_EXTDATA(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA) + +#if 0 /* Slightly smaller code without explicit flag, but explicit flag + * is very useful when 'clen' is dropped. + */ +#define DUK_HSTRING_IS_ASCII(x) (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x))) +#endif +#define DUK_HSTRING_IS_ASCII(x) DUK_HSTRING_HAS_ASCII((x)) /* lazily set! */ +#define DUK_HSTRING_IS_EMPTY(x) (DUK_HSTRING_GET_BYTELEN((x)) == 0) + +#if defined(DUK_USE_STRHASH16) +#define DUK_HSTRING_GET_HASH(x) ((x)->hdr.h_flags >> 16) +#define DUK_HSTRING_SET_HASH(x,v) do { \ + (x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \ + } while (0) +#else +#define DUK_HSTRING_GET_HASH(x) ((x)->hash) +#define DUK_HSTRING_SET_HASH(x,v) do { \ + (x)->hash = (v); \ + } while (0) +#endif + +#if defined(DUK_USE_STRLEN16) +#define DUK_HSTRING_GET_BYTELEN(x) ((x)->hdr.h_strextra16) +#define DUK_HSTRING_SET_BYTELEN(x,v) do { \ + (x)->hdr.h_strextra16 = (v); \ + } while (0) +#if defined(DUK_USE_HSTRING_CLEN) +#define DUK_HSTRING_GET_CHARLEN(x) duk_hstring_get_charlen((x)) +#define DUK_HSTRING_SET_CHARLEN(x,v) do { \ + (x)->clen16 = (v); \ + } while (0) +#else +#define DUK_HSTRING_GET_CHARLEN(x) duk_hstring_get_charlen((x)) +#define DUK_HSTRING_SET_CHARLEN(x,v) do { \ + DUK_ASSERT(0); /* should never be called */ \ + } while (0) +#endif +#else +#define DUK_HSTRING_GET_BYTELEN(x) ((x)->blen) +#define DUK_HSTRING_SET_BYTELEN(x,v) do { \ + (x)->blen = (v); \ + } while (0) +#define DUK_HSTRING_GET_CHARLEN(x) duk_hstring_get_charlen((x)) +#define DUK_HSTRING_SET_CHARLEN(x,v) do { \ + (x)->clen = (v); \ + } while (0) +#endif + +#if defined(DUK_USE_HSTRING_EXTDATA) +#define DUK_HSTRING_GET_EXTDATA(x) \ + ((x)->extdata) +#define DUK_HSTRING_GET_DATA(x) \ + (DUK_HSTRING_HAS_EXTDATA((x)) ? \ + DUK_HSTRING_GET_EXTDATA((const duk_hstring_external *) (x)) : ((const duk_uint8_t *) ((x) + 1))) +#else +#define DUK_HSTRING_GET_DATA(x) \ + ((const duk_uint8_t *) ((x) + 1)) +#endif + +#define DUK_HSTRING_GET_DATA_END(x) \ + (DUK_HSTRING_GET_DATA((x)) + (x)->blen) + +/* Marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest + * valid). + */ +#define DUK_HSTRING_NO_ARRAY_INDEX (0xffffffffUL) + +#if defined(DUK_USE_HSTRING_ARRIDX) +#define DUK_HSTRING_GET_ARRIDX_FAST(h) ((h)->arridx) +#define DUK_HSTRING_GET_ARRIDX_SLOW(h) ((h)->arridx) +#else +/* Get array index related to string (or return DUK_HSTRING_NO_ARRAY_INDEX); + * avoids helper call if string has no array index value. + */ +#define DUK_HSTRING_GET_ARRIDX_FAST(h) \ + (DUK_HSTRING_HAS_ARRIDX((h)) ? duk_js_to_arrayindex_hstring_fast_known((h)) : DUK_HSTRING_NO_ARRAY_INDEX) + +/* Slower but more compact variant. */ +#define DUK_HSTRING_GET_ARRIDX_SLOW(h) \ + (duk_js_to_arrayindex_hstring_fast((h))) +#endif + +/* XXX: these actually fit into duk_hstring */ +#define DUK_SYMBOL_TYPE_HIDDEN 0 +#define DUK_SYMBOL_TYPE_GLOBAL 1 +#define DUK_SYMBOL_TYPE_LOCAL 2 +#define DUK_SYMBOL_TYPE_WELLKNOWN 3 + +/* + * Misc + */ + +struct duk_hstring { + /* Smaller heaphdr than for other objects, because strings are held + * in string intern table which requires no link pointers. Much of + * the 32-bit flags field is unused by flags, so we can stuff a 16-bit + * field in there. + */ + duk_heaphdr_string hdr; + + /* String hash. */ +#if defined(DUK_USE_STRHASH16) + /* If 16-bit hash is in use, stuff it into duk_heaphdr_string flags. */ +#else + duk_uint32_t hash; +#endif + + /* Precomputed array index (or DUK_HSTRING_NO_ARRAY_INDEX). */ +#if defined(DUK_USE_HSTRING_ARRIDX) + duk_uarridx_t arridx; +#endif + + /* Length in bytes (not counting NUL term). */ +#if defined(DUK_USE_STRLEN16) + /* placed in duk_heaphdr_string */ +#else + duk_uint32_t blen; +#endif + + /* Length in codepoints (must be E5 compatible). */ +#if defined(DUK_USE_STRLEN16) +#if defined(DUK_USE_HSTRING_CLEN) + duk_uint16_t clen16; +#else + /* computed live */ +#endif +#else + duk_uint32_t clen; +#endif + + /* + * String data of 'blen+1' bytes follows (+1 for NUL termination + * convenience for C API). No alignment needs to be guaranteed + * for strings, but fields above should guarantee alignment-by-4 + * (but not alignment-by-8). + */ +}; + +/* The external string struct is defined even when the feature is inactive. */ +struct duk_hstring_external { + duk_hstring str; + + /* + * For an external string, the NUL-terminated string data is stored + * externally. The user must guarantee that data behind this pointer + * doesn't change while it's used. + */ + + const duk_uint8_t *extdata; +}; + +/* + * Prototypes + */ + +DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos, duk_bool_t surrogate_aware); +DUK_INTERNAL_DECL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr); +DUK_INTERNAL_DECL duk_size_t duk_hstring_get_charlen(duk_hstring *h); +#if !defined(DUK_USE_HSTRING_LAZY_CLEN) +DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h); +#endif + +#endif /* DUK_HSTRING_H_INCLUDED */ +/* #include duk_hobject.h */ +#line 1 "duk_hobject.h" +/* + * Heap object representation. + * + * Heap objects are used for Ecmascript objects, arrays, and functions, + * but also for internal control like declarative and object environment + * records. Compiled functions, native functions, and threads are also + * objects but with an extended C struct. + * + * Objects provide the required Ecmascript semantics and exotic behaviors + * especially for property access. + * + * Properties are stored in three conceptual parts: + * + * 1. A linear 'entry part' contains ordered key-value-attributes triples + * and is the main method of string properties. + * + * 2. An optional linear 'array part' is used for array objects to store a + * (dense) range of [0,N[ array indexed entries with default attributes + * (writable, enumerable, configurable). If the array part would become + * sparse or non-default attributes are required, the array part is + * abandoned and moved to the 'entry part'. + * + * 3. An optional 'hash part' is used to optimize lookups of the entry + * part; it is used only for objects with sufficiently many properties + * and can be abandoned without loss of information. + * + * These three conceptual parts are stored in a single memory allocated area. + * This minimizes memory allocation overhead but also means that all three + * parts are resized together, and makes property access a bit complicated. + */ + +#if !defined(DUK_HOBJECT_H_INCLUDED) +#define DUK_HOBJECT_H_INCLUDED + +/* Object flags. Make sure this stays in sync with debugger object + * inspection code. + */ + +/* XXX: some flags are object subtype specific (e.g. common to all function + * subtypes, duk_harray, etc) and could be reused for different subtypes. + */ +#define DUK_HOBJECT_FLAG_EXTENSIBLE DUK_HEAPHDR_USER_FLAG(0) /* object is extensible */ +#define DUK_HOBJECT_FLAG_CONSTRUCTABLE DUK_HEAPHDR_USER_FLAG(1) /* object is constructable */ +#define DUK_HOBJECT_FLAG_CALLABLE DUK_HEAPHDR_USER_FLAG(2) /* object is callable */ +#define DUK_HOBJECT_FLAG_BOUNDFUNC DUK_HEAPHDR_USER_FLAG(3) /* object established using Function.prototype.bind() */ +#define DUK_HOBJECT_FLAG_COMPFUNC DUK_HEAPHDR_USER_FLAG(4) /* object is a compiled function (duk_hcompfunc) */ +#define DUK_HOBJECT_FLAG_NATFUNC DUK_HEAPHDR_USER_FLAG(5) /* object is a native function (duk_hnatfunc) */ +#define DUK_HOBJECT_FLAG_BUFOBJ DUK_HEAPHDR_USER_FLAG(6) /* object is a buffer object (duk_hbufobj) (always exotic) */ +#define DUK_HOBJECT_FLAG_FASTREFS DUK_HEAPHDR_USER_FLAG(7) /* object has no fields needing DECREF/marking beyond base duk_hobject header */ +#define DUK_HOBJECT_FLAG_ARRAY_PART DUK_HEAPHDR_USER_FLAG(8) /* object has an array part (a_size may still be 0) */ +#define DUK_HOBJECT_FLAG_STRICT DUK_HEAPHDR_USER_FLAG(9) /* function: function object is strict */ +#define DUK_HOBJECT_FLAG_NOTAIL DUK_HEAPHDR_USER_FLAG(10) /* function: function must not be tail called */ +#define DUK_HOBJECT_FLAG_NEWENV DUK_HEAPHDR_USER_FLAG(11) /* function: create new environment when called (see duk_hcompfunc) */ +#define DUK_HOBJECT_FLAG_NAMEBINDING DUK_HEAPHDR_USER_FLAG(12) /* function: create binding for func name (function templates only, used for named function expressions) */ +#define DUK_HOBJECT_FLAG_CREATEARGS DUK_HEAPHDR_USER_FLAG(13) /* function: create an arguments object on function call */ +#define DUK_HOBJECT_FLAG_HAVE_FINALIZER DUK_HEAPHDR_USER_FLAG(14) /* object has a callable (own) finalizer property */ +#define DUK_HOBJECT_FLAG_EXOTIC_ARRAY DUK_HEAPHDR_USER_FLAG(15) /* 'Array' object, array length and index exotic behavior */ +#define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ DUK_HEAPHDR_USER_FLAG(16) /* 'String' object, array index exotic behavior */ +#define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS DUK_HEAPHDR_USER_FLAG(17) /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */ +#define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ DUK_HEAPHDR_USER_FLAG(18) /* 'Proxy' object */ +#define DUK_HOBJECT_FLAG_SPECIAL_CALL DUK_HEAPHDR_USER_FLAG(19) /* special casing in call behavior, for .call(), .apply(), etc. */ + +#define DUK_HOBJECT_FLAG_CLASS_BASE DUK_HEAPHDR_USER_FLAG_NUMBER(20) +#define DUK_HOBJECT_FLAG_CLASS_BITS 5 + +#define DUK_HOBJECT_GET_CLASS_NUMBER(h) \ + DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS) +#define DUK_HOBJECT_SET_CLASS_NUMBER(h,v) \ + DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v)) + +#define DUK_HOBJECT_GET_CLASS_MASK(h) \ + (1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)) + +/* Macro for creating flag initializer from a class number. + * Unsigned type cast is needed to avoid warnings about coercing + * a signed integer to an unsigned one; the largest class values + * have the highest bit (bit 31) set which causes this. + */ +#define DUK_HOBJECT_CLASS_AS_FLAGS(v) (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE) + +/* E5 Section 8.6.2 + custom classes */ +#define DUK_HOBJECT_CLASS_NONE 0 +#define DUK_HOBJECT_CLASS_OBJECT 1 +#define DUK_HOBJECT_CLASS_ARRAY 2 +#define DUK_HOBJECT_CLASS_FUNCTION 3 +#define DUK_HOBJECT_CLASS_ARGUMENTS 4 +#define DUK_HOBJECT_CLASS_BOOLEAN 5 +#define DUK_HOBJECT_CLASS_DATE 6 +#define DUK_HOBJECT_CLASS_ERROR 7 +#define DUK_HOBJECT_CLASS_JSON 8 +#define DUK_HOBJECT_CLASS_MATH 9 +#define DUK_HOBJECT_CLASS_NUMBER 10 +#define DUK_HOBJECT_CLASS_REGEXP 11 +#define DUK_HOBJECT_CLASS_STRING 12 +#define DUK_HOBJECT_CLASS_GLOBAL 13 +#define DUK_HOBJECT_CLASS_SYMBOL 14 +#define DUK_HOBJECT_CLASS_OBJENV 15 /* custom */ +#define DUK_HOBJECT_CLASS_DECENV 16 /* custom */ +#define DUK_HOBJECT_CLASS_POINTER 17 /* custom */ +#define DUK_HOBJECT_CLASS_THREAD 18 /* custom; implies DUK_HOBJECT_IS_THREAD */ +#define DUK_HOBJECT_CLASS_BUFOBJ_MIN 19 +#define DUK_HOBJECT_CLASS_ARRAYBUFFER 19 /* implies DUK_HOBJECT_IS_BUFOBJ */ +#define DUK_HOBJECT_CLASS_DATAVIEW 20 +#define DUK_HOBJECT_CLASS_INT8ARRAY 21 +#define DUK_HOBJECT_CLASS_UINT8ARRAY 22 +#define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY 23 +#define DUK_HOBJECT_CLASS_INT16ARRAY 24 +#define DUK_HOBJECT_CLASS_UINT16ARRAY 25 +#define DUK_HOBJECT_CLASS_INT32ARRAY 26 +#define DUK_HOBJECT_CLASS_UINT32ARRAY 27 +#define DUK_HOBJECT_CLASS_FLOAT32ARRAY 28 +#define DUK_HOBJECT_CLASS_FLOAT64ARRAY 29 +#define DUK_HOBJECT_CLASS_BUFOBJ_MAX 29 +#define DUK_HOBJECT_CLASS_MAX 29 + +/* Class masks. */ +#define DUK_HOBJECT_CMASK_ALL ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL) +#define DUK_HOBJECT_CMASK_NONE (1UL << DUK_HOBJECT_CLASS_NONE) +#define DUK_HOBJECT_CMASK_ARGUMENTS (1UL << DUK_HOBJECT_CLASS_ARGUMENTS) +#define DUK_HOBJECT_CMASK_ARRAY (1UL << DUK_HOBJECT_CLASS_ARRAY) +#define DUK_HOBJECT_CMASK_BOOLEAN (1UL << DUK_HOBJECT_CLASS_BOOLEAN) +#define DUK_HOBJECT_CMASK_DATE (1UL << DUK_HOBJECT_CLASS_DATE) +#define DUK_HOBJECT_CMASK_ERROR (1UL << DUK_HOBJECT_CLASS_ERROR) +#define DUK_HOBJECT_CMASK_FUNCTION (1UL << DUK_HOBJECT_CLASS_FUNCTION) +#define DUK_HOBJECT_CMASK_JSON (1UL << DUK_HOBJECT_CLASS_JSON) +#define DUK_HOBJECT_CMASK_MATH (1UL << DUK_HOBJECT_CLASS_MATH) +#define DUK_HOBJECT_CMASK_NUMBER (1UL << DUK_HOBJECT_CLASS_NUMBER) +#define DUK_HOBJECT_CMASK_OBJECT (1UL << DUK_HOBJECT_CLASS_OBJECT) +#define DUK_HOBJECT_CMASK_REGEXP (1UL << DUK_HOBJECT_CLASS_REGEXP) +#define DUK_HOBJECT_CMASK_STRING (1UL << DUK_HOBJECT_CLASS_STRING) +#define DUK_HOBJECT_CMASK_GLOBAL (1UL << DUK_HOBJECT_CLASS_GLOBAL) +#define DUK_HOBJECT_CMASK_SYMBOL (1UL << DUK_HOBJECT_CLASS_SYMBOL) +#define DUK_HOBJECT_CMASK_OBJENV (1UL << DUK_HOBJECT_CLASS_OBJENV) +#define DUK_HOBJECT_CMASK_DECENV (1UL << DUK_HOBJECT_CLASS_DECENV) +#define DUK_HOBJECT_CMASK_POINTER (1UL << DUK_HOBJECT_CLASS_POINTER) +#define DUK_HOBJECT_CMASK_ARRAYBUFFER (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER) +#define DUK_HOBJECT_CMASK_DATAVIEW (1UL << DUK_HOBJECT_CLASS_DATAVIEW) +#define DUK_HOBJECT_CMASK_INT8ARRAY (1UL << DUK_HOBJECT_CLASS_INT8ARRAY) +#define DUK_HOBJECT_CMASK_UINT8ARRAY (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY) +#define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY) +#define DUK_HOBJECT_CMASK_INT16ARRAY (1UL << DUK_HOBJECT_CLASS_INT16ARRAY) +#define DUK_HOBJECT_CMASK_UINT16ARRAY (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY) +#define DUK_HOBJECT_CMASK_INT32ARRAY (1UL << DUK_HOBJECT_CLASS_INT32ARRAY) +#define DUK_HOBJECT_CMASK_UINT32ARRAY (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY) +#define DUK_HOBJECT_CMASK_FLOAT32ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY) +#define DUK_HOBJECT_CMASK_FLOAT64ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY) + +#define DUK_HOBJECT_CMASK_ALL_BUFOBJS \ + (DUK_HOBJECT_CMASK_ARRAYBUFFER | \ + DUK_HOBJECT_CMASK_DATAVIEW | \ + DUK_HOBJECT_CMASK_INT8ARRAY | \ + DUK_HOBJECT_CMASK_UINT8ARRAY | \ + DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \ + DUK_HOBJECT_CMASK_INT16ARRAY | \ + DUK_HOBJECT_CMASK_UINT16ARRAY | \ + DUK_HOBJECT_CMASK_INT32ARRAY | \ + DUK_HOBJECT_CMASK_UINT32ARRAY | \ + DUK_HOBJECT_CMASK_FLOAT32ARRAY | \ + DUK_HOBJECT_CMASK_FLOAT64ARRAY) + +#define DUK_HOBJECT_IS_OBJENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV) +#define DUK_HOBJECT_IS_DECENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV) +#define DUK_HOBJECT_IS_ENV(h) (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h))) +#define DUK_HOBJECT_IS_ARRAY(h) DUK_HOBJECT_HAS_EXOTIC_ARRAY((h)) /* Rely on class Array <=> exotic Array */ +#define DUK_HOBJECT_IS_BOUNDFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC) +#define DUK_HOBJECT_IS_COMPFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC) +#define DUK_HOBJECT_IS_NATFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC) +#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) +#define DUK_HOBJECT_IS_BUFOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ) +#else +#define DUK_HOBJECT_IS_BUFOBJ(h) 0 +#endif +#define DUK_HOBJECT_IS_THREAD(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_THREAD) +#if defined(DUK_USE_ES6_PROXY) +#define DUK_HOBJECT_IS_PROXY(h) DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((h)) +#else +#define DUK_HOBJECT_IS_PROXY(h) 0 +#endif + +#define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \ + DUK_HOBJECT_FLAG_COMPFUNC | \ + DUK_HOBJECT_FLAG_NATFUNC) + +#define DUK_HOBJECT_IS_FUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \ + DUK_HOBJECT_FLAG_BOUNDFUNC | \ + DUK_HOBJECT_FLAG_COMPFUNC | \ + DUK_HOBJECT_FLAG_NATFUNC) + +#define DUK_HOBJECT_IS_CALLABLE(h) DUK_HOBJECT_HAS_CALLABLE((h)) + +/* Object has any exotic behavior(s). */ +#define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \ + DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \ + DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \ + DUK_HOBJECT_FLAG_BUFOBJ | \ + DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ) +#define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS) + +/* Object has any virtual properties (not counting Proxy behavior). */ +#define DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \ + DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \ + DUK_HOBJECT_FLAG_BUFOBJ) +#define DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS) + +#define DUK_HOBJECT_HAS_EXTENSIBLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE) +#define DUK_HOBJECT_HAS_CONSTRUCTABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE) +#define DUK_HOBJECT_HAS_CALLABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE) +#define DUK_HOBJECT_HAS_BOUNDFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC) +#define DUK_HOBJECT_HAS_COMPFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC) +#define DUK_HOBJECT_HAS_NATFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC) +#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) +#define DUK_HOBJECT_HAS_BUFOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ) +#else +#define DUK_HOBJECT_HAS_BUFOBJ(h) 0 +#endif +#define DUK_HOBJECT_HAS_FASTREFS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS) +#define DUK_HOBJECT_HAS_ARRAY_PART(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART) +#define DUK_HOBJECT_HAS_STRICT(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT) +#define DUK_HOBJECT_HAS_NOTAIL(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL) +#define DUK_HOBJECT_HAS_NEWENV(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV) +#define DUK_HOBJECT_HAS_NAMEBINDING(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING) +#define DUK_HOBJECT_HAS_CREATEARGS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS) +#define DUK_HOBJECT_HAS_HAVE_FINALIZER(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER) +#define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY) +#define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ) +#define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS) +#if defined(DUK_USE_ES6_PROXY) +#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ) +#else +#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h) 0 +#endif +#define DUK_HOBJECT_HAS_SPECIAL_CALL(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL) + +#define DUK_HOBJECT_SET_EXTENSIBLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE) +#define DUK_HOBJECT_SET_CONSTRUCTABLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE) +#define DUK_HOBJECT_SET_CALLABLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE) +#define DUK_HOBJECT_SET_BOUNDFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC) +#define DUK_HOBJECT_SET_COMPFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC) +#define DUK_HOBJECT_SET_NATFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC) +#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) +#define DUK_HOBJECT_SET_BUFOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ) +#endif +#define DUK_HOBJECT_SET_FASTREFS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS) +#define DUK_HOBJECT_SET_ARRAY_PART(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART) +#define DUK_HOBJECT_SET_STRICT(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT) +#define DUK_HOBJECT_SET_NOTAIL(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL) +#define DUK_HOBJECT_SET_NEWENV(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV) +#define DUK_HOBJECT_SET_NAMEBINDING(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING) +#define DUK_HOBJECT_SET_CREATEARGS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS) +#define DUK_HOBJECT_SET_HAVE_FINALIZER(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER) +#define DUK_HOBJECT_SET_EXOTIC_ARRAY(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY) +#define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ) +#define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS) +#if defined(DUK_USE_ES6_PROXY) +#define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ) +#endif +#define DUK_HOBJECT_SET_SPECIAL_CALL(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL) + +#define DUK_HOBJECT_CLEAR_EXTENSIBLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE) +#define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE) +#define DUK_HOBJECT_CLEAR_CALLABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE) +#define DUK_HOBJECT_CLEAR_BOUNDFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC) +#define DUK_HOBJECT_CLEAR_COMPFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC) +#define DUK_HOBJECT_CLEAR_NATFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC) +#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) +#define DUK_HOBJECT_CLEAR_BUFOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ) +#endif +#define DUK_HOBJECT_CLEAR_FASTREFS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS) +#define DUK_HOBJECT_CLEAR_ARRAY_PART(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART) +#define DUK_HOBJECT_CLEAR_STRICT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT) +#define DUK_HOBJECT_CLEAR_NOTAIL(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL) +#define DUK_HOBJECT_CLEAR_NEWENV(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV) +#define DUK_HOBJECT_CLEAR_NAMEBINDING(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING) +#define DUK_HOBJECT_CLEAR_CREATEARGS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS) +#define DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER) +#define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY) +#define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ) +#define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS) +#if defined(DUK_USE_ES6_PROXY) +#define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ) +#endif +#define DUK_HOBJECT_CLEAR_SPECIAL_CALL(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL) + +/* Object can/cannot use FASTREFS, i.e. has no strong reference fields beyond + * duk_hobject base header. This is used just for asserts so doesn't need to + * be optimized. + */ +#define DUK_HOBJECT_PROHIBITS_FASTREFS(h) \ + (DUK_HOBJECT_IS_COMPFUNC((h)) || DUK_HOBJECT_IS_DECENV((h)) || DUK_HOBJECT_IS_OBJENV((h)) || \ + DUK_HOBJECT_IS_BUFOBJ((h)) || DUK_HOBJECT_IS_THREAD((h)) || DUK_HOBJECT_IS_PROXY((h)) || \ + DUK_HOBJECT_IS_BOUNDFUNC((h))) +#define DUK_HOBJECT_ALLOWS_FASTREFS(h) (!DUK_HOBJECT_PROHIBITS_FASTREFS((h))) + +/* Flags used for property attributes in duk_propdesc and packed flags. + * Must fit into 8 bits. + */ +#define DUK_PROPDESC_FLAG_WRITABLE (1U << 0) /* E5 Section 8.6.1 */ +#define DUK_PROPDESC_FLAG_ENUMERABLE (1U << 1) /* E5 Section 8.6.1 */ +#define DUK_PROPDESC_FLAG_CONFIGURABLE (1U << 2) /* E5 Section 8.6.1 */ +#define DUK_PROPDESC_FLAG_ACCESSOR (1U << 3) /* accessor */ +#define DUK_PROPDESC_FLAG_VIRTUAL (1U << 4) /* property is virtual: used in duk_propdesc, never stored + * (used by e.g. buffer virtual properties) + */ +#define DUK_PROPDESC_FLAGS_MASK (DUK_PROPDESC_FLAG_WRITABLE | \ + DUK_PROPDESC_FLAG_ENUMERABLE | \ + DUK_PROPDESC_FLAG_CONFIGURABLE | \ + DUK_PROPDESC_FLAG_ACCESSOR) + +/* Additional flags which are passed in the same flags argument as property + * flags but are not stored in object properties. + */ +#define DUK_PROPDESC_FLAG_NO_OVERWRITE (1U << 4) /* internal define property: skip write silently if exists */ + +/* Convenience defines for property attributes. */ +#define DUK_PROPDESC_FLAGS_NONE 0 +#define DUK_PROPDESC_FLAGS_W (DUK_PROPDESC_FLAG_WRITABLE) +#define DUK_PROPDESC_FLAGS_E (DUK_PROPDESC_FLAG_ENUMERABLE) +#define DUK_PROPDESC_FLAGS_C (DUK_PROPDESC_FLAG_CONFIGURABLE) +#define DUK_PROPDESC_FLAGS_WE (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE) +#define DUK_PROPDESC_FLAGS_WC (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE) +#define DUK_PROPDESC_FLAGS_EC (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE) +#define DUK_PROPDESC_FLAGS_WEC (DUK_PROPDESC_FLAG_WRITABLE | \ + DUK_PROPDESC_FLAG_ENUMERABLE | \ + DUK_PROPDESC_FLAG_CONFIGURABLE) + +/* Flags for duk_hobject_get_own_propdesc() and variants. */ +#define DUK_GETDESC_FLAG_PUSH_VALUE (1U << 0) /* push value to stack */ +#define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP (1U << 1) /* don't throw for prototype loop */ + +/* + * Macro for object validity check + * + * Assert for currently guaranteed relations between flags, for instance. + */ + +#define DUK_ASSERT_HOBJECT_VALID(h) do { \ + DUK_ASSERT((h) != NULL); \ + DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE((h)) || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FUNCTION); \ + DUK_ASSERT(!DUK_HOBJECT_IS_BUFOBJ((h)) || \ + (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAYBUFFER || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DATAVIEW || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT8ARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8ARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT16ARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT16ARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT32ARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT32ARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT32ARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT64ARRAY)); \ + /* Object is an Array <=> object has exotic array behavior */ \ + DUK_ASSERT((DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAY && DUK_HOBJECT_HAS_EXOTIC_ARRAY((h))) || \ + (DUK_HOBJECT_GET_CLASS_NUMBER((h)) != DUK_HOBJECT_CLASS_ARRAY && !DUK_HOBJECT_HAS_EXOTIC_ARRAY((h)))); \ + } while (0) + +/* + * Macros to access the 'props' allocation. + */ + +#if defined(DUK_USE_HEAPPTR16) +#define DUK_HOBJECT_GET_PROPS(heap,h) \ + ((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16)) +#define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \ + ((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \ + } while (0) +#else +#define DUK_HOBJECT_GET_PROPS(heap,h) \ + ((h)->props) +#define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \ + (h)->props = (duk_uint8_t *) (x); \ + } while (0) +#endif + +#if defined(DUK_USE_HOBJECT_LAYOUT_1) +/* LAYOUT 1 */ +#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \ + ((duk_hstring **) (void *) ( \ + DUK_HOBJECT_GET_PROPS((heap), (h)) \ + )) +#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \ + ((duk_propvalue *) (void *) ( \ + DUK_HOBJECT_GET_PROPS((heap), (h)) + \ + DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \ + )) +#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \ + ((duk_uint8_t *) (void *) ( \ + DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \ + )) +#define DUK_HOBJECT_A_GET_BASE(heap,h) \ + ((duk_tval *) (void *) ( \ + DUK_HOBJECT_GET_PROPS((heap), (h)) + \ + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \ + )) +#define DUK_HOBJECT_H_GET_BASE(heap,h) \ + ((duk_uint32_t *) (void *) ( \ + DUK_HOBJECT_GET_PROPS((heap), (h)) + \ + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \ + DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \ + )) +#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \ + ( \ + (n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \ + (n_arr) * sizeof(duk_tval) + \ + (n_hash) * sizeof(duk_uint32_t) \ + ) +#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash) do { \ + (set_e_k) = (duk_hstring **) (void *) (p_base); \ + (set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \ + (set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \ + (set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \ + (set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \ + } while (0) +#elif defined(DUK_USE_HOBJECT_LAYOUT_2) +/* LAYOUT 2 */ +#if (DUK_USE_ALIGN_BY == 4) +#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03) +#elif (DUK_USE_ALIGN_BY == 8) +#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07) +#elif (DUK_USE_ALIGN_BY == 1) +#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0 +#else +#error invalid DUK_USE_ALIGN_BY +#endif +#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \ + ((duk_hstring **) (void *) ( \ + DUK_HOBJECT_GET_PROPS((heap), (h)) + \ + DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \ + )) +#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \ + ((duk_propvalue *) (void *) ( \ + DUK_HOBJECT_GET_PROPS((heap), (h)) \ + )) +#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \ + ((duk_uint8_t *) (void *) ( \ + DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \ + )) +#define DUK_HOBJECT_A_GET_BASE(heap,h) \ + ((duk_tval *) (void *) ( \ + DUK_HOBJECT_GET_PROPS((heap), (h)) + \ + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \ + DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \ + )) +#define DUK_HOBJECT_H_GET_BASE(heap,h) \ + ((duk_uint32_t *) (void *) ( \ + DUK_HOBJECT_GET_PROPS((heap), (h)) + \ + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \ + DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \ + DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \ + )) +#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \ + ( \ + (n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \ + DUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \ + (n_arr) * sizeof(duk_tval) + \ + (n_hash) * sizeof(duk_uint32_t) \ + ) +#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash) do { \ + (set_e_pv) = (duk_propvalue *) (void *) (p_base); \ + (set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \ + (set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \ + (set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \ + sizeof(duk_uint8_t) * (n_ent) + \ + DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \ + (set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \ + } while (0) +#elif defined(DUK_USE_HOBJECT_LAYOUT_3) +/* LAYOUT 3 */ +#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \ + ((duk_hstring **) (void *) ( \ + DUK_HOBJECT_GET_PROPS((heap), (h)) + \ + DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \ + DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \ + )) +#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \ + ((duk_propvalue *) (void *) ( \ + DUK_HOBJECT_GET_PROPS((heap), (h)) \ + )) +#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \ + ((duk_uint8_t *) (void *) ( \ + DUK_HOBJECT_GET_PROPS((heap), (h)) + \ + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \ + DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \ + DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \ + )) +#define DUK_HOBJECT_A_GET_BASE(heap,h) \ + ((duk_tval *) (void *) ( \ + DUK_HOBJECT_GET_PROPS((heap), (h)) + \ + DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \ + )) +#define DUK_HOBJECT_H_GET_BASE(heap,h) \ + ((duk_uint32_t *) (void *) ( \ + DUK_HOBJECT_GET_PROPS((heap), (h)) + \ + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \ + DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \ + )) +#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \ + ( \ + (n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + \ + (n_arr) * sizeof(duk_tval) + \ + (n_hash) * sizeof(duk_uint32_t) \ + ) +#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash) do { \ + (set_e_pv) = (duk_propvalue *) (void *) (p_base); \ + (set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \ + (set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \ + (set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \ + (set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \ + } while (0) +#else +#error invalid hobject layout defines +#endif /* hobject property layout */ + +#define DUK_HOBJECT_P_ALLOC_SIZE(h) \ + DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h))) + +#define DUK_HOBJECT_E_GET_KEY(heap,h,i) (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)]) +#define DUK_HOBJECT_E_GET_KEY_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)]) +#define DUK_HOBJECT_E_GET_VALUE(heap,h,i) (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)]) +#define DUK_HOBJECT_E_GET_VALUE_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)]) +#define DUK_HOBJECT_E_GET_VALUE_TVAL(heap,h,i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v) +#define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v) +#define DUK_HOBJECT_E_GET_VALUE_GETTER(heap,h,i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get) +#define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get) +#define DUK_HOBJECT_E_GET_VALUE_SETTER(heap,h,i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set) +#define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set) +#define DUK_HOBJECT_E_GET_FLAGS(heap,h,i) (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)]) +#define DUK_HOBJECT_E_GET_FLAGS_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)]) +#define DUK_HOBJECT_A_GET_VALUE(heap,h,i) (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)]) +#define DUK_HOBJECT_A_GET_VALUE_PTR(heap,h,i) (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)]) +#define DUK_HOBJECT_H_GET_INDEX(heap,h,i) (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)]) +#define DUK_HOBJECT_H_GET_INDEX_PTR(heap,h,i) (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)]) + +#define DUK_HOBJECT_E_SET_KEY(heap,h,i,k) do { \ + DUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \ + } while (0) +#define DUK_HOBJECT_E_SET_VALUE(heap,h,i,v) do { \ + DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \ + } while (0) +#define DUK_HOBJECT_E_SET_VALUE_TVAL(heap,h,i,v) do { \ + DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \ + } while (0) +#define DUK_HOBJECT_E_SET_VALUE_GETTER(heap,h,i,v) do { \ + DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \ + } while (0) +#define DUK_HOBJECT_E_SET_VALUE_SETTER(heap,h,i,v) do { \ + DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \ + } while (0) +#define DUK_HOBJECT_E_SET_FLAGS(heap,h,i,f) do { \ + DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \ + } while (0) +#define DUK_HOBJECT_A_SET_VALUE(heap,h,i,v) do { \ + DUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \ + } while (0) +#define DUK_HOBJECT_A_SET_VALUE_TVAL(heap,h,i,v) \ + DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v)) /* alias for above */ +#define DUK_HOBJECT_H_SET_INDEX(heap,h,i,v) do { \ + DUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \ + } while (0) + +#define DUK_HOBJECT_E_SET_FLAG_BITS(heap,h,i,mask) do { \ + DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \ + } while (0) + +#define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap,h,i,mask) do { \ + DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \ + } while (0) + +#define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0) +#define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0) +#define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0) +#define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0) + +#define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE) +#define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE) +#define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE) +#define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR) + +#define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE) +#define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE) +#define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE) +#define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR) + +#define DUK_PROPDESC_IS_WRITABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0) +#define DUK_PROPDESC_IS_ENUMERABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0) +#define DUK_PROPDESC_IS_CONFIGURABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0) +#define DUK_PROPDESC_IS_ACCESSOR(p) (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0) + +#define DUK_HOBJECT_HASHIDX_UNUSED 0xffffffffUL +#define DUK_HOBJECT_HASHIDX_DELETED 0xfffffffeUL + +/* + * Macros for accessing size fields + */ + +#if defined(DUK_USE_OBJSIZES16) +#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16) +#define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size16 = (v); } while (0) +#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16) +#define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next16 = (v); } while (0) +#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++) +#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16) +#define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size16 = (v); } while (0) +#if defined(DUK_USE_HOBJECT_HASH_PART) +#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16) +#define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size16 = (v); } while (0) +#else +#define DUK_HOBJECT_GET_HSIZE(h) 0 +#define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0) +#endif +#else +#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size) +#define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size = (v); } while (0) +#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next) +#define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next = (v); } while (0) +#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++) +#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size) +#define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size = (v); } while (0) +#if defined(DUK_USE_HOBJECT_HASH_PART) +#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size) +#define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size = (v); } while (0) +#else +#define DUK_HOBJECT_GET_HSIZE(h) 0 +#define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0) +#endif +#endif + +/* + * Misc + */ + +/* Maximum prototype traversal depth. Sanity limit which handles e.g. + * prototype loops (even complex ones like 1->2->3->4->2->3->4->2->3->4). + */ +#define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY 10000L + +/* + * Ecmascript [[Class]] + */ + +/* range check not necessary because all 4-bit values are mapped */ +#define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n) duk_class_number_to_stridx[(n)] + +#define DUK_HOBJECT_GET_CLASS_STRING(heap,h) \ + DUK_HEAP_GET_STRING( \ + (heap), \ + DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))) \ + ) + +/* + * Macros for property handling + */ + +#if defined(DUK_USE_HEAPPTR16) +#define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \ + ((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16)) +#define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \ + (h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \ + } while (0) +#else +#define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \ + ((h)->prototype) +#define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \ + (h)->prototype = (x); \ + } while (0) +#endif + +/* Set prototype, DECREF earlier value, INCREF new value (tolerating NULLs). */ +#define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p) duk_hobject_set_prototype_updref((thr), (h), (p)) + +/* Set initial prototype, assume NULL previous prototype, INCREF new value, + * tolerate NULL. + */ +#define DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr,h,proto) do { \ + duk_hthread *duk__thr = (thr); \ + duk_hobject *duk__obj = (h); \ + duk_hobject *duk__proto = (proto); \ + DUK_UNREF(duk__thr); \ + DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(duk__thr->heap, duk__obj) == NULL); \ + DUK_HOBJECT_SET_PROTOTYPE(duk__thr->heap, duk__obj, duk__proto); \ + DUK_HOBJECT_INCREF_ALLOWNULL(duk__thr, duk__proto); \ + } while (0) + +/* + * Finalizer check + */ + +#if defined(DUK_USE_HEAPPTR16) +#define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((heap), (h)) +#else +#define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((h)) +#endif + +/* + * Resizing and hash behavior + */ + +/* Sanity limit on max number of properties (allocated, not necessarily used). + * This is somewhat arbitrary, but if we're close to 2**32 properties some + * algorithms will fail (e.g. hash size selection, next prime selection). + * Also, we use negative array/entry table indices to indicate 'not found', + * so anything above 0x80000000 will cause trouble now. + */ +#if defined(DUK_USE_OBJSIZES16) +#define DUK_HOBJECT_MAX_PROPERTIES 0x0000ffffUL +#else +#define DUK_HOBJECT_MAX_PROPERTIES 0x3fffffffUL /* 2**30-1 ~= 1G properties */ +#endif + +/* internal align target for props allocation, must be 2*n for some n */ +#if (DUK_USE_ALIGN_BY == 4) +#define DUK_HOBJECT_ALIGN_TARGET 4 +#elif (DUK_USE_ALIGN_BY == 8) +#define DUK_HOBJECT_ALIGN_TARGET 8 +#elif (DUK_USE_ALIGN_BY == 1) +#define DUK_HOBJECT_ALIGN_TARGET 1 +#else +#error invalid DUK_USE_ALIGN_BY +#endif + +/* + * PC-to-line constants + */ + +#define DUK_PC2LINE_SKIP 64 + +/* maximum length for a SKIP-1 diffstream: 35 bits per entry, rounded up to bytes */ +#define DUK_PC2LINE_MAX_DIFF_LENGTH (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8) + +/* + * Struct defs + */ + +struct duk_propaccessor { + duk_hobject *get; + duk_hobject *set; +}; + +union duk_propvalue { + /* The get/set pointers could be 16-bit pointer compressed but it + * would make no difference on 32-bit platforms because duk_tval is + * 8 bytes or more anyway. + */ + duk_tval v; + duk_propaccessor a; +}; + +struct duk_propdesc { + /* read-only values 'lifted' for ease of use */ + duk_small_uint_t flags; + duk_hobject *get; + duk_hobject *set; + + /* for updating (all are set to < 0 for virtual properties) */ + duk_int_t e_idx; /* prop index in 'entry part', < 0 if not there */ + duk_int_t h_idx; /* prop index in 'hash part', < 0 if not there */ + duk_int_t a_idx; /* prop index in 'array part', < 0 if not there */ +}; + +struct duk_hobject { + duk_heaphdr hdr; + + /* + * 'props' contains {key,value,flags} entries, optional array entries, and + * an optional hash lookup table for non-array entries in a single 'sliced' + * allocation. There are several layout options, which differ slightly in + * generated code size/speed and alignment/padding; duk_features.h selects + * the layout used. + * + * Layout 1 (DUK_USE_HOBJECT_LAYOUT_1): + * + * e_size * sizeof(duk_hstring *) bytes of entry keys (e_next gc reachable) + * e_size * sizeof(duk_propvalue) bytes of entry values (e_next gc reachable) + * e_size * sizeof(duk_uint8_t) bytes of entry flags (e_next gc reachable) + * a_size * sizeof(duk_tval) bytes of (opt) array values (plain only) (all gc reachable) + * h_size * sizeof(duk_uint32_t) bytes of (opt) hash indexes to entries (e_size), + * 0xffffffffUL = unused, 0xfffffffeUL = deleted + * + * Layout 2 (DUK_USE_HOBJECT_LAYOUT_2): + * + * e_size * sizeof(duk_propvalue) bytes of entry values (e_next gc reachable) + * e_size * sizeof(duk_hstring *) bytes of entry keys (e_next gc reachable) + * e_size * sizeof(duk_uint8_t) + pad bytes of entry flags (e_next gc reachable) + * a_size * sizeof(duk_tval) bytes of (opt) array values (plain only) (all gc reachable) + * h_size * sizeof(duk_uint32_t) bytes of (opt) hash indexes to entries (e_size), + * 0xffffffffUL = unused, 0xfffffffeUL = deleted + * + * Layout 3 (DUK_USE_HOBJECT_LAYOUT_3): + * + * e_size * sizeof(duk_propvalue) bytes of entry values (e_next gc reachable) + * a_size * sizeof(duk_tval) bytes of (opt) array values (plain only) (all gc reachable) + * e_size * sizeof(duk_hstring *) bytes of entry keys (e_next gc reachable) + * h_size * sizeof(duk_uint32_t) bytes of (opt) hash indexes to entries (e_size), + * 0xffffffffUL = unused, 0xfffffffeUL = deleted + * e_size * sizeof(duk_uint8_t) bytes of entry flags (e_next gc reachable) + * + * In layout 1, the 'e_next' count is rounded to 4 or 8 on platforms + * requiring 4 or 8 byte alignment. This ensures proper alignment + * for the entries, at the cost of memory footprint. However, it's + * probably preferable to use another layout on such platforms instead. + * + * In layout 2, the key and value parts are swapped to avoid padding + * the key array on platforms requiring alignment by 8. The flags part + * is padded to get alignment for array entries. The 'e_next' count does + * not need to be rounded as in layout 1. + * + * In layout 3, entry values and array values are always aligned properly, + * and assuming pointers are at most 8 bytes, so are the entry keys. Hash + * indices will be properly aligned (assuming pointers are at least 4 bytes). + * Finally, flags don't need additional alignment. This layout provides + * compact allocations without padding (even on platforms with alignment + * requirements) at the cost of a bit slower lookups. + * + * Objects with few keys don't have a hash index; keys are looked up linearly, + * which is cache efficient because the keys are consecutive. Larger objects + * have a hash index part which contains integer indexes to the entries part. + * + * A single allocation reduces memory allocation overhead but requires more + * work when any part needs to be resized. A sliced allocation for entries + * makes linear key matching faster on most platforms (more locality) and + * skimps on flags size (which would be followed by 3 bytes of padding in + * most architectures if entries were placed in a struct). + * + * 'props' also contains internal properties distinguished with a non-BMP + * prefix. Often used properties should be placed early in 'props' whenever + * possible to make accessing them as fast a possible. + */ + +#if defined(DUK_USE_HEAPPTR16) + /* Located in duk_heaphdr h_extra16. Subclasses of duk_hobject (like + * duk_hcompfunc) are not free to use h_extra16 for this reason. + */ +#else + duk_uint8_t *props; +#endif + + /* prototype: the only internal property lifted outside 'e' as it is so central */ +#if defined(DUK_USE_HEAPPTR16) + duk_uint16_t prototype16; +#else + duk_hobject *prototype; +#endif + +#if defined(DUK_USE_OBJSIZES16) + duk_uint16_t e_size16; + duk_uint16_t e_next16; + duk_uint16_t a_size16; +#if defined(DUK_USE_HOBJECT_HASH_PART) + duk_uint16_t h_size16; +#endif +#else + duk_uint32_t e_size; /* entry part size */ + duk_uint32_t e_next; /* index for next new key ([0,e_next[ are gc reachable) */ + duk_uint32_t a_size; /* array part size (entirely gc reachable) */ +#if defined(DUK_USE_HOBJECT_HASH_PART) + duk_uint32_t h_size; /* hash part size or 0 if unused */ +#endif +#endif +}; + +/* + * Exposed data + */ + +#if !defined(DUK_SINGLE_FILE) +DUK_INTERNAL_DECL duk_uint8_t duk_class_number_to_stridx[32]; +#endif /* !DUK_SINGLE_FILE */ + +/* + * Prototypes + */ + +/* alloc and init */ +DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags); +DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags); +DUK_INTERNAL_DECL duk_harray *duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags); +DUK_INTERNAL_DECL duk_hcompfunc *duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags); +DUK_INTERNAL_DECL duk_hnatfunc *duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags); +DUK_INTERNAL_DECL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags); +#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) +DUK_INTERNAL_DECL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags); +#endif +DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags); +DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags); +DUK_INTERNAL_DECL duk_hdecenv *duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags); +DUK_INTERNAL_DECL duk_hobjenv *duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags); +DUK_INTERNAL_DECL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags); + +/* resize */ +DUK_INTERNAL_DECL void duk_hobject_realloc_props(duk_hthread *thr, + duk_hobject *obj, + duk_uint32_t new_e_size, + duk_uint32_t new_a_size, + duk_uint32_t new_h_size, + duk_bool_t abandon_array); +DUK_INTERNAL_DECL void duk_hobject_resize_entrypart(duk_hthread *thr, + duk_hobject *obj, + duk_uint32_t new_e_size); +#if 0 /*unused*/ +DUK_INTERNAL_DECL void duk_hobject_resize_arraypart(duk_hthread *thr, + duk_hobject *obj, + duk_uint32_t new_a_size); +#endif + +/* low-level property functions */ +DUK_INTERNAL_DECL duk_bool_t duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx); +DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key); +DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs); +DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i); +DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_own_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags); + +/* XXX: when optimizing for guaranteed property slots, use a guaranteed + * slot for internal value; this call can then access it directly. + */ +#define duk_hobject_get_internal_value_tval_ptr(heap,obj) \ + duk_hobject_find_existing_entry_tval_ptr((heap), (obj), DUK_HEAP_STRING_INT_VALUE((heap))) + +/* core property functions */ +DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key); +DUK_INTERNAL_DECL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag); +DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag); +DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key); + +/* internal property functions */ +#define DUK_DELPROP_FLAG_THROW (1U << 0) +#define DUK_DELPROP_FLAG_FORCE (1U << 1) +DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags); +DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key); +DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags); +DUK_INTERNAL_DECL void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *obj, duk_uarridx_t arr_idx, duk_small_uint_t flags); +DUK_INTERNAL_DECL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj); +#if defined(DUK_USE_HEAPPTR16) +DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj); +#else +DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj); +#endif + +/* helpers for defineProperty() and defineProperties() */ +DUK_INTERNAL_DECL void duk_hobject_prepare_property_descriptor(duk_hthread *thr, + duk_idx_t idx_in, + duk_uint_t *out_defprop_flags, + duk_idx_t *out_idx_value, + duk_hobject **out_getter, + duk_hobject **out_setter); +DUK_INTERNAL_DECL duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr, + duk_uint_t defprop_flags, + duk_hobject *obj, + duk_hstring *key, + duk_idx_t idx_value, + duk_hobject *get, + duk_hobject *set, + duk_bool_t throw_flag); + +/* Object built-in methods */ +DUK_INTERNAL_DECL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx); +DUK_INTERNAL_DECL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze); +DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen); +DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags); + +/* internal properties */ +DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv); +DUK_INTERNAL_DECL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj); + +/* hobject management functions */ +DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj); + +/* ES2015 proxy */ +#if defined(DUK_USE_ES6_PROXY) +DUK_INTERNAL_DECL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler); +DUK_INTERNAL_DECL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj); +#endif + +/* enumeration */ +DUK_INTERNAL_DECL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags); +DUK_INTERNAL_DECL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags); +DUK_INTERNAL_DECL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value); + +/* macros */ +DUK_INTERNAL_DECL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p); + +/* pc2line */ +#if defined(DUK_USE_PC2LINE) +DUK_INTERNAL_DECL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length); +DUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc); +#endif + +/* misc */ +DUK_INTERNAL_DECL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop); + +#if !defined(DUK_USE_OBJECT_BUILTIN) +/* These declarations are needed when related built-in is disabled and + * genbuiltins.py won't automatically emit the declerations. + */ +DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr); +DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_hthread *thr); +#endif + +#endif /* DUK_HOBJECT_H_INCLUDED */ +/* #include duk_hcompfunc.h */ +#line 1 "duk_hcompfunc.h" +/* + * Heap compiled function (Ecmascript function) representation. + * + * There is a single data buffer containing the Ecmascript function's + * bytecode, constants, and inner functions. + */ + +#if !defined(DUK_HCOMPFUNC_H_INCLUDED) +#define DUK_HCOMPFUNC_H_INCLUDED + +/* + * Field accessor macros + */ + +/* XXX: casts could be improved, especially for GET/SET DATA */ + +#if defined(DUK_USE_HEAPPTR16) +#define DUK_HCOMPFUNC_GET_DATA(heap,h) \ + ((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16)) +#define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \ + (h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ + } while (0) +#define DUK_HCOMPFUNC_GET_FUNCS(heap,h) \ + ((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16))) +#define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v) do { \ + (h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ + } while (0) +#define DUK_HCOMPFUNC_GET_BYTECODE(heap,h) \ + ((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16))) +#define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v) do { \ + (h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ + } while (0) +#define DUK_HCOMPFUNC_GET_LEXENV(heap,h) \ + ((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->lex_env16))) +#define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v) do { \ + (h)->lex_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ + } while (0) +#define DUK_HCOMPFUNC_GET_VARENV(heap,h) \ + ((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->var_env16))) +#define DUK_HCOMPFUNC_SET_VARENV(heap,h,v) do { \ + (h)->var_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ + } while (0) +#else +#define DUK_HCOMPFUNC_GET_DATA(heap,h) ((duk_hbuffer_fixed *) (void *) (h)->data) +#define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \ + (h)->data = (duk_hbuffer *) (v); \ + } while (0) +#define DUK_HCOMPFUNC_GET_FUNCS(heap,h) ((h)->funcs) +#define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v) do { \ + (h)->funcs = (v); \ + } while (0) +#define DUK_HCOMPFUNC_GET_BYTECODE(heap,h) ((h)->bytecode) +#define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v) do { \ + (h)->bytecode = (v); \ + } while (0) +#define DUK_HCOMPFUNC_GET_LEXENV(heap,h) ((h)->lex_env) +#define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v) do { \ + (h)->lex_env = (v); \ + } while (0) +#define DUK_HCOMPFUNC_GET_VARENV(heap,h) ((h)->var_env) +#define DUK_HCOMPFUNC_SET_VARENV(heap,h,v) do { \ + (h)->var_env = (v); \ + } while (0) +#endif + +/* + * Accessor macros for function specific data areas + */ + +/* Note: assumes 'data' is always a fixed buffer */ +#define DUK_HCOMPFUNC_GET_BUFFER_BASE(heap,h) \ + DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h))) + +#define DUK_HCOMPFUNC_GET_CONSTS_BASE(heap,h) \ + ((duk_tval *) (void *) DUK_HCOMPFUNC_GET_BUFFER_BASE((heap), (h))) + +#define DUK_HCOMPFUNC_GET_FUNCS_BASE(heap,h) \ + DUK_HCOMPFUNC_GET_FUNCS((heap), (h)) + +#define DUK_HCOMPFUNC_GET_CODE_BASE(heap,h) \ + DUK_HCOMPFUNC_GET_BYTECODE((heap), (h)) + +#define DUK_HCOMPFUNC_GET_CONSTS_END(heap,h) \ + ((duk_tval *) (void *) DUK_HCOMPFUNC_GET_FUNCS((heap), (h))) + +#define DUK_HCOMPFUNC_GET_FUNCS_END(heap,h) \ + ((duk_hobject **) (void *) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h))) + +/* XXX: double evaluation of DUK_HCOMPFUNC_GET_DATA() */ +#define DUK_HCOMPFUNC_GET_CODE_END(heap,h) \ + ((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h))) + \ + DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA((heap), h)))) + +#define DUK_HCOMPFUNC_GET_CONSTS_SIZE(heap,h) \ + ( \ + (duk_size_t) \ + ( \ + ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_END((heap), (h))) - \ + ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_BASE((heap), (h))) \ + ) \ + ) + +#define DUK_HCOMPFUNC_GET_FUNCS_SIZE(heap,h) \ + ( \ + (duk_size_t) \ + ( \ + ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_END((heap), (h))) - \ + ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_BASE((heap), (h))) \ + ) \ + ) + +#define DUK_HCOMPFUNC_GET_CODE_SIZE(heap,h) \ + ( \ + (duk_size_t) \ + ( \ + ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_END((heap),(h))) - \ + ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_BASE((heap),(h))) \ + ) \ + ) + +#define DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap,h) \ + ((duk_size_t) (DUK_HCOMPFUNC_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval))) + +#define DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap,h) \ + ((duk_size_t) (DUK_HCOMPFUNC_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *))) + +#define DUK_HCOMPFUNC_GET_CODE_COUNT(heap,h) \ + ((duk_size_t) (DUK_HCOMPFUNC_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t))) + +/* + * Validity assert + */ + +#define DUK_ASSERT_HCOMPFUNC_VALID(h) do { \ + DUK_ASSERT((h) != NULL); \ + } while (0) + +/* + * Main struct + */ + +struct duk_hcompfunc { + /* shared object part */ + duk_hobject obj; + + /* + * Pointers to function data area for faster access. Function + * data is a buffer shared between all closures of the same + * "template" function. The data buffer is always fixed (non- + * dynamic, hence stable), with a layout as follows: + * + * constants (duk_tval) + * inner functions (duk_hobject *) + * bytecode (duk_instr_t) + * + * Note: bytecode end address can be computed from 'data' buffer + * size. It is not strictly necessary functionally, assuming + * bytecode never jumps outside its allocated area. However, + * it's a safety/robustness feature for avoiding the chance of + * executing random data as bytecode due to a compiler error. + * + * Note: values in the data buffer must be incref'd (they will + * be decref'd on release) for every compiledfunction referring + * to the 'data' element. + */ + + /* Data area, fixed allocation, stable data ptrs. */ +#if defined(DUK_USE_HEAPPTR16) + duk_uint16_t data16; +#else + duk_hbuffer *data; +#endif + + /* No need for constants pointer (= same as data). + * + * When using 16-bit packing alignment to 4 is nice. 'funcs' will be + * 4-byte aligned because 'constants' are duk_tvals. For now the + * inner function pointers are not compressed, so that 'bytecode' will + * also be 4-byte aligned. + */ +#if defined(DUK_USE_HEAPPTR16) + duk_uint16_t funcs16; + duk_uint16_t bytecode16; +#else + duk_hobject **funcs; + duk_instr_t *bytecode; +#endif + + /* Lexenv: lexical environment of closure, NULL for templates. + * Varenv: variable environment of closure, NULL for templates. + */ +#if defined(DUK_USE_HEAPPTR16) + duk_uint16_t lex_env16; + duk_uint16_t var_env16; +#else + duk_hobject *lex_env; + duk_hobject *var_env; +#endif + + /* + * 'nregs' registers are allocated on function entry, at most 'nargs' + * are initialized to arguments, and the rest to undefined. Arguments + * above 'nregs' are not mapped to registers. All registers in the + * active stack range must be initialized because they are GC reachable. + * 'nargs' is needed so that if the function is given more than 'nargs' + * arguments, the additional arguments do not 'clobber' registers + * beyond 'nregs' which must be consistently initialized to undefined. + * + * Usually there is no need to know which registers are mapped to + * local variables. Registers may be allocated to variable in any + * way (even including gaps). However, a register-variable mapping + * must be the same for the duration of the function execution and + * the register cannot be used for anything else. + * + * When looking up variables by name, the '_Varmap' map is used. + * When an activation closes, registers mapped to arguments are + * copied into the environment record based on the same map. The + * reverse map (from register to variable) is not currently needed + * at run time, except for debugging, so it is not maintained. + */ + + duk_uint16_t nregs; /* regs to allocate */ + duk_uint16_t nargs; /* number of arguments allocated to regs */ + + /* + * Additional control information is placed into the object itself + * as internal properties to avoid unnecessary fields for the + * majority of functions. The compiler tries to omit internal + * control fields when possible. + * + * Function templates: + * + * { + * name: "func", // declaration, named function expressions + * fileName: <debug info for creating nice errors> + * _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 }, + * _Formals: [ "arg1", "arg2" ], + * _Source: "function func(arg1, arg2) { ... }", + * _Pc2line: <debug info for pc-to-line mapping>, + * } + * + * Function instances: + * + * { + * length: 2, + * prototype: { constructor: <func> }, + * caller: <thrower>, + * arguments: <thrower>, + * name: "func", // declaration, named function expressions + * fileName: <debug info for creating nice errors> + * _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 }, + * _Formals: [ "arg1", "arg2" ], + * _Source: "function func(arg1, arg2) { ... }", + * _Pc2line: <debug info for pc-to-line mapping>, + * } + * + * More detailed description of these properties can be found + * in the documentation. + */ + +#if defined(DUK_USE_DEBUGGER_SUPPORT) + /* Line number range for function. Needed during debugging to + * determine active breakpoints. + */ + duk_uint32_t start_line; + duk_uint32_t end_line; +#endif +}; + +#endif /* DUK_HCOMPFUNC_H_INCLUDED */ +/* #include duk_hnatfunc.h */ +#line 1 "duk_hnatfunc.h" +/* + * Heap native function representation. + */ + +#if !defined(DUK_HNATFUNC_H_INCLUDED) +#define DUK_HNATFUNC_H_INCLUDED + +#define DUK_HNATFUNC_NARGS_VARARGS ((duk_int16_t) -1) +#define DUK_HNATFUNC_NARGS_MAX ((duk_int16_t) 0x7fff) + +struct duk_hnatfunc { + /* shared object part */ + duk_hobject obj; + + duk_c_function func; + duk_int16_t nargs; + duk_int16_t magic; + + /* The 'magic' field allows an opaque 16-bit field to be accessed by the + * Duktape/C function. This allows, for instance, the same native function + * to be used for a set of very similar functions, with the 'magic' field + * providing the necessary non-argument flags / values to guide the behavior + * of the native function. The value is signed on purpose: it is easier to + * convert a signed value to unsigned (simply AND with 0xffff) than vice + * versa. + * + * Note: cannot place nargs/magic into the heaphdr flags, because + * duk_hobject takes almost all flags already. + */ +}; + +#endif /* DUK_HNATFUNC_H_INCLUDED */ +/* #include duk_hboundfunc.h */ +#line 1 "duk_hboundfunc.h" +/* + * Bound function representation. + */ + +#if !defined(DUK_HBOUNDFUNC_H_INCLUDED) +#define DUK_HBOUNDFUNC_H_INCLUDED + +/* Artificial limit for args length. Ensures arithmetic won't overflow + * 32 bits when combining bound functions. + */ +#define DUK_HBOUNDFUNC_MAX_ARGS 0x20000000UL + +#define DUK_ASSERT_HBOUNDFUNC_VALID(h) do { \ + DUK_ASSERT((h) != NULL); \ + DUK_ASSERT(DUK_HOBJECT_IS_BOUNDFUNC((duk_hobject *) (h))); \ + DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&(h)->target) || \ + (DUK_TVAL_IS_OBJECT(&(h)->target) && \ + DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&(h)->target)))); \ + DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&(h)->this_binding)); \ + DUK_ASSERT((h)->nargs == 0 || (h)->args != NULL); \ + } while (0) + +struct duk_hboundfunc { + /* Shared object part. */ + duk_hobject obj; + + /* Final target function, stored as duk_tval so that lightfunc can be + * represented too. + */ + duk_tval target; + + /* This binding. */ + duk_tval this_binding; + + /* Arguments to prepend. */ + duk_tval *args; /* Separate allocation. */ + duk_idx_t nargs; +}; + +#endif /* DUK_HBOUNDFUNC_H_INCLUDED */ +/* #include duk_hbufobj.h */ +#line 1 "duk_hbufobj.h" +/* + * Heap Buffer object representation. Used for all Buffer variants. + */ + +#if !defined(DUK_HBUFOBJ_H_INCLUDED) +#define DUK_HBUFOBJ_H_INCLUDED + +#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) + +/* All element accessors are host endian now (driven by TypedArray spec). */ +#define DUK_HBUFOBJ_ELEM_UINT8 0 +#define DUK_HBUFOBJ_ELEM_UINT8CLAMPED 1 +#define DUK_HBUFOBJ_ELEM_INT8 2 +#define DUK_HBUFOBJ_ELEM_UINT16 3 +#define DUK_HBUFOBJ_ELEM_INT16 4 +#define DUK_HBUFOBJ_ELEM_UINT32 5 +#define DUK_HBUFOBJ_ELEM_INT32 6 +#define DUK_HBUFOBJ_ELEM_FLOAT32 7 +#define DUK_HBUFOBJ_ELEM_FLOAT64 8 +#define DUK_HBUFOBJ_ELEM_MAX 8 + +#define DUK_ASSERT_HBUFOBJ_VALID(h) do { \ + DUK_ASSERT((h) != NULL); \ + DUK_ASSERT((h)->shift <= 3); \ + DUK_ASSERT((h)->elem_type <= DUK_HBUFOBJ_ELEM_MAX); \ + DUK_ASSERT(((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT8) || \ + ((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT8CLAMPED) || \ + ((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT8) || \ + ((h)->shift == 1 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT16) || \ + ((h)->shift == 1 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT16) || \ + ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT32) || \ + ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT32) || \ + ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_FLOAT32) || \ + ((h)->shift == 3 && (h)->elem_type == DUK_HBUFOBJ_ELEM_FLOAT64)); \ + DUK_ASSERT((h)->is_typedarray == 0 || (h)->is_typedarray == 1); \ + DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) (h))); \ + if ((h)->buf == NULL) { \ + DUK_ASSERT((h)->offset == 0); \ + DUK_ASSERT((h)->length == 0); \ + } else { \ + /* No assertions for offset or length; in particular, \ + * it's OK for length to be longer than underlying \ + * buffer. Just ensure they don't wrap when added. \ + */ \ + DUK_ASSERT((h)->offset + (h)->length >= (h)->offset); \ + } \ + } while (0) + +/* Get the current data pointer (caller must ensure buf != NULL) as a + * duk_uint8_t ptr. + */ +#define DUK_HBUFOBJ_GET_SLICE_BASE(heap,h) \ + (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \ + (((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset)) + +/* True if slice is full, i.e. offset is zero and length covers the entire + * buffer. This status may change independently of the duk_hbufobj if + * the underlying buffer is dynamic and changes without the hbufobj + * being changed. + */ +#define DUK_HBUFOBJ_FULL_SLICE(h) \ + (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \ + ((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf))) + +/* Validate that the whole slice [0,length[ is contained in the underlying + * buffer. Caller must ensure 'buf' != NULL. + */ +#define DUK_HBUFOBJ_VALID_SLICE(h) \ + (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \ + ((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf))) + +/* Validate byte read/write for virtual 'offset', i.e. check that the + * offset, taking into account h->offset, is within the underlying + * buffer size. This is a safety check which is needed to ensure + * that even a misconfigured duk_hbufobj never causes memory unsafe + * behavior (e.g. if an underlying dynamic buffer changes after being + * setup). Caller must ensure 'buf' != NULL. + */ +#define DUK_HBUFOBJ_VALID_BYTEOFFSET_INCL(h,off) \ + (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \ + ((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf))) + +#define DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h,off) \ + (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \ + ((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf))) + +/* Clamp an input byte length (already assumed to be within the nominal + * duk_hbufobj 'length') to the current dynamic buffer limits to yield + * a byte length limit that's safe for memory accesses. This value can + * be invalidated by any side effect because it may trigger a user + * callback that resizes the underlying buffer. + */ +#define DUK_HBUFOBJ_CLAMP_BYTELENGTH(h,len) \ + (DUK_ASSERT_EXPR((h) != NULL), \ + duk_hbufobj_clamp_bytelength((h), (len))) + +/* Typed arrays have virtual indices, ArrayBuffer and DataView do not. */ +#define DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h) ((h)->is_typedarray) + +struct duk_hbufobj { + /* Shared object part. */ + duk_hobject obj; + + /* Underlying buffer (refcounted), may be NULL. */ + duk_hbuffer *buf; + + /* .buffer reference to an ArrayBuffer, may be NULL. */ + duk_hobject *buf_prop; + + /* Slice and accessor information. + * + * Because the underlying buffer may be dynamic, these may be + * invalidated by the buffer being modified so that both offset + * and length should be validated before every access. Behavior + * when the underlying buffer has changed doesn't need to be clean: + * virtual 'length' doesn't need to be affected, reads can return + * zero/NaN, and writes can be ignored. + * + * Note that a data pointer cannot be precomputed because 'buf' may + * be dynamic and its pointer unstable. + */ + + duk_uint_t offset; /* byte offset to buf */ + duk_uint_t length; /* byte index limit for element access, exclusive */ + duk_uint8_t shift; /* element size shift: + * 0 = u8/i8 + * 1 = u16/i16 + * 2 = u32/i32/float + * 3 = double + */ + duk_uint8_t elem_type; /* element type */ + duk_uint8_t is_typedarray; +}; + +DUK_INTERNAL_DECL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len); +DUK_INTERNAL_DECL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf); +DUK_INTERNAL_DECL void duk_hbufobj_push_validated_read(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size); +DUK_INTERNAL_DECL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size); +DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx); + +#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ +#endif /* DUK_HBUFOBJ_H_INCLUDED */ +/* #include duk_hthread.h */ +#line 1 "duk_hthread.h" +/* + * Heap thread object representation. + * + * duk_hthread is also the 'context' for public API functions via a + * different typedef. Most API calls operate on the topmost frame + * of the value stack only. + */ + +#if !defined(DUK_HTHREAD_H_INCLUDED) +#define DUK_HTHREAD_H_INCLUDED + +/* + * Stack constants + */ + +/* Initial valstack size, roughly 0.7kiB. */ +#define DUK_VALSTACK_INITIAL_SIZE 96U + +/* Internal extra elements assumed on function entry, always added to + * user-defined 'extra' for e.g. the duk_check_stack() call. + */ +#define DUK_VALSTACK_INTERNAL_EXTRA 32U + +/* Number of elements guaranteed to be user accessible (in addition to call + * arguments) on Duktape/C function entry. This is the major public API + * commitment. + */ +#define DUK_VALSTACK_API_ENTRY_MINIMUM DUK_API_ENTRY_STACK + +/* + * Activation defines + */ + +#define DUK_ACT_FLAG_STRICT (1U << 0) /* function executes in strict mode */ +#define DUK_ACT_FLAG_TAILCALLED (1U << 1) /* activation has tail called one or more times */ +#define DUK_ACT_FLAG_CONSTRUCT (1U << 2) /* function executes as a constructor (called via "new") */ +#define DUK_ACT_FLAG_PREVENT_YIELD (1U << 3) /* activation prevents yield (native call or "new") */ +#define DUK_ACT_FLAG_DIRECT_EVAL (1U << 4) /* activation is a direct eval call */ +#define DUK_ACT_FLAG_CONSTRUCT_PROXY (1U << 5) /* activation is for Proxy 'construct' call, special return value handling */ +#define DUK_ACT_FLAG_BREAKPOINT_ACTIVE (1U << 6) /* activation has active breakpoint(s) */ + +#define DUK_ACT_GET_FUNC(act) ((act)->func) + +/* + * Flags for __FILE__ / __LINE__ registered into tracedata + */ + +#define DUK_TB_FLAG_NOBLAME_FILELINE (1U << 0) /* don't report __FILE__ / __LINE__ as fileName/lineNumber */ + +/* + * Catcher defines + */ + +/* XXX: remove catcher type entirely */ + +/* flags field: LLLLLLFT, L = label (24 bits), F = flags (4 bits), T = type (4 bits) */ +#define DUK_CAT_TYPE_MASK 0x0000000fUL +#define DUK_CAT_TYPE_BITS 4 +#define DUK_CAT_LABEL_MASK 0xffffff00UL +#define DUK_CAT_LABEL_BITS 24 +#define DUK_CAT_LABEL_SHIFT 8 + +#define DUK_CAT_FLAG_CATCH_ENABLED (1U << 4) /* catch part will catch */ +#define DUK_CAT_FLAG_FINALLY_ENABLED (1U << 5) /* finally part will catch */ +#define DUK_CAT_FLAG_CATCH_BINDING_ENABLED (1U << 6) /* request to create catch binding */ +#define DUK_CAT_FLAG_LEXENV_ACTIVE (1U << 7) /* catch or with binding is currently active */ + +#define DUK_CAT_TYPE_UNKNOWN 0 +#define DUK_CAT_TYPE_TCF 1 +#define DUK_CAT_TYPE_LABEL 2 + +#define DUK_CAT_GET_TYPE(c) ((c)->flags & DUK_CAT_TYPE_MASK) +#define DUK_CAT_GET_LABEL(c) (((c)->flags & DUK_CAT_LABEL_MASK) >> DUK_CAT_LABEL_SHIFT) + +#define DUK_CAT_HAS_CATCH_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_CATCH_ENABLED) +#define DUK_CAT_HAS_FINALLY_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_FINALLY_ENABLED) +#define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_CATCH_BINDING_ENABLED) +#define DUK_CAT_HAS_LEXENV_ACTIVE(c) ((c)->flags & DUK_CAT_FLAG_LEXENV_ACTIVE) + +#define DUK_CAT_SET_CATCH_ENABLED(c) do { \ + (c)->flags |= DUK_CAT_FLAG_CATCH_ENABLED; \ + } while (0) +#define DUK_CAT_SET_FINALLY_ENABLED(c) do { \ + (c)->flags |= DUK_CAT_FLAG_FINALLY_ENABLED; \ + } while (0) +#define DUK_CAT_SET_CATCH_BINDING_ENABLED(c) do { \ + (c)->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \ + } while (0) +#define DUK_CAT_SET_LEXENV_ACTIVE(c) do { \ + (c)->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE; \ + } while (0) + +#define DUK_CAT_CLEAR_CATCH_ENABLED(c) do { \ + (c)->flags &= ~DUK_CAT_FLAG_CATCH_ENABLED; \ + } while (0) +#define DUK_CAT_CLEAR_FINALLY_ENABLED(c) do { \ + (c)->flags &= ~DUK_CAT_FLAG_FINALLY_ENABLED; \ + } while (0) +#define DUK_CAT_CLEAR_CATCH_BINDING_ENABLED(c) do { \ + (c)->flags &= ~DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \ + } while (0) +#define DUK_CAT_CLEAR_LEXENV_ACTIVE(c) do { \ + (c)->flags &= ~DUK_CAT_FLAG_LEXENV_ACTIVE; \ + } while (0) + +/* + * Thread defines + */ + +#if defined(DUK_USE_ROM_STRINGS) +#define DUK_HTHREAD_GET_STRING(thr,idx) \ + ((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)])) +#else /* DUK_USE_ROM_STRINGS */ +#if defined(DUK_USE_HEAPPTR16) +#define DUK_HTHREAD_GET_STRING(thr,idx) \ + ((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)])) +#else +#define DUK_HTHREAD_GET_STRING(thr,idx) \ + ((thr)->strs[(idx)]) +#endif +#endif /* DUK_USE_ROM_STRINGS */ + +/* values for the state field */ +#define DUK_HTHREAD_STATE_INACTIVE 1 /* thread not currently running */ +#define DUK_HTHREAD_STATE_RUNNING 2 /* thread currently running (only one at a time) */ +#define DUK_HTHREAD_STATE_RESUMED 3 /* thread resumed another thread (active but not running) */ +#define DUK_HTHREAD_STATE_YIELDED 4 /* thread has yielded */ +#define DUK_HTHREAD_STATE_TERMINATED 5 /* thread has terminated */ + +/* Executor interrupt default interval when nothing else requires a + * smaller value. The default interval must be small enough to allow + * for reasonable execution timeout checking but large enough to keep + * impact on execution performance low. + */ +#if defined(DUK_USE_INTERRUPT_COUNTER) +#define DUK_HTHREAD_INTCTR_DEFAULT (256L * 1024L) +#endif + +/* + * Assert context is valid: non-NULL pointer, fields look sane. + * + * This is used by public API call entrypoints to catch invalid 'ctx' pointers + * as early as possible; invalid 'ctx' pointers cause very odd and difficult to + * diagnose behavior so it's worth checking even when the check is not 100%. + */ + +/* Assertions for internals. */ +#define DUK_ASSERT_HTHREAD_VALID(thr) do { \ + DUK_ASSERT((thr) != NULL); \ + DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) (thr)) == DUK_HTYPE_OBJECT); \ + DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) (thr))); \ + DUK_ASSERT((thr)->unused1 == 0); \ + DUK_ASSERT((thr)->unused2 == 0); \ + } while (0) + +/* Assertions for public API calls; a bit stronger. */ +#define DUK_ASSERT_CTX_VALID(thr) do { \ + DUK_ASSERT((thr) != NULL); \ + DUK_ASSERT_HTHREAD_VALID((thr)); \ + DUK_ASSERT((thr)->valstack != NULL); \ + DUK_ASSERT((thr)->valstack_bottom != NULL); \ + DUK_ASSERT((thr)->valstack_top != NULL); \ + DUK_ASSERT((thr)->valstack_end != NULL); \ + DUK_ASSERT((thr)->valstack_alloc_end != NULL); \ + DUK_ASSERT((thr)->valstack_alloc_end >= (thr)->valstack); \ + DUK_ASSERT((thr)->valstack_end >= (thr)->valstack); \ + DUK_ASSERT((thr)->valstack_top >= (thr)->valstack); \ + DUK_ASSERT((thr)->valstack_top >= (thr)->valstack_bottom); \ + DUK_ASSERT((thr)->valstack_end >= (thr)->valstack_top); \ + DUK_ASSERT((thr)->valstack_alloc_end >= (thr)->valstack_end); \ + } while (0) + +/* Assertions for API call entry specifically. Checks 'ctx' but also may + * check internal state (e.g. not in a debugger transport callback). + */ +#define DUK_ASSERT_API_ENTRY(thr) do { \ + DUK_ASSERT_CTX_VALID((thr)); \ + DUK_ASSERT((thr)->heap != NULL); \ + DUK_ASSERT((thr)->heap->dbg_calling_transport == 0); \ + } while (0) + +/* + * Assertion helpers. + */ + +#define DUK_ASSERT_STRIDX_VALID(val) \ + DUK_ASSERT((duk_uint_t) (val) < DUK_HEAP_NUM_STRINGS) + +#define DUK_ASSERT_BIDX_VALID(val) \ + DUK_ASSERT((duk_uint_t) (val) < DUK_NUM_BUILTINS) + +/* + * Misc + */ + +/* Fast access to 'this' binding. Assumes there's a call in progress. */ +#define DUK_HTHREAD_THIS_PTR(thr) \ + (DUK_ASSERT_EXPR((thr) != NULL), \ + DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \ + (thr)->valstack_bottom - 1) + +/* + * Struct defines + */ + +/* Fields are ordered for alignment/packing. */ +struct duk_activation { + duk_tval tv_func; /* borrowed: full duk_tval for function being executed; for lightfuncs */ + duk_hobject *func; /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL for lightfuncs */ + duk_activation *parent; /* previous (parent) activation (or NULL if none) */ + duk_hobject *var_env; /* current variable environment (may be NULL if delayed) */ + duk_hobject *lex_env; /* current lexical environment (may be NULL if delayed) */ + duk_catcher *cat; /* current catcher (or NULL) */ + +#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY) + /* Previous value of 'func' caller, restored when unwound. Only in use + * when 'func' is non-strict. + */ + duk_hobject *prev_caller; +#endif + + duk_instr_t *curr_pc; /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */ + + /* bottom_byteoff and retval_byteoff are only used for book-keeping + * of Ecmascript-initiated calls, to allow returning to an Ecmascript + * function properly. + */ + + /* Bottom of valstack for this activation, used to reset + * valstack_bottom on return; offset is absolute. There's + * no need to track 'top' because native call handling deals + * with that using locals, and for Ecmascript returns 'nregs' + * indicates the necessary top. + */ + duk_size_t bottom_byteoff; + + /* Return value when returning to this activation (points to caller + * reg, not callee reg); offset is absolute (only set if activation is + * not topmost). + * + * Note: bottom_byteoff is always set, while retval_byteoff is only + * applicable for activations below the topmost one. Currently + * retval_byteoff for the topmost activation is considered garbage + * (and it not initialized on entry or cleared on return; may contain + * previous or garbage values). + */ + duk_size_t retval_byteoff; + + /* Current 'this' binding is the value just below bottom. + * Previously, 'this' binding was handled with an index to the + * (calling) valstack. This works for everything except tail + * calls, which must not "accumulate" valstack temps. + */ + + /* Value stack reserve (valstack_end) byte offset to be restored + * when returning to this activation. Only used by the bytecode + * executor. + */ + duk_size_t reserve_byteoff; + +#if defined(DUK_USE_DEBUGGER_SUPPORT) + duk_uint32_t prev_line; /* needed for stepping */ +#endif + + duk_small_uint_t flags; +}; + +struct duk_catcher { + duk_catcher *parent; /* previous (parent) catcher (or NULL if none) */ + duk_hstring *h_varname; /* borrowed reference to catch variable name (or NULL if none) */ + /* (reference is valid as long activation exists) */ + duk_instr_t *pc_base; /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */ + duk_size_t idx_base; /* idx_base and idx_base+1 get completion value and type */ + duk_uint32_t flags; /* type and control flags, label number */ + /* XXX: could pack 'flags' and 'idx_base' to same value in practice, + * on 32-bit targets this would make duk_catcher 16 bytes. + */ +}; + +struct duk_hthread { + /* Shared object part */ + duk_hobject obj; + + /* Pointer to bytecode executor's 'curr_pc' variable. Used to copy + * the current PC back into the topmost activation when activation + * state is about to change (or "syncing" is otherwise needed). This + * is rather awkward but important for performance, see execution.rst. + */ + duk_instr_t **ptr_curr_pc; + + /* Backpointers. */ + duk_heap *heap; + + /* Current strictness flag: affects API calls. */ + duk_uint8_t strict; + + /* Thread state. */ + duk_uint8_t state; + duk_uint8_t unused1; + duk_uint8_t unused2; + + /* XXX: Valstack and callstack are currently assumed to have non-NULL + * pointers. Relaxing this would not lead to big benefits (except + * perhaps for terminated threads). + */ + + /* Value stack: these are expressed as pointers for faster stack + * manipulation. [valstack,valstack_top[ is GC-reachable, + * [valstack_top,valstack_alloc_end[ is not GC-reachable but kept + * initialized as 'undefined'. [valstack,valstack_end[ is the + * guaranteed/reserved space and the valstack cannot be resized to + * a smaller size. [valstack_end,valstack_alloc_end[ is currently + * allocated slack that can be used to grow the current guaranteed + * space but may be shrunk away without notice. + * + * + * <----------------------- guaranteed ---> + * <---- slack ---> + * <--- frame ---> + * .-------------+=============+----------+--------------. + * |xxxxxxxxxxxxx|yyyyyyyyyyyyy|uuuuuuuuuu|uuuuuuuuuuuuuu| + * `-------------+=============+----------+--------------' + * + * ^ ^ ^ ^ ^ + * | | | | | + * valstack bottom top end alloc_end + * + * xxx = arbitrary values, below current frame + * yyy = arbitrary values, inside current frame + * uuu = outside active value stack, initialized to 'undefined' + */ + duk_tval *valstack; /* start of valstack allocation */ + duk_tval *valstack_end; /* end of valstack reservation/guarantee (exclusive) */ + duk_tval *valstack_alloc_end; /* end of valstack allocation */ + duk_tval *valstack_bottom; /* bottom of current frame */ + duk_tval *valstack_top; /* top of current frame (exclusive) */ + + /* Call stack, represented as a linked list starting from the current + * activation (or NULL if nothing is active). + */ + duk_activation *callstack_curr; /* current activation (or NULL if none) */ + duk_size_t callstack_top; /* number of activation records in callstack (0 if none) */ + duk_size_t callstack_preventcount; /* number of activation records in callstack preventing a yield */ + + /* Yield/resume book-keeping. */ + duk_hthread *resumer; /* who resumed us (if any) */ + + /* Current compiler state (if any), used for augmenting SyntaxErrors. */ + duk_compiler_ctx *compile_ctx; + +#if defined(DUK_USE_INTERRUPT_COUNTER) + /* Interrupt counter for triggering a slow path check for execution + * timeout, debugger interaction such as breakpoints, etc. The value + * is valid for the current running thread, and both the init and + * counter values are copied whenever a thread switch occurs. It's + * important for the counter to be conveniently accessible for the + * bytecode executor inner loop for performance reasons. + */ + duk_int_t interrupt_counter; /* countdown state */ + duk_int_t interrupt_init; /* start value for current countdown */ +#endif + + /* Builtin-objects; may or may not be shared with other threads, + * threads existing in different "compartments" will have different + * built-ins. Must be stored on a per-thread basis because there + * is no intermediate structure for a thread group / compartment. + * This takes quite a lot of space, currently 43x4 = 172 bytes on + * 32-bit platforms. + * + * In some cases the builtins array could be ROM based, but it's + * sometimes edited (e.g. for sandboxing) so it's better to keep + * this array in RAM. + */ + duk_hobject *builtins[DUK_NUM_BUILTINS]; + + /* Convenience copies from heap/vm for faster access. */ +#if defined(DUK_USE_ROM_STRINGS) + /* No field needed when strings are in ROM. */ +#else +#if defined(DUK_USE_HEAPPTR16) + duk_uint16_t *strs16; +#else + duk_hstring **strs; +#endif +#endif +}; + +/* + * Prototypes + */ + +DUK_INTERNAL_DECL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to); +DUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr); +DUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr); +DUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr); + +DUK_INTERNAL_DECL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act); +DUK_INTERNAL_DECL void duk_hthread_activation_unwind_norz(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr); +DUK_INTERNAL_DECL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level); + +DUK_INTERNAL_DECL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat); +DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act); +DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act); + +#if defined(DUK_USE_FINALIZER_TORTURE) +DUK_INTERNAL_DECL void duk_hthread_valstack_torture_realloc(duk_hthread *thr); +#endif + +DUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud); /* indirect allocs */ + +#if defined(DUK_USE_DEBUGGER_SUPPORT) +DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act); +#endif +DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act); +DUK_INTERNAL_DECL void duk_hthread_sync_currpc(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr); + +#endif /* DUK_HTHREAD_H_INCLUDED */ +/* #include duk_harray.h */ +#line 1 "duk_harray.h" +/* + * Array object representation, used for actual Array instances. + * + * All objects with the exotic array behavior (which must coincide with having + * internal class array) MUST be duk_harrays. No other object can be a + * duk_harray. However, duk_harrays may not always have an array part. + */ + +#if !defined(DUK_HARRAY_H_INCLUDED) +#define DUK_HARRAY_H_INCLUDED + +#define DUK_ASSERT_HARRAY_VALID(h) do { \ + DUK_ASSERT((h) != NULL); \ + DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) (h))); \ + DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY((duk_hobject *) (h))); \ + } while (0) + +#define DUK_HARRAY_LENGTH_WRITABLE(h) (!(h)->length_nonwritable) +#define DUK_HARRAY_LENGTH_NONWRITABLE(h) ((h)->length_nonwritable) +#define DUK_HARRAY_SET_LENGTH_WRITABLE(h) do { (h)->length_nonwritable = 0; } while (0) +#define DUK_HARRAY_SET_LENGTH_NONWRITABLE(h) do { (h)->length_nonwritable = 1; } while (0) + +struct duk_harray { + /* Shared object part. */ + duk_hobject obj; + + /* Array .length. + * + * At present Array .length may be smaller, equal, or even larger + * than the allocated underlying array part. Fast path code must + * always take this into account carefully. + */ + duk_uint32_t length; + + /* Array .length property attributes. The property is always + * non-enumerable and non-configurable. It's initially writable + * but per Object.defineProperty() rules it can be made non-writable + * even if it is non-configurable. Thus we need to track the + * writability explicitly. + * + * XXX: this field to be eliminated and moved into duk_hobject + * flags field to save space. + */ + duk_bool_t length_nonwritable; +}; + +#endif /* DUK_HARRAY_H_INCLUDED */ +/* #include duk_henv.h */ +#line 1 "duk_henv.h" +/* + * Environment object representation. + */ + +#if !defined(DUK_HENV_H_INCLUDED) +#define DUK_HENV_H_INCLUDED + +#define DUK_ASSERT_HDECENV_VALID(h) do { \ + DUK_ASSERT((h) != NULL); \ + DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) (h))); \ + DUK_ASSERT((h)->thread == NULL || (h)->varmap != NULL); \ + } while (0) + +#define DUK_ASSERT_HOBJENV_VALID(h) do { \ + DUK_ASSERT((h) != NULL); \ + DUK_ASSERT(DUK_HOBJECT_IS_OBJENV((duk_hobject *) (h))); \ + DUK_ASSERT((h)->target != NULL); \ + DUK_ASSERT((h)->has_this == 0 || (h)->has_this == 1); \ + } while (0) + +struct duk_hdecenv { + /* Shared object part. */ + duk_hobject obj; + + /* These control variables provide enough information to access live + * variables for a closure that is still open. If thread == NULL, + * the record is closed and the identifiers are in the property table. + */ + duk_hthread *thread; + duk_hobject *varmap; + duk_size_t regbase_byteoff; +}; + +struct duk_hobjenv { + /* Shared object part. */ + duk_hobject obj; + + /* Target object and 'this' binding for object binding. */ + duk_hobject *target; + + /* The 'target' object is used as a this binding in only some object + * environments. For example, the global environment does not provide + * a this binding, but a with statement does. + */ + duk_bool_t has_this; +}; + +#endif /* DUK_HENV_H_INCLUDED */ +/* #include duk_hbuffer.h */ +#line 1 "duk_hbuffer.h" +/* + * Heap buffer representation. + * + * Heap allocated user data buffer which is either: + * + * 1. A fixed size buffer (data follows header statically) + * 2. A dynamic size buffer (data pointer follows header) + * + * The data pointer for a variable size buffer of zero size may be NULL. + */ + +#if !defined(DUK_HBUFFER_H_INCLUDED) +#define DUK_HBUFFER_H_INCLUDED + +/* + * Flags + * + * Fixed buffer: 0 + * Dynamic buffer: DUK_HBUFFER_FLAG_DYNAMIC + * External buffer: DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL + */ + +#define DUK_HBUFFER_FLAG_DYNAMIC DUK_HEAPHDR_USER_FLAG(0) /* buffer is behind a pointer, dynamic or external */ +#define DUK_HBUFFER_FLAG_EXTERNAL DUK_HEAPHDR_USER_FLAG(1) /* buffer pointer is to an externally allocated buffer */ + +#define DUK_HBUFFER_HAS_DYNAMIC(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC) +#define DUK_HBUFFER_HAS_EXTERNAL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL) + +#define DUK_HBUFFER_SET_DYNAMIC(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC) +#define DUK_HBUFFER_SET_EXTERNAL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL) + +#define DUK_HBUFFER_CLEAR_DYNAMIC(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC) +#define DUK_HBUFFER_CLEAR_EXTERNAL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL) + +/* + * Misc defines + */ + +/* Impose a maximum buffer length for now. Restricted artificially to + * ensure resize computations or adding a heap header length won't + * overflow size_t and that a signed duk_int_t can hold a buffer + * length. The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN. + */ + +#if defined(DUK_USE_BUFLEN16) +#define DUK_HBUFFER_MAX_BYTELEN (0x0000ffffUL) +#else +/* Intentionally not 0x7fffffffUL; at least JSON code expects that + * 2*len + 2 fits in 32 bits. + */ +#define DUK_HBUFFER_MAX_BYTELEN (0x7ffffffeUL) +#endif + +/* + * Field access + */ + +#if defined(DUK_USE_BUFLEN16) +/* size stored in duk_heaphdr unused flag bits */ +#define DUK_HBUFFER_GET_SIZE(x) ((x)->hdr.h_flags >> 16) +#define DUK_HBUFFER_SET_SIZE(x,v) do { \ + duk_size_t duk__v; \ + duk__v = (v); \ + DUK_ASSERT(duk__v <= 0xffffUL); \ + (x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | (((duk_uint32_t) duk__v) << 16); \ + } while (0) +#define DUK_HBUFFER_ADD_SIZE(x,dv) do { \ + (x)->hdr.h_flags += ((dv) << 16); \ + } while (0) +#define DUK_HBUFFER_SUB_SIZE(x,dv) do { \ + (x)->hdr.h_flags -= ((dv) << 16); \ + } while (0) +#else +#define DUK_HBUFFER_GET_SIZE(x) (((duk_hbuffer *) (x))->size) +#define DUK_HBUFFER_SET_SIZE(x,v) do { \ + ((duk_hbuffer *) (x))->size = (v); \ + } while (0) +#define DUK_HBUFFER_ADD_SIZE(x,dv) do { \ + (x)->size += (dv); \ + } while (0) +#define DUK_HBUFFER_SUB_SIZE(x,dv) do { \ + (x)->size -= (dv); \ + } while (0) +#endif + +#define DUK_HBUFFER_FIXED_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x)) +#define DUK_HBUFFER_FIXED_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x)) + +#define DUK_HBUFFER_DYNAMIC_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x)) +#define DUK_HBUFFER_DYNAMIC_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v)) +#define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv) DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv)) +#define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv) DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv)) + +#define DUK_HBUFFER_EXTERNAL_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x)) +#define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v)) + +#define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x) ((duk_uint8_t *) (((duk_hbuffer_fixed *) (x)) + 1)) + +#if defined(DUK_USE_HEAPPTR16) +#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \ + ((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16)) +#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v) do { \ + ((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ + } while (0) +#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x) do { \ + ((duk_heaphdr *) (x))->h_extra16 = 0; /* assume 0 <=> NULL */ \ + } while (0) +#else +#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) ((x)->curr_alloc) +#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v) do { \ + (x)->curr_alloc = (void *) (v); \ + } while (0) +#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x) do { \ + (x)->curr_alloc = (void *) NULL; \ + } while (0) +#endif + +/* No pointer compression because pointer is potentially outside of + * Duktape heap. + */ +#if defined(DUK_USE_HEAPPTR16) +#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \ + ((void *) (x)->curr_alloc) +#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v) do { \ + (x)->curr_alloc = (void *) (v); \ + } while (0) +#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x) do { \ + (x)->curr_alloc = (void *) NULL; \ + } while (0) +#else +#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \ + ((void *) (x)->curr_alloc) +#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v) do { \ + (x)->curr_alloc = (void *) (v); \ + } while (0) +#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x) do { \ + (x)->curr_alloc = (void *) NULL; \ + } while (0) +#endif + +/* Get a pointer to the current buffer contents (matching current allocation + * size). May be NULL for zero size dynamic/external buffer. + */ +#if defined(DUK_USE_HEAPPTR16) +#define DUK_HBUFFER_GET_DATA_PTR(heap,x) ( \ + DUK_HBUFFER_HAS_DYNAMIC((x)) ? \ + ( \ + DUK_HBUFFER_HAS_EXTERNAL((x)) ? \ + DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \ + DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \ + ) : \ + DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \ + ) +#else +/* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external + * have the same layout so checking for fixed vs. dynamic (or external) is enough. + */ +#define DUK_HBUFFER_GET_DATA_PTR(heap,x) ( \ + DUK_HBUFFER_HAS_DYNAMIC((x)) ? \ + DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \ + DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \ + ) +#endif + +/* + * Structs + */ + +/* Shared prefix for all buffer types. */ +struct duk_hbuffer { + duk_heaphdr hdr; + + /* It's not strictly necessary to track the current size, but + * it is useful for writing robust native code. + */ + + /* Current size. */ +#if defined(DUK_USE_BUFLEN16) + /* Stored in duk_heaphdr unused flags. */ +#else + duk_size_t size; +#endif + + /* + * Data following the header depends on the DUK_HBUFFER_FLAG_DYNAMIC + * flag. + * + * If the flag is clear (the buffer is a fixed size one), the buffer + * data follows the header directly, consisting of 'size' bytes. + * + * If the flag is set, the actual buffer is allocated separately, and + * a few control fields follow the header. Specifically: + * + * - a "void *" pointing to the current allocation + * - a duk_size_t indicating the full allocated size (always >= 'size') + * + * If DUK_HBUFFER_FLAG_EXTERNAL is set, the buffer has been allocated + * by user code, so that Duktape won't be able to resize it and won't + * free it. This allows buffers to point to e.g. an externally + * allocated structure such as a frame buffer. + * + * Unlike strings, no terminator byte (NUL) is guaranteed after the + * data. This would be convenient, but would pad aligned user buffers + * unnecessarily upwards in size. For instance, if user code requested + * a 64-byte dynamic buffer, 65 bytes would actually be allocated which + * would then potentially round upwards to perhaps 68 or 72 bytes. + */ +}; + +/* Fixed buffer; data follows struct, with proper alignment guaranteed by + * struct size. + */ +#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA) +#pragma pack(push, 8) +#endif +struct duk_hbuffer_fixed { + /* A union is used here as a portable struct size / alignment trick: + * by adding a 32-bit or a 64-bit (unused) union member, the size of + * the struct is effectively forced to be a multiple of 4 or 8 bytes + * (respectively) without increasing the size of the struct unless + * necessary. + */ + union { + struct { + duk_heaphdr hdr; +#if defined(DUK_USE_BUFLEN16) + /* Stored in duk_heaphdr unused flags. */ +#else + duk_size_t size; +#endif + } s; +#if (DUK_USE_ALIGN_BY == 4) + duk_uint32_t dummy_for_align4; +#elif (DUK_USE_ALIGN_BY == 8) + duk_double_t dummy_for_align8; +#elif (DUK_USE_ALIGN_BY == 1) + /* no extra padding */ +#else +#error invalid DUK_USE_ALIGN_BY +#endif + } u; + + /* + * Data follows the struct header. The struct size is padded by the + * compiler based on the struct members. This guarantees that the + * buffer data will be aligned-by-4 but not necessarily aligned-by-8. + * + * On platforms where alignment does not matter, the struct padding + * could be removed (if there is any). On platforms where alignment + * by 8 is required, the struct size must be forced to be a multiple + * of 8 by some means. Without it, some user code may break, and also + * Duktape itself breaks (e.g. the compiler stores duk_tvals in a + * dynamic buffer). + */ +} +#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR) +__attribute__ ((aligned (8))) +#elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR) +__attribute__ ((aligned (8))) +#endif +; +#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA) +#pragma pack(pop) +#endif + +/* Dynamic buffer with 'curr_alloc' pointing to a dynamic area allocated using + * heap allocation primitives. Also used for external buffers when low memory + * options are not used. + */ +struct duk_hbuffer_dynamic { + duk_heaphdr hdr; + +#if defined(DUK_USE_BUFLEN16) + /* Stored in duk_heaphdr unused flags. */ +#else + duk_size_t size; +#endif + +#if defined(DUK_USE_HEAPPTR16) + /* Stored in duk_heaphdr h_extra16. */ +#else + void *curr_alloc; /* may be NULL if alloc_size == 0 */ +#endif + + /* + * Allocation size for 'curr_alloc' is alloc_size. There is no + * automatic NUL terminator for buffers (see above for rationale). + * + * 'curr_alloc' is explicitly allocated with heap allocation + * primitives and will thus always have alignment suitable for + * e.g. duk_tval and an IEEE double. + */ +}; + +/* External buffer with 'curr_alloc' managed by user code and pointing to an + * arbitrary address. When heap pointer compression is not used, this struct + * has the same layout as duk_hbuffer_dynamic. + */ +struct duk_hbuffer_external { + duk_heaphdr hdr; + +#if defined(DUK_USE_BUFLEN16) + /* Stored in duk_heaphdr unused flags. */ +#else + duk_size_t size; +#endif + + /* Cannot be compressed as a heap pointer because may point to + * an arbitrary address. + */ + void *curr_alloc; /* may be NULL if alloc_size == 0 */ +}; + +/* + * Prototypes + */ + +DUK_INTERNAL_DECL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata); +DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud); /* indirect allocs */ + +/* dynamic buffer ops */ +DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size); +DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf); + +#endif /* DUK_HBUFFER_H_INCLUDED */ +/* #include duk_hproxy.h */ +#line 1 "duk_hproxy.h" +/* + * Proxy object representation. + */ + +#if !defined(DUK_HPROXY_H_INCLUDED) +#define DUK_HPROXY_H_INCLUDED + +#define DUK_ASSERT_HPROXY_VALID(h) do { \ + DUK_ASSERT((h) != NULL); \ + DUK_ASSERT((h)->target != NULL); \ + DUK_ASSERT((h)->handler != NULL); \ + DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((duk_hobject *) (h))); \ + } while (0) + +struct duk_hproxy { + /* Shared object part. */ + duk_hobject obj; + + /* Proxy target object. */ + duk_hobject *target; + + /* Proxy handlers (traps). */ + duk_hobject *handler; +}; + +#endif /* DUK_HPROXY_H_INCLUDED */ +/* #include duk_heap.h */ +#line 1 "duk_heap.h" +/* + * Heap structure. + * + * Heap contains allocated heap objects, interned strings, and built-in + * strings for one or more threads. + */ + +#if !defined(DUK_HEAP_H_INCLUDED) +#define DUK_HEAP_H_INCLUDED + +/* alloc function typedefs in duktape.h */ + +/* + * Heap flags + */ + +#define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED (1U << 0) /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */ +#define DUK_HEAP_FLAG_INTERRUPT_RUNNING (1U << 1) /* executor interrupt running (used to avoid nested interrupts) */ +#define DUK_HEAP_FLAG_FINALIZER_NORESCUE (1U << 2) /* heap destruction ongoing, finalizer rescue no longer possible */ +#define DUK_HEAP_FLAG_DEBUGGER_PAUSED (1U << 3) /* debugger is paused: talk with debug client until step/resume */ + +#define DUK__HEAP_HAS_FLAGS(heap,bits) ((heap)->flags & (bits)) +#define DUK__HEAP_SET_FLAGS(heap,bits) do { \ + (heap)->flags |= (bits); \ + } while (0) +#define DUK__HEAP_CLEAR_FLAGS(heap,bits) do { \ + (heap)->flags &= ~(bits); \ + } while (0) + +#define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED) +#define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING) +#define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE) +#define DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED) + +#define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED) +#define DUK_HEAP_SET_INTERRUPT_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING) +#define DUK_HEAP_SET_FINALIZER_NORESCUE(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE) +#define DUK_HEAP_SET_DEBUGGER_PAUSED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED) + +#define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED) +#define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING) +#define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE) +#define DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED) + +/* + * Longjmp types, also double as identifying continuation type for a rethrow (in 'finally') + */ + +#define DUK_LJ_TYPE_UNKNOWN 0 /* unused */ +#define DUK_LJ_TYPE_THROW 1 /* value1 -> error object */ +#define DUK_LJ_TYPE_YIELD 2 /* value1 -> yield value, iserror -> error / normal */ +#define DUK_LJ_TYPE_RESUME 3 /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */ +#define DUK_LJ_TYPE_BREAK 4 /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */ +#define DUK_LJ_TYPE_CONTINUE 5 /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */ +#define DUK_LJ_TYPE_RETURN 6 /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */ +#define DUK_LJ_TYPE_NORMAL 7 /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */ + +/* + * Mark-and-sweep flags + * + * These are separate from heap level flags now but could be merged. + * The heap structure only contains a 'base mark-and-sweep flags' + * field and the GC caller can impose further flags. + */ + +/* Emergency mark-and-sweep: try extra hard, even at the cost of + * performance. + */ +#define DUK_MS_FLAG_EMERGENCY (1U << 0) + +/* Voluntary mark-and-sweep: triggered periodically. */ +#define DUK_MS_FLAG_VOLUNTARY (1U << 1) + +/* Postpone rescue decisions for reachable objects with FINALIZED set. + * Used during finalize_list processing to avoid incorrect rescue + * decisions due to finalize_list being a reachability root. + */ +#define DUK_MS_FLAG_POSTPONE_RESCUE (1U << 2) + +/* Don't compact objects; needed during object property table resize + * to prevent a recursive resize. It would suffice to protect only the + * current object being resized, but this is not yet implemented. + */ +#define DUK_MS_FLAG_NO_OBJECT_COMPACTION (1U << 3) + +/* + * Thread switching + * + * To switch heap->curr_thread, use the macro below so that interrupt counters + * get updated correctly. The macro allows a NULL target thread because that + * happens e.g. in call handling. + */ + +#if defined(DUK_USE_INTERRUPT_COUNTER) +#define DUK_HEAP_SWITCH_THREAD(heap,newthr) duk_heap_switch_thread((heap), (newthr)) +#else +#define DUK_HEAP_SWITCH_THREAD(heap,newthr) do { \ + (heap)->curr_thread = (newthr); \ + } while (0) +#endif + +/* + * Stats + */ + +#if defined(DUK_USE_DEBUG) +#define DUK_STATS_INC(heap,fieldname) do { \ + (heap)->fieldname += 1; \ + } while (0) +#else +#define DUK_STATS_INC(heap,fieldname) do {} while (0) +#endif + +/* + * Other heap related defines + */ + +/* Mark-and-sweep interval is relative to combined count of objects and + * strings kept in the heap during the latest mark-and-sweep pass. + * Fixed point .8 multiplier and .0 adder. Trigger count (interval) is + * decreased by each (re)allocation attempt (regardless of size), and each + * refzero processed object. + * + * 'SKIP' indicates how many (re)allocations to wait until a retry if + * GC is skipped because there is no thread do it with yet (happens + * only during init phases). + */ +#if defined(DUK_USE_REFERENCE_COUNTING) +#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 12800L /* 50x heap size */ +#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L +#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L +#else +#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 256L /* 1x heap size */ +#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L +#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L +#endif + +/* GC torture. */ +#if defined(DUK_USE_GC_TORTURE) +#define DUK_GC_TORTURE(heap) do { duk_heap_mark_and_sweep((heap), 0); } while (0) +#else +#define DUK_GC_TORTURE(heap) do { } while (0) +#endif + +/* Stringcache is used for speeding up char-offset-to-byte-offset + * translations for non-ASCII strings. + */ +#define DUK_HEAP_STRCACHE_SIZE 4 +#define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT 16 /* strings up to the this length are not cached */ + +/* Some list management macros. */ +#define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr) duk_heap_insert_into_heap_allocated((heap), (hdr)) +#if defined(DUK_USE_REFERENCE_COUNTING) +#define DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap,hdr) duk_heap_remove_from_heap_allocated((heap), (hdr)) +#endif +#if defined(DUK_USE_FINALIZER_SUPPORT) +#define DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap,hdr) duk_heap_insert_into_finalize_list((heap), (hdr)) +#define DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap,hdr) duk_heap_remove_from_finalize_list((heap), (hdr)) +#endif + +/* + * Built-in strings + */ + +/* heap string indices are autogenerated in duk_strings.h */