]> git.kaiwu.me - njs.git/commitdiff
Various Number methods.
authorValentin Bartenev <vbart@nginx.com>
Sun, 6 Nov 2016 13:03:29 +0000 (16:03 +0300)
committerValentin Bartenev <vbart@nginx.com>
Sun, 6 Nov 2016 13:03:29 +0000 (16:03 +0300)
njs/njs_builtin.c
njs/njs_number.c
njs/njs_number.h
njs/test/njs_unit_test.c

index 4f2d281d5a8c912c82b67bf8194e4c5ed1593e0f..a87539f5bb63af4016e57cdb05478345239fcb5c 100644 (file)
@@ -143,7 +143,7 @@ njs_builtin_objects_create(njs_vm_t *vm)
         /* SunC does not allow empty array initialization. */
         { njs_eval_function,               { 0 } },
         { njs_object_prototype_to_string,  { 0 } },
-        { njs_number_is_nan,               { NJS_SKIP_ARG, NJS_NUMBER_ARG } },
+        { njs_number_global_is_nan,        { NJS_SKIP_ARG, NJS_NUMBER_ARG } },
         { njs_number_is_finite,            { NJS_SKIP_ARG, NJS_NUMBER_ARG } },
         { njs_number_parse_int,
           { NJS_SKIP_ARG, NJS_STRING_ARG, NJS_INTEGER_ARG } },
index 66dea2bada91616647e6fba802e82c14bf157e21..2b9e1501f16dd098b1ff79b03aa7f6a6e4d27504 100644 (file)
@@ -260,6 +260,74 @@ njs_number_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 }
 
 
+static njs_ret_t
+njs_number_is_integer(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double             num;
+    const njs_value_t  *value;
+
+    value = &njs_value_false;
+
+    if (nargs > 1 && njs_is_number(&args[1])) {
+        num = args[1].data.u.number;
+
+        if (num == trunc(num) && !isinf(num)) {
+            value = &njs_value_true;
+        }
+    }
+
+    vm->retval = *value;
+
+    return NXT_OK;
+}
+
+
+
+static njs_ret_t
+njs_number_is_safe_integer(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    double             num;
+    const njs_value_t  *value;
+
+    value = &njs_value_false;
+
+    if (nargs > 1 && njs_is_number(&args[1])) {
+        num = args[1].data.u.number;
+
+        if (num == (int64_t) num && fabs(num) <= NJS_MAX_SAFE_INTEGER) {
+            value = &njs_value_true;
+        }
+    }
+
+    vm->retval = *value;
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_number_is_nan(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    const njs_value_t  *value;
+
+    value = &njs_value_false;
+
+    if (nargs > 1
+        && njs_is_number(&args[1])
+        && isnan(args[1].data.u.number))
+    {
+        value = &njs_value_true;
+    }
+
+    vm->retval = *value;
+
+    return NXT_OK;
+}
+
+
 static const njs_object_prop_t  njs_number_constructor_properties[] =
 {
     /* Number.name == "Number". */
@@ -333,6 +401,50 @@ static const njs_object_prop_t  njs_number_constructor_properties[] =
         .name = njs_long_string("NEGATIVE_INFINITY"),
         .value = njs_value(NJS_NUMBER, 1, -INFINITY),
     },
+
+    /* ES6. */
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("isFinite"),
+        .value = njs_native_function(njs_number_is_finite, 0, 0),
+    },
+
+    /* ES6. */
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("isInteger"),
+        .value = njs_native_function(njs_number_is_integer, 0, 0),
+    },
+
+    /* ES6. */
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("isSafeInteger"),
+        .value = njs_native_function(njs_number_is_safe_integer, 0, 0),
+    },
+
+    /* ES6. */
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("isNaN"),
+        .value = njs_native_function(njs_number_is_nan, 0, 0),
+    },
+
+    /* ES6. */
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("parseFloat"),
+        .value = njs_native_function(njs_number_parse_float, 0,
+                     NJS_SKIP_ARG, NJS_STRING_ARG),
+    },
+
+    /* ES6. */
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("parseInt"),
+        .value = njs_native_function(njs_number_parse_int, 0,
+                     NJS_SKIP_ARG, NJS_STRING_ARG, NJS_INTEGER_ARG),
+    },
 };
 
 
@@ -498,7 +610,7 @@ const njs_object_init_t  njs_number_prototype_init = {
 
 
 njs_ret_t
-njs_number_is_nan(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_number_global_is_nan(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_index_t unused)
 {
     const njs_value_t  *value;
@@ -524,7 +636,7 @@ njs_number_is_finite(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 
     value = &njs_value_false;
 
-    if (nargs > 1) {
+    if (nargs > 1 && njs_is_number(&args[1])) {
         num = args[1].data.u.number;
 
         if (!isnan(num) && !isinf(num)) {
index 8190a6ccfbfb4cf8e95bc03e9b95ee8de754042d..724dfbbede15d300e7e160a79449c14d825e264e 100644 (file)
@@ -19,8 +19,8 @@ njs_ret_t njs_number_to_string(njs_vm_t *vm, njs_value_t *string,
     const njs_value_t *number);
 njs_ret_t njs_number_constructor(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused);
-njs_ret_t njs_number_is_nan(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
-    njs_index_t unused);
+njs_ret_t njs_number_global_is_nan(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused);
 njs_ret_t njs_number_is_finite(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused);
 njs_ret_t njs_number_parse_int(njs_vm_t *vm, njs_value_t *args,
index f891b83d4c06066d5963d400a4ece16d42e7e0c3..203661bb3edc51f5b48dc51199e31320e80bf440 100644 (file)
@@ -4766,6 +4766,95 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("var n = new Number(1); n.__proto__ === Number.prototype"),
       nxt_string("true") },
 
+    { nxt_string("Number.isFinite()"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isFinite(123)"),
+      nxt_string("true") },
+
+    { nxt_string("Number.isFinite('123')"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isFinite(Infinity)"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isFinite(NaN)"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isInteger()"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isInteger('123')"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isInteger(123)"),
+      nxt_string("true") },
+
+    { nxt_string("Number.isInteger(-123.0)"),
+      nxt_string("true") },
+
+    { nxt_string("Number.isInteger(123.4)"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isInteger(Infinity)"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isInteger(NaN)"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isSafeInteger()"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isSafeInteger('123')"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isSafeInteger(9007199254740991)"),
+      nxt_string("true") },
+
+    { nxt_string("Number.isSafeInteger(-9007199254740991.0)"),
+      nxt_string("true") },
+
+    { nxt_string("Number.isSafeInteger(9007199254740992)"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isSafeInteger(-9007199254740992.0)"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isSafeInteger(123.4)"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isSafeInteger(Infinity)"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isSafeInteger(-Infinity)"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isSafeInteger(NaN)"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isNaN()"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isNaN('NaN')"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isNaN(NaN)"),
+      nxt_string("true") },
+
+    { nxt_string("Number.isNaN(123)"),
+      nxt_string("false") },
+
+    { nxt_string("Number.isNaN(Infinity)"),
+      nxt_string("false") },
+
+#if 0
+    { nxt_string("parseFloat === Number.parseFloat"),
+      nxt_string("true") },
+
+    { nxt_string("parseInt === Number.parseInt"),
+      nxt_string("true") },
+#endif
+
     { nxt_string("String()"),
       nxt_string("") },