$(NXT_BUILDDIR)/njs_array.o \
$(NXT_BUILDDIR)/njs_function.o \
$(NXT_BUILDDIR)/njs_regexp.o \
+ $(NXT_BUILDDIR)/njs_math.o \
$(NXT_BUILDDIR)/njs_extern.o \
$(NXT_BUILDDIR)/njs_variable.o \
$(NXT_BUILDDIR)/njs_builtin.o \
$(NXT_BUILDDIR)/njs_array.o \
$(NXT_BUILDDIR)/njs_function.o \
$(NXT_BUILDDIR)/njs_regexp.o \
+ $(NXT_BUILDDIR)/njs_math.o \
$(NXT_BUILDDIR)/njs_extern.o \
$(NXT_BUILDDIR)/njs_variable.o \
$(NXT_BUILDDIR)/njs_builtin.o \
-I$(NXT_LIB) -Injs $(NXT_PCRE_CFLAGS) \
njs/njs_regexp.c
+$(NXT_BUILDDIR)/njs_math.o: \
+ $(NXT_BUILDDIR)/libnxt.a \
+ njs/njscript.h \
+ njs/njs_vm.h \
+ njs/njs_object.h \
+ njs/njs_math.h \
+ njs/njs_math.c \
+
+ $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_math.o $(NXT_CFLAGS) \
+ -I$(NXT_LIB) -Injs \
+ njs/njs_math.c
+
$(NXT_BUILDDIR)/njs_extern.o: \
$(NXT_BUILDDIR)/libnxt.a \
njs/njscript.h \
nxt_lvlhsh_init(&array->object.hash);
nxt_lvlhsh_init(&array->object.shared_hash);
array->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_ARRAY];
+ array->object.shared = 0;
array->size = size;
array->length = length;
#include <njs_array.h>
#include <njs_function.h>
#include <njs_regexp.h>
+#include <njs_math.h>
#include <string.h>
{
nxt_int_t ret;
nxt_uint_t i;
- njs_object_t *prototypes;
+ njs_object_t *objects, *prototypes;
njs_function_t *functions;
static const njs_object_init_t *prototype_init[] = {
{ njs_eval_function, { 0 } },
};
+ static const njs_object_init_t *objects_init[] = {
+ &njs_math_object_init,
+ };
+
static const njs_object_prop_t null_proto_property = {
.type = NJS_WHITEOUT,
.name = njs_string("__proto__"),
return NXT_ERROR;
}
+ objects = vm->shared->objects;
+
+ for (i = NJS_OBJECT_MATH; i < NJS_OBJECT_MAX; i++) {
+ ret = njs_object_hash_create(vm, &objects[i].shared_hash,
+ objects_init[i]->properties,
+ objects_init[i]->items);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NXT_ERROR;
+ }
+
+ objects[i].shared = 1;
+ }
+
prototypes = vm->shared->prototypes;
for (i = NJS_PROTOTYPE_OBJECT; i < NJS_PROTOTYPE_MAX; i++) {
functions = vm->shared->functions;
for (i = NJS_FUNCTION_OBJECT; i < NJS_FUNCTION_MAX; i++) {
+ functions[i].object.shared = 0;
functions[i].native = 1;
functions[i].args_offset = 1;
- functions[i].shared = 0;
functions[i].u.native = native_functions[i].native;
functions[i].args_types[0] = native_functions[i].args_types[0];
functions[i].args_types[1] = native_functions[i].args_types[1];
nxt_string("OBJECT ") },
{ njs_vmcode_function, sizeof(njs_vmcode_function_t),
nxt_string("FUNCTION ") },
- { njs_vmcode_function_copy, sizeof(njs_vmcode_function_copy_t),
- nxt_string("FUNCTION COPY ") },
{ njs_vmcode_regexp, sizeof(njs_vmcode_regexp_t),
nxt_string("REGEXP ") },
+ { njs_vmcode_object_copy, sizeof(njs_vmcode_object_copy_t),
+ nxt_string("OBJECT COPY ") },
{ njs_vmcode_property_get, sizeof(njs_vmcode_prop_get_t),
nxt_string("PROPERTY GET ") },
function = nxt_mem_cache_zalloc(vm->mem_cache_pool, sizeof(njs_function_t));
if (nxt_fast_path(function != NULL)) {
+ /*
+ * nxt_mem_cache_zalloc() does also:
+ * nxt_lvlhsh_init(&function->object.hash);
+ * nxt_lvlhsh_init(&function->object.shared_hash);
+ * function->object.__proto__ = NULL;
+ */
+
+ function->object.shared = 1;
function->args_offset = 1;
- function->shared = 1;
function->u.lambda = nxt_mem_cache_zalloc(vm->mem_cache_pool,
sizeof(njs_function_lambda_t));
function = value->data.u.function;
- if (!function->shared) {
+ if (!function->object.shared) {
return function;
}
if (nxt_fast_path(function != NULL)) {
*function = *value->data.u.function;
function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION];
- function->shared = 0;
+ function->object.shared = 0;
value->data.u.function = function;
}
*function = *args[0].data.u.function;
function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION];
- function->shared = 0;
+ function->object.shared = 0;
if (nargs == 1) {
args = (njs_value_t *) &njs_value_void;
njs_parser_node_t *node);
static nxt_int_t njs_generate_name(njs_vm_t *vm, njs_parser_t *parser,
njs_parser_node_t *node);
+static nxt_int_t njs_generate_builtin_object(njs_vm_t *vm, njs_parser_t *parser,
+ njs_parser_node_t *node);
static nxt_int_t njs_generate_variable(njs_parser_t *parser,
njs_parser_node_t *node);
static nxt_int_t njs_generate_if_statement(njs_vm_t *vm, njs_parser_t *parser,
case NJS_TOKEN_NAME:
return njs_generate_name(vm, parser, node);
+ case NJS_TOKEN_MATH:
+ return njs_generate_builtin_object(vm, parser, node);
+
case NJS_TOKEN_FUNCTION:
return njs_generate_function_declaration(vm, parser, node);
static nxt_int_t
njs_generate_name(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node)
{
- njs_index_t index;
- njs_value_t *value;
- njs_vmcode_function_copy_t *copy;
+ njs_index_t index;
+ njs_value_t *value;
+ njs_vmcode_object_copy_t *copy;
index = node->u.variable->index;
value = njs_variable_value(parser, index);
return node->index;
}
- njs_generate_code(parser, njs_vmcode_function_copy_t, copy);
- copy->code.operation = njs_vmcode_function_copy;
+ njs_generate_code(parser, njs_vmcode_object_copy_t, copy);
+ copy->code.operation = njs_vmcode_object_copy;
copy->code.operands = NJS_VMCODE_2OPERANDS;
copy->code.retval = NJS_VMCODE_RETVAL;
copy->retval = node->index;
- copy->function = index;
+ copy->object = index;
return NXT_OK;
}
}
+static nxt_int_t
+njs_generate_builtin_object(njs_vm_t *vm, njs_parser_t *parser,
+ njs_parser_node_t *node)
+{
+ njs_index_t index;
+ njs_vmcode_object_copy_t *copy;
+
+ index = node->index;
+
+ node->index = njs_generator_dest_index(vm, parser, node);
+ if (nxt_slow_path(node->index == NJS_INDEX_ERROR)) {
+ return node->index;
+ }
+
+ njs_generate_code(parser, njs_vmcode_object_copy_t, copy);
+ copy->code.operation = njs_vmcode_object_copy;
+ copy->code.operands = NJS_VMCODE_2OPERANDS;
+ copy->code.retval = NJS_VMCODE_RETVAL;
+ copy->retval = node->index;
+ copy->object = index;
+
+ return NXT_OK;
+}
+
+
static nxt_int_t
njs_generate_variable(njs_parser_t *parser, njs_parser_node_t *node)
{
/* Builtin objects. */
{ nxt_string("this"), NJS_TOKEN_THIS, 0 },
+ { nxt_string("Math"), NJS_TOKEN_MATH, 0 },
/* Builtin functions. */
--- /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_number.h>
+#include <njs_object.h>
+#include <njs_function.h>
+#include <math.h>
+
+
+static njs_ret_t
+njs_object_math_abs(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, fabs(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_acos(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, acos(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_asin(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, asin(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_atan(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, atan(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_atan2(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double y, x;
+
+ y = NJS_NAN;
+ x = NJS_NAN;
+
+ if (nargs > 1) {
+ y = args[1].data.u.number;
+ }
+
+ if (nargs > 2) {
+ x = args[2].data.u.number;
+ }
+
+ njs_number_set(&vm->retval, atan2(y, x));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_ceil(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, ceil(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_cos(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, cos(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_exp(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, exp(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_floor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, floor(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_log(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, log(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_max(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+ nxt_uint_t i;
+
+ if (nargs > 1) {
+ for (i = 1; i < nargs; i++) {
+ if (!njs_is_numeric(&args[i])) {
+ vm->frame->trap_scratch.data.u.value = &args[i];
+ return NJS_TRAP_NUMBER_ARG;
+ }
+ }
+
+ num = args[1].data.u.number;
+
+ for (i = 2; i < nargs; i++) {
+ num = fmax(num, args[i].data.u.number);
+ }
+
+ } else {
+ num = -NJS_INFINITY;
+ }
+
+ njs_number_set(&vm->retval, num);
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_min(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+ nxt_uint_t i;
+
+ if (nargs > 1) {
+ for (i = 1; i < nargs; i++) {
+ if (!njs_is_numeric(&args[i])) {
+ vm->frame->trap_scratch.data.u.value = &args[i];
+ return NJS_TRAP_NUMBER_ARG;
+ }
+ }
+
+ num = args[1].data.u.number;
+
+ for (i = 2; i < nargs; i++) {
+ num = fmin(num, args[i].data.u.number);
+ }
+
+ } else {
+ num = NJS_INFINITY;
+ }
+
+ njs_number_set(&vm->retval, num);
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_pow(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double base, exponent;
+
+ base = NJS_NAN;
+ exponent = NJS_NAN;
+
+ if (nargs > 1) {
+ base = args[1].data.u.number;
+ }
+
+ if (nargs > 2) {
+ exponent = args[2].data.u.number;
+ }
+
+ njs_number_set(&vm->retval, pow(base, exponent));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_round(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, round(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_sin(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, sin(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_sqrt(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, sqrt(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_tan(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, tan(num));
+
+ return NXT_OK;
+}
+
+
+static const njs_object_prop_t njs_math_object_properties[] =
+{
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("E"),
+ .value = njs_value(NJS_NUMBER, 1, 2.718281828459045),
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("LN10"),
+ .value = njs_value(NJS_NUMBER, 1, 2.302585092994046),
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("LN2"),
+ .value = njs_value(NJS_NUMBER, 1, 0.6931471805599453),
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("LOG10E"),
+ .value = njs_value(NJS_NUMBER, 1, 0.4342944819032518),
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("LOG2E"),
+ .value = njs_value(NJS_NUMBER, 1, 1.4426950408889634),
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("PI"),
+ .value = njs_value(NJS_NUMBER, 1, 3.141592653589793),
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("SQRT1_2"),
+ .value = njs_value(NJS_NUMBER, 1, 0.7071067811865476),
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("SQRT2"),
+ .value = njs_value(NJS_NUMBER, 1, 1.4142135623730951),
+ },
+
+ {
+ .type = NJS_NATIVE_GETTER,
+ .name = njs_string("__proto__"),
+ .value = njs_native_getter(njs_object_prototype_get_proto),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("abs"),
+ .value = njs_native_function(njs_object_math_abs, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("acos"),
+ .value = njs_native_function(njs_object_math_acos, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("asin"),
+ .value = njs_native_function(njs_object_math_asin, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("atan"),
+ .value = njs_native_function(njs_object_math_atan, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("atan2"),
+ .value = njs_native_function(njs_object_math_atan2, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("ceil"),
+ .value = njs_native_function(njs_object_math_ceil, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("cos"),
+ .value = njs_native_function(njs_object_math_cos, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("exp"),
+ .value = njs_native_function(njs_object_math_exp, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("floor"),
+ .value = njs_native_function(njs_object_math_floor, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("log"),
+ .value = njs_native_function(njs_object_math_log, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("max"),
+ .value = njs_native_function(njs_object_math_max, 0, 0),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("min"),
+ .value = njs_native_function(njs_object_math_min, 0, 0),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("pow"),
+ .value = njs_native_function(njs_object_math_pow, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("round"),
+ .value = njs_native_function(njs_object_math_round, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("sin"),
+ .value = njs_native_function(njs_object_math_sin, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("sqrt"),
+ .value = njs_native_function(njs_object_math_sqrt, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("tan"),
+ .value = njs_native_function(njs_object_math_tan, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+};
+
+
+const njs_object_init_t njs_math_object_init = {
+ njs_math_object_properties,
+ nxt_nitems(njs_math_object_properties),
+};
--- /dev/null
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NJS_MATH_H_INCLUDED_
+#define _NJS_MATH_H_INCLUDED_
+
+
+#include <math.h>
+
+
+extern const njs_object_init_t njs_math_object_init;
+
+
+#endif /* _NJS_MATH_H_INCLUDED_ */
nxt_lvlhsh_init(&object->hash);
nxt_lvlhsh_init(&object->shared_hash);
object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+ object->shared = 0;
+ }
+
+ return object;
+}
+
+
+njs_object_t *
+njs_object_value_copy(njs_vm_t *vm, njs_value_t *value)
+{
+ njs_object_t *object;
+
+ object = value->data.u.object;
+
+ if (!object->shared) {
+ return object;
+ }
+
+ object = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_object_t));
+
+ if (nxt_fast_path(object != NULL)) {
+ *object = *value->data.u.object;
+ object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+ object->shared = 0;
+ value->data.u.object = object;
}
return object;
if (nxt_fast_path(ov != NULL)) {
nxt_lvlhsh_init(&ov->object.hash);
nxt_lvlhsh_init(&ov->object.shared_hash);
+ ov->object.shared = 0;
index = njs_primitive_prototype_index(type);
ov->object.__proto__ = &vm->prototypes[index];
};
-static njs_ret_t
+njs_ret_t
njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value)
{
njs_object_t *proto;
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,
nxt_uint_t type);
njs_object_prop_t *njs_object_property(njs_vm_t *vm, njs_object_t *obj,
njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name);
njs_ret_t njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value);
njs_ret_t njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value);
+njs_ret_t njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value);
njs_ret_t njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused);
njs_parser_t *parser);
static njs_token_t njs_parser_grouping_expression(njs_vm_t *vm,
njs_parser_t *parser);
+static njs_token_t njs_parser_builtin_object(njs_vm_t *vm, njs_parser_t *parser,
+ njs_parser_node_t *node);
static njs_token_t njs_parser_object(njs_vm_t *vm, njs_parser_t *parser,
njs_parser_node_t *obj);
static njs_token_t njs_parser_array(njs_vm_t *vm, njs_parser_t *parser,
break;
}
- parser->code_size += sizeof(njs_vmcode_function_copy_t);
+ parser->code_size += sizeof(njs_vmcode_object_copy_t);
node->lvalue = NJS_LVALUE_ENABLED;
node->u.variable = var;
break;
node->index = NJS_INDEX_THIS;
break;
+ case NJS_TOKEN_MATH:
+ return njs_parser_builtin_object(vm, parser, node);
+
case NJS_TOKEN_OBJECT_CONSTRUCTOR:
node->index = NJS_INDEX_OBJECT;
break;
}
+static njs_token_t
+njs_parser_builtin_object(njs_vm_t *vm, njs_parser_t *parser,
+ njs_parser_node_t *node)
+{
+ nxt_uint_t index, level;
+ njs_value_t *value;
+ njs_variable_t *var;
+
+ var = njs_parser_variable(vm, parser, &level);
+ if (nxt_slow_path(var == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ var->state = NJS_VARIABLE_DECLARED;
+ node->index = var->index;
+
+ value = njs_variable_value(parser, node->index);
+
+ index = node->token - NJS_TOKEN_FIRST_OBJECT;
+ value->data.u.object = &vm->shared->objects[index];
+ value->type = NJS_OBJECT;
+ value->data.truth = 1;
+
+ parser->node = node;
+ parser->code_size += sizeof(njs_vmcode_object_copy_t);
+
+ return njs_lexer_token(parser->lexer);
+}
+
+
static njs_token_t
njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj)
{
NJS_TOKEN_THIS,
+#define NJS_TOKEN_FIRST_OBJECT NJS_TOKEN_MATH
+
+ NJS_TOKEN_MATH,
+
NJS_TOKEN_OBJECT_CONSTRUCTOR,
NJS_TOKEN_ARRAY_CONSTRUCTOR,
NJS_TOKEN_FUNCTION_CONSTRUCTOR,
nxt_lvlhsh_init(®exp->object.hash);
nxt_lvlhsh_init(®exp->object.shared_hash);
regexp->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_REGEXP];
+ regexp->object.shared = 0;
regexp->last_index = 0;
regexp->pattern = pattern;
}
}
-njs_ret_t
-njs_vmcode_function_copy(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld)
-{
- njs_function_t *function;
-
- if (njs_is_function(value)) {
-
- function = njs_function_value_copy(vm, value);
-
- if (nxt_fast_path(function != NULL)) {
- vm->retval.data.u.function = function;
- vm->retval.type = NJS_FUNCTION;
- vm->retval.data.truth = 1;
-
- return sizeof(njs_vmcode_function_copy_t);
- }
-
- return NXT_ERROR;
- }
-
- vm->retval = *value;
-
- njs_retain(value);
-
- return sizeof(njs_vmcode_function_copy_t);
-}
-
-
njs_ret_t
njs_vmcode_regexp(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
{
}
+njs_ret_t
+njs_vmcode_object_copy(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld)
+{
+ njs_object_t *object;
+ njs_function_t *function;
+
+ switch (value->type) {
+
+ case NJS_OBJECT:
+ object = njs_object_value_copy(vm, value);
+ if (nxt_slow_path(object == NULL)) {
+ return NXT_ERROR;
+ }
+
+ break;
+
+ case NJS_FUNCTION:
+ function = njs_function_value_copy(vm, value);
+ if (nxt_slow_path(function == NULL)) {
+ return NXT_ERROR;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ vm->retval = *value;
+
+ njs_retain(value);
+
+ return sizeof(njs_vmcode_object_copy_t);
+}
+
+
njs_ret_t
njs_vmcode_property_get(njs_vm_t *vm, njs_value_t *object,
njs_value_t *property)
/* An object __proto__. */
njs_object_t *__proto__;
+
+ uint32_t shared; /* 1 bit */
};
#if (NXT_64BIT)
uint8_t native;
uint8_t continuation_size;
- uint8_t shared;
#else
uint8_t native;
uint8_t continuation_size;
- uint8_t shared;
#endif
union {
.type = NJS_FUNCTION, \
.truth = 1, \
.u.function = & (njs_function_t) { \
+ .object.shared = 1, \
.native = 1, \
.continuation_size = _size, \
.args_types = { __VA_ARGS__ }, \
.args_offset = 1, \
- .shared = 1, \
.u.native = _function, \
} \
} \
typedef struct {
njs_vmcode_t code;
njs_index_t retval;
- njs_index_t function;
-} njs_vmcode_function_copy_t;
+ njs_regexp_pattern_t *pattern;
+} njs_vmcode_regexp_t;
typedef struct {
njs_vmcode_t code;
njs_index_t retval;
- njs_regexp_pattern_t *pattern;
-} njs_vmcode_regexp_t;
+ njs_index_t object;
+} njs_vmcode_object_copy_t;
typedef struct {
};
+enum njs_object_e {
+ NJS_OBJECT_MATH = 0,
+#define NJS_OBJECT_MAX (NJS_OBJECT_MATH + 1)
+};
+
+
#define njs_scope_index(value) \
((njs_index_t) ((value) << NJS_SCOPE_SHIFT))
nxt_lvlhsh_t values_hash;
nxt_lvlhsh_t null_proto_hash;
+ njs_object_t objects[NJS_OBJECT_MAX];
+
/*
* The prototypes and functions arrays must be togther because they are
* copied to njs_vm_t by single memcpy() in njs_builtin_objects_clone().
njs_value_t *inlvd2);
njs_ret_t njs_vmcode_function(njs_vm_t *vm, njs_value_t *inlvd1,
njs_value_t *invld2);
-njs_ret_t njs_vmcode_function_copy(njs_vm_t *vm, njs_value_t *value,
- njs_value_t *invld);
njs_ret_t njs_vmcode_regexp(njs_vm_t *vm, njs_value_t *inlvd1,
njs_value_t *invld2);
+njs_ret_t njs_vmcode_object_copy(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *invld);
njs_ret_t njs_vmcode_property_get(njs_vm_t *vm, njs_value_t *object,
njs_value_t *property);
{ nxt_string("eval()"),
nxt_string("") },
+ /* Math. */
+
+ { nxt_string("Math.PI"),
+ nxt_string("3.14159") },
+
+ { nxt_string("Math.E"),
+ nxt_string("2.71828") },
+
+ { nxt_string("Math.SQRT2"),
+ nxt_string("1.41421") },
+
+ { nxt_string("Math.abs(5)"),
+ nxt_string("5") },
+
+ { nxt_string("Math.abs(-5)"),
+ nxt_string("5") },
+
+ { nxt_string("Math.abs('5.0')"),
+ nxt_string("5") },
+
+ { nxt_string("Math.abs('abc')"),
+ nxt_string("NaN") },
+
+ { nxt_string("Math.max()"),
+ nxt_string("-Infinity") },
+
+ { nxt_string("Math.max(null)"),
+ nxt_string("0") },
+
+ { nxt_string("Math.max(undefined)"),
+ nxt_string("NaN") },
+
+ { nxt_string("Math.max('1', '2', '5')"),
+ nxt_string("5") },
+
+ { nxt_string("Math.min()"),
+ nxt_string("Infinity") },
+
+ { nxt_string("Math.min(null)"),
+ nxt_string("0") },
+
+ { nxt_string("Math.min(undefined)"),
+ nxt_string("NaN") },
+
+ { nxt_string("Math.min('1', '2', '5')"),
+ nxt_string("1") },
+
+ { nxt_string("Math.pow(2, 5)"),
+ nxt_string("32") },
+
+ { nxt_string("Math.pow(2)"),
+ nxt_string("NaN") },
+
+ { nxt_string("Math.pow()"),
+ nxt_string("NaN") },
+
+ /* ES5: Must be "[object Math]". */
+ { nxt_string("Math"),
+ nxt_string("[object Object]") },
+
+ /* External interface. */
+
{ nxt_string("function f(req) { return req.uri }"),
nxt_string("АБВ") },