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