Browse Source

Refactor error message handling further

pull/441/head
Sami Vaarala 9 years ago
parent
commit
041ed4f67b
  1. 39
      src/duk_api_internal.h
  2. 2
      src/duk_api_public.h.in
  3. 266
      src/duk_api_stack.c
  4. 2
      src/duk_bi_regexp.c
  5. 2
      src/duk_regexp_executor.c

39
src/duk_api_internal.h

@ -28,6 +28,8 @@ duk_bool_t duk_valstack_resize_raw(duk_context *ctx,
duk_size_t min_new_size,
duk_small_uint_t flags);
DUK_INTERNAL_DECL const char *duk_get_type_name(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL duk_tval *duk_get_tval(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL duk_tval *duk_require_tval(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL void duk_push_tval(duk_context *ctx, duk_tval *tv);
@ -69,11 +71,6 @@ DUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_context *ctx);
#define duk_push_size_t(ctx,val) \
duk_push_uint((ctx), (duk_uint_t) (val)) /* XXX: assumed to fit for now */
/* internal helper for looking up a tagged type */
#define DUK_GETTAGGED_FLAG_ALLOW_NULL (1L << 24)
#define DUK_GETTAGGED_FLAG_CHECK_CLASS (1L << 25)
#define DUK_GETTAGGED_CLASS_SHIFT 16
DUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL duk_hobject *duk_get_hobject(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL duk_hbuffer *duk_get_hbuffer(duk_context *ctx, duk_idx_t index);
@ -81,30 +78,7 @@ DUK_INTERNAL_DECL duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t index
DUK_INTERNAL_DECL duk_hcompiledfunction *duk_get_hcompiledfunction(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL duk_hnativefunction *duk_get_hnativefunction(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL duk_heaphdr *duk_get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t flags_and_tag, const char *error_format_string);
/* FIXME: "%s required..." and convert tag into a name? */
#if defined(DUK_USE_VERBOSE_ERRORS)
#if defined(DUK_USE_PARANOID_ERRORS)
#define DUK_GET_TAGGED_HEAPHDR_RAW(ctx,index,flags_and_tag,expectname,lowmemstr) \
duk_get_tagged_heaphdr_raw((ctx), (index), (flags_and_tag), \
expectname " required (stack index %ld)")
#else
#define DUK_GET_TAGGED_HEAPHDR_RAW(ctx,index,flags_and_tag,expectname,lowmemstr) \
duk_get_tagged_heaphdr_raw((ctx), (index), (flags_and_tag), \
expectname " required, found %s (stack index %ld)")
#endif
#else
#define DUK_GET_TAGGED_HEAPHDR_RAW(ctx,index,flags_and_tag,expectname,lowmemstr) \
duk_get_tagged_heaphdr_raw((ctx), (index), (flags_and_tag), (lowmemstr))
#endif
/* FIXME: unnecessary arguments, we allow NULL here so error is never thrown. */
#define duk_get_hobject_with_class(ctx,index,classnum) \
((duk_hobject *) DUK_GET_TAGGED_HEAPHDR_RAW((ctx), (index), \
DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL | \
DUK_GETTAGGED_FLAG_CHECK_CLASS | ((classnum) << DUK_GETTAGGED_CLASS_SHIFT), \
"object", DUK_STR_NOT_OBJECT))
DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum);
#if 0 /* This would be pointless: unexpected type and lightfunc would both return NULL */
DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_or_lfunc(duk_context *ctx, duk_idx_t index);
@ -136,11 +110,7 @@ DUK_INTERNAL_DECL duk_hthread *duk_require_hthread(duk_context *ctx, duk_idx_t i
DUK_INTERNAL_DECL duk_hcompiledfunction *duk_require_hcompiledfunction(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL duk_hnativefunction *duk_require_hnativefunction(duk_context *ctx, duk_idx_t index);
#define duk_require_hobject_with_class(ctx,index,classnum,expectname,lowmemstr) \
((duk_hobject *) DUK_GET_TAGGED_HEAPHDR_RAW((ctx), (index), \
DUK_TAG_OBJECT | \
DUK_GETTAGGED_FLAG_CHECK_CLASS | ((classnum) << DUK_GETTAGGED_CLASS_SHIFT), \
expectname, (lowmemstr)))
DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum);
DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_or_lfunc(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index);
@ -168,6 +138,7 @@ DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_context *ctx, duk_tval *tv);
DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_context *ctx, duk_tval *tv);
DUK_INTERNAL_DECL duk_hbufferobject *duk_push_bufferobject_raw(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
DUK_INTERNAL_DECL const char *duk_push_string_readable(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL const char *duk_push_string_tval_readable(duk_context *ctx, duk_tval *tv);
DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx); /* [] -> [val] */

2
src/duk_api_public.h.in

@ -117,6 +117,7 @@ struct duk_number_list_entry {
#define DUK_API_ENTRY_STACK 64
/* Value types, used by e.g. duk_get_type() */
#define DUK_TYPE_MIN 0
#define DUK_TYPE_NONE 0 /* no value, e.g. invalid index */
#define DUK_TYPE_UNDEFINED 1 /* Ecmascript undefined */
#define DUK_TYPE_NULL 2 /* Ecmascript null */
@ -127,6 +128,7 @@ struct duk_number_list_entry {
#define DUK_TYPE_BUFFER 7 /* fixed or dynamic, garbage collected byte buffer */
#define DUK_TYPE_POINTER 8 /* raw void pointer */
#define DUK_TYPE_LIGHTFUNC 9 /* lightweight function pointer */
#define DUK_TYPE_MAX 9
/* Value mask types, used by e.g. duk_get_type_mask() */
#define DUK_TYPE_MASK_NONE (1 << DUK_TYPE_NONE)

266
src/duk_api_stack.c

@ -39,7 +39,7 @@ DUK_EXTERNAL duk_int_t duk_api_global_line = 0;
} while (0)
#else
#define DUK__CHECK_SPACE() do { \
if (thr->valstack_top >= thr->valstack_end) { \
if (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \
DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK); \
} \
} while (0)
@ -47,22 +47,40 @@ DUK_EXTERNAL duk_int_t duk_api_global_line = 0;
#if defined(DUK_USE_VERBOSE_ERRORS)
#if defined(DUK_USE_PARANOID_ERRORS)
#define DUK__REQUIRE_ERROR(thr,index,tvptr,expectname,lowmemstr) do { \
DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "%s required (stack index %ld)", (expectname), (long) (index)); \
#define DUK__REQUIRE_ERROR_TVAL(thr,index,tvptr,expectname,lowmemstr) do { \
duk_hthread *duk__thr; duk_idx_t duk__index; \
duk__thr = (thr); duk__index = (index); \
DUK_ERROR(duk__thr, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)", \
(expectname), duk_get_type_name((duk_context *) duk__thr, duk__index), (long) duk__index); \
} while (0)
#define DUK__REQUIRE_ERROR_INDEX(thr,index,expectname,lowmemstr) do { \
duk_hthread *duk__thr; duk_idx_t duk__index; \
duk__thr = (thr); duk__index = (index); \
DUK_ERROR(duk__thr, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)", \
(expectname), duk_get_type_name((duk_context *) duk__thr, duk__index), (long) duk__index); \
} while (0)
#else
#define DUK__REQUIRE_ERROR(thr,index,tvptr,expectname,lowmemstr) do { \
duk_tval *tv__ptr; \
tv__ptr = (tvptr); \
DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)", \
(expectname), duk_push_string_tval_readable((duk_context *) (thr), tv__ptr), (long) index); \
#define DUK__REQUIRE_ERROR_TVAL(thr,index,tvptr,expectname,lowmemstr) do { \
duk_hthread *duk__thr; duk_idx_t duk__index; duk_tval *duk__tvptr; \
duk__thr = (thr); duk__index = (index); duk__tvptr = (tvptr); \
DUK_ERROR(duk__thr, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)", \
(expectname), duk_push_string_tval_readable((duk_context *) duk__thr, duk__tvptr), (long) duk__index); \
} while (0)
#define DUK__REQUIRE_ERROR_INDEX(thr,index,expectname,lowmemstr) do { \
duk_hthread *duk__thr; duk_idx_t duk__index; \
duk__thr = (thr); duk__index = (index); \
DUK_ERROR(duk__thr, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)", \
(expectname), duk_push_string_readable((duk_context *) duk__thr, duk__index), (long) duk__index); \
} while (0)
#endif
#define DUK__INDEX_ERROR(thr,index) do { \
DUK_ERROR(thr, DUK_ERR_API_ERROR, "invalid stack index %ld", (long) (index)); \
} while (0)
#else
#define DUK__REQUIRE_ERROR(thr,index,tvptr,expectname,lowmemstr) do { \
#define DUK__REQUIRE_ERROR_TVAL(thr,index,tvptr,expectname,lowmemstr) do { \
DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, (lowmemstr)); \
} while (0)
#define DUK__REQUIRE_ERROR_INDEX(thr,index,expectname,lowmemstr) do { \
DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, (lowmemstr)); \
} while (0)
#define DUK__INDEX_ERROR(thr,index) do { \
@ -70,6 +88,8 @@ DUK_EXTERNAL duk_int_t duk_api_global_line = 0;
} while (0)
#endif
DUK_LOCAL_DECL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t tag);
DUK_LOCAL duk_int_t duk__api_coerce_d2i(duk_context *ctx, duk_idx_t index, duk_bool_t require) {
duk_hthread *thr;
duk_tval *tv;
@ -131,7 +151,7 @@ DUK_LOCAL duk_int_t duk__api_coerce_d2i(duk_context *ctx, duk_idx_t index, duk_b
error_notnumber:
if (require) {
DUK__REQUIRE_ERROR(thr, index, tv, "number", DUK_STR_NOT_NUMBER);
DUK__REQUIRE_ERROR_TVAL(thr, index, tv, "number", DUK_STR_NOT_NUMBER);
/* not reachable */
}
return 0;
@ -188,7 +208,7 @@ DUK_LOCAL duk_uint_t duk__api_coerce_d2ui(duk_context *ctx, duk_idx_t index, duk
error_notnumber:
if (require) {
DUK__REQUIRE_ERROR(thr, index, tv, "number", DUK_STR_NOT_NUMBER);
DUK__REQUIRE_ERROR_TVAL(thr, index, tv, "number", DUK_STR_NOT_NUMBER);
/* not reachable */
}
return 0;
@ -1093,7 +1113,7 @@ DUK_EXTERNAL void duk_require_undefined(duk_context *ctx, duk_idx_t index) {
if (tv && DUK_TVAL_IS_UNDEFINED(tv)) {
return;
}
DUK__REQUIRE_ERROR(thr, index, tv, "undefined", DUK_STR_NOT_UNDEFINED);
DUK__REQUIRE_ERROR_TVAL(thr, index, tv, "undefined", DUK_STR_NOT_UNDEFINED);
return; /* not reachable */
}
@ -1107,7 +1127,7 @@ DUK_EXTERNAL void duk_require_null(duk_context *ctx, duk_idx_t index) {
if (tv && DUK_TVAL_IS_NULL(tv)) {
return;
}
DUK__REQUIRE_ERROR(thr, index, tv, "null", DUK_STR_NOT_NULL);
DUK__REQUIRE_ERROR_TVAL(thr, index, tv, "null", DUK_STR_NOT_NULL);
return; /* not reachable */
}
@ -1138,7 +1158,7 @@ DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_context *ctx, duk_idx_t index) {
DUK_ASSERT(ret == 0 || ret == 1);
return ret;
}
DUK__REQUIRE_ERROR(thr, index, tv, "boolean", DUK_STR_NOT_BOOLEAN);
DUK__REQUIRE_ERROR_TVAL(thr, index, tv, "boolean", DUK_STR_NOT_BOOLEAN);
return 0; /* not reachable */
}
@ -1182,7 +1202,7 @@ DUK_EXTERNAL duk_double_t duk_require_number(duk_context *ctx, duk_idx_t index)
DUK_DBLUNION_NORMALIZE_NAN_CHECK(&ret);
return ret.d;
}
DUK__REQUIRE_ERROR(thr, index, tv, "number", DUK_STR_NOT_NUMBER);
DUK__REQUIRE_ERROR_TVAL(thr, index, tv, "number", DUK_STR_NOT_NUMBER);
return DUK_DOUBLE_NAN; /* not reachable */
}
@ -1251,7 +1271,7 @@ DUK_EXTERNAL const char *duk_require_lstring(duk_context *ctx, duk_idx_t index,
if (ret) {
return ret;
}
DUK__REQUIRE_ERROR(thr, index, duk_get_tval(ctx, index), "string", DUK_STR_NOT_STRING);
DUK__REQUIRE_ERROR_INDEX(thr, index, "string", DUK_STR_NOT_STRING);
return NULL; /* not reachable */
}
@ -1295,7 +1315,7 @@ DUK_EXTERNAL void *duk_require_pointer(duk_context *ctx, duk_idx_t index) {
void *p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */
return (void *) p;
}
DUK__REQUIRE_ERROR(thr, index, tv, "pointer", DUK_STR_NOT_POINTER);
DUK__REQUIRE_ERROR_TVAL(thr, index, tv, "pointer", DUK_STR_NOT_POINTER);
return NULL; /* not reachable */
}
@ -1338,7 +1358,7 @@ DUK_LOCAL void *duk__get_buffer_helper(duk_context *ctx, duk_idx_t index, duk_si
}
if (throw_flag) {
DUK__REQUIRE_ERROR(thr, index, tv, "buffer", DUK_STR_NOT_BUFFER);
DUK__REQUIRE_ERROR_TVAL(thr, index, tv, "buffer", DUK_STR_NOT_BUFFER);
}
return NULL;
}
@ -1400,7 +1420,7 @@ DUK_LOCAL void *duk__get_buffer_data_helper(duk_context *ctx, duk_idx_t index, d
fail:
if (throw_flag) {
DUK__REQUIRE_ERROR(thr, index, tv, "buffer", DUK_STR_NOT_BUFFER);
DUK__REQUIRE_ERROR_TVAL(thr, index, tv, "buffer", DUK_STR_NOT_BUFFER);
}
return NULL;
}
@ -1413,91 +1433,68 @@ DUK_EXTERNAL void *duk_require_buffer_data(duk_context *ctx, duk_idx_t index, du
return duk__get_buffer_data_helper(ctx, index, out_size, 1 /*throw_flag*/);
}
/* Raw helper for getting a value from the stack, checking its tag, and possible its object class.
* The tag cannot be a number because numbers don't have an internal tag in the packed representation.
/* Raw helper for getting a value from the stack, checking its tag.
* The tag cannot be a number because numbers don't have an internal
* tag in the packed representation.
*/
DUK_INTERNAL duk_heaphdr *duk_get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t flags_and_tag, const char *error_format_string) {
duk_hthread *thr = (duk_hthread *) ctx;
DUK_LOCAL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t tag) {
duk_tval *tv;
duk_small_uint_t tag = flags_and_tag & 0xffffU; /* tags can be up to 16 bits */
DUK_ASSERT_CTX_VALID(ctx);
tv = duk_get_tval(ctx, index);
if (tv && (DUK_TVAL_GET_TAG(tv) == tag)) {
duk_heaphdr *ret;
/* Note: tag comparison in general doesn't work for numbers,
* but it does work for everything else (heap objects here).
*/
ret = DUK_TVAL_GET_HEAPHDR(tv);
DUK_ASSERT(ret != NULL); /* tagged null pointers should never occur */
/* If class check has been requested, tag must also be DUK_TAG_OBJECT.
* This allows us to just check the class check flag without checking
* the tag also.
*/
DUK_ASSERT((flags_and_tag & DUK_GETTAGGED_FLAG_CHECK_CLASS) == 0 ||
tag == DUK_TAG_OBJECT);
if ((flags_and_tag & DUK_GETTAGGED_FLAG_CHECK_CLASS) == 0 || /* no class check */
(duk_int_t) DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) ret) == /* or class check matches */
(duk_int_t) ((flags_and_tag >> DUK_GETTAGGED_CLASS_SHIFT) & 0xff)) {
return ret;
}
}
if (flags_and_tag & DUK_GETTAGGED_FLAG_ALLOW_NULL) {
return (duk_heaphdr *) NULL;
return ret;
}
#if defined(DUK_USE_VERBOSE_ERRORS)
#if defined(DUK_USE_PARANOID_ERRORS)
DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, error_format_string, (long) index);
#else
DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, error_format_string, duk_push_string_tval_readable(ctx, tv), (long) index);
#endif
#else
DUK_UNREF(error_format_string);
DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, error_format_string);
#endif
return NULL; /* not reachable */
return (duk_heaphdr *) NULL;
}
DUK_INTERNAL duk_hstring *duk_get_hstring(duk_context *ctx, duk_idx_t index) {
return (duk_hstring *) DUK_GET_TAGGED_HEAPHDR_RAW(ctx, index, DUK_TAG_STRING | DUK_GETTAGGED_FLAG_ALLOW_NULL,
"string", DUK_STR_NOT_STRING);
return (duk_hstring *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_STRING);
}
DUK_INTERNAL duk_hstring *duk_require_hstring(duk_context *ctx, duk_idx_t index) {
return (duk_hstring *) DUK_GET_TAGGED_HEAPHDR_RAW(ctx, index, DUK_TAG_STRING,
"string", DUK_STR_NOT_STRING);
duk_heaphdr *h;
h = duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_STRING);
if (h == NULL) {
DUK__REQUIRE_ERROR_INDEX(ctx, index, "string", DUK_STR_NOT_STRING);
}
return (duk_hstring *) h;
}
DUK_INTERNAL duk_hobject *duk_get_hobject(duk_context *ctx, duk_idx_t index) {
return (duk_hobject *) DUK_GET_TAGGED_HEAPHDR_RAW(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL,
"object", DUK_STR_NOT_OBJECT);
return (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
}
DUK_INTERNAL duk_hobject *duk_require_hobject(duk_context *ctx, duk_idx_t index) {
return (duk_hobject *) DUK_GET_TAGGED_HEAPHDR_RAW(ctx, index, DUK_TAG_OBJECT,
"object", DUK_STR_NOT_OBJECT);
duk_heaphdr *h;
h = duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
if (h == NULL) {
DUK__REQUIRE_ERROR_INDEX(ctx, index, "object", DUK_STR_NOT_OBJECT);
}
return (duk_hobject *) h;
}
DUK_INTERNAL duk_hbuffer *duk_get_hbuffer(duk_context *ctx, duk_idx_t index) {
return (duk_hbuffer *) DUK_GET_TAGGED_HEAPHDR_RAW(ctx, index, DUK_TAG_BUFFER | DUK_GETTAGGED_FLAG_ALLOW_NULL,
"buffer", DUK_STR_NOT_BUFFER);
return (duk_hbuffer *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_BUFFER);
}
DUK_INTERNAL duk_hbuffer *duk_require_hbuffer(duk_context *ctx, duk_idx_t index) {
return (duk_hbuffer *) DUK_GET_TAGGED_HEAPHDR_RAW(ctx, index, DUK_TAG_BUFFER,
"buffer", DUK_STR_NOT_BUFFER);
duk_heaphdr *h;
h = duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_BUFFER);
if (h == NULL) {
DUK__REQUIRE_ERROR_INDEX(ctx, index, "buffer", DUK_STR_NOT_BUFFER);
}
return (duk_hbuffer *) h;
}
DUK_INTERNAL duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t index) {
duk_hobject *h = (duk_hobject *) DUK_GET_TAGGED_HEAPHDR_RAW(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL,
"thread", DUK_STR_NOT_THREAD);
duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
if (h != NULL && !DUK_HOBJECT_IS_THREAD(h)) {
h = NULL;
}
@ -1506,18 +1503,15 @@ DUK_INTERNAL duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t index) {
DUK_INTERNAL duk_hthread *duk_require_hthread(duk_context *ctx, duk_idx_t index) {
duk_hthread *thr = (duk_hthread *) ctx;
duk_hobject *h = (duk_hobject *) DUK_GET_TAGGED_HEAPHDR_RAW(ctx, index, DUK_TAG_OBJECT,
"thread", DUK_STR_NOT_THREAD);
DUK_ASSERT(h != NULL);
if (!DUK_HOBJECT_IS_THREAD(h)) {
DUK__REQUIRE_ERROR(thr, index, duk_get_tval(ctx, index), "thread", DUK_STR_NOT_THREAD);
duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
if (!(h != NULL && DUK_HOBJECT_IS_THREAD(h))) {
DUK__REQUIRE_ERROR_INDEX(thr, index, "thread", DUK_STR_NOT_THREAD);
}
return (duk_hthread *) h;
}
DUK_INTERNAL duk_hcompiledfunction *duk_get_hcompiledfunction(duk_context *ctx, duk_idx_t index) {
duk_hobject *h = (duk_hobject *) DUK_GET_TAGGED_HEAPHDR_RAW(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL,
"compiledfunction", DUK_STR_NOT_COMPILEDFUNCTION);
duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
if (h != NULL && !DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
h = NULL;
}
@ -1526,18 +1520,15 @@ DUK_INTERNAL duk_hcompiledfunction *duk_get_hcompiledfunction(duk_context *ctx,
DUK_INTERNAL duk_hcompiledfunction *duk_require_hcompiledfunction(duk_context *ctx, duk_idx_t index) {
duk_hthread *thr = (duk_hthread *) ctx;
duk_hobject *h = (duk_hobject *) DUK_GET_TAGGED_HEAPHDR_RAW(ctx, index, DUK_TAG_OBJECT,
"compiledfunction", DUK_STR_NOT_COMPILEDFUNCTION);
DUK_ASSERT(h != NULL);
if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
DUK__REQUIRE_ERROR(thr, index, duk_get_tval(ctx, index), "compiledfunction", DUK_STR_NOT_COMPILEDFUNCTION);
duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
if (!(h != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(h))) {
DUK__REQUIRE_ERROR_INDEX(thr, index, "compiledfunction", DUK_STR_NOT_COMPILEDFUNCTION);
}
return (duk_hcompiledfunction *) h;
}
DUK_INTERNAL duk_hnativefunction *duk_get_hnativefunction(duk_context *ctx, duk_idx_t index) {
duk_hobject *h = (duk_hobject *) DUK_GET_TAGGED_HEAPHDR_RAW(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL,
"nativefunction", DUK_STR_NOT_NATIVEFUNCTION);
duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
if (h != NULL && !DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
h = NULL;
}
@ -1546,11 +1537,9 @@ DUK_INTERNAL duk_hnativefunction *duk_get_hnativefunction(duk_context *ctx, duk_
DUK_INTERNAL duk_hnativefunction *duk_require_hnativefunction(duk_context *ctx, duk_idx_t index) {
duk_hthread *thr = (duk_hthread *) ctx;
duk_hobject *h = (duk_hobject *) DUK_GET_TAGGED_HEAPHDR_RAW(ctx, index, DUK_TAG_OBJECT,
"nativefunction", DUK_STR_NOT_NATIVEFUNCTION);
DUK_ASSERT(h != NULL);
if (!DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
DUK__REQUIRE_ERROR(thr, index, duk_get_tval(ctx, index), "nativefunction", DUK_STR_NOT_NATIVEFUNCTION);
duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
if (!(h != NULL && DUK_HOBJECT_IS_NATIVEFUNCTION(h))) {
DUK__REQUIRE_ERROR_INDEX(thr, index, "nativefunction", DUK_STR_NOT_NATIVEFUNCTION);
}
return (duk_hnativefunction *) h;
}
@ -1589,14 +1578,14 @@ DUK_EXTERNAL duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t i
ret = duk_get_c_function(ctx, index);
if (!ret) {
DUK__REQUIRE_ERROR(thr, index, duk_get_tval(ctx, index), "nativefunction", DUK_STR_NOT_NATIVEFUNCTION);
DUK__REQUIRE_ERROR_INDEX(thr, index, "nativefunction", DUK_STR_NOT_NATIVEFUNCTION);
}
return ret;
}
DUK_EXTERNAL void duk_require_function(duk_context *ctx, duk_idx_t index) {
if (!duk_is_function(ctx, index)) {
DUK__REQUIRE_ERROR((duk_hthread *) ctx, index, duk_get_tval(ctx, index), "function", DUK_STR_NOT_FUNCTION);
DUK__REQUIRE_ERROR_INDEX((duk_hthread *) ctx, index, "function", DUK_STR_NOT_FUNCTION);
}
}
@ -1643,7 +1632,7 @@ DUK_EXTERNAL void *duk_require_heapptr(duk_context *ctx, duk_idx_t index) {
return ret;
}
DUK__REQUIRE_ERROR(thr, index, tv, "heapobject", DUK_STR_UNEXPECTED_TYPE);
DUK__REQUIRE_ERROR_TVAL(thr, index, tv, "heapobject", DUK_STR_UNEXPECTED_TYPE);
return (void *) NULL; /* not reachable */
}
@ -1693,7 +1682,7 @@ DUK_INTERNAL duk_hobject *duk_require_hobject_or_lfunc(duk_context *ctx, duk_idx
} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
return NULL;
}
DUK__REQUIRE_ERROR(thr, index, tv, "object", DUK_STR_NOT_OBJECT);
DUK__REQUIRE_ERROR_TVAL(thr, index, tv, "object", DUK_STR_NOT_OBJECT);
return NULL; /* not reachable */
}
@ -1714,10 +1703,57 @@ DUK_INTERNAL duk_hobject *duk_require_hobject_or_lfunc_coerce(duk_context *ctx,
duk_to_object(ctx, index);
return duk_require_hobject(ctx, index);
}
DUK__REQUIRE_ERROR(thr, index, tv, "object", DUK_STR_NOT_OBJECT);
DUK__REQUIRE_ERROR_TVAL(thr, index, tv, "object", DUK_STR_NOT_OBJECT);
return NULL; /* not reachable */
}
DUK_INTERNAL duk_hobject *duk_get_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum) {
duk_hobject *h;
DUK_ASSERT_CTX_VALID(ctx);
DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
if (h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) != classnum) {
h = NULL;
}
return h;
}
DUK_INTERNAL duk_hobject *duk_require_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum) {
duk_hthread *thr;
duk_hobject *h;
DUK_ASSERT_CTX_VALID(ctx);
DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
thr = (duk_hthread *) ctx;
h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
if (!(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) == classnum)) {
duk_hstring *h_class;
h_class = DUK_HTHREAD_GET_STRING(thr, DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum));
#if defined(DUK_USE_VERBOSE_ERRORS)
#if defined(DUK_USE_PARANOID_ERRORS)
DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
(const char *) DUK_HSTRING_GET_DATA(h_class),
duk_get_type_name(ctx, index),
(long) index);
#else
DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
(const char *) DUK_HSTRING_GET_DATA(h_class),
duk_push_string_readable(ctx, index),
(long) index);
#endif
#else
DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_UNEXPECTED_TYPE);
#endif
}
return h;
}
DUK_EXTERNAL duk_size_t duk_get_length(duk_context *ctx, duk_idx_t index) {
duk_tval *tv;
@ -2668,6 +2704,29 @@ DUK_EXTERNAL duk_int_t duk_get_type(duk_context *ctx, duk_idx_t index) {
DUK_UNREACHABLE();
}
DUK_LOCAL const char *duk__type_names[] = {
"none",
"undefined",
"null",
"boolean",
"number",
"string",
"object",
"buffer",
"pointer",
"lightfunc"
};
DUK_INTERNAL const char *duk_get_type_name(duk_context *ctx, duk_idx_t index) {
duk_int_t type_tag;
type_tag = duk_get_type(ctx, index);
DUK_ASSERT(type_tag >= DUK_TYPE_MIN && type_tag <= DUK_TYPE_MAX);
DUK_ASSERT(DUK_TYPE_MIN == 0 && sizeof(duk__type_names) / sizeof(const char *) == DUK_TYPE_MAX + 1);
return duk__type_names[type_tag];
}
DUK_EXTERNAL duk_bool_t duk_check_type(duk_context *ctx, duk_idx_t index, duk_int_t type) {
DUK_ASSERT_CTX_VALID(ctx);
@ -4609,7 +4668,7 @@ DUK_INTERNAL const char *duk_push_string_tval_readable(duk_context *ctx, duk_tva
DUK_UNREF(thr);
if (tv == NULL) {
duk_push_string(ctx, "[none]");
duk_push_string(ctx, "none");
} else {
switch (DUK_TVAL_GET_TAG(tv)) {
case DUK_TAG_STRING: {
@ -4629,6 +4688,15 @@ DUK_INTERNAL const char *duk_push_string_tval_readable(duk_context *ctx, duk_tva
duk_push_sprintf(ctx, "[buffer:%ld]", (long) DUK_HBUFFER_GET_SIZE(h));
break;
}
case DUK_TAG_POINTER: {
/* Surround with parentheses like in JX, ensures NULL pointer
* is distinguishable from null value ("(null)" vs "null").
*/
duk_push_tval(ctx, tv);
duk_push_sprintf(ctx, "(%s)", duk_to_string(ctx, -1));
duk_remove(ctx, -2);
break;
}
default: {
duk_push_tval(ctx, tv);
break;
@ -4639,7 +4707,13 @@ DUK_INTERNAL const char *duk_push_string_tval_readable(duk_context *ctx, duk_tva
return duk_to_string(ctx, -1);
}
DUK_INTERNAL const char *duk_push_string_readable(duk_context *ctx, duk_idx_t index) {
DUK_ASSERT_CTX_VALID(ctx);
return duk_push_string_tval_readable(ctx, duk_get_tval(ctx, index));
}
#undef DUK__CHECK_SPACE
#undef DUK__REQUIRE_ERROR
#undef DUK__REQUIRE_ERROR_TVAL
#undef DUK__REQUIRE_ERROR_INDEX
#undef DUK__PACK_ARGS
#undef DUK__READABLE_STRING_MAXCHARS

2
src/duk_bi_regexp.c

@ -10,7 +10,7 @@ DUK_LOCAL void duk__get_this_regexp(duk_context *ctx) {
duk_hobject *h;
duk_push_this(ctx);
h = duk_require_hobject_with_class(ctx, -1, DUK_HOBJECT_CLASS_REGEXP, "regexp", DUK_STR_NOT_REGEXP);
h = duk_require_hobject_with_class(ctx, -1, DUK_HOBJECT_CLASS_REGEXP);
DUK_ASSERT(h != NULL);
DUK_UNREF(h);
duk_insert(ctx, 0); /* prepend regexp to valstack 0 index */

2
src/duk_regexp_executor.c

@ -685,7 +685,7 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_
*/
/* TypeError if wrong; class check, see E5 Section 15.10.6 */
h_regexp = duk_require_hobject_with_class(ctx, -2, DUK_HOBJECT_CLASS_REGEXP, "regexp", DUK_STR_NOT_REGEXP);
h_regexp = duk_require_hobject_with_class(ctx, -2, DUK_HOBJECT_CLASS_REGEXP);
DUK_ASSERT(h_regexp != NULL);
DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_regexp) == DUK_HOBJECT_CLASS_REGEXP);
DUK_UNREF(h_regexp);

Loading…
Cancel
Save