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