• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright JS Foundation and other contributors, http://js.foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "jerryscript.h"
17 #include "jerryscript-port.h"
18 #include "jerryscript-port-default.h"
19 #include "test-common.h"
20 
21 /**
22  * Register a JavaScript function in the global object.
23  */
24 static jerry_value_t
register_js_function(const char * name_p,jerry_external_handler_t handler_p)25 register_js_function (const char *name_p, /**< name of the function */
26                       jerry_external_handler_t handler_p) /**< function callback */
27 {
28   jerry_value_t global_obj_val = jerry_get_global_object ();
29 
30   jerry_value_t function_val = jerry_create_external_function (handler_p);
31   jerry_value_t function_name_val = jerry_create_string ((const jerry_char_t *) name_p);
32   jerry_value_t result_val = jerry_set_property (global_obj_val, function_name_val, function_val);
33 
34   jerry_release_value (function_name_val);
35   jerry_release_value (global_obj_val);
36 
37   jerry_release_value (result_val);
38 
39   return function_val;
40 } /* register_js_function */
41 
42 enum
43 {
44   TEST_ID_SIMPLE_CONSTRUCT = 1,
45   TEST_ID_SIMPLE_CALL = 2,
46   TEST_ID_CONSTRUCT_AND_CALL_SUB = 3,
47 };
48 
49 static jerry_value_t
construct_handler(const jerry_value_t func_obj_val,const jerry_value_t this_val,const jerry_value_t args_p[],const jerry_length_t args_cnt)50 construct_handler (const jerry_value_t func_obj_val, /**< function object */
51                    const jerry_value_t this_val, /**< this arg */
52                    const jerry_value_t args_p[], /**< function arguments */
53                    const jerry_length_t args_cnt) /**< number of function arguments */
54 {
55   JERRY_UNUSED (func_obj_val);
56   JERRY_UNUSED (this_val);
57   JERRY_UNUSED (args_p);
58 
59   if (args_cnt != 1 || !jerry_value_is_number (args_p[0]))
60   {
61     TEST_ASSERT (0 && "Invalid arguments for demo method");
62   }
63 
64   int test_id = (int) jerry_get_number_value (args_p[0]);
65 
66   switch (test_id)
67   {
68     case TEST_ID_SIMPLE_CONSTRUCT:
69     {
70       /* Method was called with "new": new.target should be equal to the function object. */
71       jerry_value_t target = jerry_get_new_target ();
72       TEST_ASSERT (!jerry_value_is_undefined (target));
73       TEST_ASSERT (target == func_obj_val);
74       jerry_release_value (target);
75       break;
76     }
77     case TEST_ID_SIMPLE_CALL:
78     {
79       /* Method was called directly without "new": new.target should be equal undefined. */
80       jerry_value_t target = jerry_get_new_target ();
81       TEST_ASSERT (jerry_value_is_undefined (target));
82       TEST_ASSERT (target != func_obj_val);
83       jerry_release_value (target);
84       break;
85     }
86     case TEST_ID_CONSTRUCT_AND_CALL_SUB:
87     {
88       /* Method was called with "new": new.target should be equal to the function object. */
89       jerry_value_t target = jerry_get_new_target ();
90       TEST_ASSERT (!jerry_value_is_undefined (target));
91       TEST_ASSERT (target == func_obj_val);
92       jerry_release_value (target);
93 
94       /* Calling a function should hide the old "new.target". */
95       jerry_value_t sub_arg = jerry_create_number (TEST_ID_SIMPLE_CALL);
96       jerry_value_t func_call_result = jerry_call_function (func_obj_val, this_val, &sub_arg, 1);
97       TEST_ASSERT (!jerry_value_is_error (func_call_result));
98       TEST_ASSERT (jerry_value_is_undefined (func_call_result));
99       break;
100     }
101 
102     default:
103     {
104       TEST_ASSERT (0 && "Incorrect test ID");
105       break;
106     }
107   }
108 
109   return jerry_create_undefined ();
110 } /* construct_handler */
111 
112 int
main(void)113 main (void)
114 {
115   /* Test JERRY_FEATURE_SYMBOL feature as it is a must-have in ES2015 */
116   if (!jerry_is_feature_enabled (JERRY_FEATURE_SYMBOL))
117   {
118     jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Skipping test, ES2015 support is disabled.\n");
119     return 0;
120   }
121 
122   jerry_init (JERRY_INIT_EMPTY);
123 
124   jerry_value_t demo_func = register_js_function ("Demo", construct_handler);
125 
126   {
127     jerry_value_t test_arg = jerry_create_number (TEST_ID_SIMPLE_CONSTRUCT);
128     jerry_value_t constructed = jerry_construct_object (demo_func, &test_arg, 1);
129     TEST_ASSERT (!jerry_value_is_error (constructed));
130     TEST_ASSERT (jerry_value_is_object (constructed));
131     jerry_release_value (test_arg);
132     jerry_release_value (constructed);
133   }
134 
135   {
136     jerry_value_t test_arg = jerry_create_number (TEST_ID_SIMPLE_CALL);
137     jerry_value_t this_arg = jerry_create_undefined ();
138     jerry_value_t constructed = jerry_call_function (demo_func, this_arg, &test_arg, 1);
139     TEST_ASSERT (jerry_value_is_undefined (constructed));
140     jerry_release_value (constructed);
141     jerry_release_value (constructed);
142     jerry_release_value (test_arg);
143   }
144 
145   {
146     jerry_value_t test_arg = jerry_create_number (TEST_ID_CONSTRUCT_AND_CALL_SUB);
147     jerry_value_t constructed = jerry_construct_object (demo_func, &test_arg, 1);
148     TEST_ASSERT (!jerry_value_is_error (constructed));
149     TEST_ASSERT (jerry_value_is_object (constructed));
150     jerry_release_value (test_arg);
151     jerry_release_value (constructed);
152   }
153 
154   {
155     static const jerry_char_t test_source[] = TEST_STRING_LITERAL ("new Demo (1)");
156 
157     jerry_value_t parsed_code_val = jerry_parse (NULL,
158                                                  0,
159                                                  test_source,
160                                                  sizeof (test_source) - 1,
161                                                  JERRY_PARSE_NO_OPTS);
162     TEST_ASSERT (!jerry_value_is_error (parsed_code_val));
163 
164     jerry_value_t res = jerry_run (parsed_code_val);
165     TEST_ASSERT (!jerry_value_is_error (res));
166 
167     jerry_release_value (res);
168     jerry_release_value (parsed_code_val);
169   }
170 
171   {
172     static const jerry_char_t test_source[] = TEST_STRING_LITERAL ("Demo (2)");
173 
174     jerry_value_t parsed_code_val = jerry_parse (NULL,
175                                                  0,
176                                                  test_source,
177                                                  sizeof (test_source) - 1,
178                                                  JERRY_PARSE_NO_OPTS);
179     TEST_ASSERT (!jerry_value_is_error (parsed_code_val));
180 
181     jerry_value_t res = jerry_run (parsed_code_val);
182     TEST_ASSERT (!jerry_value_is_error (res));
183 
184     jerry_release_value (res);
185     jerry_release_value (parsed_code_val);
186   }
187 
188   {
189     static const jerry_char_t test_source[] = TEST_STRING_LITERAL (
190       "function base(arg) { new Demo (arg); };"
191       "base (1);"
192       "new base(1);"
193       "new base(3);"
194     );
195 
196     jerry_value_t parsed_code_val = jerry_parse (NULL,
197                                                  0,
198                                                  test_source,
199                                                  sizeof (test_source) - 1,
200                                                  JERRY_PARSE_NO_OPTS);
201     TEST_ASSERT (!jerry_value_is_error (parsed_code_val));
202 
203     jerry_value_t res = jerry_run (parsed_code_val);
204     TEST_ASSERT (!jerry_value_is_error (res));
205 
206     jerry_release_value (res);
207     jerry_release_value (parsed_code_val);
208   }
209 
210   jerry_release_value (demo_func);
211   jerry_cleanup ();
212   return 0;
213 } /* main */
214