array->start = array->data;
nxt_lvlhsh_init(&array->object.hash);
nxt_lvlhsh_init(&array->object.shared_hash);
- array->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_ARRAY];
+ array->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_ARRAY].object;
+ array->object.type = NJS_ARRAY;
array->object.shared = 0;
array->size = size;
array->length = length;
#define NJS_ARRAY_SPARE 8
-struct njs_array_s {
- /* Must be aligned to njs_value_t. */
- njs_object_t object;
- uint32_t size;
- uint32_t length;
- njs_value_t *start;
- njs_value_t *data;
-};
-
njs_array_t *njs_array_alloc(njs_vm_t *vm, uint32_t length, uint32_t spare);
njs_ret_t njs_array_string_add(njs_vm_t *vm, njs_array_t *array, u_char *start,
nxt_int_t
njs_builtin_objects_create(njs_vm_t *vm)
{
- nxt_int_t ret;
- nxt_uint_t i;
- njs_object_t *objects, *prototypes;
- njs_function_t *functions, *constructors;
+ nxt_int_t ret;
+ nxt_uint_t i;
+ njs_object_t *objects;
+ njs_function_t *functions, *constructors;
+ njs_object_prototype_t *prototypes;
static const njs_object_init_t *prototype_init[] = {
&njs_object_prototype_init,
&njs_date_prototype_init,
};
+ static const njs_object_prototype_t prototype_values[] = {
+ { .object.type = NJS_OBJECT },
+ { .object.type = NJS_ARRAY },
+
+ /*
+ * The .object.type field must be initialzed after the .value field,
+ * otherwise SunC 5.9 treats the .value as .object.value or so.
+ */
+ { .object_value = { .value = njs_value(NJS_BOOLEAN, 0, 0.0),
+ .object.type = NJS_OBJECT_BOOLEAN } },
+
+ { .object_value = { .value = njs_value(NJS_NUMBER, 0, 0.0),
+ .object.type = NJS_OBJECT_NUMBER } },
+
+ { .object_value = { .value = njs_string(""),
+ .object.type = NJS_OBJECT_STRING } },
+
+ { .object.type = NJS_FUNCTION },
+ { .object.type = NJS_REGEXP },
+
+ { .date = { .time = NJS_NAN, .object.type = NJS_DATE } },
+ };
+
static const njs_object_init_t *constructor_init[] = {
&njs_object_constructor_init,
&njs_array_constructor_init,
prototypes = vm->shared->prototypes;
for (i = NJS_PROTOTYPE_OBJECT; i < NJS_PROTOTYPE_MAX; i++) {
- ret = njs_object_hash_create(vm, &prototypes[i].shared_hash,
+ prototypes[i] = prototype_values[i];
+
+ ret = njs_object_hash_create(vm, &prototypes[i].object.shared_hash,
prototype_init[i]->properties,
prototype_init[i]->items);
if (nxt_slow_path(ret != NXT_OK)) {
}
}
+ prototypes[NJS_PROTOTYPE_REGEXP].regexp.pattern =
+ vm->empty_regexp.data.u.regexp->pattern;
+
constructors = vm->shared->constructors;
for (i = NJS_CONSTRUCTOR_OBJECT; i < NJS_CONSTRUCTOR_MAX; i++) {
size_t size;
nxt_uint_t i;
njs_value_t *values;
- njs_object_t *function_prototype;
+ njs_object_t *object_prototype, *function_prototype;
/*
* Copy both prototypes and constructors arrays by one memcpy()
* because they are stored together.
*/
- size = NJS_PROTOTYPE_MAX * sizeof(njs_object_t)
+ size = NJS_PROTOTYPE_MAX * sizeof(njs_object_prototype_t)
+ NJS_CONSTRUCTOR_MAX * sizeof(njs_function_t);
memcpy(vm->prototypes, vm->shared->prototypes, size);
+ object_prototype = &vm->prototypes[NJS_PROTOTYPE_OBJECT].object;
+
for (i = NJS_PROTOTYPE_ARRAY; i < NJS_PROTOTYPE_MAX; i++) {
- vm->prototypes[i].__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+ vm->prototypes[i].object.__proto__ = object_prototype;
}
- function_prototype = &vm->prototypes[NJS_CONSTRUCTOR_FUNCTION];
+ function_prototype = &vm->prototypes[NJS_CONSTRUCTOR_FUNCTION].object;
values = vm->scopes[NJS_SCOPE_GLOBAL];
for (i = NJS_CONSTRUCTOR_OBJECT; i < NJS_CONSTRUCTOR_MAX; i++) {
nxt_lvlhsh_init(&date->object.hash);
nxt_lvlhsh_init(&date->object.shared_hash);
+ date->object.type = NJS_DATE;
date->object.shared = 0;
- date->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_DATE];
+ date->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_DATE].object;
date->time = time;
#define _NJS_DATE_H_INCLUDED_
-struct njs_date_s {
- njs_object_t object;
- double time;
-};
-
-
njs_ret_t njs_date_constructor(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused);
*/
function->object.shared_hash = vm->shared->function_prototype_hash;
+ function->object.type = NJS_FUNCTION;
function->object.shared = 1;
function->args_offset = 1;
if (nxt_fast_path(function != NULL)) {
*function = *value->data.u.function;
- function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION];
+ function->object.__proto__ =
+ &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object;
function->object.shared = 0;
value->data.u.function = function;
}
*function = *args[0].data.u.function;
- function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION];
+ function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object;
function->object.shared = 0;
if (nargs == 1) {
if (nxt_fast_path(object != NULL)) {
nxt_lvlhsh_init(&object->hash);
nxt_lvlhsh_init(&object->shared_hash);
- object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+ object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT].object;
+ object->type = NJS_OBJECT;
object->shared = 0;
}
if (nxt_fast_path(object != NULL)) {
*object = *value->data.u.object;
- object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+ object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT].object;
object->shared = 0;
value->data.u.object = object;
}
if (nxt_fast_path(ov != NULL)) {
nxt_lvlhsh_init(&ov->object.hash);
nxt_lvlhsh_init(&ov->object.shared_hash);
+ ov->object.type = njs_object_value_type(type);
ov->object.shared = 0;
index = njs_primitive_prototype_index(type);
- ov->object.__proto__ = &vm->prototypes[index];
+ ov->object.__proto__ = &vm->prototypes[index].object;
ov->value = *value;
}
return NXT_ERROR;
}
- type = NJS_OBJECT + value->type;
+ type = njs_object_value_type(value->type);
} else {
vm->exception = &njs_exception_type_error;
njs_ret_t
njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value)
{
+ nxt_uint_t index;
njs_object_t *proto;
/*
* and have to return different results for primitive type and for objects.
*/
if (njs_is_object(value)) {
- proto = value->data.u.object->__proto__;
+ proto = value->data.u.object->__proto__;
} else {
- proto = &vm->prototypes[njs_primitive_prototype_index(value->type)];
+ index = njs_primitive_prototype_index(value->type);
+ proto = &vm->prototypes[index].object;
}
vm->retval.data.u.object = proto;
- vm->retval.type = NJS_OBJECT;
+ vm->retval.type = proto->type;
vm->retval.data.truth = 1;
return NXT_OK;
if (index >= 0 && index < NJS_PROTOTYPE_MAX) {
proto = njs_property_prototype_create(vm, &function->object.hash,
- &vm->prototypes[index]);
+ &vm->prototypes[index].object);
}
if (proto == NULL) {
/* GC */
prop->value.data.u.object = prototype;
- prop->value.type = NJS_OBJECT;
+ prop->value.type = prototype->type;
prop->value.data.truth = 1;
prop->enumerable = 0;
if (nxt_fast_path(proto != NULL)) {
vm->retval.data.u.object = proto;
- vm->retval.type = NJS_OBJECT;
+ vm->retval.type = proto->type;
vm->retval.data.truth = 1;
} else {
static njs_ret_t
njs_object_prototype_create_constructor(njs_vm_t *vm, njs_value_t *value)
{
- int32_t index;
- njs_value_t *cons;
- njs_object_t *prototype;
+ int32_t index;
+ njs_value_t *cons;
+ njs_object_t *object;
+ njs_object_prototype_t *prototype;
if (njs_is_object(value)) {
- prototype = value->data.u.object;
+ object = value->data.u.object;
do {
+ prototype = (njs_object_prototype_t *) object;
index = prototype - vm->prototypes;
if (index >= 0 && index < NJS_PROTOTYPE_MAX) {
goto found;
}
- prototype = prototype->__proto__;
+ object = object->__proto__;
- } while (prototype != NULL);
+ } while (object != NULL);
nxt_thread_log_alert("prototype not found");
found:
- cons = njs_property_constructor_create(vm, &prototype->hash,
+ cons = njs_property_constructor_create(vm, &prototype->object.hash,
&vm->scopes[NJS_SCOPE_GLOBAL][index]);
if (nxt_fast_path(cons != NULL)) {
vm->retval = *cons;
njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused)
{
- int32_t index;
- njs_object_t *prototype;
+ int32_t index;
+ njs_object_t *object;
+ njs_object_prototype_t *prototype;
static const njs_value_t *class_name[] = {
/* Primitives. */
index = args[0].type;
if (njs_is_object(&args[0])) {
- prototype = args[0].data.u.object;
+ object = args[0].data.u.object;
do {
+ prototype = (njs_object_prototype_t *) object;
index = prototype - vm->prototypes;
if (index >= 0 && index < NJS_PROTOTYPE_MAX) {
goto found;
}
- prototype = prototype->__proto__;
+ object = object->__proto__;
- } while (prototype != NULL);
+ } while (object != NULL);
nxt_thread_log_alert("prototype not found");
#define _NJS_OBJECT_H_INCLUDED_
-struct njs_object_value_s {
- njs_object_t object;
- njs_value_t value;
-};
-
-
typedef enum {
NJS_PROPERTY = 0,
NJS_GETTER,
if (nxt_fast_path(regexp != NULL)) {
nxt_lvlhsh_init(®exp->object.hash);
nxt_lvlhsh_init(®exp->object.shared_hash);
- regexp->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_REGEXP];
+ regexp->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_REGEXP].object;
+ regexp->object.type = NJS_REGEXP;
regexp->object.shared = 0;
regexp->last_index = 0;
regexp->pattern = pattern;
} njs_regexp_flags_t;
-struct njs_regexp_s {
- /* Must be aligned to njs_value_t. */
- njs_object_t object;
-
- uint32_t last_index;
-
- njs_regexp_pattern_t *pattern;
-
- /*
- * This string value can be unaligned since
- * it never used in nJSVM operations.
- */
- njs_value_t string;
-};
-
-
njs_ret_t njs_regexp_init(njs_vm_t *vm);
njs_ret_t njs_regexp_constructor(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused);
function = nxt_mem_cache_zalloc(vm->mem_cache_pool, sizeof(njs_function_t));
if (nxt_fast_path(function != NULL)) {
- function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION];
+ function->object.__proto__ =
+ &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object;
function->args_offset = 1;
code = (njs_vmcode_function_t *) vm->current;
return NJS_PRIMITIVE_VALUE;
}
- obj = &vm->prototypes[njs_primitive_prototype_index(object->type)];
+ index = njs_primitive_prototype_index(object->type);
+ obj = &vm->prototypes[index].object;
break;
case NJS_STRING:
return NXT_DECLINED;
}
- obj = &vm->prototypes[NJS_PROTOTYPE_STRING];
+ obj = &vm->prototypes[NJS_PROTOTYPE_STRING].object;
break;
case NJS_ARRAY:
typedef struct njs_string_s njs_string_t;
+typedef struct njs_object_s njs_object_t;
typedef struct njs_object_init_s njs_object_init_t;
typedef struct njs_object_value_s njs_object_value_t;
typedef struct njs_array_s njs_array_t;
typedef struct njs_property_next_s njs_property_next_t;
-typedef struct njs_object_s njs_object_t;
-
-struct njs_object_s {
- /* A private hash of njs_object_prop_t. */
- nxt_lvlhsh_t hash;
-
- /* A shared hash of njs_object_prop_t. */
- nxt_lvlhsh_t shared_hash;
-
- /* An object __proto__. */
- njs_object_t *__proto__;
-
- uint32_t shared; /* 1 bit */
-};
-
-
-#define NJS_ARGS_TYPES_MAX 5
-
-struct njs_function_s {
- njs_object_t object;
-
- uint8_t args_types[NJS_ARGS_TYPES_MAX];
- uint8_t args_offset;
-
- /*
- * TODO Shared
- * When function object is used as value: in assignments,
- * as function argument, as property and as object to get properties.
- */
-
-#if (NXT_64BIT)
- uint8_t native;
- uint8_t continuation_size;
-#else
- uint8_t native;
- uint8_t continuation_size;
-#endif
-
- union {
- njs_function_lambda_t *lambda;
- njs_function_native_t native;
- } u;
-
- njs_value_t *bound;
-};
-
-
typedef struct njs_continuation_s njs_continuation_t;
struct njs_continuation_s {
};
+struct njs_object_s {
+ /* A private hash of njs_object_prop_t. */
+ nxt_lvlhsh_t hash;
+
+ /* A shared hash of njs_object_prop_t. */
+ nxt_lvlhsh_t shared_hash;
+
+ /* An object __proto__. */
+ njs_object_t *__proto__;
+
+ /* The type is used in constructor prototypes. */
+ njs_value_type_t type:8;
+ uint8_t shared; /* 1 bit */
+};
+
+
+struct njs_object_value_s {
+ njs_object_t object;
+ /* The value can be unaligned since it never used in nJSVM operations. */
+ njs_value_t value;
+};
+
+
+struct njs_array_s {
+ njs_object_t object;
+ uint32_t size;
+ uint32_t length;
+ njs_value_t *start;
+ njs_value_t *data;
+};
+
+
+#define NJS_ARGS_TYPES_MAX 5
+
+struct njs_function_s {
+ njs_object_t object;
+
+ uint8_t args_types[NJS_ARGS_TYPES_MAX];
+ uint8_t args_offset;
+
+ /*
+ * TODO Shared
+ * When function object is used as value: in assignments,
+ * as function argument, as property and as object to get properties.
+ */
+
+#if (NXT_64BIT)
+ uint8_t native;
+ uint8_t continuation_size;
+#else
+ uint8_t native;
+ uint8_t continuation_size;
+#endif
+
+ union {
+ njs_function_lambda_t *lambda;
+ njs_function_native_t native;
+ } u;
+
+ njs_value_t *bound;
+};
+
+
+struct njs_regexp_s {
+ njs_object_t object;
+ uint32_t last_index;
+ njs_regexp_pattern_t *pattern;
+ /*
+ * This string value can be unaligned since
+ * it never used in nJSVM operations.
+ */
+ njs_value_t string;
+};
+
+
+struct njs_date_s {
+ njs_object_t object;
+ double time;
+};
+
+
+typedef union {
+ njs_object_t object;
+ njs_object_value_t object_value;
+ njs_array_t array;
+ njs_function_t function;
+ njs_regexp_t regexp;
+ njs_date_t date;
+} njs_object_prototype_t;
+
+
#define njs_value(_type, _truth, _number) { \
.data = { \
.type = _type, \
(((value)->type & NJS_OBJECT) != 0)
+#define njs_object_value_type(type) \
+ (type + NJS_OBJECT)
+
+
#define njs_is_array(value) \
((value)->type == NJS_ARRAY)
#define njs_primitive_prototype_index(type) \
(NJS_PROTOTYPE_BOOLEAN + ((type) - NJS_BOOLEAN))
+#define njs_prototype_type(index) \
+ (index + NJS_OBJECT)
+
enum njs_constructor_e {
NJS_CONSTRUCTOR_OBJECT = NJS_PROTOTYPE_OBJECT,
* they are copied from njs_vm_shared_t by single memcpy()
* in njs_builtin_objects_clone().
*/
- njs_object_t prototypes[NJS_PROTOTYPE_MAX];
+ njs_object_prototype_t prototypes[NJS_PROTOTYPE_MAX];
njs_function_t constructors[NJS_CONSTRUCTOR_MAX];
nxt_mem_cache_pool_t *mem_cache_pool;
* The prototypes and constructors arrays must be togther because they are
* copied to njs_vm_t by single memcpy() in njs_builtin_objects_clone().
*/
- njs_object_t prototypes[NJS_PROTOTYPE_MAX];
+ njs_object_prototype_t prototypes[NJS_PROTOTYPE_MAX];
njs_function_t constructors[NJS_CONSTRUCTOR_MAX];
};
{ nxt_string("Object.prototype.__proto__ === null"),
nxt_string("true") },
+ { nxt_string("Object.prototype.toString.call(Object.prototype)"),
+ nxt_string("[object Object]") },
+
+ { nxt_string("Object.prototype"),
+ nxt_string("[object Object]") },
+
{ nxt_string("Object.constructor === Function"),
nxt_string("true") },
{ nxt_string("Array.prototype.__proto__ === Object.prototype"),
nxt_string("true") },
+ { nxt_string("Object.prototype.toString.call(Array.prototype)"),
+ nxt_string("[object Array]") },
+
+ { nxt_string("Array.prototype"),
+ nxt_string("") },
+
{ nxt_string("Array.constructor === Function"),
nxt_string("true") },
{ nxt_string("Boolean.prototype.__proto__ === Object.prototype"),
nxt_string("true") },
+ { nxt_string("Object.prototype.toString.call(Boolean.prototype)"),
+ nxt_string("[object Boolean]") },
+
+ { nxt_string("Boolean.prototype"),
+ nxt_string("false") },
+
{ nxt_string("Boolean.constructor === Function"),
nxt_string("true") },
{ nxt_string("Number.prototype.__proto__ === Object.prototype"),
nxt_string("true") },
+ { nxt_string("Object.prototype.toString.call(Number.prototype)"),
+ nxt_string("[object Number]") },
+
+ { nxt_string("Number.prototype"),
+ nxt_string("0") },
+
{ nxt_string("Number.constructor === Function"),
nxt_string("true") },
{ nxt_string("String.__proto__ === Function.prototype"),
nxt_string("true") },
+ { nxt_string("Object.prototype.toString.call(String.prototype)"),
+ nxt_string("[object String]") },
+
+ { nxt_string("String.prototype"),
+ nxt_string("") },
+
{ nxt_string("String.prototype.length"),
nxt_string("0") },
{ nxt_string("Function.prototype.__proto__ === Object.prototype"),
nxt_string("true") },
+ { nxt_string("Object.prototype.toString.call(Function.prototype)"),
+ nxt_string("[object Function]") },
+
+ { nxt_string("Function.prototype"),
+ nxt_string("[object Function]") },
+
{ nxt_string("Function.constructor === Function"),
nxt_string("true") },
{ nxt_string("RegExp.prototype.__proto__ === Object.prototype"),
nxt_string("true") },
+ { nxt_string("Object.prototype.toString.call(RegExp.prototype)"),
+ nxt_string("[object RegExp]") },
+
+ { nxt_string("RegExp.prototype"),
+ nxt_string("/(?:)/") },
+
{ nxt_string("RegExp.constructor === Function"),
nxt_string("true") },
{ nxt_string("Date.prototype.__proto__ === Object.prototype"),
nxt_string("true") },
+ { nxt_string("Date.prototype"),
+ nxt_string("Invalid Date") },
+
+ { nxt_string("Date.prototype.valueOf()"),
+ nxt_string("NaN") },
+
{ nxt_string("Date.constructor === Function"),
nxt_string("true") },