1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation
2425bb815Sopenharmony_ci *
3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License.
5425bb815Sopenharmony_ci * You may obtain a copy of the License at
6425bb815Sopenharmony_ci *
7425bb815Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8425bb815Sopenharmony_ci *
9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS
11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and
13425bb815Sopenharmony_ci * limitations under the License.
14425bb815Sopenharmony_ci */
15425bb815Sopenharmony_ci
16425bb815Sopenharmony_ci#include "jerryscript.h"
17425bb815Sopenharmony_ci#include "jerryscript-port.h"
18425bb815Sopenharmony_ci#include "jerryscript-port-default.h"
19425bb815Sopenharmony_ci#include "test-common.h"
20425bb815Sopenharmony_ci#include <gtest/gtest.h>
21425bb815Sopenharmony_ci
22425bb815Sopenharmony_ci/**
23425bb815Sopenharmony_ci * Register a JavaScript function in the global object.
24425bb815Sopenharmony_ci */
25425bb815Sopenharmony_cistatic jerry_value_t
26425bb815Sopenharmony_ciregister_js_function (const char *name_p, /**< name of the function */
27425bb815Sopenharmony_ci                      jerry_external_handler_t handler_p) /**< function callback */
28425bb815Sopenharmony_ci{
29425bb815Sopenharmony_ci  jerry_value_t global_obj_val = jerry_get_global_object ();
30425bb815Sopenharmony_ci
31425bb815Sopenharmony_ci  jerry_value_t function_val = jerry_create_external_function (handler_p);
32425bb815Sopenharmony_ci  jerry_value_t function_name_val = jerry_create_string ((const jerry_char_t *) name_p);
33425bb815Sopenharmony_ci  jerry_value_t result_val = jerry_set_property (global_obj_val, function_name_val, function_val);
34425bb815Sopenharmony_ci
35425bb815Sopenharmony_ci  jerry_release_value (function_name_val);
36425bb815Sopenharmony_ci  jerry_release_value (global_obj_val);
37425bb815Sopenharmony_ci
38425bb815Sopenharmony_ci  jerry_release_value (result_val);
39425bb815Sopenharmony_ci
40425bb815Sopenharmony_ci  return function_val;
41425bb815Sopenharmony_ci} /* register_js_function */
42425bb815Sopenharmony_ci
43425bb815Sopenharmony_cienum
44425bb815Sopenharmony_ci{
45425bb815Sopenharmony_ci  TEST_ID_SIMPLE_CONSTRUCT = 1,
46425bb815Sopenharmony_ci  TEST_ID_SIMPLE_CALL = 2,
47425bb815Sopenharmony_ci  TEST_ID_CONSTRUCT_AND_CALL_SUB = 3,
48425bb815Sopenharmony_ci};
49425bb815Sopenharmony_ci
50425bb815Sopenharmony_cistatic jerry_value_t
51425bb815Sopenharmony_ciconstruct_handler (const jerry_value_t func_obj_val, /**< function object */
52425bb815Sopenharmony_ci                   const jerry_value_t this_val, /**< this arg */
53425bb815Sopenharmony_ci                   const jerry_value_t args_p[], /**< function arguments */
54425bb815Sopenharmony_ci                   const jerry_length_t args_cnt) /**< number of function arguments */
55425bb815Sopenharmony_ci{
56425bb815Sopenharmony_ci  JERRY_UNUSED (func_obj_val);
57425bb815Sopenharmony_ci  JERRY_UNUSED (this_val);
58425bb815Sopenharmony_ci  JERRY_UNUSED (args_p);
59425bb815Sopenharmony_ci
60425bb815Sopenharmony_ci  if (args_cnt != 1 || !jerry_value_is_number (args_p[0]))
61425bb815Sopenharmony_ci  {
62425bb815Sopenharmony_ci    TEST_ASSERT (0 && "Invalid arguments for demo method");
63425bb815Sopenharmony_ci  }
64425bb815Sopenharmony_ci
65425bb815Sopenharmony_ci  int test_id = (int) jerry_get_number_value (args_p[0]);
66425bb815Sopenharmony_ci
67425bb815Sopenharmony_ci  switch (test_id)
68425bb815Sopenharmony_ci  {
69425bb815Sopenharmony_ci    case TEST_ID_SIMPLE_CONSTRUCT:
70425bb815Sopenharmony_ci    {
71425bb815Sopenharmony_ci      /* Method was called with "new": new.target should be equal to the function object. */
72425bb815Sopenharmony_ci      jerry_value_t target = jerry_get_new_target ();
73425bb815Sopenharmony_ci      TEST_ASSERT (!jerry_value_is_undefined (target));
74425bb815Sopenharmony_ci      TEST_ASSERT (target == func_obj_val);
75425bb815Sopenharmony_ci      jerry_release_value (target);
76425bb815Sopenharmony_ci      break;
77425bb815Sopenharmony_ci    }
78425bb815Sopenharmony_ci    case TEST_ID_SIMPLE_CALL:
79425bb815Sopenharmony_ci    {
80425bb815Sopenharmony_ci      /* Method was called directly without "new": new.target should be equal undefined. */
81425bb815Sopenharmony_ci      jerry_value_t target = jerry_get_new_target ();
82425bb815Sopenharmony_ci      TEST_ASSERT (jerry_value_is_undefined (target));
83425bb815Sopenharmony_ci      TEST_ASSERT (target != func_obj_val);
84425bb815Sopenharmony_ci      jerry_release_value (target);
85425bb815Sopenharmony_ci      break;
86425bb815Sopenharmony_ci    }
87425bb815Sopenharmony_ci    case TEST_ID_CONSTRUCT_AND_CALL_SUB:
88425bb815Sopenharmony_ci    {
89425bb815Sopenharmony_ci      /* Method was called with "new": new.target should be equal to the function object. */
90425bb815Sopenharmony_ci      jerry_value_t target = jerry_get_new_target ();
91425bb815Sopenharmony_ci      TEST_ASSERT (!jerry_value_is_undefined (target));
92425bb815Sopenharmony_ci      TEST_ASSERT (target == func_obj_val);
93425bb815Sopenharmony_ci      jerry_release_value (target);
94425bb815Sopenharmony_ci
95425bb815Sopenharmony_ci      /* Calling a function should hide the old "new.target". */
96425bb815Sopenharmony_ci      jerry_value_t sub_arg = jerry_create_number (TEST_ID_SIMPLE_CALL);
97425bb815Sopenharmony_ci      jerry_value_t func_call_result = jerry_call_function (func_obj_val, this_val, &sub_arg, 1);
98425bb815Sopenharmony_ci      TEST_ASSERT (!jerry_value_is_error (func_call_result));
99425bb815Sopenharmony_ci      TEST_ASSERT (jerry_value_is_undefined (func_call_result));
100425bb815Sopenharmony_ci      break;
101425bb815Sopenharmony_ci    }
102425bb815Sopenharmony_ci
103425bb815Sopenharmony_ci    default:
104425bb815Sopenharmony_ci    {
105425bb815Sopenharmony_ci      TEST_ASSERT (0 && "Incorrect test ID");
106425bb815Sopenharmony_ci      break;
107425bb815Sopenharmony_ci    }
108425bb815Sopenharmony_ci  }
109425bb815Sopenharmony_ci
110425bb815Sopenharmony_ci  return jerry_create_undefined ();
111425bb815Sopenharmony_ci} /* construct_handler */
112425bb815Sopenharmony_ci
113425bb815Sopenharmony_ciclass NewtargetTest : public testing::Test{
114425bb815Sopenharmony_cipublic:
115425bb815Sopenharmony_ci    static void SetUpTestCase()
116425bb815Sopenharmony_ci    {
117425bb815Sopenharmony_ci        GTEST_LOG_(INFO) << "NewtargetTest SetUpTestCase";
118425bb815Sopenharmony_ci    }
119425bb815Sopenharmony_ci
120425bb815Sopenharmony_ci    static void TearDownTestCase()
121425bb815Sopenharmony_ci    {
122425bb815Sopenharmony_ci        GTEST_LOG_(INFO) << "NewtargetTest TearDownTestCase";
123425bb815Sopenharmony_ci    }
124425bb815Sopenharmony_ci
125425bb815Sopenharmony_ci    void SetUp() override {}
126425bb815Sopenharmony_ci    void TearDown() override {}
127425bb815Sopenharmony_ci
128425bb815Sopenharmony_ci};
129425bb815Sopenharmony_cistatic constexpr size_t JERRY_SCRIPT_MEM_SIZE = 50 * 1024 * 1024;
130425bb815Sopenharmony_cistatic void* context_alloc_fn(size_t size, void* cb_data)
131425bb815Sopenharmony_ci{
132425bb815Sopenharmony_ci    (void)cb_data;
133425bb815Sopenharmony_ci    size_t newSize = size > JERRY_SCRIPT_MEM_SIZE ? JERRY_SCRIPT_MEM_SIZE : size;
134425bb815Sopenharmony_ci    return malloc(newSize);
135425bb815Sopenharmony_ci}
136425bb815Sopenharmony_ciHWTEST_F(NewtargetTest, Test001, testing::ext::TestSize.Level1)
137425bb815Sopenharmony_ci{
138425bb815Sopenharmony_ci  jerry_context_t *ctx_p = jerry_create_context (1024, context_alloc_fn, NULL);
139425bb815Sopenharmony_ci  jerry_port_default_set_current_context (ctx_p);
140425bb815Sopenharmony_ci  /* Test JERRY_FEATURE_SYMBOL feature as it is a must-have in ES2015 */
141425bb815Sopenharmony_ci  if (!jerry_is_feature_enabled (JERRY_FEATURE_SYMBOL))
142425bb815Sopenharmony_ci  {
143425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Skipping test, ES2015 support is disabled.\n");
144425bb815Sopenharmony_ci  }
145425bb815Sopenharmony_ci
146425bb815Sopenharmony_ci  jerry_init (JERRY_INIT_EMPTY);
147425bb815Sopenharmony_ci
148425bb815Sopenharmony_ci  jerry_value_t demo_func = register_js_function ("Demo", construct_handler);
149425bb815Sopenharmony_ci
150425bb815Sopenharmony_ci  {
151425bb815Sopenharmony_ci    jerry_value_t test_arg = jerry_create_number (TEST_ID_SIMPLE_CONSTRUCT);
152425bb815Sopenharmony_ci    jerry_value_t constructed = jerry_construct_object (demo_func, &test_arg, 1);
153425bb815Sopenharmony_ci    TEST_ASSERT (!jerry_value_is_error (constructed));
154425bb815Sopenharmony_ci    TEST_ASSERT (jerry_value_is_object (constructed));
155425bb815Sopenharmony_ci    jerry_release_value (test_arg);
156425bb815Sopenharmony_ci    jerry_release_value (constructed);
157425bb815Sopenharmony_ci  }
158425bb815Sopenharmony_ci
159425bb815Sopenharmony_ci  {
160425bb815Sopenharmony_ci    jerry_value_t test_arg = jerry_create_number (TEST_ID_SIMPLE_CALL);
161425bb815Sopenharmony_ci    jerry_value_t this_arg = jerry_create_undefined ();
162425bb815Sopenharmony_ci    jerry_value_t constructed = jerry_call_function (demo_func, this_arg, &test_arg, 1);
163425bb815Sopenharmony_ci    TEST_ASSERT (jerry_value_is_undefined (constructed));
164425bb815Sopenharmony_ci    jerry_release_value (constructed);
165425bb815Sopenharmony_ci    jerry_release_value (constructed);
166425bb815Sopenharmony_ci    jerry_release_value (test_arg);
167425bb815Sopenharmony_ci  }
168425bb815Sopenharmony_ci
169425bb815Sopenharmony_ci  {
170425bb815Sopenharmony_ci    jerry_value_t test_arg = jerry_create_number (TEST_ID_CONSTRUCT_AND_CALL_SUB);
171425bb815Sopenharmony_ci    jerry_value_t constructed = jerry_construct_object (demo_func, &test_arg, 1);
172425bb815Sopenharmony_ci    TEST_ASSERT (!jerry_value_is_error (constructed));
173425bb815Sopenharmony_ci    TEST_ASSERT (jerry_value_is_object (constructed));
174425bb815Sopenharmony_ci    jerry_release_value (test_arg);
175425bb815Sopenharmony_ci    jerry_release_value (constructed);
176425bb815Sopenharmony_ci  }
177425bb815Sopenharmony_ci
178425bb815Sopenharmony_ci  {
179425bb815Sopenharmony_ci    static const jerry_char_t test_source[] = TEST_STRING_LITERAL ("new Demo (1)");
180425bb815Sopenharmony_ci
181425bb815Sopenharmony_ci    jerry_value_t parsed_code_val = jerry_parse (NULL,
182425bb815Sopenharmony_ci                                                 0,
183425bb815Sopenharmony_ci                                                 test_source,
184425bb815Sopenharmony_ci                                                 sizeof (test_source) - 1,
185425bb815Sopenharmony_ci                                                 JERRY_PARSE_NO_OPTS);
186425bb815Sopenharmony_ci    TEST_ASSERT (!jerry_value_is_error (parsed_code_val));
187425bb815Sopenharmony_ci
188425bb815Sopenharmony_ci    jerry_value_t res = jerry_run (parsed_code_val);
189425bb815Sopenharmony_ci    TEST_ASSERT (!jerry_value_is_error (res));
190425bb815Sopenharmony_ci
191425bb815Sopenharmony_ci    jerry_release_value (res);
192425bb815Sopenharmony_ci    jerry_release_value (parsed_code_val);
193425bb815Sopenharmony_ci  }
194425bb815Sopenharmony_ci
195425bb815Sopenharmony_ci  {
196425bb815Sopenharmony_ci    static const jerry_char_t test_source[] = TEST_STRING_LITERAL ("Demo (2)");
197425bb815Sopenharmony_ci
198425bb815Sopenharmony_ci    jerry_value_t parsed_code_val = jerry_parse (NULL,
199425bb815Sopenharmony_ci                                                 0,
200425bb815Sopenharmony_ci                                                 test_source,
201425bb815Sopenharmony_ci                                                 sizeof (test_source) - 1,
202425bb815Sopenharmony_ci                                                 JERRY_PARSE_NO_OPTS);
203425bb815Sopenharmony_ci    TEST_ASSERT (!jerry_value_is_error (parsed_code_val));
204425bb815Sopenharmony_ci
205425bb815Sopenharmony_ci    jerry_value_t res = jerry_run (parsed_code_val);
206425bb815Sopenharmony_ci    TEST_ASSERT (!jerry_value_is_error (res));
207425bb815Sopenharmony_ci
208425bb815Sopenharmony_ci    jerry_release_value (res);
209425bb815Sopenharmony_ci    jerry_release_value (parsed_code_val);
210425bb815Sopenharmony_ci  }
211425bb815Sopenharmony_ci
212425bb815Sopenharmony_ci  {
213425bb815Sopenharmony_ci    static const jerry_char_t test_source[] = TEST_STRING_LITERAL (
214425bb815Sopenharmony_ci      "function base(arg) { new Demo (arg); };"
215425bb815Sopenharmony_ci      "base (1);"
216425bb815Sopenharmony_ci      "new base(1);"
217425bb815Sopenharmony_ci      "new base(3);"
218425bb815Sopenharmony_ci    );
219425bb815Sopenharmony_ci
220425bb815Sopenharmony_ci    jerry_value_t parsed_code_val = jerry_parse (NULL,
221425bb815Sopenharmony_ci                                                 0,
222425bb815Sopenharmony_ci                                                 test_source,
223425bb815Sopenharmony_ci                                                 sizeof (test_source) - 1,
224425bb815Sopenharmony_ci                                                 JERRY_PARSE_NO_OPTS);
225425bb815Sopenharmony_ci    TEST_ASSERT (!jerry_value_is_error (parsed_code_val));
226425bb815Sopenharmony_ci
227425bb815Sopenharmony_ci    jerry_value_t res = jerry_run (parsed_code_val);
228425bb815Sopenharmony_ci    TEST_ASSERT (!jerry_value_is_error (res));
229425bb815Sopenharmony_ci
230425bb815Sopenharmony_ci    jerry_release_value (res);
231425bb815Sopenharmony_ci    jerry_release_value (parsed_code_val);
232425bb815Sopenharmony_ci  }
233425bb815Sopenharmony_ci
234425bb815Sopenharmony_ci  jerry_release_value (demo_func);
235425bb815Sopenharmony_ci  jerry_cleanup ();
236425bb815Sopenharmony_ci  free(ctx_p);
237425bb815Sopenharmony_ci}
238