1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
|
/*
* Copyright (C) Igor Sysoev
* Copyright (C) NGINX, Inc.
*/
#ifndef _NJS_OBJECT_H_INCLUDED_
#define _NJS_OBJECT_H_INCLUDED_
typedef enum {
NJS_OBJECT_PROP_DESCRIPTOR = 0,
NJS_OBJECT_PROP_VALUE = 1,
NJS_OBJECT_PROP_GETTER = 2,
NJS_OBJECT_PROP_SETTER = 3,
#define njs_prop_type(flags) (flags & 3)
NJS_OBJECT_PROP_CREATE = 4,
NJS_OBJECT_PROP_ENUMERABLE = 8,
NJS_OBJECT_PROP_CONFIGURABLE = 16,
NJS_OBJECT_PROP_WRITABLE = 32,
NJS_OBJECT_PROP_UNSET = 64,
NJS_OBJECT_PROP_IS_STRING = 128,
#define NJS_OBJECT_PROP_VALUE_ECW (NJS_OBJECT_PROP_VALUE \
| NJS_OBJECT_PROP_ENUMERABLE \
| NJS_OBJECT_PROP_CONFIGURABLE \
| NJS_OBJECT_PROP_WRITABLE)
#define NJS_OBJECT_PROP_VALUE_EC (NJS_OBJECT_PROP_VALUE \
| NJS_OBJECT_PROP_ENUMERABLE \
| NJS_OBJECT_PROP_CONFIGURABLE)
#define NJS_OBJECT_PROP_VALUE_CW (NJS_OBJECT_PROP_VALUE \
| NJS_OBJECT_PROP_CONFIGURABLE \
| NJS_OBJECT_PROP_WRITABLE)
#define NJS_OBJECT_PROP_VALUE_E (NJS_OBJECT_PROP_VALUE \
| NJS_OBJECT_PROP_ENUMERABLE)
#define NJS_OBJECT_PROP_VALUE_C (NJS_OBJECT_PROP_VALUE \
| NJS_OBJECT_PROP_CONFIGURABLE)
#define NJS_OBJECT_PROP_VALUE_W (NJS_OBJECT_PROP_VALUE \
| NJS_OBJECT_PROP_WRITABLE)
} njs_object_prop_flags_t;
struct njs_object_init_s {
const njs_object_prop_init_t *properties;
njs_uint_t items;
};
typedef struct njs_traverse_s njs_traverse_t;
struct njs_traverse_s {
struct njs_traverse_s *parent;
njs_object_prop_t *prop;
uint32_t atom_id;
njs_value_t value;
njs_array_t *keys;
int64_t index;
#define NJS_TRAVERSE_MAX_DEPTH 32
};
typedef njs_int_t (*njs_object_traverse_cb_t)(njs_vm_t *vm,
njs_traverse_t *traverse, void *ctx);
njs_object_t *njs_object_alloc(njs_vm_t *vm);
njs_object_t *njs_object_value_copy(njs_vm_t *vm, njs_value_t *value);
njs_object_value_t *njs_object_value_alloc(njs_vm_t *vm, njs_uint_t index,
size_t extra,const njs_value_t *value);
njs_array_t *njs_object_enumerate(njs_vm_t *vm, const njs_object_t *object,
uint32_t flags);
njs_array_t *njs_object_own_enumerate(njs_vm_t *vm, const njs_object_t *object,
uint32_t flags);
njs_int_t njs_object_traverse(njs_vm_t *vm, njs_object_t *object, void *ctx,
njs_object_traverse_cb_t cb);
njs_int_t njs_object_make_shared(njs_vm_t *vm, njs_object_t *object);
njs_int_t njs_object_hash_create(njs_vm_t *vm, njs_flathsh_t *hash,
const njs_object_prop_init_t *prop, njs_uint_t n);
njs_int_t njs_primitive_prototype_get_proto(njs_vm_t *vm,
njs_object_prop_t *prop, uint32_t unused, njs_value_t *value,
njs_value_t *setval, njs_value_t *retval);
njs_int_t njs_object_prototype_create(njs_vm_t *vm, njs_object_prop_t *prop,
uint32_t unused, njs_value_t *value, njs_value_t *setval,
njs_value_t *retval);
njs_value_t *njs_property_prototype_create(njs_vm_t *vm, njs_flathsh_t *hash,
njs_object_t *prototype);
njs_int_t njs_object_prototype_proto(njs_vm_t *vm, njs_object_prop_t *prop,
uint32_t unused, njs_value_t *value, njs_value_t *setval,
njs_value_t *retval);
njs_int_t njs_object_prototype_create_constructor(njs_vm_t *vm,
njs_object_prop_t *prop, uint32_t unused, njs_value_t *value,
njs_value_t *setval, njs_value_t *retval);
njs_value_t *njs_property_constructor_set(njs_vm_t *vm, njs_flathsh_t *hash,
njs_value_t *constructor);
njs_int_t njs_object_to_string(njs_vm_t *vm, njs_value_t *value,
njs_value_t *retval);
njs_int_t njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused, njs_value_t *retval);
njs_int_t njs_object_length(njs_vm_t *vm, njs_value_t *value, int64_t *dst);
njs_int_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq,
njs_object_t *proto);
void njs_object_prop_init(njs_object_prop_t *prop, njs_object_prop_type_t type,
uint8_t attributes);
njs_int_t njs_object_property(njs_vm_t *vm, njs_object_t *object,
njs_flathsh_query_t *lhq, njs_value_t *retval);
njs_object_prop_t *njs_object_property_add(njs_vm_t *vm, njs_value_t *object,
uint32_t atom_id, njs_bool_t replace);
njs_int_t njs_object_prop_define(njs_vm_t *vm, njs_value_t *object,
uint32_t atom_id, njs_value_t *value, uint32_t flags);
njs_int_t njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest,
njs_value_t *value, njs_value_t *setval);
njs_int_t njs_object_get_prototype_of(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused, njs_value_t *retval);
const char *njs_prop_type_string(njs_object_prop_type_t type);
njs_int_t njs_object_props_init(njs_vm_t *vm, const njs_object_init_t* init,
njs_object_prop_t *base, uint32_t atom_id, njs_value_t *value,
njs_value_t *retval);
njs_inline njs_bool_t
njs_is_data_descriptor(njs_object_prop_t *prop)
{
return (prop->type == NJS_PROPERTY && njs_is_valid(njs_prop_value(prop)))
|| prop->type == NJS_PROPERTY_HANDLER
|| prop->type == NJS_PROPERTY_REF
|| prop->type == NJS_PROPERTY_PLACE_REF
|| prop->type == NJS_PROPERTY_TYPED_ARRAY_REF;
}
njs_inline njs_bool_t
njs_is_accessor_descriptor(njs_object_prop_t *prop)
{
return prop->type == NJS_ACCESSOR;
}
njs_inline njs_int_t
njs_primitive_value_to_key(njs_vm_t *vm, njs_value_t *dst,
const njs_value_t *src)
{
switch (src->type) {
case NJS_NULL:
njs_atom_to_value(vm, dst, NJS_ATOM_STRING_null);
return NJS_OK;
case NJS_UNDEFINED:
njs_atom_to_value(vm, dst, NJS_ATOM_STRING_undefined);
return NJS_OK;
case NJS_BOOLEAN:
if (njs_is_true(src)) {
njs_atom_to_value(vm, dst, NJS_ATOM_STRING_true);
} else {
njs_atom_to_value(vm, dst, NJS_ATOM_STRING_false);
}
return NJS_OK;
case NJS_NUMBER:
case NJS_SYMBOL:
case NJS_STRING:
*dst = *src;
return NJS_OK;
default:
return NJS_ERROR;
}
}
njs_inline njs_int_t
njs_value_to_key2(njs_vm_t *vm, njs_value_t *dst, njs_value_t *value,
njs_bool_t convert)
{
njs_int_t ret;
njs_value_t primitive;
if (njs_slow_path(!njs_is_primitive(value))) {
if (njs_slow_path(njs_is_object_symbol(value))) {
/* should fail */
value = njs_object_value(value);
} else {
if (convert) {
ret = njs_value_to_primitive(vm, &primitive, value, 1);
} else {
ret = njs_object_to_string(vm, value, &primitive);
}
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
value = &primitive;
}
}
return njs_primitive_value_to_key(vm, dst, value);
}
njs_inline njs_int_t
njs_value_to_key(njs_vm_t *vm, njs_value_t *dst, njs_value_t *value)
{
return njs_value_to_key2(vm, dst, value, 1);
}
njs_inline njs_int_t
njs_key_string_get(njs_vm_t *vm, njs_value_t *key, njs_str_t *str)
{
njs_int_t ret;
if (njs_slow_path(njs_is_symbol(key))) {
ret = njs_symbol_descriptive_string(vm, key, key);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
} else if (njs_slow_path(!njs_is_string(key))) {
ret = njs_value_to_string(vm, key, key);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
}
njs_string_get(vm, key, str);
return NJS_OK;
}
njs_inline void
njs_atom_string_get(njs_vm_t *vm, uint32_t atom_id, njs_str_t *str)
{
njs_value_t value;
if (njs_atom_to_value(vm, &value, atom_id) != NJS_OK) {
str->start = (u_char *) "unknown";
str->length = njs_length("unknown");
}
njs_key_string_get(vm, &value, str);
}
njs_inline njs_int_t
njs_object_prop_define_val(njs_vm_t *vm, njs_value_t *object, njs_value_t *name,
njs_value_t *value, unsigned flags)
{
njs_int_t ret;
if (njs_value_atom(name) == NJS_ATOM_STRING_unknown) {
ret = njs_atom_atomize_key(vm, name);
if (ret != NJS_OK) {
return ret;
}
}
if (njs_is_string(name)) {
flags |= NJS_OBJECT_PROP_IS_STRING;
}
return njs_object_prop_define(vm, object, name->atom_id, value, flags);
}
njs_inline njs_int_t
njs_value_create_data_prop(njs_vm_t *vm, njs_value_t *value,
njs_value_t *name, njs_value_t *setval, uint32_t hash)
{
return njs_object_prop_define_val(vm, value, name, setval,
NJS_OBJECT_PROP_CREATE
| NJS_OBJECT_PROP_VALUE_ECW);
}
njs_inline njs_int_t
njs_value_create_data_prop_i64(njs_vm_t *vm, njs_value_t *value, int64_t index,
njs_value_t *setval, uint32_t hash)
{
njs_value_t key;
njs_set_number(&key, index);
return njs_value_create_data_prop(vm, value, &key, setval, hash);
}
njs_inline njs_int_t
njs_object_length_set(njs_vm_t *vm, njs_value_t *value, int64_t length)
{
njs_value_t index;
njs_value_number_set(&index, length);
return njs_value_property_set(vm, value, NJS_ATOM_STRING_length, &index);
}
njs_inline njs_int_t
njs_object_string_tag(njs_vm_t *vm, njs_value_t *value, njs_value_t *tag)
{
njs_int_t ret;
ret = njs_value_property(vm, value, NJS_ATOM_SYMBOL_toStringTag, tag);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
if (!njs_is_string(tag)) {
return NJS_DECLINED;
}
return NJS_OK;
}
njs_inline njs_object_t *
_njs_object_proto_lookup(njs_object_t *proto, njs_value_type_t type)
{
do {
if (njs_fast_path(proto->type == type)) {
break;
}
proto = proto->__proto__;
} while (proto != NULL);
return proto;
}
#define njs_object_proto_lookup(proto, vtype, ctype) \
(ctype *) _njs_object_proto_lookup(proto, vtype)
extern const njs_object_type_init_t njs_obj_type_init;
#endif /* _NJS_OBJECT_H_INCLUDED_ */
|