@@ -57,6 +57,8 @@ static const jerry_char_t test_source[] = TEST_STRING_LITERAL (
57
57
"test_validator_array1(arr);"
58
58
"test_validator_array1();"
59
59
"test_validator_array2(arr);"
60
+ "test_validator_restore(false, 3.0);"
61
+ "test_validator_restore(3.0, false);"
60
62
);
61
63
62
64
static const jerry_object_native_info_t thing_a_info =
@@ -87,6 +89,7 @@ static int validator2_count = 0;
87
89
static int validator_int_count = 0 ;
88
90
static int validator_prop_count = 0 ;
89
91
static int validator_array_count = 0 ;
92
+ static int validator_restore_count = 0 ;
90
93
91
94
/**
92
95
* The handler should have following arguments:
@@ -561,6 +564,164 @@ test_validator_array2_handler (const jerry_value_t func_obj_val __attribute__((u
561
564
return jerry_create_undefined ();
562
565
} /* test_validator_array2_handler */
563
566
567
+ /**
568
+ * This validator is designed to test the
569
+ * jerryx_arg_js_iterator_restore function. We'll introduce a union
570
+ * type to hold a bool or double and a transform function that will
571
+ * look for this type. Then, we'll call the handler with two
572
+ * parameters, one bool and one double and see if we correctly build
573
+ * the union types for each parameter. To check that the code protects
574
+ * against backing up too far, when the check for the double fails,
575
+ * we'll "restore" the stack three times; this shouldn't break
576
+ * anything.
577
+ */
578
+ /*
579
+ * This enumeration type specifies the kind of thing held in the union.
580
+ */
581
+ typedef enum
582
+ {
583
+ DOUBLE_VALUE ,
584
+ BOOL_VALUE
585
+ } union_type_t ;
586
+
587
+ /*
588
+ * This struct holds either a boolean or double in a union and has a
589
+ * second field that describes the type held in the union.
590
+ */
591
+ typedef struct
592
+ {
593
+ union_type_t type_of_value ;
594
+ union
595
+ {
596
+ double double_field ;
597
+ bool bool_field ;
598
+ } value ;
599
+ } double_or_bool_t ;
600
+
601
+ /**
602
+ * This creates a jerryx_arg_t that can be used like any
603
+ * of the installed functions, like jerryx_arg_bool().
604
+ */
605
+ #define jerryx_arg_double_or_bool_t (value_ptr , coerce_or_not , optional_or_not , last_parameter ) \
606
+ jerryx_arg_custom (value_ptr, \
607
+ (uintptr_t)&((uintptr_t []){(uintptr_t)coerce_or_not, \
608
+ (uintptr_t)optional_or_not, \
609
+ (uintptr_t)last_parameter}), \
610
+ jerry_arg_to_double_or_bool_t)
611
+ /*
612
+ * This function is the argument validator used in the above macro called
613
+ * jerryx_arg_double_or_bool. It calls jerryx_arg_js_iterator_restore()
614
+ * more times than it should to ensure that calling that function too
615
+ * often doesn't cause an error.
616
+ */
617
+ static jerry_value_t
618
+ jerry_arg_to_double_or_bool_t (jerryx_arg_js_iterator_t * js_arg_iter_p ,
619
+ const jerryx_arg_t * c_arg_p )
620
+ {
621
+ /* c_arg_p has two fields: dest, which is a pointer to the data that
622
+ * gets filled in, and extra_info, which contains the flags used to
623
+ * control coercion and optional-ness, respectively. For this test,
624
+ * we added an extra flag that tells us that we're working on the
625
+ * last parameter; when we know it's the last parameter, we'll "restore"
626
+ * the stack more times than there are actual stack values to ensure
627
+ * that the restore function doesn't produce an error. */
628
+ double_or_bool_t * destination = c_arg_p -> dest ;
629
+ uintptr_t * extra_info = (uintptr_t * )(c_arg_p -> extra_info );
630
+ jerryx_arg_t conversion_function ;
631
+ jerry_value_t conversion_result ;
632
+ jerry_value_t restore_result ;
633
+ bool last_parameter = (extra_info [2 ] == 1 );
634
+
635
+ validator_restore_count ++ ;
636
+
637
+ conversion_function = jerryx_arg_number ((double * ) (& (destination -> value .double_field )),
638
+ (jerryx_arg_coerce_t ) extra_info [0 ],
639
+ JERRYX_ARG_OPTIONAL );
640
+ conversion_result = conversion_function .func (js_arg_iter_p , & conversion_function );
641
+ if (!jerry_value_is_error (conversion_result ))
642
+ {
643
+ if (last_parameter )
644
+ {
645
+ /* The stack is only two parameters high, but we want to ensure that
646
+ * excessive calls will not result in aberrant behavior... */
647
+ jerryx_arg_js_iterator_restore (js_arg_iter_p );
648
+ jerryx_arg_js_iterator_restore (js_arg_iter_p );
649
+ jerryx_arg_js_iterator_restore (js_arg_iter_p );
650
+ restore_result = jerryx_arg_js_iterator_restore (js_arg_iter_p );
651
+ TEST_ASSERT (jerry_value_is_undefined (restore_result ));
652
+ }
653
+
654
+ destination -> type_of_value = DOUBLE_VALUE ;
655
+ return conversion_result ;
656
+ }
657
+
658
+ jerryx_arg_js_iterator_restore (js_arg_iter_p );
659
+
660
+ conversion_function = jerryx_arg_boolean ((bool * ) (& (destination -> value .bool_field )),
661
+ (jerryx_arg_coerce_t ) extra_info [0 ],
662
+ (jerryx_arg_optional_t ) extra_info [1 ]);
663
+
664
+ jerry_release_value (conversion_result );
665
+ conversion_result = conversion_function .func (js_arg_iter_p , & conversion_function );
666
+ if (!jerry_value_is_error (conversion_result ))
667
+ {
668
+ if (last_parameter )
669
+ {
670
+ /* The stack is only two parameters high, but we want to ensure that
671
+ * excessive calls will not result in aberrant behavior... */
672
+ jerryx_arg_js_iterator_restore (js_arg_iter_p );
673
+ jerryx_arg_js_iterator_restore (js_arg_iter_p );
674
+ jerryx_arg_js_iterator_restore (js_arg_iter_p );
675
+ restore_result = jerryx_arg_js_iterator_restore (js_arg_iter_p );
676
+ TEST_ASSERT (jerry_value_is_undefined (restore_result ));
677
+ }
678
+
679
+ destination -> type_of_value = BOOL_VALUE ;
680
+ return conversion_result ;
681
+ }
682
+
683
+ /* Fall through indicates that whatever they gave us, it wasn't
684
+ * one of the types we were expecting... */
685
+ jerry_release_value (conversion_result );
686
+ return jerry_create_error (JERRY_ERROR_TYPE ,
687
+ (const jerry_char_t * ) "double_or_bool-type error." );
688
+ } /* jerry_arg_to_double_or_bool_t */
689
+
690
+ /**
691
+ * This validator expects two parameters, one a bool and one a double -- the
692
+ * order doesn't matter (so we'll call it twice with the orders reversed).
693
+ */
694
+ static jerry_value_t
695
+ test_validator_restore_handler (const jerry_value_t func_obj_val __attribute__((unused )), /**< function object */
696
+ const jerry_value_t this_val __attribute__((unused )), /**< this value */
697
+ const jerry_value_t args_p [], /**< arguments list */
698
+ const jerry_length_t args_cnt __attribute__((unused ))) /**< arguments length */
699
+ {
700
+ double_or_bool_t arg1 ;
701
+ double_or_bool_t arg2 ;
702
+
703
+ jerryx_arg_t item_mapping [] =
704
+ {
705
+ jerryx_arg_double_or_bool_t (& arg1 , JERRYX_ARG_NO_COERCE , JERRYX_ARG_REQUIRED , 0 ),
706
+ jerryx_arg_double_or_bool_t (& arg2 , JERRYX_ARG_NO_COERCE , JERRYX_ARG_REQUIRED , 1 )
707
+ };
708
+
709
+ jerry_value_t is_ok = jerryx_arg_transform_args (args_p , args_cnt , item_mapping , ARRAY_SIZE (item_mapping ));
710
+
711
+ TEST_ASSERT (!jerry_value_is_error (is_ok ));
712
+
713
+ /* We are going to call this with [false, 3.0] and [3.0, false] parameters... */
714
+ bool arg1_is_false = (arg1 .type_of_value == BOOL_VALUE && arg1 .value .bool_field == false);
715
+ bool arg1_is_three = (arg1 .type_of_value == DOUBLE_VALUE && arg1 .value .double_field == 3.0 );
716
+ bool arg2_is_false = (arg2 .type_of_value == BOOL_VALUE && arg2 .value .bool_field == false);
717
+ bool arg2_is_three = (arg2 .type_of_value == DOUBLE_VALUE && arg2 .value .double_field == 3.0 );
718
+ TEST_ASSERT ((arg1_is_false && arg2_is_three ) || (arg1_is_three && arg2_is_false ));
719
+
720
+ jerry_release_value (is_ok );
721
+
722
+ return jerry_create_undefined ();
723
+ } /* test_validator_restore_handler */
724
+
564
725
static void
565
726
test_utf8_string (void )
566
727
{
@@ -657,6 +818,7 @@ main (void)
657
818
register_js_function ("test_validator_prop3" , test_validator_prop3_handler );
658
819
register_js_function ("test_validator_array1" , test_validator_array1_handler );
659
820
register_js_function ("test_validator_array2" , test_validator_array2_handler );
821
+ register_js_function ("test_validator_restore" , test_validator_restore_handler );
660
822
661
823
jerry_value_t parsed_code_val = jerry_parse (NULL ,
662
824
0 ,
@@ -672,6 +834,7 @@ main (void)
672
834
TEST_ASSERT (validator_prop_count == 4 );
673
835
TEST_ASSERT (validator_int_count == 3 );
674
836
TEST_ASSERT (validator_array_count == 3 );
837
+ TEST_ASSERT (validator_restore_count == 4 );
675
838
676
839
jerry_release_value (res );
677
840
jerry_release_value (parsed_code_val );
0 commit comments