Github User Fetcher 1.0.0
C Application with Server and GUI
Loading...
Searching...
No Matches
duk_js_ops.c File Reference
#include "duk_internal.h"

Go to the source code of this file.

Functions

DUK_INTERNAL duk_bool_t duk_js_toboolean (duk_tval *tv)
 
DUK_LOCAL duk_double_t duk__tonumber_string_raw (duk_hthread *thr)
 
DUK_INTERNAL duk_double_t duk_js_tonumber (duk_hthread *thr, duk_tval *tv)
 
DUK_INTERNAL duk_double_t duk_js_tointeger_number (duk_double_t x)
 
DUK_INTERNAL duk_double_t duk_js_tointeger (duk_hthread *thr, duk_tval *tv)
 
DUK_LOCAL duk_double_t duk__toint32_touint32_helper (duk_double_t x, duk_bool_t is_toint32)
 
DUK_INTERNAL duk_int32_t duk_js_toint32 (duk_hthread *thr, duk_tval *tv)
 
DUK_INTERNAL duk_uint32_t duk_js_touint32 (duk_hthread *thr, duk_tval *tv)
 
DUK_INTERNAL duk_uint16_t duk_js_touint16 (duk_hthread *thr, duk_tval *tv)
 
DUK_LOCAL duk_bool_t duk__js_equals_number (duk_double_t x, duk_double_t y)
 
DUK_LOCAL duk_bool_t duk__js_samevalue_number (duk_double_t x, duk_double_t y)
 
DUK_INTERNAL duk_bool_t duk_js_equals_helper (duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags)
 
DUK_INTERNAL duk_small_int_t duk_js_data_compare (const duk_uint8_t *buf1, const duk_uint8_t *buf2, duk_size_t len1, duk_size_t len2)
 
DUK_INTERNAL duk_small_int_t duk_js_string_compare (duk_hstring *h1, duk_hstring *h2)
 
DUK_INTERNAL duk_bool_t duk_js_compare_helper (duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags)
 
DUK_INTERNAL duk_bool_t duk_js_instanceof (duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y)
 
DUK_INTERNAL duk_bool_t duk_js_in (duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y)
 
DUK_INTERNAL duk_hstringduk_js_typeof (duk_hthread *thr, duk_tval *tv_x)
 
DUK_INTERNAL duk_small_int_t duk_js_to_arrayindex_raw_string (const duk_uint8_t *str, duk_uint32_t blen, duk_uarridx_t *out_idx)
 
DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string_helper (duk_hstring *h)
 

Function Documentation

◆ duk__js_equals_number()

DUK_LOCAL duk_bool_t duk__js_equals_number ( duk_double_t x,
duk_double_t y )

Definition at line 440 of file duktape-1.5.2/src-separate/duk_js_ops.c.

440 {
441#if defined(DUK_USE_PARANOID_MATH)
442 /* Straightforward algorithm, makes fewer compiler assumptions. */
445 if (cx == DUK_FP_NAN || cy == DUK_FP_NAN) {
446 return 0;
447 }
448 if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
449 return 1;
450 }
451 if (x == y) {
452 return 1;
453 }
454 return 0;
455#else /* DUK_USE_PARANOID_MATH */
456 /* Better equivalent algorithm. If the compiler is compliant, C and
457 * Ecmascript semantics are identical for this particular comparison.
458 * In particular, NaNs must never compare equal and zeroes must compare
459 * equal regardless of sign. Could also use a macro, but this inlines
460 * already nicely (no difference on gcc, for instance).
461 */
462 if (x == y) {
463 /* IEEE requires that NaNs compare false */
466 return 1;
467 } else {
468 /* IEEE requires that zeros compare the same regardless
469 * of their signed, so if both x and y are zeroes, they
470 * are caught above.
471 */
473 return 0;
474 }
475#endif /* DUK_USE_PARANOID_MATH */
476}

References DUK_ASSERT, DUK_FP_NAN, DUK_FP_ZERO, and DUK_FPCLASSIFY.

Referenced by duk_js_equals_helper().

◆ duk__js_samevalue_number()

DUK_LOCAL duk_bool_t duk__js_samevalue_number ( duk_double_t x,
duk_double_t y )

Definition at line 478 of file duktape-1.5.2/src-separate/duk_js_ops.c.

478 {
479#if defined(DUK_USE_PARANOID_MATH)
482
483 if (cx == DUK_FP_NAN && cy == DUK_FP_NAN) {
484 /* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
485 return 1;
486 }
487 if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
488 /* Note: cannot assume that a non-zero return value of signbit() would
489 * always be the same -- hence cannot (portably) use something like:
490 *
491 * signbit(x) == signbit(y)
492 */
493 duk_small_int_t sx = (DUK_SIGNBIT(x) ? 1 : 0);
494 duk_small_int_t sy = (DUK_SIGNBIT(y) ? 1 : 0);
495 return (sx == sy);
496 }
497
498 /* normal comparison; known:
499 * - both x and y are not NaNs (but one of them can be)
500 * - both x and y are not zero (but one of them can be)
501 * - x and y may be denormal or infinite
502 */
503
504 return (x == y);
505#else /* DUK_USE_PARANOID_MATH */
508
509 if (x == y) {
510 /* IEEE requires that NaNs compare false */
513
514 /* Using classification has smaller footprint than direct comparison. */
515 if (DUK_UNLIKELY(cx == DUK_FP_ZERO && cy == DUK_FP_ZERO)) {
516 /* Note: cannot assume that a non-zero return value of signbit() would
517 * always be the same -- hence cannot (portably) use something like:
518 *
519 * signbit(x) == signbit(y)
520 */
521 duk_small_int_t sx = (DUK_SIGNBIT(x) ? 1 : 0);
522 duk_small_int_t sy = (DUK_SIGNBIT(y) ? 1 : 0);
523 return (sx == sy);
524 }
525 return 1;
526 } else {
527 /* IEEE requires that zeros compare the same regardless
528 * of their signed, so if both x and y are zeroes, they
529 * are caught above.
530 */
532
533 /* Difference to non-strict/strict comparison is that NaNs compare
534 * equal and signed zero signs matter.
535 */
536 if (DUK_UNLIKELY(cx == DUK_FP_NAN && cy == DUK_FP_NAN)) {
537 /* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
538 return 1;
539 }
540 return 0;
541 }
542#endif /* DUK_USE_PARANOID_MATH */
543}

References DUK_ASSERT, DUK_FP_NAN, DUK_FP_ZERO, DUK_FPCLASSIFY, DUK_SIGNBIT, and DUK_UNLIKELY.

Referenced by duk_js_equals_helper().

◆ duk__toint32_touint32_helper()

DUK_LOCAL duk_double_t duk__toint32_touint32_helper ( duk_double_t x,
duk_bool_t is_toint32 )

Definition at line 289 of file duktape-1.5.2/src-separate/duk_js_ops.c.

289 {
292
293 if (c == DUK_FP_NAN || c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
294 return 0.0;
295 }
296
297
298 /* x = sign(x) * floor(abs(x)), i.e. truncate towards zero, keep sign */
300 x = DUK_FLOOR(DUK_FABS(x));
301 if (s) {
302 x = -x;
303 }
304
305 /* NOTE: fmod(x) result sign is same as sign of x, which
306 * differs from what Javascript wants (see Section 9.6).
307 */
308
309 x = DUK_FMOD(x, DUK_DOUBLE_2TO32); /* -> x in ]-2**32, 2**32[ */
310
311 if (x < 0.0) {
312 x += DUK_DOUBLE_2TO32;
313 }
314 /* -> x in [0, 2**32[ */
315
316 if (is_toint32) {
317 if (x >= DUK_DOUBLE_2TO31) {
318 /* x in [2**31, 2**32[ */
319
320 x -= DUK_DOUBLE_2TO32; /* -> x in [-2**31,2**31[ */
321 }
322 }
323
324 return x;
325}
CURL_EXTERN CURLMcode curl_socket_t s
Definition multi.h:318

References DUK_DOUBLE_2TO31, DUK_DOUBLE_2TO32, DUK_FABS, DUK_FLOOR, DUK_FMOD, DUK_FP_INFINITE, DUK_FP_NAN, DUK_FP_ZERO, DUK_FPCLASSIFY, DUK_SIGNBIT, and s.

Referenced by duk_js_toint32(), and duk_js_touint32().

◆ duk__tonumber_string_raw()

DUK_LOCAL duk_double_t duk__tonumber_string_raw ( duk_hthread * thr)

Definition at line 148 of file duktape-1.5.2/src-separate/duk_js_ops.c.

148 {
149 duk_context *ctx = (duk_context *) thr;
150 duk_small_uint_t s2n_flags;
151 duk_double_t d;
152
153 /* Quite lenient, e.g. allow empty as zero, but don't allow trailing
154 * garbage.
155 */
156 s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
167
168 duk_numconv_parse(ctx, 10 /*radix*/, s2n_flags);
169 d = duk_get_number(ctx, -1);
170 duk_pop(ctx);
171
172 return d;
173}
unsigned int duk_small_uint_t
#define DUK_S2N_FLAG_ALLOW_FRAC
DUK_EXTERNAL duk_double_t duk_get_number(duk_context *ctx, duk_idx_t index)
#define DUK_S2N_FLAG_ALLOW_MINUS
#define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC
#define DUK_S2N_FLAG_ALLOW_NAKED_FRAC
#define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT
#define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO
#define DUK_S2N_FLAG_ALLOW_PLUS
#define DUK_S2N_FLAG_ALLOW_INF
DUK_EXTERNAL void duk_pop(duk_context *ctx)
DUK_INTERNAL_DECL void duk_numconv_parse(duk_context *ctx, duk_small_int_t radix, duk_small_uint_t flags)
#define DUK_S2N_FLAG_TRIM_WHITE
#define DUK_S2N_FLAG_ALLOW_LEADING_ZERO
#define DUK_S2N_FLAG_ALLOW_EXP

References duk_get_number(), duk_numconv_parse(), duk_pop(), DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT, DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO, DUK_S2N_FLAG_ALLOW_EMPTY_FRAC, DUK_S2N_FLAG_ALLOW_EXP, DUK_S2N_FLAG_ALLOW_FRAC, DUK_S2N_FLAG_ALLOW_INF, DUK_S2N_FLAG_ALLOW_LEADING_ZERO, DUK_S2N_FLAG_ALLOW_MINUS, DUK_S2N_FLAG_ALLOW_NAKED_FRAC, DUK_S2N_FLAG_ALLOW_PLUS, and DUK_S2N_FLAG_TRIM_WHITE.

Referenced by duk_js_tonumber().

◆ duk_js_compare_helper()

DUK_INTERNAL duk_bool_t duk_js_compare_helper ( duk_hthread * thr,
duk_tval * tv_x,
duk_tval * tv_y,
duk_small_int_t flags )

Definition at line 845 of file duktape-1.5.2/src-separate/duk_js_ops.c.

845 {
846 duk_context *ctx = (duk_context *) thr;
847 duk_double_t d1, d2;
848 duk_small_int_t c1, c2;
849 duk_small_int_t s1, s2;
851 duk_bool_t retval;
852
853 /* Fast path for fastints */
854#if defined(DUK_USE_FASTINT)
855 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
856 duk_int64_t v1 = DUK_TVAL_GET_FASTINT(tv_x);
857 duk_int64_t v2 = DUK_TVAL_GET_FASTINT(tv_y);
858 if (v1 < v2) {
859 /* 'lt is true' */
860 retval = 1;
861 } else {
862 retval = 0;
863 }
864 if (flags & DUK_COMPARE_FLAG_NEGATE) {
865 retval ^= 1;
866 }
867 return retval;
868 }
869#endif /* DUK_USE_FASTINT */
870
871 /* Fast path for numbers (one of which may be a fastint) */
872#if 1 /* XXX: make fast paths optional for size minimization? */
873 if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
874 d1 = DUK_TVAL_GET_NUMBER(tv_x);
875 d2 = DUK_TVAL_GET_NUMBER(tv_y);
876 c1 = DUK_FPCLASSIFY(d1);
877 c2 = DUK_FPCLASSIFY(d2);
878
879 if (c1 == DUK_FP_NORMAL && c2 == DUK_FP_NORMAL) {
880 /* XXX: this is a very narrow check, and doesn't cover
881 * zeroes, subnormals, infinities, which compare normally.
882 */
883
884 if (d1 < d2) {
885 /* 'lt is true' */
886 retval = 1;
887 } else {
888 retval = 0;
889 }
890 if (flags & DUK_COMPARE_FLAG_NEGATE) {
891 retval ^= 1;
892 }
893 return retval;
894 }
895 }
896#endif
897
898 /* Slow path */
899
900 duk_push_tval(ctx, tv_x);
901 duk_push_tval(ctx, tv_y);
902
906 } else {
909 }
910
911 /* Note: reuse variables */
912 tv_x = DUK_GET_TVAL_NEGIDX(ctx, -2);
913 tv_y = DUK_GET_TVAL_NEGIDX(ctx, -1);
914
915 if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
918 DUK_ASSERT(h1 != NULL);
919 DUK_ASSERT(h2 != NULL);
920
921 rc = duk_js_string_compare(h1, h2);
922 if (rc < 0) {
923 goto lt_true;
924 } else {
925 goto lt_false;
926 }
927 } else {
928 /* Ordering should not matter (E5 Section 11.8.5, step 3.a) but
929 * preserve it just in case.
930 */
931
933 d1 = duk_to_number(ctx, -2);
934 d2 = duk_to_number(ctx, -1);
935 } else {
936 d2 = duk_to_number(ctx, -1);
937 d1 = duk_to_number(ctx, -2);
938 }
939
941 s1 = (duk_small_int_t) DUK_SIGNBIT(d1);
943 s2 = (duk_small_int_t) DUK_SIGNBIT(d2);
944
945 if (c1 == DUK_FP_NAN || c2 == DUK_FP_NAN) {
946 goto lt_undefined;
947 }
948
949 if (c1 == DUK_FP_ZERO && c2 == DUK_FP_ZERO) {
950 /* For all combinations: +0 < +0, +0 < -0, -0 < +0, -0 < -0,
951 * steps e, f, and g.
952 */
953 goto lt_false;
954 }
955
956 if (d1 == d2) {
957 goto lt_false;
958 }
959
960 if (c1 == DUK_FP_INFINITE && s1 == 0) {
961 /* x == +Infinity */
962 goto lt_false;
963 }
964
965 if (c2 == DUK_FP_INFINITE && s2 == 0) {
966 /* y == +Infinity */
967 goto lt_true;
968 }
969
970 if (c2 == DUK_FP_INFINITE && s2 != 0) {
971 /* y == -Infinity */
972 goto lt_false;
973 }
974
975 if (c1 == DUK_FP_INFINITE && s1 != 0) {
976 /* x == -Infinity */
977 goto lt_true;
978 }
979
980 if (d1 < d2) {
981 goto lt_true;
982 }
983
984 goto lt_false;
985 }
986
987 lt_undefined:
988 /* Note: undefined from Section 11.8.5 always results in false
989 * return (see e.g. Section 11.8.3) - hence special treatment here.
990 */
991 retval = 0;
992 goto cleanup;
993
994 lt_true:
995 if (flags & DUK_COMPARE_FLAG_NEGATE) {
996 retval = 0;
997 goto cleanup;
998 } else {
999 retval = 1;
1000 goto cleanup;
1001 }
1002 /* never here */
1003
1004 lt_false:
1005 if (flags & DUK_COMPARE_FLAG_NEGATE) {
1006 retval = 1;
1007 goto cleanup;
1008 } else {
1009 retval = 0;
1010 goto cleanup;
1011 }
1012 /* never here */
1013
1014 cleanup:
1015 duk_pop_2(ctx);
1016 return retval;
1017}
duk_small_int_t duk_bool_t
DUK_EXTERNAL void duk_pop_2(duk_context *ctx)
#define DUK_TVAL_IS_NUMBER(tv)
DUK_EXTERNAL void duk_to_primitive(duk_context *ctx, duk_idx_t index, duk_int_t hint)
#define DUK_COMPARE_FLAG_NEGATE
#define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST
DUK_EXTERNAL duk_double_t duk_to_number(duk_context *ctx, duk_idx_t index)
#define DUK_TVAL_GET_STRING(tv)
#define DUK_TVAL_IS_STRING(tv)
DUK_INTERNAL_DECL void duk_push_tval(duk_context *ctx, duk_tval *tv)
#define DUK_GET_TVAL_NEGIDX(ctx, idx)
#define DUK_TVAL_GET_NUMBER(tv)
DUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2)
#define NULL
Definition gmacros.h:924

References DUK_ASSERT, DUK_COMPARE_FLAG_EVAL_LEFT_FIRST, DUK_COMPARE_FLAG_NEGATE, DUK_FP_INFINITE, DUK_FP_NAN, DUK_FP_NORMAL, DUK_FP_ZERO, DUK_FPCLASSIFY, DUK_GET_TVAL_NEGIDX, DUK_HINT_NUMBER, duk_js_string_compare(), duk_pop_2(), duk_push_tval(), DUK_SIGNBIT, duk_to_number(), duk_to_primitive(), DUK_TVAL_GET_NUMBER, DUK_TVAL_GET_STRING, DUK_TVAL_IS_NUMBER, DUK_TVAL_IS_STRING, and NULL.

◆ duk_js_data_compare()

DUK_INTERNAL duk_small_int_t duk_js_data_compare ( const duk_uint8_t * buf1,
const duk_uint8_t * buf2,
duk_size_t len1,
duk_size_t len2 )

Definition at line 777 of file duktape-1.5.2/src-separate/duk_js_ops.c.

777 {
778 duk_size_t prefix_len;
780
781 prefix_len = (len1 <= len2 ? len1 : len2);
782
783 /* DUK_MEMCMP() is guaranteed to return zero (equal) for zero length
784 * inputs so no zero length check is needed.
785 */
786 rc = DUK_MEMCMP((const void *) buf1,
787 (const void *) buf2,
788 (size_t) prefix_len);
789
790 if (rc < 0) {
791 return -1;
792 } else if (rc > 0) {
793 return 1;
794 }
795
796 /* prefix matches, lengths matter now */
797 if (len1 < len2) {
798 /* e.g. "x" < "xx" */
799 return -1;
800 } else if (len1 > len2) {
801 return 1;
802 }
803
804 return 0;
805}

References DUK_MEMCMP.

Referenced by duk_js_string_compare().

◆ duk_js_equals_helper()

DUK_INTERNAL duk_bool_t duk_js_equals_helper ( duk_hthread * thr,
duk_tval * tv_x,
duk_tval * tv_y,
duk_small_int_t flags )

Definition at line 545 of file duktape-1.5.2/src-separate/duk_js_ops.c.

545 {
546 duk_context *ctx = (duk_context *) thr;
547 duk_tval *tv_tmp;
548
549 /* If flags != 0 (strict or SameValue), thr can be NULL. For loose
550 * equals comparison it must be != NULL.
551 */
552 DUK_ASSERT(flags != 0 || thr != NULL);
553
554 /*
555 * Same type?
556 *
557 * Note: since number values have no explicit tag in the 8-byte
558 * representation, need the awkward if + switch.
559 */
560
561#if defined(DUK_USE_FASTINT)
562 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
563 if (DUK_TVAL_GET_FASTINT(tv_x) == DUK_TVAL_GET_FASTINT(tv_y)) {
564 return 1;
565 } else {
566 return 0;
567 }
568 }
569 else
570#endif
571 if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
572 /* Catches both doubles and cases where only one argument is a fastint */
573 if (DUK_UNLIKELY((flags & DUK_EQUALS_FLAG_SAMEVALUE) != 0)) {
574 /* SameValue */
576 DUK_TVAL_GET_NUMBER(tv_y));
577 } else {
578 /* equals and strict equals */
580 DUK_TVAL_GET_NUMBER(tv_y));
581 }
582 } else if (DUK_TVAL_GET_TAG(tv_x) == DUK_TVAL_GET_TAG(tv_y)) {
583 switch (DUK_TVAL_GET_TAG(tv_x)) {
585 case DUK_TAG_NULL: {
586 return 1;
587 }
588 case DUK_TAG_BOOLEAN: {
589 return DUK_TVAL_GET_BOOLEAN(tv_x) == DUK_TVAL_GET_BOOLEAN(tv_y);
590 }
591 case DUK_TAG_POINTER: {
592 return DUK_TVAL_GET_POINTER(tv_x) == DUK_TVAL_GET_POINTER(tv_y);
593 }
594 case DUK_TAG_STRING:
595 case DUK_TAG_OBJECT: {
596 /* heap pointer comparison suffices */
597 return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
598 }
599 case DUK_TAG_BUFFER: {
600 if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
601 /* heap pointer comparison suffices */
602 return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
603 } else {
604 /* non-strict equality for buffers compares contents */
605 duk_hbuffer *h_x = DUK_TVAL_GET_BUFFER(tv_x);
606 duk_hbuffer *h_y = DUK_TVAL_GET_BUFFER(tv_y);
607 duk_size_t len_x = DUK_HBUFFER_GET_SIZE(h_x);
608 duk_size_t len_y = DUK_HBUFFER_GET_SIZE(h_y);
609 void *buf_x;
610 void *buf_y;
611 if (len_x != len_y) {
612 return 0;
613 }
614 buf_x = (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_x);
615 buf_y = (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_y);
616 /* if len_x == len_y == 0, buf_x and/or buf_y may
617 * be NULL, but that's OK.
618 */
619 DUK_ASSERT(len_x == len_y);
620 DUK_ASSERT(len_x == 0 || buf_x != NULL);
621 DUK_ASSERT(len_y == 0 || buf_y != NULL);
622 return (DUK_MEMCMP((const void *) buf_x, (const void *) buf_y, (size_t) len_x) == 0) ? 1 : 0;
623 }
624 }
625 case DUK_TAG_LIGHTFUNC: {
626 /* At least 'magic' has a significant impact on function
627 * identity.
628 */
629 duk_small_uint_t lf_flags_x;
630 duk_small_uint_t lf_flags_y;
631 duk_c_function func_x;
632 duk_c_function func_y;
633
634 DUK_TVAL_GET_LIGHTFUNC(tv_x, func_x, lf_flags_x);
635 DUK_TVAL_GET_LIGHTFUNC(tv_y, func_y, lf_flags_y);
636 return ((func_x == func_y) && (lf_flags_x == lf_flags_y)) ? 1 : 0;
637 }
638#if defined(DUK_USE_FASTINT)
639 case DUK_TAG_FASTINT:
640#endif
641 default: {
647 return 0;
648 }
649 }
650 }
651
652 if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
653 return 0;
654 }
655
656 DUK_ASSERT(flags == 0); /* non-strict equality from here on */
657
658 /*
659 * Types are different; various cases for non-strict comparison
660 *
661 * Since comparison is symmetric, we use a "swap trick" to reduce
662 * code size.
663 */
664
665 /* Undefined/null are considered equal (e.g. "null == undefined" -> true). */
666 if ((DUK_TVAL_IS_UNDEFINED(tv_x) && DUK_TVAL_IS_NULL(tv_y)) ||
667 (DUK_TVAL_IS_NULL(tv_x) && DUK_TVAL_IS_UNDEFINED(tv_y))) {
668 return 1;
669 }
670
671 /* Number/string-or-buffer -> coerce string to number (e.g. "'1.5' == 1.5" -> true). */
672 if (DUK_TVAL_IS_NUMBER(tv_x) && (DUK_TVAL_IS_STRING(tv_y) || DUK_TVAL_IS_BUFFER(tv_y))) {
673 /* the next 'if' is guaranteed to match after swap */
674 tv_tmp = tv_x;
675 tv_x = tv_y;
676 tv_y = tv_tmp;
677 }
678 if ((DUK_TVAL_IS_STRING(tv_x) || DUK_TVAL_IS_BUFFER(tv_x)) && DUK_TVAL_IS_NUMBER(tv_y)) {
679 /* XXX: this is possible without resorting to the value stack */
680 duk_double_t d1, d2;
681 d2 = DUK_TVAL_GET_NUMBER(tv_y);
682 duk_push_tval(ctx, tv_x);
683 duk_to_string(ctx, -1); /* buffer values are coerced first to string here */
684 duk_to_number(ctx, -1);
685 d1 = duk_require_number(ctx, -1);
686 duk_pop(ctx);
687 return duk__js_equals_number(d1, d2);
688 }
689
690 /* Buffer/string -> compare contents. */
691 if (DUK_TVAL_IS_BUFFER(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
692 tv_tmp = tv_x;
693 tv_x = tv_y;
694 tv_y = tv_tmp;
695 }
696 if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_BUFFER(tv_y)) {
697 duk_hstring *h_x = DUK_TVAL_GET_STRING(tv_x);
698 duk_hbuffer *h_y = DUK_TVAL_GET_BUFFER(tv_y);
700 duk_size_t len_y = DUK_HBUFFER_GET_SIZE(h_y);
701 const void *buf_x;
702 const void *buf_y;
703 if (len_x != len_y) {
704 return 0;
705 }
706 buf_x = (const void *) DUK_HSTRING_GET_DATA(h_x);
707 buf_y = (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_y);
708 /* if len_x == len_y == 0, buf_x and/or buf_y may
709 * be NULL, but that's OK.
710 */
711 DUK_ASSERT(len_x == len_y);
712 DUK_ASSERT(len_x == 0 || buf_x != NULL);
713 DUK_ASSERT(len_y == 0 || buf_y != NULL);
714 return (DUK_MEMCMP((const void *) buf_x, (const void *) buf_y, (size_t) len_x) == 0) ? 1 : 0;
715 }
716
717 /* Boolean/any -> coerce boolean to number and try again. If boolean is
718 * compared to a pointer, the final comparison after coercion now always
719 * yields false (as pointer vs. number compares to false), but this is
720 * not special cased.
721 */
722 if (DUK_TVAL_IS_BOOLEAN(tv_x)) {
723 tv_tmp = tv_x;
724 tv_x = tv_y;
725 tv_y = tv_tmp;
726 }
727 if (DUK_TVAL_IS_BOOLEAN(tv_y)) {
728 /* ToNumber(bool) is +1.0 or 0.0. Tagged boolean value is always 0 or 1. */
729 duk_bool_t rc;
730 DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_y) == 0 || DUK_TVAL_GET_BOOLEAN(tv_y) == 1);
731 duk_push_tval(ctx, tv_x);
733 rc = duk_js_equals_helper(thr,
734 DUK_GET_TVAL_NEGIDX(ctx, -2),
735 DUK_GET_TVAL_NEGIDX(ctx, -1),
736 0 /*flags:nonstrict*/);
737 duk_pop_2(ctx);
738 return rc;
739 }
740
741 /* String-number-buffer/object -> coerce object to primitive (apparently without hint), then try again. */
742 if ((DUK_TVAL_IS_STRING(tv_x) || DUK_TVAL_IS_NUMBER(tv_x) || DUK_TVAL_IS_BUFFER(tv_x)) &&
743 DUK_TVAL_IS_OBJECT(tv_y)) {
744 tv_tmp = tv_x;
745 tv_x = tv_y;
746 tv_y = tv_tmp;
747 }
748 if (DUK_TVAL_IS_OBJECT(tv_x) &&
749 (DUK_TVAL_IS_STRING(tv_y) || DUK_TVAL_IS_NUMBER(tv_y) || DUK_TVAL_IS_BUFFER(tv_y))) {
750 duk_bool_t rc;
751 duk_push_tval(ctx, tv_x);
752 duk_push_tval(ctx, tv_y);
753 duk_to_primitive(ctx, -2, DUK_HINT_NONE); /* apparently no hint? */
754 rc = duk_js_equals_helper(thr,
755 DUK_GET_TVAL_NEGIDX(ctx, -2),
756 DUK_GET_TVAL_NEGIDX(ctx, -1),
757 0 /*flags:nonstrict*/);
758 duk_pop_2(ctx);
759 return rc;
760 }
761
762 /* Nothing worked -> not equal. */
763 return 0;
764}
#define DUK_HSTRING_GET_DATA(x)
DUK_EXTERNAL duk_double_t duk_require_number(duk_context *ctx, duk_idx_t index)
#define DUK_TVAL_IS_NULL(tv)
#define DUK_TVAL_IS_BUFFER(tv)
#define DUK_TVAL_IS_UNDEFINED(tv)
#define DUK_EQUALS_FLAG_SAMEVALUE
#define DUK_TVAL_IS_OBJECT(tv)
#define DUK_TVAL_GET_BUFFER(tv)
#define DUK_TVAL_GET_TAG(tv)
#define DUK_TVAL_IS_UNUSED(tv)
DUK_EXTERNAL void duk_push_int(duk_context *ctx, duk_int_t val)
#define DUK_HSTRING_GET_BYTELEN(x)
#define DUK_TVAL_GET_POINTER(tv)
#define DUK_TVAL_GET_LIGHTFUNC(tv, out_fp, out_flags)
#define DUK_TVAL_GET_BOOLEAN(tv)
DUK_EXTERNAL const char * duk_to_string(duk_context *ctx, duk_idx_t index)
#define DUK_HBUFFER_GET_DATA_PTR(heap, x)
#define DUK_TVAL_GET_HEAPHDR(tv)
#define DUK_EQUALS_FLAG_STRICT
#define DUK_TVAL_IS_BOOLEAN(tv)
#define DUK_HBUFFER_GET_SIZE(x)
duk_ret_t(* duk_c_function)(duk_context *ctx)
DUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y)
DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y)
DUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags)

References duk__js_equals_number(), duk__js_samevalue_number(), DUK_ASSERT, DUK_EQUALS_FLAG_SAMEVALUE, DUK_EQUALS_FLAG_STRICT, DUK_GET_TVAL_NEGIDX, DUK_HBUFFER_GET_DATA_PTR, DUK_HBUFFER_GET_SIZE, DUK_HINT_NONE, DUK_HSTRING_GET_BYTELEN, DUK_HSTRING_GET_DATA, duk_js_equals_helper(), DUK_MEMCMP, duk_pop(), duk_pop_2(), duk_push_int(), duk_push_tval(), duk_require_number(), DUK_TAG_BOOLEAN, DUK_TAG_BUFFER, DUK_TAG_LIGHTFUNC, DUK_TAG_NULL, DUK_TAG_OBJECT, DUK_TAG_POINTER, DUK_TAG_STRING, DUK_TAG_UNDEFINED, duk_to_number(), duk_to_primitive(), duk_to_string(), DUK_TVAL_GET_BOOLEAN, DUK_TVAL_GET_BUFFER, DUK_TVAL_GET_HEAPHDR, DUK_TVAL_GET_LIGHTFUNC, DUK_TVAL_GET_NUMBER, DUK_TVAL_GET_POINTER, DUK_TVAL_GET_STRING, DUK_TVAL_GET_TAG, DUK_TVAL_IS_BOOLEAN, DUK_TVAL_IS_BUFFER, DUK_TVAL_IS_NULL, DUK_TVAL_IS_NUMBER, DUK_TVAL_IS_OBJECT, DUK_TVAL_IS_STRING, DUK_TVAL_IS_UNDEFINED, DUK_TVAL_IS_UNUSED, DUK_UNLIKELY, DUK_UNREACHABLE, duk_hthread::heap, and NULL.

Referenced by duk_js_equals_helper().

◆ duk_js_in()

DUK_INTERNAL duk_bool_t duk_js_in ( duk_hthread * thr,
duk_tval * tv_x,
duk_tval * tv_y )

Definition at line 1196 of file duktape-1.5.2/src-separate/duk_js_ops.c.

1196 {
1197 duk_context *ctx = (duk_context *) thr;
1198 duk_bool_t retval;
1199
1200 /*
1201 * Get the values onto the stack first. It would be possible to cover
1202 * some normal cases without resorting to the value stack (e.g. if
1203 * lval is already a string).
1204 */
1205
1206 /* XXX: The ES5/5.1/6 specifications require that the key in 'key in obj'
1207 * must be string coerced before the internal HasProperty() algorithm is
1208 * invoked. A fast path skipping coercion could be safely implemented for
1209 * numbers (as number-to-string coercion has no side effects). For ES6
1210 * proxy behavior, the trap 'key' argument must be in a string coerced
1211 * form (which is a shame).
1212 */
1213
1214 /* TypeError if rval is not an object (or lightfunc which should behave
1215 * like a Function instance).
1216 */
1217 duk_push_tval(ctx, tv_x);
1218 duk_push_tval(ctx, tv_y);
1220 duk_to_string(ctx, -2); /* coerce lval with ToString() */
1221
1222 retval = duk_hobject_hasprop(thr,
1223 DUK_GET_TVAL_NEGIDX(ctx, -1),
1224 DUK_GET_TVAL_NEGIDX(ctx, -2));
1225
1226 duk_pop_2(ctx);
1227 return retval;
1228}
DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key)
#define DUK_TYPE_MASK_OBJECT
#define DUK_TYPE_MASK_LIGHTFUNC
#define duk_require_type_mask(ctx, index, mask)

References DUK_GET_TVAL_NEGIDX, duk_hobject_hasprop(), duk_pop_2(), duk_push_tval(), duk_require_type_mask, duk_to_string(), DUK_TYPE_MASK_LIGHTFUNC, and DUK_TYPE_MASK_OBJECT.

◆ duk_js_instanceof()

DUK_INTERNAL duk_bool_t duk_js_instanceof ( duk_hthread * thr,
duk_tval * tv_x,
duk_tval * tv_y )

Definition at line 1039 of file duktape-1.5.2/src-separate/duk_js_ops.c.

1039 {
1040 duk_context *ctx = (duk_context *) thr;
1041 duk_hobject *func;
1042 duk_hobject *val;
1044 duk_uint_t sanity;
1045
1046 /*
1047 * Get the values onto the stack first. It would be possible to cover
1048 * some normal cases without resorting to the value stack.
1049 *
1050 * The right hand side could be a light function (as they generally
1051 * behave like objects). Light functions never have a 'prototype'
1052 * property so E5.1 Section 15.3.5.3 step 3 always throws a TypeError.
1053 * Using duk_require_hobject() is thus correct (except for error msg).
1054 */
1055
1056 duk_push_tval(ctx, tv_x);
1057 duk_push_tval(ctx, tv_y);
1058 func = duk_require_hobject(ctx, -1);
1059
1060 /*
1061 * For bound objects, [[HasInstance]] just calls the target function
1062 * [[HasInstance]]. If that is again a bound object, repeat until
1063 * we find a non-bound Function object.
1064 */
1065
1066 /* XXX: this bound function resolution also happens elsewhere,
1067 * move into a shared helper.
1068 */
1069
1071 do {
1072 /* check func supports [[HasInstance]] (this is checked for every function
1073 * in the bound chain, including the final one)
1074 */
1075
1076 if (!DUK_HOBJECT_IS_CALLABLE(func)) {
1077 /*
1078 * Note: of native Ecmascript objects, only Function instances
1079 * have a [[HasInstance]] internal property. Custom objects might
1080 * also have it, but not in current implementation.
1081 *
1082 * XXX: add a separate flag, DUK_HOBJECT_FLAG_ALLOW_INSTANCEOF?
1083 */
1084 DUK_ERROR_TYPE(thr, "invalid instanceof rval");
1085 }
1086
1087 if (!DUK_HOBJECT_HAS_BOUND(func)) {
1088 break;
1089 }
1090
1091 /* [ ... lval rval ] */
1092
1093 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TARGET); /* -> [ ... lval rval new_rval ] */
1094 duk_replace(ctx, -1); /* -> [ ... lval new_rval ] */
1095 func = duk_require_hobject(ctx, -1);
1096
1097 /* func support for [[HasInstance]] checked in the beginning of the loop */
1098 } while (--sanity > 0);
1099
1100 if (sanity == 0) {
1102 }
1103
1104 /*
1105 * 'func' is now a non-bound object which supports [[HasInstance]]
1106 * (which here just means DUK_HOBJECT_FLAG_CALLABLE). Move on
1107 * to execute E5 Section 15.3.5.3.
1108 */
1109
1112
1113 /* [ ... lval rval(func) ] */
1114
1115 /* Handle lightfuncs through object coercion for now. */
1116 /* XXX: direct implementation */
1117 val = duk_get_hobject_or_lfunc_coerce(ctx, -2);
1118 if (!val) {
1119 goto pop_and_false;
1120 }
1121
1122 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_PROTOTYPE); /* -> [ ... lval rval rval.prototype ] */
1123 proto = duk_require_hobject(ctx, -1);
1124 duk_pop(ctx); /* -> [ ... lval rval ] */
1125
1126 DUK_ASSERT(val != NULL);
1127
1128#if defined(DUK_USE_ES6_PROXY)
1129 val = duk_hobject_resolve_proxy_target(thr, val);
1130 DUK_ASSERT(val != NULL);
1131#endif
1132
1134 do {
1135 /*
1136 * Note: prototype chain is followed BEFORE first comparison. This
1137 * means that the instanceof lval is never itself compared to the
1138 * rval.prototype property. This is apparently intentional, see E5
1139 * Section 15.3.5.3, step 4.a.
1140 *
1141 * Also note:
1142 *
1143 * js> (function() {}) instanceof Function
1144 * true
1145 * js> Function instanceof Function
1146 * true
1147 *
1148 * For the latter, h_proto will be Function.prototype, which is the
1149 * built-in Function prototype. Because Function.[[Prototype]] is
1150 * also the built-in Function prototype, the result is true.
1151 */
1152
1153 DUK_ASSERT(val != NULL);
1154 val = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val);
1155
1156 if (!val) {
1157 goto pop_and_false;
1158 }
1159
1160 DUK_ASSERT(val != NULL);
1161#if defined(DUK_USE_ES6_PROXY)
1162 val = duk_hobject_resolve_proxy_target(thr, val);
1163#endif
1164
1165 if (val == proto) {
1166 goto pop_and_true;
1167 }
1168
1169 /* follow prototype chain */
1170 } while (--sanity > 0);
1171
1172 if (sanity == 0) {
1174 }
1176
1177 pop_and_false:
1178 duk_pop_2(ctx);
1179 return 0;
1180
1181 pop_and_true:
1182 duk_pop_2(ctx);
1183 return 1;
1184}
const char * proto
Definition civetweb.c:18378
duk_uint_fast32_t duk_uint_t
#define DUK_ERROR_RANGE(thr, msg)
#define DUK_HOBJECT_GET_PROTOTYPE(heap, h)
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject(duk_context *ctx, duk_idx_t index)
#define DUK_ERROR_TYPE(thr, msg)
#define DUK_HOBJECT_HAS_BOUND(h)
DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx)
DUK_INTERNAL_DECL duk_hobject * duk_get_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_IS_CALLABLE(h)
DUK_EXTERNAL void duk_replace(duk_context *ctx, duk_idx_t to_index)
DUK_INTERNAL_DECL duk_hobject * duk_hobject_resolve_proxy_target(duk_hthread *thr, duk_hobject *obj)
#define DUK_STR_PROTOTYPE_CHAIN_LIMIT
#define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY
#define DUK_STRIDX_INT_TARGET
#define DUK_HOBJECT_BOUND_CHAIN_SANITY
#define DUK_STR_BOUND_CHAIN_LIMIT

References DUK_ASSERT, DUK_ERROR_RANGE, DUK_ERROR_TYPE, duk_get_hobject_or_lfunc_coerce(), duk_get_prop_stridx(), DUK_HOBJECT_BOUND_CHAIN_SANITY, DUK_HOBJECT_GET_PROTOTYPE, DUK_HOBJECT_HAS_BOUND, DUK_HOBJECT_IS_CALLABLE, DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY, duk_hobject_resolve_proxy_target(), duk_pop(), duk_pop_2(), duk_push_tval(), duk_replace(), duk_require_hobject(), DUK_STR_BOUND_CHAIN_LIMIT, DUK_STR_PROTOTYPE_CHAIN_LIMIT, DUK_STRIDX_INT_TARGET, DUK_STRIDX_PROTOTYPE, DUK_UNREACHABLE, duk_hthread::heap, NULL, and proto.

◆ duk_js_string_compare()

DUK_INTERNAL duk_small_int_t duk_js_string_compare ( duk_hstring * h1,
duk_hstring * h2 )

Definition at line 807 of file duktape-1.5.2/src-separate/duk_js_ops.c.

807 {
808 /*
809 * String comparison (E5 Section 11.8.5, step 4), which
810 * needs to compare codepoint by codepoint.
811 *
812 * However, UTF-8 allows us to use strcmp directly: the shared
813 * prefix will be encoded identically (UTF-8 has unique encoding)
814 * and the first differing character can be compared with a simple
815 * unsigned byte comparison (which strcmp does).
816 *
817 * This will not work properly for non-xutf-8 strings, but this
818 * is not an issue for compliance.
819 */
820
821 DUK_ASSERT(h1 != NULL);
822 DUK_ASSERT(h2 != NULL);
823
824 return duk_js_data_compare((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h1),
825 (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h2),
828}
DUK_INTERNAL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1, const duk_uint8_t *buf2, duk_size_t len1, duk_size_t len2)

References DUK_ASSERT, DUK_HSTRING_GET_BYTELEN, DUK_HSTRING_GET_DATA, duk_js_data_compare(), and NULL.

Referenced by duk_js_compare_helper().

◆ duk_js_to_arrayindex_raw_string()

DUK_INTERNAL duk_small_int_t duk_js_to_arrayindex_raw_string ( const duk_uint8_t * str,
duk_uint32_t blen,
duk_uarridx_t * out_idx )

Definition at line 1317 of file duktape-1.5.2/src-separate/duk_js_ops.c.

1317 {
1318 duk_uarridx_t res, new_res;
1319
1320 if (blen == 0 || blen > 10) {
1321 goto parse_fail;
1322 }
1323 if (str[0] == (duk_uint8_t) '0' && blen > 1) {
1324 goto parse_fail;
1325 }
1326
1327 /* Accept 32-bit decimal integers, no leading zeroes, signs, etc.
1328 * Leading zeroes are not accepted (zero index "0" is an exception
1329 * handled above).
1330 */
1331
1332 res = 0;
1333 while (blen-- > 0) {
1334 duk_uint8_t c = *str++;
1335 if (c >= (duk_uint8_t) '0' && c <= (duk_uint8_t) '9') {
1336 new_res = res * 10 + (duk_uint32_t) (c - (duk_uint8_t) '0');
1337 if (new_res < res) {
1338 /* overflow, more than 32 bits -> not an array index */
1339 goto parse_fail;
1340 }
1341 res = new_res;
1342 } else {
1343 goto parse_fail;
1344 }
1345 }
1346
1347 *out_idx = res;
1348 return 1;
1349
1350 parse_fail:
1351 *out_idx = DUK_HSTRING_NO_ARRAY_INDEX;
1352 return 0;
1353}
#define DUK_HSTRING_NO_ARRAY_INDEX

References DUK_HSTRING_NO_ARRAY_INDEX.

Referenced by duk_js_to_arrayindex_string_helper().

◆ duk_js_to_arrayindex_string_helper()

DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string_helper ( duk_hstring * h)

Definition at line 1356 of file duktape-1.5.2/src-separate/duk_js_ops.c.

1356 {
1357 duk_uarridx_t res;
1358 duk_small_int_t rc;
1359
1360 if (!DUK_HSTRING_HAS_ARRIDX(h)) {
1362 }
1363
1366 &res);
1367 DUK_UNREF(rc);
1368 DUK_ASSERT(rc != 0);
1369 return res;
1370}
#define DUK_HSTRING_HAS_ARRIDX(x)
DUK_INTERNAL duk_small_int_t duk_js_to_arrayindex_raw_string(const duk_uint8_t *str, duk_uint32_t blen, duk_uarridx_t *out_idx)

References DUK_ASSERT, DUK_HSTRING_GET_BYTELEN, DUK_HSTRING_GET_DATA, DUK_HSTRING_HAS_ARRIDX, DUK_HSTRING_NO_ARRAY_INDEX, duk_js_to_arrayindex_raw_string(), and DUK_UNREF.

◆ duk_js_toboolean()

DUK_INTERNAL duk_bool_t duk_js_toboolean ( duk_tval * tv)

Definition at line 65 of file duktape-1.5.2/src-separate/duk_js_ops.c.

65 {
66 switch (DUK_TVAL_GET_TAG(tv)) {
68 case DUK_TAG_NULL:
69 return 0;
70 case DUK_TAG_BOOLEAN:
71 return DUK_TVAL_GET_BOOLEAN(tv);
72 case DUK_TAG_STRING: {
74 DUK_ASSERT(h != NULL);
75 return (DUK_HSTRING_GET_BYTELEN(h) > 0 ? 1 : 0);
76 }
77 case DUK_TAG_OBJECT: {
78 return 1;
79 }
80 case DUK_TAG_BUFFER: {
81 /* mimic semantics for strings */
83 DUK_ASSERT(h != NULL);
84 return (DUK_HBUFFER_GET_SIZE(h) > 0 ? 1 : 0);
85 }
86 case DUK_TAG_POINTER: {
87 void *p = DUK_TVAL_GET_POINTER(tv);
88 return (p != NULL ? 1 : 0);
89 }
90 case DUK_TAG_LIGHTFUNC: {
91 return 1;
92 }
93#if defined(DUK_USE_FASTINT)
94 case DUK_TAG_FASTINT:
95 if (DUK_TVAL_GET_FASTINT(tv) != 0) {
96 return 1;
97 } else {
98 return 0;
99 }
100#endif
101 default: {
102 /* number */
103 duk_double_t d;
104 int c;
107 d = DUK_TVAL_GET_DOUBLE(tv);
108 c = DUK_FPCLASSIFY((double) d);
109 if (c == DUK_FP_ZERO || c == DUK_FP_NAN) {
110 return 0;
111 } else {
112 return 1;
113 }
114 }
115 }
117}
#define DUK_TVAL_IS_DOUBLE(v)
#define DUK_TVAL_GET_DOUBLE(tv)

References DUK_ASSERT, DUK_FP_NAN, DUK_FP_ZERO, DUK_FPCLASSIFY, DUK_HBUFFER_GET_SIZE, DUK_HSTRING_GET_BYTELEN, DUK_TAG_BOOLEAN, DUK_TAG_BUFFER, DUK_TAG_LIGHTFUNC, DUK_TAG_NULL, DUK_TAG_OBJECT, DUK_TAG_POINTER, DUK_TAG_STRING, DUK_TAG_UNDEFINED, DUK_TVAL_GET_BOOLEAN, DUK_TVAL_GET_BUFFER, DUK_TVAL_GET_DOUBLE, DUK_TVAL_GET_POINTER, DUK_TVAL_GET_STRING, DUK_TVAL_GET_TAG, DUK_TVAL_IS_DOUBLE, DUK_TVAL_IS_UNUSED, DUK_UNREACHABLE, and NULL.

◆ duk_js_toint32()

DUK_INTERNAL duk_int32_t duk_js_toint32 ( duk_hthread * thr,
duk_tval * tv )

Definition at line 327 of file duktape-1.5.2/src-separate/duk_js_ops.c.

327 {
328 duk_double_t d;
329
330#if defined(DUK_USE_FASTINT)
331 if (DUK_TVAL_IS_FASTINT(tv)) {
332 return DUK_TVAL_GET_FASTINT_I32(tv);
333 }
334#endif
335
336 d = duk_js_tonumber(thr, tv); /* invalidates tv */
339 DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0); /* [-0x80000000,0x7fffffff] */
340 DUK_ASSERT(d == ((duk_double_t) ((duk_int32_t) d))); /* whole, won't clip */
341 return (duk_int32_t) d;
342}
DUK_LOCAL duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_toint32)
DUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv)

References duk__toint32_touint32_helper(), DUK_ASSERT, DUK_FP_NORMAL, DUK_FP_ZERO, DUK_FPCLASSIFY, and duk_js_tonumber().

◆ duk_js_tointeger()

DUK_INTERNAL duk_double_t duk_js_tointeger ( duk_hthread * thr,
duk_tval * tv )

Definition at line 278 of file duktape-1.5.2/src-separate/duk_js_ops.c.

278 {
279 /* XXX: fastint */
280 duk_double_t d = duk_js_tonumber(thr, tv); /* invalidates tv */
281 return duk_js_tointeger_number(d);
282}
DUK_INTERNAL duk_double_t duk_js_tointeger_number(duk_double_t x)

References duk_js_tointeger_number(), and duk_js_tonumber().

◆ duk_js_tointeger_number()

DUK_INTERNAL duk_double_t duk_js_tointeger_number ( duk_double_t x)

Definition at line 258 of file duktape-1.5.2/src-separate/duk_js_ops.c.

258 {
260
261 if (c == DUK_FP_NAN) {
262 return 0.0;
263 } else if (c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
264 /* XXX: FP_ZERO check can be removed, the else clause handles it
265 * correctly (preserving sign).
266 */
267 return x;
268 } else {
270 x = DUK_FLOOR(DUK_FABS(x)); /* truncate towards zero */
271 if (s) {
272 x = -x;
273 }
274 return x;
275 }
276}

References DUK_FABS, DUK_FLOOR, DUK_FP_INFINITE, DUK_FP_NAN, DUK_FP_ZERO, DUK_FPCLASSIFY, DUK_SIGNBIT, and s.

Referenced by duk_js_tointeger().

◆ duk_js_tonumber()

DUK_INTERNAL duk_double_t duk_js_tonumber ( duk_hthread * thr,
duk_tval * tv )

Definition at line 175 of file duktape-1.5.2/src-separate/duk_js_ops.c.

175 {
176 duk_context *ctx = (duk_hthread *) thr;
177
178 DUK_ASSERT(thr != NULL);
179 DUK_ASSERT(tv != NULL);
180
181 switch (DUK_TVAL_GET_TAG(tv)) {
182 case DUK_TAG_UNDEFINED: {
183 /* return a specific NaN (although not strictly necessary) */
187 return du.d;
188 }
189 case DUK_TAG_NULL: {
190 /* +0.0 */
191 return 0.0;
192 }
193 case DUK_TAG_BOOLEAN: {
194 if (DUK_TVAL_IS_BOOLEAN_TRUE(tv)) {
195 return 1.0;
196 }
197 return 0.0;
198 }
199 case DUK_TAG_STRING: {
201 duk_push_hstring(ctx, h);
202 return duk__tonumber_string_raw(thr);
203 }
204 case DUK_TAG_OBJECT: {
205 /* Note: ToPrimitive(object,hint) == [[DefaultValue]](object,hint),
206 * so use [[DefaultValue]] directly.
207 */
208 duk_double_t d;
209 duk_push_tval(ctx, tv);
210 duk_to_defaultvalue(ctx, -1, DUK_HINT_NUMBER); /* 'tv' becomes invalid */
211
212 /* recursive call for a primitive value (guaranteed not to cause second
213 * recursion).
214 */
215 d = duk_js_tonumber(thr, duk_require_tval(ctx, -1));
216
217 duk_pop(ctx);
218 return d;
219 }
220 case DUK_TAG_BUFFER: {
221 /* Coerce like a string. This makes sense because addition also treats
222 * buffers like strings.
223 */
225 duk_push_hbuffer(ctx, h);
226 duk_to_string(ctx, -1); /* XXX: expensive, but numconv now expects to see a string */
227 return duk__tonumber_string_raw(thr);
228 }
229 case DUK_TAG_POINTER: {
230 /* Coerce like boolean */
231 void *p = DUK_TVAL_GET_POINTER(tv);
232 return (p != NULL ? 1.0 : 0.0);
233 }
234 case DUK_TAG_LIGHTFUNC: {
235 /* +(function(){}) -> NaN */
236 return DUK_DOUBLE_NAN;
237 }
238#if defined(DUK_USE_FASTINT)
239 case DUK_TAG_FASTINT:
240 return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
241#endif
242 default: {
243 /* number */
246 return DUK_TVAL_GET_DOUBLE(tv);
247 }
248 }
249
251}
#define DUK_TVAL_IS_BOOLEAN_TRUE(tv)
DUK_EXTERNAL void duk_to_defaultvalue(duk_context *ctx, duk_idx_t index, duk_int_t hint)
DUK_INTERNAL_DECL duk_tval * duk_require_tval(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL void duk_push_hstring(duk_context *ctx, duk_hstring *h)
DUK_INTERNAL_DECL void duk_push_hbuffer(duk_context *ctx, duk_hbuffer *h)
#define DUK_DBLUNION_SET_NAN(u)
#define DUK_DBLUNION_IS_NORMALIZED(u)
DUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr)

References duk_double_union::d, duk__tonumber_string_raw(), DUK_ASSERT, DUK_DBLUNION_IS_NORMALIZED, DUK_DBLUNION_SET_NAN, DUK_DOUBLE_NAN, DUK_HINT_NUMBER, duk_js_tonumber(), duk_pop(), duk_push_hbuffer(), duk_push_hstring(), duk_push_tval(), duk_require_tval(), DUK_TAG_BOOLEAN, DUK_TAG_BUFFER, DUK_TAG_LIGHTFUNC, DUK_TAG_NULL, DUK_TAG_OBJECT, DUK_TAG_POINTER, DUK_TAG_STRING, DUK_TAG_UNDEFINED, duk_to_defaultvalue(), duk_to_string(), DUK_TVAL_GET_BUFFER, DUK_TVAL_GET_DOUBLE, DUK_TVAL_GET_POINTER, DUK_TVAL_GET_STRING, DUK_TVAL_GET_TAG, DUK_TVAL_IS_BOOLEAN_TRUE, DUK_TVAL_IS_DOUBLE, DUK_TVAL_IS_UNUSED, DUK_UNREACHABLE, and NULL.

Referenced by duk_js_toint32(), duk_js_tointeger(), duk_js_tonumber(), and duk_js_touint32().

◆ duk_js_touint16()

DUK_INTERNAL duk_uint16_t duk_js_touint16 ( duk_hthread * thr,
duk_tval * tv )

Definition at line 363 of file duktape-1.5.2/src-separate/duk_js_ops.c.

363 {
364 /* should be a safe way to compute this */
365 return (duk_uint16_t) (duk_js_touint32(thr, tv) & 0x0000ffffU);
366}
DUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv)

References duk_js_touint32().

◆ duk_js_touint32()

DUK_INTERNAL duk_uint32_t duk_js_touint32 ( duk_hthread * thr,
duk_tval * tv )

Definition at line 345 of file duktape-1.5.2/src-separate/duk_js_ops.c.

345 {
346 duk_double_t d;
347
348#if defined(DUK_USE_FASTINT)
349 if (DUK_TVAL_IS_FASTINT(tv)) {
350 return DUK_TVAL_GET_FASTINT_U32(tv);
351 }
352#endif
353
354 d = duk_js_tonumber(thr, tv); /* invalidates tv */
357 DUK_ASSERT(d >= 0.0 && d <= 4294967295.0); /* [0x00000000, 0xffffffff] */
358 DUK_ASSERT(d == ((duk_double_t) ((duk_uint32_t) d))); /* whole, won't clip */
359 return (duk_uint32_t) d;
360
361}

References duk__toint32_touint32_helper(), DUK_ASSERT, DUK_FP_NORMAL, DUK_FP_ZERO, DUK_FPCLASSIFY, and duk_js_tonumber().

Referenced by duk_js_touint16().

◆ duk_js_typeof()

DUK_INTERNAL duk_hstring * duk_js_typeof ( duk_hthread * thr,
duk_tval * tv_x )

Definition at line 1244 of file duktape-1.5.2/src-separate/duk_js_ops.c.

1244 {
1245 duk_small_int_t stridx = 0;
1246
1247 DUK_UNREF(thr);
1248
1249 switch (DUK_TVAL_GET_TAG(tv_x)) {
1250 case DUK_TAG_UNDEFINED: {
1251 stridx = DUK_STRIDX_LC_UNDEFINED;
1252 break;
1253 }
1254 case DUK_TAG_NULL: {
1255 /* Note: not a typo, "object" is returned for a null value */
1256 stridx = DUK_STRIDX_LC_OBJECT;
1257 break;
1258 }
1259 case DUK_TAG_BOOLEAN: {
1260 stridx = DUK_STRIDX_LC_BOOLEAN;
1261 break;
1262 }
1263 case DUK_TAG_POINTER: {
1264 /* implementation specific */
1265 stridx = DUK_STRIDX_LC_POINTER;
1266 break;
1267 }
1268 case DUK_TAG_STRING: {
1269 stridx = DUK_STRIDX_LC_STRING;
1270 break;
1271 }
1272 case DUK_TAG_OBJECT: {
1273 duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_x);
1274 DUK_ASSERT(obj != NULL);
1275 if (DUK_HOBJECT_IS_CALLABLE(obj)) {
1276 stridx = DUK_STRIDX_LC_FUNCTION;
1277 } else {
1278 stridx = DUK_STRIDX_LC_OBJECT;
1279 }
1280 break;
1281 }
1282 case DUK_TAG_BUFFER: {
1283 /* implementation specific */
1284 stridx = DUK_STRIDX_LC_BUFFER;
1285 break;
1286 }
1287 case DUK_TAG_LIGHTFUNC: {
1288 stridx = DUK_STRIDX_LC_FUNCTION;
1289 break;
1290 }
1291#if defined(DUK_USE_FASTINT)
1292 case DUK_TAG_FASTINT:
1293#endif
1294 default: {
1295 /* number */
1298 stridx = DUK_STRIDX_LC_NUMBER;
1299 break;
1300 }
1301 }
1302
1303 DUK_ASSERT(stridx >= 0 && stridx < DUK_HEAP_NUM_STRINGS);
1304 return DUK_HTHREAD_GET_STRING(thr, stridx);
1305}
#define DUK_STRIDX_LC_POINTER
#define DUK_TVAL_GET_OBJECT(tv)
#define DUK_STRIDX_LC_FUNCTION
#define DUK_STRIDX_LC_UNDEFINED
#define DUK_STRIDX_LC_BOOLEAN
#define DUK_HTHREAD_GET_STRING(thr, idx)

References DUK_ASSERT, DUK_HEAP_NUM_STRINGS, DUK_HOBJECT_IS_CALLABLE, DUK_HTHREAD_GET_STRING, DUK_STRIDX_LC_BOOLEAN, DUK_STRIDX_LC_BUFFER, DUK_STRIDX_LC_FUNCTION, DUK_STRIDX_LC_NUMBER, DUK_STRIDX_LC_OBJECT, DUK_STRIDX_LC_POINTER, DUK_STRIDX_LC_STRING, DUK_STRIDX_LC_UNDEFINED, DUK_TAG_BOOLEAN, DUK_TAG_BUFFER, DUK_TAG_LIGHTFUNC, DUK_TAG_NULL, DUK_TAG_OBJECT, DUK_TAG_POINTER, DUK_TAG_STRING, DUK_TAG_UNDEFINED, DUK_TVAL_GET_OBJECT, DUK_TVAL_GET_TAG, DUK_TVAL_IS_NUMBER, DUK_TVAL_IS_UNUSED, DUK_UNREF, and NULL.