$(NXT_BUILDDIR)/libnjs.a: \
$(NXT_BUILDDIR)/njscript.o \
$(NXT_BUILDDIR)/njs_vm.o \
+ $(NXT_BUILDDIR)/njs_boolean.o \
$(NXT_BUILDDIR)/njs_number.o \
$(NXT_BUILDDIR)/njs_string.o \
$(NXT_BUILDDIR)/njs_object.o \
ar -r -c $(NXT_BUILDDIR)/libnjs.a \
$(NXT_BUILDDIR)/njscript.o \
$(NXT_BUILDDIR)/njs_vm.o \
+ $(NXT_BUILDDIR)/njs_boolean.o \
$(NXT_BUILDDIR)/njs_number.o \
$(NXT_BUILDDIR)/njs_string.o \
$(NXT_BUILDDIR)/njs_object.o \
-I$(NXT_LIB) -Injs \
njs/njs_vm.c
+$(NXT_BUILDDIR)/njs_boolean.o: \
+ $(NXT_BUILDDIR)/libnxt.a \
+ njs/njscript.h \
+ njs/njs_vm.h \
+ njs/njs_boolean.h \
+ njs/njs_object.h \
+ njs/njs_function.h \
+ njs/njs_boolean.c \
+
+ $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_boolean.o $(NXT_CFLAGS) \
+ -I$(NXT_LIB) -Injs \
+ njs/njs_boolean.c
+
$(NXT_BUILDDIR)/njs_number.o: \
$(NXT_BUILDDIR)/libnxt.a \
njs/njscript.h \
$(NXT_BUILDDIR)/libnxt.a \
njs/njscript.h \
njs/njs_vm.h \
+ njs/njs_boolean.h \
njs/njs_number.h \
njs/njs_string.h \
njs/njs_object.h \
--- /dev/null
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_types.h>
+#include <nxt_clang.h>
+#include <nxt_stub.h>
+#include <nxt_array.h>
+#include <nxt_lvlhsh.h>
+#include <nxt_mem_cache_pool.h>
+#include <njscript.h>
+#include <njs_vm.h>
+#include <njs_boolean.h>
+#include <njs_object.h>
+#include <njs_function.h>
+
+
+njs_ret_t
+njs_boolean_function(njs_vm_t *vm, njs_param_t *param)
+{
+ njs_object_t *object;
+ const njs_value_t *value;
+
+ if (param->nargs == 0) {
+ value = &njs_value_false;
+
+ } else {
+ value = njs_is_true(¶m->args[0]) ? &njs_value_true:
+ &njs_value_false;
+ }
+
+ if (vm->frame->ctor) {
+ /* value->type is the same as prototype offset. */
+ object = njs_object_value_alloc(vm, value, value->type);
+ if (nxt_slow_path(object == NULL)) {
+ return NXT_ERROR;
+ }
+
+ vm->retval.data.u.object = object;
+ vm->retval.type = NJS_OBJECT_BOOLEAN;
+ vm->retval.data.truth = 1;
+
+ } else {
+ vm->retval = *value;
+ }
+
+ return NXT_OK;
+}
+
+
+static const njs_object_prop_t njs_boolean_function_properties[] =
+{
+ /* Boolean.name == "Boolean". */
+ { njs_string("Boolean"),
+ njs_string("name"),
+ NJS_PROPERTY, 0, 0, 0, },
+
+ /* Boolean.length == 1. */
+ { njs_value(NJS_NUMBER, 1, 1.0),
+ njs_string("length"),
+ NJS_PROPERTY, 0, 0, 0, },
+
+ /* Boolean.prototype. */
+ { njs_getter(njs_object_prototype_create_prototype),
+ njs_string("prototype"),
+ NJS_NATIVE_GETTER, 0, 0, 0, },
+};
+
+
+nxt_int_t
+njs_boolean_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
+{
+ return njs_object_hash_create(vm, hash, njs_boolean_function_properties,
+ nxt_nitems(njs_boolean_function_properties));
+}
+
+
+static njs_ret_t
+njs_boolean_prototype_value_of(njs_vm_t *vm, njs_param_t *param)
+{
+ njs_value_t *value;
+
+ value = param->object;
+
+ if (value->type != NJS_BOOLEAN) {
+
+ if (value->type == NJS_OBJECT_BOOLEAN) {
+ value = &value->data.u.object_value->value;
+
+ } else {
+ vm->exception = &njs_exception_type_error;
+ return NXT_ERROR;
+ }
+ }
+
+ vm->retval = *value;
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_boolean_prototype_to_string(njs_vm_t *vm, njs_param_t *param)
+{
+ njs_value_t *value;
+
+ value = param->object;
+
+ if (value->type != NJS_BOOLEAN) {
+
+ if (value->type == NJS_OBJECT_BOOLEAN) {
+ value = &value->data.u.object_value->value;
+
+ } else {
+ vm->exception = &njs_exception_type_error;
+ return NXT_ERROR;
+ }
+ }
+
+ vm->retval = njs_is_true(value) ? njs_string_true : njs_string_false;
+
+ return NXT_OK;
+}
+
+
+static const njs_object_prop_t njs_boolean_prototype_properties[] =
+{
+ { njs_getter(njs_primitive_prototype_get_proto),
+ njs_string("__proto__"),
+ NJS_NATIVE_GETTER, 0, 0, 0, },
+
+ { njs_native_function(njs_boolean_prototype_value_of, 0),
+ njs_string("valueOf"),
+ NJS_METHOD, 0, 0, 0, },
+
+ { njs_native_function(njs_boolean_prototype_to_string, 0),
+ njs_string("toString"),
+ NJS_METHOD, 0, 0, 0, },
+};
+
+
+nxt_int_t
+njs_boolean_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
+{
+ return njs_object_hash_create(vm, hash, njs_boolean_prototype_properties,
+ nxt_nitems(njs_boolean_prototype_properties));
+}
--- /dev/null
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NJS_BOOLEAN_H_INCLUDED_
+#define _NJS_BOOLEAN_H_INCLUDED_
+
+
+njs_ret_t njs_boolean_function(njs_vm_t *vm, njs_param_t *param);
+nxt_int_t njs_boolean_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+nxt_int_t njs_boolean_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+
+
+#endif /* _NJS_BOOLEAN_H_INCLUDED_ */
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
+#include <njs_boolean.h>
#include <njs_number.h>
#include <njs_string.h>
#include <njs_object.h>
static const njs_shared_hash_t prototype_hash[] = {
njs_object_prototype_hash,
njs_array_prototype_hash,
- njs_stub_hash,
+ njs_boolean_prototype_hash,
njs_number_prototype_hash,
njs_string_prototype_hash,
njs_function_prototype_hash,
static const njs_shared_hash_t function_hash[] = {
njs_object_function_hash,
njs_array_function_hash,
- njs_stub_hash,
+ njs_boolean_function_hash,
njs_number_function_hash,
njs_string_function_hash,
njs_function_function_hash,
static const njs_native_t native_functions[] = {
njs_object_function,
njs_array_function,
- njs_stub_function,
+ njs_boolean_function,
njs_number_function,
njs_string_ctor_function,
njs_stub_function,
* NXT_OK property has been found in object,
* NXT_DECLINED property was not found in object,
* NJS_PRIMITIVE_VALUE property operation was applied to a numeric
- * or undefined value,
+ * or boolean value,
* NJS_STRING_VALUE property operation was applied to a string,
* NJS_ARRAY_VALUE object is array,
* NJS_EXTERNAL_VALUE object is external entity,
switch (object->type) {
- case NJS_NULL:
- case NJS_VOID:
- vm->exception = &njs_exception_type_error;
- return NXT_ERROR;
-
+ case NJS_BOOLEAN:
case NJS_NUMBER:
if (pq->query != NJS_PROPERTY_QUERY_GET) {
return NJS_PRIMITIVE_VALUE;
}
- obj = &vm->prototypes[NJS_PROTOTYPE_NUMBER];
+ obj = &vm->prototypes[object->type];
break;
case NJS_STRING:
obj = NULL;
break;
- default:
- return NJS_PRIMITIVE_VALUE;
+ default: /* NJS_VOID, NJS_NULL. */
+ vm->exception = &njs_exception_type_error;
+ return NXT_ERROR;
}
if (nxt_fast_path(njs_is_primitive(property))) {
* The object types have the third bit set. It is used in njs_is_object().
* NJS_OBJECT_BOOLEAN, NJS_OBJECT_NUMBER, and NJS_OBJECT_STRING must be
* equal to NJS_BOOLEAN, NJS_NUMBER, and NJS_STRING respectively with
- * the third bit set. It is used in njs_primitive_prototype_get_proto().
- * The order of object types is used in vm->prototypes and vm->functions
- * arrays.
+ * the third bit set. It is used in njs_primitive_prototype_get_proto()
+ * and in njs_property_query(). The order of object types is used in
+ * vm->prototypes and vm->functions arrays.
*/
NJS_OBJECT = 0x08,
NJS_ARRAY = 0x09,
{ nxt_string("a = 1; b = { x:2 }; a = b.x += (a = 1)"),
nxt_string("3") },
+ { nxt_string("a = undefined; a.b++; a.b"),
+ nxt_string("TypeError") },
+
+ { nxt_string("a = null; a.b++; a.b"),
+ nxt_string("TypeError") },
+
+ { nxt_string("a = true; a.b++; a.b"),
+ nxt_string("undefined") },
+
{ nxt_string("a = 1; a.b++; a.b"),
nxt_string("undefined") },
{ nxt_string("a = 1; 1 in a"),
nxt_string("TypeError") },
+ { nxt_string("a = true; 1 in a"),
+ nxt_string("TypeError") },
+
{ nxt_string("var n = { toString: function() { return 'a' } };"
"var o = { a: 5 }; o[n]"),
nxt_string("5") },
{ nxt_string("var o = { valueOf: function() { return 'OK' } } o.valueOf()"),
nxt_string("OK") },
+ { nxt_string("false.__proto__ === true.__proto__"),
+ nxt_string("true") },
+
{ nxt_string("0..__proto__ === 1..__proto__"),
nxt_string("true") },
{ nxt_string("[].constructor === Array"),
nxt_string("true") },
- /* TODO: Boolean */
+ { nxt_string("Boolean()"),
+ nxt_string("false") },
+
+ { nxt_string("Boolean(0)"),
+ nxt_string("false") },
+
+ { nxt_string("Boolean('')"),
+ nxt_string("false") },
+
+ { nxt_string("Boolean(1)"),
+ nxt_string("true") },
+
+ { nxt_string("Boolean('a')"),
+ nxt_string("true") },
+
+ { nxt_string("Boolean({})"),
+ nxt_string("true") },
+
+ { nxt_string("Boolean([])"),
+ nxt_string("true") },
+
+ { nxt_string("typeof Boolean(1)"),
+ nxt_string("boolean") },
+
+ { nxt_string("typeof new Boolean(1)"),
+ nxt_string("object") },
+
+ { nxt_string("Boolean.name"),
+ nxt_string("Boolean") },
+
+ { nxt_string("Boolean.length"),
+ nxt_string("1") },
+
+ { nxt_string("Boolean.__proto__ === Function.prototype"),
+ nxt_string("true") },
+
+ { nxt_string("Boolean.prototype.constructor === Boolean"),
+ nxt_string("true") },
+
+ { nxt_string("Boolean.prototype.__proto__ === Object.prototype"),
+ nxt_string("true") },
+
+ { nxt_string("Boolean.constructor === Function"),
+ nxt_string("true") },
+
+ { nxt_string("true.__proto__ === Boolean.prototype"),
+ nxt_string("true") },
+
+ { nxt_string("false.__proto__ === Boolean.prototype"),
+ nxt_string("true") },
{ nxt_string("Number()"),
nxt_string("0") },