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 "ecma-alloc.h" 17425bb815Sopenharmony_ci#include "ecma-array-object.h" 18425bb815Sopenharmony_ci#include "ecma-globals.h" 19425bb815Sopenharmony_ci#include "ecma-objects.h" 20425bb815Sopenharmony_ci#include "ecma-objects-general.h" 21425bb815Sopenharmony_ci#include "ecma-helpers.h" 22425bb815Sopenharmony_ci 23425bb815Sopenharmony_ci/** \addtogroup ecma ECMA 24425bb815Sopenharmony_ci * @{ 25425bb815Sopenharmony_ci * 26425bb815Sopenharmony_ci * \addtogroup ecmahelpers Helpers for operations with ECMA data types 27425bb815Sopenharmony_ci * @{ 28425bb815Sopenharmony_ci */ 29425bb815Sopenharmony_ci 30425bb815Sopenharmony_ci/** 31425bb815Sopenharmony_ci * Create a native pointer property to store the native pointer and its type info. 32425bb815Sopenharmony_ci * 33425bb815Sopenharmony_ci * @return true - if property was just created with specified value, 34425bb815Sopenharmony_ci * false - otherwise, if property existed before the call, it's value was updated 35425bb815Sopenharmony_ci */ 36425bb815Sopenharmony_cibool 37425bb815Sopenharmony_ciecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create property in */ 38425bb815Sopenharmony_ci void *native_p, /**< native pointer */ 39425bb815Sopenharmony_ci void *info_p) /**< native pointer's type info */ 40425bb815Sopenharmony_ci{ 41425bb815Sopenharmony_ci ecma_string_t *name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER); 42425bb815Sopenharmony_ci 43425bb815Sopenharmony_ci if (ecma_op_object_is_fast_array (obj_p)) 44425bb815Sopenharmony_ci { 45425bb815Sopenharmony_ci ecma_fast_array_convert_to_normal (obj_p); 46425bb815Sopenharmony_ci } 47425bb815Sopenharmony_ci 48425bb815Sopenharmony_ci ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); 49425bb815Sopenharmony_ci 50425bb815Sopenharmony_ci bool is_new = (property_p == NULL); 51425bb815Sopenharmony_ci 52425bb815Sopenharmony_ci ecma_native_pointer_t *native_pointer_p; 53425bb815Sopenharmony_ci 54425bb815Sopenharmony_ci if (property_p == NULL) 55425bb815Sopenharmony_ci { 56425bb815Sopenharmony_ci ecma_property_value_t *value_p; 57425bb815Sopenharmony_ci value_p = ecma_create_named_data_property (obj_p, name_p, ECMA_PROPERTY_CONFIGURABLE_WRITABLE, &property_p); 58425bb815Sopenharmony_ci 59425bb815Sopenharmony_ci ECMA_CONVERT_DATA_PROPERTY_TO_INTERNAL_PROPERTY (property_p); 60425bb815Sopenharmony_ci 61425bb815Sopenharmony_ci native_pointer_p = jmem_heap_alloc_block (sizeof (ecma_native_pointer_t)); 62425bb815Sopenharmony_ci 63425bb815Sopenharmony_ci ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, native_pointer_p); 64425bb815Sopenharmony_ci } 65425bb815Sopenharmony_ci else 66425bb815Sopenharmony_ci { 67425bb815Sopenharmony_ci ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); 68425bb815Sopenharmony_ci 69425bb815Sopenharmony_ci ecma_native_pointer_t *iter_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value_p->value); 70425bb815Sopenharmony_ci 71425bb815Sopenharmony_ci /* There should be at least 1 native pointer in the chain */ 72425bb815Sopenharmony_ci JERRY_ASSERT (iter_p != NULL); 73425bb815Sopenharmony_ci 74425bb815Sopenharmony_ci while (true) 75425bb815Sopenharmony_ci { 76425bb815Sopenharmony_ci if (iter_p->info_p == info_p) 77425bb815Sopenharmony_ci { 78425bb815Sopenharmony_ci /* The native info already exists -> update the corresponding data */ 79425bb815Sopenharmony_ci iter_p->data_p = native_p; 80425bb815Sopenharmony_ci return false; 81425bb815Sopenharmony_ci } 82425bb815Sopenharmony_ci 83425bb815Sopenharmony_ci if (iter_p->next_p == NULL) 84425bb815Sopenharmony_ci { 85425bb815Sopenharmony_ci /* The native info does not exist -> append a new element to the chain */ 86425bb815Sopenharmony_ci break; 87425bb815Sopenharmony_ci } 88425bb815Sopenharmony_ci 89425bb815Sopenharmony_ci iter_p = iter_p->next_p; 90425bb815Sopenharmony_ci } 91425bb815Sopenharmony_ci 92425bb815Sopenharmony_ci native_pointer_p = jmem_heap_alloc_block (sizeof (ecma_native_pointer_t)); 93425bb815Sopenharmony_ci 94425bb815Sopenharmony_ci iter_p->next_p = native_pointer_p; 95425bb815Sopenharmony_ci } 96425bb815Sopenharmony_ci 97425bb815Sopenharmony_ci native_pointer_p->data_p = native_p; 98425bb815Sopenharmony_ci native_pointer_p->info_p = info_p; 99425bb815Sopenharmony_ci native_pointer_p->next_p = NULL; 100425bb815Sopenharmony_ci 101425bb815Sopenharmony_ci return is_new; 102425bb815Sopenharmony_ci} /* ecma_create_native_pointer_property */ 103425bb815Sopenharmony_ci 104425bb815Sopenharmony_ci/** 105425bb815Sopenharmony_ci * Get value of native package stored in the object's property with specified identifier 106425bb815Sopenharmony_ci * 107425bb815Sopenharmony_ci * Note: 108425bb815Sopenharmony_ci * property identifier should be one of the following: 109425bb815Sopenharmony_ci * - LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER 110425bb815Sopenharmony_ci * 111425bb815Sopenharmony_ci * @return native pointer data if property exists 112425bb815Sopenharmony_ci * NULL otherwise 113425bb815Sopenharmony_ci */ 114425bb815Sopenharmony_ciecma_native_pointer_t * 115425bb815Sopenharmony_ciecma_get_native_pointer_value (ecma_object_t *obj_p, /**< object to get property value from */ 116425bb815Sopenharmony_ci void *info_p) /**< native pointer's type info */ 117425bb815Sopenharmony_ci{ 118425bb815Sopenharmony_ci if (ecma_op_object_is_fast_array (obj_p)) 119425bb815Sopenharmony_ci { 120425bb815Sopenharmony_ci /* Fast access mode array can not have native pointer properties */ 121425bb815Sopenharmony_ci return NULL; 122425bb815Sopenharmony_ci } 123425bb815Sopenharmony_ci 124425bb815Sopenharmony_ci ecma_string_t *name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER); 125425bb815Sopenharmony_ci ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); 126425bb815Sopenharmony_ci 127425bb815Sopenharmony_ci if (property_p == NULL) 128425bb815Sopenharmony_ci { 129425bb815Sopenharmony_ci return NULL; 130425bb815Sopenharmony_ci } 131425bb815Sopenharmony_ci 132425bb815Sopenharmony_ci ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); 133425bb815Sopenharmony_ci 134425bb815Sopenharmony_ci ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, 135425bb815Sopenharmony_ci value_p->value); 136425bb815Sopenharmony_ci 137425bb815Sopenharmony_ci JERRY_ASSERT (native_pointer_p != NULL); 138425bb815Sopenharmony_ci 139425bb815Sopenharmony_ci while (native_pointer_p != NULL) 140425bb815Sopenharmony_ci { 141425bb815Sopenharmony_ci if (native_pointer_p->info_p == info_p) 142425bb815Sopenharmony_ci { 143425bb815Sopenharmony_ci return native_pointer_p; 144425bb815Sopenharmony_ci } 145425bb815Sopenharmony_ci 146425bb815Sopenharmony_ci native_pointer_p = native_pointer_p->next_p; 147425bb815Sopenharmony_ci } 148425bb815Sopenharmony_ci 149425bb815Sopenharmony_ci return NULL; 150425bb815Sopenharmony_ci} /* ecma_get_native_pointer_value */ 151425bb815Sopenharmony_ci 152425bb815Sopenharmony_ci/** 153425bb815Sopenharmony_ci * Delete the previously set native pointer by the native type info from the specified object. 154425bb815Sopenharmony_ci * 155425bb815Sopenharmony_ci * Note: 156425bb815Sopenharmony_ci * If the specified object has no matching native pointer for the given native type info 157425bb815Sopenharmony_ci * the function has no effect. 158425bb815Sopenharmony_ci * 159425bb815Sopenharmony_ci * @return true - if the native pointer has been deleted succesfully 160425bb815Sopenharmony_ci * false - otherwise 161425bb815Sopenharmony_ci */ 162425bb815Sopenharmony_cibool 163425bb815Sopenharmony_ciecma_delete_native_pointer_property (ecma_object_t *obj_p, /**< object to delete property from */ 164425bb815Sopenharmony_ci void *info_p) /**< native pointer's type info */ 165425bb815Sopenharmony_ci{ 166425bb815Sopenharmony_ci if (ecma_op_object_is_fast_array (obj_p)) 167425bb815Sopenharmony_ci { 168425bb815Sopenharmony_ci /* Fast access mode array can not have native pointer properties */ 169425bb815Sopenharmony_ci return false; 170425bb815Sopenharmony_ci } 171425bb815Sopenharmony_ci 172425bb815Sopenharmony_ci ecma_string_t *name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER); 173425bb815Sopenharmony_ci ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); 174425bb815Sopenharmony_ci 175425bb815Sopenharmony_ci if (property_p == NULL) 176425bb815Sopenharmony_ci { 177425bb815Sopenharmony_ci return false; 178425bb815Sopenharmony_ci } 179425bb815Sopenharmony_ci 180425bb815Sopenharmony_ci ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); 181425bb815Sopenharmony_ci 182425bb815Sopenharmony_ci ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, 183425bb815Sopenharmony_ci value_p->value); 184425bb815Sopenharmony_ci ecma_native_pointer_t *prev_p = NULL; 185425bb815Sopenharmony_ci 186425bb815Sopenharmony_ci JERRY_ASSERT (native_pointer_p != NULL); 187425bb815Sopenharmony_ci 188425bb815Sopenharmony_ci while (native_pointer_p != NULL) 189425bb815Sopenharmony_ci { 190425bb815Sopenharmony_ci if (native_pointer_p->info_p == info_p) 191425bb815Sopenharmony_ci { 192425bb815Sopenharmony_ci if (prev_p == NULL) 193425bb815Sopenharmony_ci { 194425bb815Sopenharmony_ci if (native_pointer_p->next_p == NULL) 195425bb815Sopenharmony_ci { 196425bb815Sopenharmony_ci /* Only one native pointer property exists, so the property can be deleted as well. */ 197425bb815Sopenharmony_ci ecma_op_general_object_delete (obj_p, name_p, false); 198425bb815Sopenharmony_ci 199425bb815Sopenharmony_ci jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t)); 200425bb815Sopenharmony_ci return true; 201425bb815Sopenharmony_ci } 202425bb815Sopenharmony_ci else 203425bb815Sopenharmony_ci { 204425bb815Sopenharmony_ci /* There are at least two native pointers and the first one should be deleted. 205425bb815Sopenharmony_ci In this case the second element's data is copied to the head of the chain, and freed as well. */ 206425bb815Sopenharmony_ci ecma_native_pointer_t *next_p = native_pointer_p->next_p; 207425bb815Sopenharmony_ci memcpy (native_pointer_p, next_p, sizeof (ecma_native_pointer_t)); 208425bb815Sopenharmony_ci jmem_heap_free_block (next_p, sizeof (ecma_native_pointer_t)); 209425bb815Sopenharmony_ci return true; 210425bb815Sopenharmony_ci } 211425bb815Sopenharmony_ci } 212425bb815Sopenharmony_ci else 213425bb815Sopenharmony_ci { 214425bb815Sopenharmony_ci /* There are at least two native pointers and not the first element should be deleted. 215425bb815Sopenharmony_ci In this case the current element's next element reference is copied to the previous element. */ 216425bb815Sopenharmony_ci prev_p->next_p = native_pointer_p->next_p; 217425bb815Sopenharmony_ci jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t)); 218425bb815Sopenharmony_ci return true; 219425bb815Sopenharmony_ci } 220425bb815Sopenharmony_ci } 221425bb815Sopenharmony_ci 222425bb815Sopenharmony_ci prev_p = native_pointer_p; 223425bb815Sopenharmony_ci native_pointer_p = native_pointer_p->next_p; 224425bb815Sopenharmony_ci } 225425bb815Sopenharmony_ci 226425bb815Sopenharmony_ci return false; 227425bb815Sopenharmony_ci} /* ecma_delete_native_pointer_property */ 228425bb815Sopenharmony_ci 229425bb815Sopenharmony_ci/** 230425bb815Sopenharmony_ci * @} 231425bb815Sopenharmony_ci * @} 232425bb815Sopenharmony_ci */ 233