length--;
} while (length != 0);
- } else if (njs_is_string(this) || this->type == NJS_OBJECT_STRING) {
+ } else if (njs_is_string(this) || njs_is_object_string(this)) {
- if (this->type == NJS_OBJECT_STRING) {
+ if (njs_is_object_string(this)) {
this = njs_object_value(this);
}
njs_boolean_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- njs_object_t *object;
- const njs_value_t *value;
+ const njs_value_t *value;
+ njs_object_value_t *object;
if (nargs == 1) {
value = &njs_value_false;
}
if (vm->top_frame->ctor) {
- object = njs_object_value_alloc(vm, value, value->type);
+ object = njs_object_value_alloc(vm, NJS_OBJ_TYPE_BOOLEAN, 0, value);
if (njs_slow_path(object == NULL)) {
return NJS_ERROR;
}
- njs_set_type_object(&vm->retval, object, NJS_OBJECT_BOOLEAN);
+ njs_set_object_value(&vm->retval, object);
} else {
vm->retval = *value;
if (value->type != NJS_BOOLEAN) {
- if (value->type == NJS_OBJECT_BOOLEAN) {
+ if (njs_is_object_boolean(value)) {
value = njs_object_value(value);
} else {
if (value->type != NJS_BOOLEAN) {
- if (value->type == NJS_OBJECT_BOOLEAN) {
+ if (njs_is_object_boolean(value)) {
value = njs_object_value(value);
} else {
.prototype_props = &njs_boolean_prototype_init,
.prototype_value = { .object_value = {
.value = njs_value(NJS_BOOLEAN, 0, 0.0),
- .object = { .type = NJS_OBJECT_BOOLEAN } }
+ .object = { .type = NJS_OBJECT_VALUE } }
},
};
string_object = &shared->string_object;
njs_lvlhsh_init(&string_object->hash);
string_object->shared_hash = shared->string_instance_hash;
- string_object->type = NJS_OBJECT_STRING;
+ string_object->type = NJS_OBJECT_VALUE;
string_object->shared = 1;
string_object->extensible = 0;
njs_object_iterate(njs_vm_t *vm, njs_iterator_args_t *args,
njs_iterator_handler_t handler)
{
- double idx;
- int64_t length, i, from, to;
- njs_int_t ret;
- njs_array_t *array, *keys;
- njs_value_t *value, *entry, prop, character, string_obj;
- njs_object_t *object;
- const u_char *p, *end, *pos;
- njs_string_prop_t string_prop;
+ double idx;
+ int64_t length, i, from, to;
+ njs_int_t ret;
+ njs_array_t *array, *keys;
+ njs_value_t *value, *entry, prop, character, string_obj;
+ const u_char *p, *end, *pos;
+ njs_string_prop_t string_prop;
+ njs_object_value_t *object;
value = args->value;
from = args->from;
if (njs_is_string(value) || njs_is_object_string(value)) {
if (njs_is_string(value)) {
- object = njs_object_value_alloc(vm, value, NJS_STRING);
+ object = njs_object_value_alloc(vm, NJS_OBJ_TYPE_STRING, 0, value);
if (njs_slow_path(object == NULL)) {
return NJS_ERROR;
}
- njs_set_type_object(&string_obj, object, NJS_OBJECT_STRING);
+ njs_set_object_value(&string_obj, object);
args->value = &string_obj;
}
njs_object_iterate_reverse(njs_vm_t *vm, njs_iterator_args_t *args,
njs_iterator_handler_t handler)
{
- double idx;
- int64_t i, from, to, length;
- njs_int_t ret;
- njs_array_t *array, *keys;
- njs_value_t *entry, *value, prop, character, string_obj;
- njs_object_t *object;
- const u_char *p, *end, *pos;
- njs_string_prop_t string_prop;
+ double idx;
+ int64_t i, from, to, length;
+ njs_int_t ret;
+ njs_array_t *array, *keys;
+ njs_value_t *entry, *value, prop, character, string_obj;
+ const u_char *p, *end, *pos;
+ njs_string_prop_t string_prop;
+ njs_object_value_t *object;
value = args->value;
from = args->from;
if (njs_is_string(value) || njs_is_object_string(value)) {
if (njs_is_string(value)) {
- object = njs_object_value_alloc(vm, value, NJS_STRING);
+ object = njs_object_value_alloc(vm, NJS_OBJ_TYPE_STRING, 0, value);
if (njs_slow_path(object == NULL)) {
return NJS_ERROR;
}
- njs_set_type_object(&string_obj, object, NJS_OBJECT_STRING);
+ njs_set_object_value(&string_obj, object);
args->value = &string_obj;
}
space = njs_arg(args, nargs, 3);
- switch (space->type) {
- case NJS_OBJECT_STRING:
- ret = njs_value_to_string(vm, space, space);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ if (njs_is_object(space)) {
+ if (njs_is_object_number(space)) {
+ ret = njs_value_to_numeric(vm, space, space);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
- /* Fall through. */
+ } else if (njs_is_object_string(space)) {
+ ret = njs_value_to_string(vm, space, space);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+ }
+ }
+ switch (space->type) {
case NJS_STRING:
length = njs_string_prop(&prop, space);
break;
- case NJS_OBJECT_NUMBER:
- ret = njs_value_to_numeric(vm, space, space);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
-
- /* Fall through. */
-
case NJS_NUMBER:
i64 = njs_min(njs_number_to_integer(njs_number(space)), 10);
njs_inline njs_bool_t
njs_json_is_object(const njs_value_t *value)
{
- return (((value)->type == NJS_OBJECT)
- || ((value)->type == NJS_ARRAY)
- || ((value)->type == NJS_OBJECT_SYMBOL)
- || ((value)->type >= NJS_REGEXP));
+ if (!njs_is_object(value)) {
+ return 0;
+ }
+
+ if (njs_is_function(value)) {
+ return 0;
+ }
+
+ if (njs_is_object_value(value)) {
+ switch (njs_object_value(value)->type) {
+ case NJS_BOOLEAN:
+ case NJS_NUMBER:
+ case NJS_STRING:
+ return 0;
+
+ default:
+ break;
+ }
+ }
+
+ return 1;
}
njs_json_stringify_array(njs_vm_t *vm, njs_json_stringify_t *stringify)
{
njs_int_t ret;
- uint32_t i, n, k, properties_length, array_length;
- njs_value_t *value, num_value;
- njs_array_t *properties, *array;
+ int64_t i, k, length;
+ njs_value_t *value, *item;
+ njs_array_t *properties;
- properties_length = 1;
- array = njs_array(&stringify->replacer);
- array_length = array->length;
-
- for (i = 0; i < array_length; i++) {
- if (njs_is_valid(&array->start[i])) {
- properties_length++;
- }
+ ret = njs_object_length(vm, &stringify->replacer, &length);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
- properties = njs_array_alloc(vm, 1, properties_length, NJS_ARRAY_SPARE);
+ properties = njs_array_alloc(vm, 1, 0, NJS_ARRAY_SPARE);
if (njs_slow_path(properties == NULL)) {
return NJS_ERROR;
}
- n = 0;
- properties->start[n++] = njs_string_empty;
-
- for (i = 0; i < array_length; i++) {
- value = &array->start[i];
+ item = njs_array_push(vm, properties);
+ njs_value_assign(item, &njs_string_empty);
- if (!njs_is_valid(&array->start[i])) {
- continue;
+ for (i = 0; i < length; i++) {
+ ret = njs_value_property_i64(vm, &stringify->replacer, i,
+ &stringify->retval);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
}
+ value = &stringify->retval;
+
switch (value->type) {
+ case NJS_STRING:
+ break;
+
case NJS_NUMBER:
- ret = njs_number_to_string(vm, &num_value, value);
+ ret = njs_number_to_string(vm, value, value);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
- value = &num_value;
break;
- case NJS_OBJECT_NUMBER:
- case NJS_OBJECT_STRING:
- ret = njs_value_to_string(vm, value, value);
- if (njs_slow_path(ret != NJS_OK)) {
- return NJS_ERROR;
- }
+ case NJS_OBJECT_VALUE:
+ switch (njs_object_value(value)->type) {
+ case NJS_NUMBER:
+ case NJS_STRING:
+ ret = njs_value_to_string(vm, value, value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
+ }
+
+ break;
- /* Fall through. */
+ default:
+ continue;
+ }
- case NJS_STRING:
break;
default:
continue;
}
- for (k = 0; k < n; k ++) {
+ for (k = 0; k < properties->length; k++) {
if (njs_values_strict_equal(value, &properties->start[k]) == 1) {
break;
}
}
- if (k == n) {
- properties->start[n++] = *value;
+ if (k == properties->length) {
+ item = njs_array_push(vm, properties);
+ if (njs_slow_path(item == NULL)) {
+ return NJS_ERROR;
+ }
+
+ njs_value_assign(item, value);
}
}
- properties->length = n;
- stringify->replacer.data.u.array = properties;
+ njs_set_array(&stringify->replacer, properties);
return NJS_OK;
}
{
njs_int_t ret;
- switch (value->type) {
- case NJS_OBJECT_STRING:
- ret = njs_value_to_string(vm, value, value);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ if (njs_is_object_value(value)) {
+ switch (njs_object_value(value)->type) {
+ case NJS_NUMBER:
+ ret = njs_value_to_numeric(vm, value, value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
- /* Fall through. */
+ break;
+
+ case NJS_BOOLEAN:
+ njs_value_assign(value, njs_object_value(value));
+ break;
+
+ case NJS_STRING:
+ ret = njs_value_to_string(vm, value, value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch (value->type) {
case NJS_STRING:
njs_json_append_string(chain, value, '\"');
break;
- case NJS_OBJECT_NUMBER:
- ret = njs_value_to_numeric(vm, value, value);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
-
- /* Fall through. */
-
case NJS_NUMBER:
njs_json_append_number(chain, value);
break;
- case NJS_OBJECT_BOOLEAN:
- value = njs_object_value(value);
- /* Fall through. */
-
case NJS_BOOLEAN:
if (njs_is_true(value)) {
njs_chb_append_literal(chain, "true");
njs_int_t (*to_string)(njs_vm_t *, njs_value_t *, const njs_value_t *);
switch (value->type) {
- case NJS_OBJECT_STRING:
- value = njs_object_value(value);
+ case NJS_NULL:
+ njs_chb_append_literal(chain, "null");
+ break;
+
+ case NJS_UNDEFINED:
+ njs_chb_append_literal(chain, "undefined");
+ break;
+
+ case NJS_BOOLEAN:
+ if (njs_is_true(value)) {
+ njs_chb_append_literal(chain, "true");
+
+ } else {
+ njs_chb_append_literal(chain, "false");
+ }
- njs_chb_append_literal(chain, "[String: ");
- njs_json_append_string(chain, value, '\'');
- njs_chb_append_literal(chain, "]");
break;
case NJS_STRING:
break;
- case NJS_OBJECT_SYMBOL:
- value = njs_object_value(value);
-
- ret = njs_symbol_descriptive_string(stringify->vm, &str_val, value);
- if (njs_slow_path(ret != NJS_OK)) {
- return NJS_ERROR;
- }
-
- njs_string_get(&str_val, &str);
- njs_chb_sprintf(chain, 16 + str.length, "[Symbol: %V]", &str);
-
- break;
-
case NJS_SYMBOL:
ret = njs_symbol_descriptive_string(stringify->vm, &str_val, value);
if (njs_slow_path(ret != NJS_OK)) {
break;
- case NJS_OBJECT_NUMBER:
+ case NJS_INVALID:
+ njs_chb_append_literal(chain, "<empty>");
+ break;
+
+ case NJS_OBJECT_VALUE:
value = njs_object_value(value);
- if (njs_slow_path(njs_number(value) == 0.0
- && signbit(njs_number(value))))
- {
+ switch (value->type) {
+ case NJS_BOOLEAN:
+ if (njs_is_true(value)) {
+ njs_chb_append_literal(chain, "[Boolean: true]");
- njs_chb_append_literal(chain, "[Number: -0]");
- break;
- }
+ } else {
+ njs_chb_append_literal(chain, "[Boolean: false]");
+ }
- ret = njs_number_to_string(stringify->vm, &str_val, value);
- if (njs_slow_path(ret != NJS_OK)) {
- return NJS_ERROR;
- }
+ break;
- njs_string_get(&str_val, &str);
- njs_chb_sprintf(chain, 16 + str.length, "[Number: %V]", &str);
+ case NJS_NUMBER:
+ if (njs_slow_path(njs_number(value) == 0.0
+ && signbit(njs_number(value))))
+ {
- break;
+ njs_chb_append_literal(chain, "[Number: -0]");
+ break;
+ }
- case NJS_OBJECT_BOOLEAN:
- value = njs_object_value(value);
+ ret = njs_number_to_string(stringify->vm, &str_val, value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
+ }
- if (njs_is_true(value)) {
- njs_chb_append_literal(chain, "[Boolean: true]");
+ njs_string_get(&str_val, &str);
+ njs_chb_sprintf(chain, 16 + str.length, "[Number: %V]", &str);
+ break;
- } else {
- njs_chb_append_literal(chain, "[Boolean: false]");
- }
+ case NJS_SYMBOL:
+ ret = njs_symbol_descriptive_string(stringify->vm, &str_val, value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
+ }
- break;
+ njs_string_get(&str_val, &str);
+ njs_chb_sprintf(chain, 16 + str.length, "[Symbol: %V]", &str);
- case NJS_BOOLEAN:
- if (njs_is_true(value)) {
- njs_chb_append_literal(chain, "true");
+ break;
- } else {
- njs_chb_append_literal(chain, "false");
+ case NJS_STRING:
+ default:
+ njs_chb_append_literal(chain, "[String: ");
+ njs_json_append_string(chain, value, '\'');
+ njs_chb_append_literal(chain, "]");
+ break;
}
break;
- case NJS_UNDEFINED:
- njs_chb_append_literal(chain, "undefined");
- break;
-
- case NJS_NULL:
- njs_chb_append_literal(chain, "null");
- break;
-
- case NJS_INVALID:
- njs_chb_append_literal(chain, "<empty>");
- break;
-
case NJS_FUNCTION:
ret = njs_value_property(stringify->vm, value,
njs_value_arg(&name_string), &tag);
{
return (value->type == NJS_OBJECT && !njs_object(value)->error_data)
|| (value->type == NJS_ARRAY)
- || (value->type >= NJS_OBJECT_SPECIAL_MAX);
+ || (value->type >= NJS_OBJECT_SPECIAL_MAX
+ && !njs_is_object_primitive(value));
}
njs_number_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- njs_int_t ret;
- njs_value_t *value;
- njs_object_t *object;
+ njs_int_t ret;
+ njs_value_t *value;
+ njs_object_value_t *object;
if (nargs == 1) {
value = njs_value_arg(&njs_value_zero);
}
if (vm->top_frame->ctor) {
- object = njs_object_value_alloc(vm, value, NJS_NUMBER);
+ object = njs_object_value_alloc(vm, NJS_OBJ_TYPE_NUMBER, 0, value);
if (njs_slow_path(object == NULL)) {
return NJS_ERROR;
}
- njs_set_type_object(&vm->retval, object, NJS_OBJECT_NUMBER);
+ njs_set_object_value(&vm->retval, object);
} else {
njs_set_number(&vm->retval, njs_number(value));
if (value->type != NJS_NUMBER) {
- if (value->type == NJS_OBJECT_NUMBER) {
+ if (njs_is_object_number(value)) {
value = njs_object_value(value);
} else {
if (value->type != NJS_NUMBER) {
- if (value->type == NJS_OBJECT_NUMBER) {
+ if (njs_is_object_number(value)) {
value = njs_object_value(value);
} else {
value = &args[0];
if (value->type != NJS_NUMBER) {
- if (value->type == NJS_OBJECT_NUMBER) {
+ if (njs_is_object_number(value)) {
value = njs_object_value(value);
} else {
value = &args[0];
if (value->type != NJS_NUMBER) {
- if (value->type == NJS_OBJECT_NUMBER) {
+ if (njs_is_object_number(value)) {
value = njs_object_value(value);
} else {
value = &args[0];
if (value->type != NJS_NUMBER) {
- if (value->type == NJS_OBJECT_NUMBER) {
+ if (njs_is_object_number(value)) {
value = njs_object_value(value);
} else {
.prototype_props = &njs_number_prototype_init,
.prototype_value = { .object_value = {
.value = njs_value(NJS_NUMBER, 0, 0.0),
- .object = { .type = NJS_OBJECT_NUMBER } }
+ .object = { .type = NJS_OBJECT_VALUE } }
},
};
}
-njs_object_t *
-njs_object_value_alloc(njs_vm_t *vm, const njs_value_t *value, njs_uint_t type)
+njs_object_value_t *
+njs_object_value_alloc(njs_vm_t *vm, njs_uint_t prototype_index, size_t extra,
+ const njs_value_t *value)
{
- njs_uint_t index;
njs_object_value_t *ov;
- ov = njs_mp_alloc(vm->mem_pool, sizeof(njs_object_value_t));
+ ov = njs_mp_alloc(vm->mem_pool, sizeof(njs_object_value_t) + extra);
+ if (njs_slow_path(ov == NULL)) {
+ njs_memory_error(vm);
+ return NULL;
+ }
- if (njs_fast_path(ov != NULL)) {
- njs_lvlhsh_init(&ov->object.hash);
+ njs_lvlhsh_init(&ov->object.hash);
- if (type == NJS_STRING) {
- ov->object.shared_hash = vm->shared->string_instance_hash;
+ if (prototype_index == NJS_OBJ_TYPE_STRING) {
+ ov->object.shared_hash = vm->shared->string_instance_hash;
- } else {
- njs_lvlhsh_init(&ov->object.shared_hash);
- }
+ } else {
+ njs_lvlhsh_init(&ov->object.shared_hash);
+ }
- ov->object.type = njs_object_value_type(type);
- ov->object.shared = 0;
- ov->object.extensible = 1;
- ov->object.error_data = 0;
- ov->object.fast_array = 0;
+ ov->object.type = NJS_OBJECT_VALUE;
+ ov->object.shared = 0;
+ ov->object.extensible = 1;
+ ov->object.error_data = 0;
+ ov->object.fast_array = 0;
- index = njs_primitive_prototype_index(type);
- ov->object.__proto__ = &vm->prototypes[index].object;
- ov->object.slots = NULL;
+ ov->object.__proto__ = &vm->prototypes[prototype_index].object;
+ ov->object.slots = NULL;
+ if (value != NULL) {
ov->value = *value;
-
- return &ov->object;
}
- njs_memory_error(vm);
-
- return NULL;
+ return ov;
}
njs_object_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- njs_uint_t type;
- njs_value_t *value;
- njs_object_t *object;
+ njs_uint_t type, index;
+ njs_value_t *value;
+ njs_object_t *object;
+ njs_object_value_t *obj_val;
value = njs_arg(args, nargs, 1);
type = value->type;
if (njs_is_null_or_undefined(value)) {
-
object = njs_object_alloc(vm);
if (njs_slow_path(object == NULL)) {
return NJS_ERROR;
}
- type = NJS_OBJECT;
-
- } else {
+ njs_set_object(&vm->retval, object);
- if (njs_is_object(value)) {
- object = njs_object(value);
+ return NJS_OK;
+ }
- } else if (njs_is_primitive(value)) {
+ if (njs_is_primitive(value)) {
+ index = njs_primitive_prototype_index(type);
+ obj_val = njs_object_value_alloc(vm, index, 0, value);
+ if (njs_slow_path(obj_val == NULL)) {
+ return NJS_ERROR;
+ }
- /* value->type is the same as prototype offset. */
- object = njs_object_value_alloc(vm, value, type);
- if (njs_slow_path(object == NULL)) {
- return NJS_ERROR;
- }
+ njs_set_object_value(&vm->retval, obj_val);
- type = njs_object_value_type(type);
+ return NJS_OK;
+ }
- } else {
- njs_type_error(vm, "unexpected constructor argument:%s",
- njs_type_string(type));
+ if (njs_slow_path(!njs_is_object(value))) {
+ njs_type_error(vm, "unexpected constructor argument:%s",
+ njs_type_string(type));
- return NJS_ERROR;
- }
+ return NJS_ERROR;
}
- njs_set_type_object(&vm->retval, object, type);
+ njs_value_assign(&vm->retval, value);
return NJS_OK;
}
items, kind);
break;
- case NJS_OBJECT_STRING:
+ case NJS_OBJECT_VALUE:
obj_val = (njs_object_value_t *) object;
- ret = njs_object_enumerate_string(vm, &obj_val->value, items, kind);
- break;
+ if (njs_is_string(&obj_val->value)) {
+ ret = njs_object_enumerate_string(vm, &obj_val->value, items,
+ kind);
+ break;
+ }
+
+ /* Fall through. */
default:
goto object;
items, kind);
break;
- case NJS_OBJECT_STRING:
+ case NJS_OBJECT_VALUE:
obj_val = (njs_object_value_t *) object;
- ret = njs_object_enumerate_string(vm, &obj_val->value, items, kind);
- break;
+ if (njs_is_string(&obj_val->value)) {
+ ret = njs_object_enumerate_string(vm, &obj_val->value, items,
+ kind);
+ break;
+ }
+
+ /* Fall through. */
default:
goto object;
njs_object_get_prototype_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- uint32_t index, type;
+ uint32_t index;
njs_value_t *value;
value = njs_arg(args, nargs, 1);
if (!njs_is_null_or_undefined(value)) {
index = njs_primitive_prototype_index(value->type);
- type = njs_is_symbol(value) ? NJS_OBJECT
- : njs_object_value_type(value->type);
- njs_set_type_object(&vm->retval, &vm->prototypes[index].object, type);
+ if (njs_is_symbol(value)) {
+ njs_set_object(&vm->retval, &vm->prototypes[index].object);
+
+ } else {
+ njs_set_object_value(&vm->retval,
+ &vm->prototypes[index].object_value);
+ }
return NJS_OK;
}
njs_long_string("[object Boolean]");
static const njs_value_t njs_object_number_string =
njs_long_string("[object Number]");
-static const njs_value_t njs_object_symbol_string =
- njs_long_string("[object Symbol]");
static const njs_value_t njs_object_string_string =
njs_long_string("[object String]");
-static const njs_value_t njs_object_data_string =
- njs_string("[object Data]");
-static const njs_value_t njs_object_exernal_string =
- njs_long_string("[object External]");
static const njs_value_t njs_object_object_string =
njs_long_string("[object Object]");
static const njs_value_t njs_object_array_string =
{
u_char *p;
njs_int_t ret;
- njs_value_t tag, *value;
+ njs_value_t tag, *this;
njs_string_prop_t string;
const njs_value_t *name;
- static const njs_value_t *class_name[NJS_VALUE_TYPE_MAX] = {
- /* Primitives. */
- &njs_object_null_string,
- &njs_object_undefined_string,
- &njs_object_boolean_string,
- &njs_object_number_string,
- &njs_object_symbol_string,
- &njs_object_string_string,
-
- &njs_object_data_string,
- &njs_object_exernal_string,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
-
- /* Objects. */
- &njs_object_object_string,
- &njs_object_array_string,
- &njs_object_boolean_string,
- &njs_object_number_string,
- &njs_object_symbol_string,
- &njs_object_string_string,
- &njs_object_function_string,
- &njs_object_regexp_string,
- &njs_object_date_string,
- &njs_object_object_string,
- &njs_object_object_string,
- &njs_object_object_string,
- &njs_object_object_string,
- };
-
- value = njs_argument(args, 0);
- name = class_name[value->type];
+ this = njs_argument(args, 0);
- if (njs_is_null_or_undefined(value)) {
- vm->retval = *name;
+ if (njs_is_null_or_undefined(this)) {
+ vm->retval = njs_is_null(this) ? njs_object_null_string
+ : njs_object_undefined_string;
return NJS_OK;
}
- if (njs_is_error(value)) {
- name = &njs_object_error_string;
+ ret = njs_value_to_object(vm, this);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
- if (njs_is_object(value)
- && njs_lvlhsh_eq(&njs_object(value)->shared_hash,
+ name = &njs_object_object_string;
+
+ if (njs_is_array(this)) {
+ name = &njs_object_array_string;
+
+ } else if (njs_is_object(this)
+ && njs_lvlhsh_eq(&njs_object(this)->shared_hash,
&vm->shared->arguments_object_instance_hash))
{
name = &njs_object_arguments_string;
+
+ } else if (njs_is_function(this)) {
+ name = &njs_object_function_string;
+
+ } else if (njs_is_error(this)) {
+ name = &njs_object_error_string;
+
+ } else if (njs_is_object_value(this)) {
+
+ switch (njs_object_value(this)->type) {
+ case NJS_BOOLEAN:
+ name = &njs_object_boolean_string;
+ break;
+
+ case NJS_NUMBER:
+ name = &njs_object_number_string;
+ break;
+
+ case NJS_STRING:
+ name = &njs_object_string_string;
+ break;
+
+ default:
+ break;
+ }
+
+ } else if (njs_is_date(this)) {
+ name = &njs_object_date_string;
+
+ } else if (njs_is_regexp(this)) {
+ name = &njs_object_regexp_string;
}
- ret = njs_object_string_tag(vm, value, &tag);
+ ret = njs_object_string_tag(vm, this, &tag);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
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_t *njs_object_value_alloc(njs_vm_t *vm, const njs_value_t *value,
- njs_uint_t type);
+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,
njs_object_enum_t kind, njs_object_enum_type_t type, njs_bool_t all);
njs_array_t *njs_object_own_enumerate(njs_vm_t *vm, const njs_object_t *object,
njs_value_t primitive;
if (njs_slow_path(!njs_is_primitive(value))) {
- if (njs_slow_path(value->type == NJS_OBJECT_SYMBOL)) {
+ if (njs_slow_path(njs_is_object_symbol(value))) {
/* should fail */
value = njs_object_value(value);
njs_string_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- njs_int_t ret;
- njs_value_t *value;
- njs_object_t *object;
+ njs_int_t ret;
+ njs_value_t *value;
+ njs_object_value_t *object;
if (nargs == 1) {
value = njs_value_arg(&njs_string_empty);
}
if (vm->top_frame->ctor) {
- object = njs_object_value_alloc(vm, value, value->type);
+ object = njs_object_value_alloc(vm, NJS_OBJ_TYPE_STRING, 0, value);
if (njs_slow_path(object == NULL)) {
return NJS_ERROR;
}
- njs_set_type_object(&vm->retval, object, NJS_OBJECT_STRING);
+ njs_set_object_value(&vm->retval, object);
} else {
vm->retval = *value;
proto = njs_object(value);
do {
- if (njs_fast_path(proto->type == NJS_OBJECT_STRING)) {
+ if (njs_fast_path(proto->type == NJS_OBJECT_VALUE)) {
break;
}
if (value->type != NJS_STRING) {
- if (value->type == NJS_OBJECT_STRING) {
+ if (njs_is_object_string(value)) {
value = njs_object_value(value);
} else {
value = njs_arg(args, nargs, 1);
- switch (value->type) {
- case NJS_OBJECT_STRING:
- value = njs_object_value(value);
-
- /* Fall through. */
-
- case NJS_STRING:
+ if (njs_is_string(value)) {
return njs_string_bytes_from_string(vm, value, njs_arg(args, nargs, 2));
- default:
- if (njs_is_object(value)) {
- return njs_string_bytes_from_array_like(vm, value);
+ } else if (njs_is_object(value)) {
+
+ if (njs_is_object_string(value)) {
+ value = njs_object_value(value);
+ return njs_string_bytes_from_string(vm, value,
+ njs_arg(args, nargs, 2));
}
+
+ return njs_string_bytes_from_array_like(vm, value);
}
njs_type_error(vm, "value must be a string or array-like object");
.prototype_props = &njs_string_prototype_init,
.prototype_value = { .object_value = {
.value = njs_string(""),
- .object = { .type = NJS_OBJECT_STRING } }
+ .object = { .type = NJS_OBJECT_VALUE } }
},
};
if (value->type != NJS_SYMBOL) {
- if (value->type == NJS_OBJECT_SYMBOL) {
+ if (njs_is_object_symbol(value)) {
value = njs_object_value(value);
} else {
case NJS_TYPED_ARRAY:
return "typed array";
- case NJS_OBJECT_BOOLEAN:
- return "object boolean";
-
- case NJS_OBJECT_NUMBER:
- return "object number";
-
- case NJS_OBJECT_SYMBOL:
- return "object symbol";
-
- case NJS_OBJECT_STRING:
- return "object string";
-
case NJS_FUNCTION:
return "function";
case NJS_ARRAY_BUFFER:
case NJS_DATA_VIEW:
case NJS_TYPED_ARRAY:
- case NJS_OBJECT_BOOLEAN:
- case NJS_OBJECT_NUMBER:
- case NJS_OBJECT_SYMBOL:
- case NJS_OBJECT_STRING:
case NJS_REGEXP:
case NJS_DATE:
case NJS_PROMISE:
break;
- case NJS_OBJECT_STRING:
+ case NJS_OBJECT_VALUE:
+ ov = (njs_object_value_t *) proto;
+ if (!njs_is_string(&ov->value)) {
+ break;
+ }
+
num = njs_key_to_index(key);
if (njs_fast_path(njs_key_is_integer_index(num, key))) {
ov = (njs_object_value_t *) proto;
}
}
+ break;
+
default:
break;
}
njs_int_t
njs_value_to_object(njs_vm_t *vm, njs_value_t *value)
{
- njs_object_t *object;
+ njs_uint_t index;
+ njs_object_value_t *object;
if (njs_slow_path(njs_is_null_or_undefined(value))) {
njs_type_error(vm, "cannot convert null or undefined to object");
}
if (njs_is_primitive(value)) {
- object = njs_object_value_alloc(vm, value, value->type);
+ index = njs_primitive_prototype_index(value->type);
+ object = njs_object_value_alloc(vm, index, 0, value);
if (njs_slow_path(object == NULL)) {
return NJS_ERROR;
}
- njs_set_type_object(value, object, njs_object_value_type(value->type));
+ njs_set_object_value(value, object);
return NJS_OK;
}
*/
NJS_INVALID,
- /*
- * The object types are >= NJS_OBJECT, this is used in njs_is_object().
- * NJS_OBJECT_BOOLEAN, NJS_OBJECT_NUMBER, and NJS_OBJECT_STRING must be
- * in the same order as NJS_BOOLEAN, NJS_NUMBER, and NJS_STRING. It is
- * used in njs_primitive_prototype_index(). The order of object types
- * is used in vm->prototypes and vm->constructors arrays.
- */
NJS_OBJECT = 0x10,
NJS_ARRAY,
-#define NJS_OBJECT_WRAPPER_MIN (NJS_OBJECT_BOOLEAN)
- NJS_OBJECT_BOOLEAN,
- NJS_OBJECT_NUMBER,
- NJS_OBJECT_SYMBOL,
- NJS_OBJECT_STRING,
-#define NJS_OBJECT_WRAPPER_MAX (NJS_OBJECT_STRING + 1)
#define NJS_OBJECT_SPECIAL_MIN (NJS_FUNCTION)
NJS_FUNCTION,
NJS_REGEXP,
((value)->type == NJS_OBJECT_VALUE)
-#define njs_is_object_data(_value, tag) \
+#define njs_is_object_boolean(_value) \
(((_value)->type == NJS_OBJECT_VALUE) \
- && njs_is_data(njs_object_value(_value), tag))
+ && njs_is_boolean(njs_object_value(_value)))
-#define njs_is_object_string(value) \
- ((value)->type == NJS_OBJECT_STRING)
+#define njs_is_object_number(_value) \
+ (((_value)->type == NJS_OBJECT_VALUE) \
+ && njs_is_number(njs_object_value(_value)))
-#define njs_object_value_type(type) \
- (type + NJS_OBJECT)
+#define njs_is_object_symbol(_value) \
+ (((_value)->type == NJS_OBJECT_VALUE) \
+ && njs_is_symbol(njs_object_value(_value)))
+
+
+#define njs_is_object_string(_value) \
+ (((_value)->type == NJS_OBJECT_VALUE) \
+ && njs_is_string(njs_object_value(_value)))
+
+
+#define njs_is_object_primitive(_value) \
+ (((_value)->type == NJS_OBJECT_VALUE) \
+ && njs_is_primitive(njs_object_value(_value)))
+
+
+#define njs_is_object_data(_value, tag) \
+ (((_value)->type == NJS_OBJECT_VALUE) \
+ && njs_is_data(njs_object_value(_value), tag))
#define njs_is_array(value) \
njs_value_t primitive;
if (njs_slow_path(!njs_is_primitive(value))) {
- if (njs_slow_path(value->type == NJS_OBJECT_SYMBOL)) {
+ if (njs_slow_path(njs_is_object_symbol(value))) {
/* should fail */
value = njs_object_value(value);
njs_value_t primitive;
if (njs_slow_path(!njs_is_primitive(value))) {
- if (njs_slow_path(value->type == NJS_OBJECT_SYMBOL)) {
+ if (njs_slow_path(njs_is_object_symbol(value))) {
/* should fail */
value = njs_object_value(value);
&njs_string_undefined,
&njs_string_undefined,
- &njs_string_object,
- &njs_string_object,
- &njs_string_object,
- &njs_string_object,
&njs_string_object,
&njs_string_object,
&njs_string_function,
njs_str("β") },
{ njs_str("var s = new String('αβ'); s[1] = 'b'"),
- njs_str("TypeError: Cannot assign to read-only property \"1\" of object string") },
+ njs_str("TypeError: Cannot assign to read-only property \"1\" of object") },
{ njs_str("var o = Object.create(new String('αβ')); o[1] = 'a'"),
njs_str("TypeError: Cannot assign to read-only property \"1\" of object") },
"JSON.stringify(a)"),
njs_str("[null,null,\"a\"]") },
+ { njs_str(njs_declare_sparse_array("a", 8)
+ "a[1] = 'a'; a[2] = 'b'; a.length = 3;"
+ "JSON.stringify({a:1,b:2,c:3}, a)"),
+ njs_str("{\"a\":1,\"b\":2}") },
+
{ njs_str("var a = [1,2,3];"
"Object.defineProperty(a, '1', {enumerable:false});"
"JSON.stringify(a)"),