[njs] Fixed comparison of objects and strings.

Dmitry Volyntsev xeioex at nginx.com
Thu Aug 30 17:37:22 UTC 2018


details:   http://hg.nginx.org/njs/rev/5dd7d38bb08c
branches:  
changeset: 595:5dd7d38bb08c
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Thu Aug 30 20:21:18 2018 +0300
description:
Fixed comparison of objects and strings.

diffstat:

 njs/njs_vm.c             |  40 ++++++++++++++++++++++++++--------------
 njs/test/njs_unit_test.c |  28 ++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+), 14 deletions(-)

diffs (99 lines):

diff -r 6931a42f5bed -r 5dd7d38bb08c njs/njs_vm.c
--- a/njs/njs_vm.c	Thu Aug 30 17:21:51 2018 +0300
+++ b/njs/njs_vm.c	Thu Aug 30 20:21:18 2018 +0300
@@ -1814,6 +1814,7 @@ njs_vmcode_greater_or_equal(njs_vm_t *vm
 
 
 /*
+ * ECMAScript 5.1: 11.8.5
  * njs_values_compare() returns
  *   1 if val1 is less than val2,
  *   0 if val1 is greater than or equal to val2,
@@ -1825,24 +1826,35 @@ static nxt_noinline njs_ret_t
 njs_values_compare(njs_vm_t *vm, const njs_value_t *val1,
     const njs_value_t *val2)
 {
-    if (nxt_fast_path(njs_is_numeric(val1) || njs_is_numeric(val2))) {
-
-        if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
-
-            /* NaN and void values are not comparable with anything. */
-            if (isnan(val1->data.u.number) || isnan(val2->data.u.number)) {
-                return -1;
+    double  num1, num2;
+
+    if (nxt_fast_path(njs_is_primitive(val1) && njs_is_primitive(val2))) {
+
+        if (nxt_fast_path(njs_is_numeric(val1))) {
+            num1 = val1->data.u.number;
+
+            if (nxt_fast_path(njs_is_numeric(val2))) {
+                num2 = val2->data.u.number;
+
+            } else {
+                num2 = njs_string_to_number(val2, 0);
             }
 
-            /* Infinities are handled correctly by comparision. */
-            return (val1->data.u.number < val2->data.u.number);
+        } else if (njs_is_numeric(val2)) {
+            num1 = njs_string_to_number(val1, 0);
+            num2 = val2->data.u.number;
+
+        } else {
+            return (njs_string_cmp(val1, val2) < 0) ? 1 : 0;
         }
 
-        return njs_trap(vm, NJS_TRAP_NUMBERS);
-    }
-
-    if (nxt_fast_path(njs_is_string(val1) && njs_is_string(val2))) {
-        return (njs_string_cmp(val1, val2) < 0) ? 1 : 0;
+        /* NaN and void values are not comparable with anything. */
+        if (isnan(num1) || isnan(num2)) {
+            return -1;
+        }
+
+        /* Infinities are handled correctly by comparision. */
+        return (num1 < num2);
     }
 
     return njs_trap(vm, NJS_TRAP_COMPARISON);
diff -r 6931a42f5bed -r 5dd7d38bb08c njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Thu Aug 30 17:21:51 2018 +0300
+++ b/njs/test/njs_unit_test.c	Thu Aug 30 20:21:18 2018 +0300
@@ -1528,6 +1528,34 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("false") },
 
     /**/
+    { nxt_string("new String('1') > new Number(1)"),
+      nxt_string("false") },
+
+    { nxt_string("new Boolean(true) > '1'"),
+      nxt_string("false") },
+
+    { nxt_string("'0' >= new Number(1)"),
+      nxt_string("false") },
+
+    { nxt_string("'1' >= new Number(1)"),
+      nxt_string("true") },
+
+    { nxt_string("new String('1') < new Number(1)"),
+      nxt_string("false") },
+
+    { nxt_string("new Boolean(true) < '1'"),
+      nxt_string("false") },
+
+    { nxt_string("new String('1') <= new Number(1)"),
+      nxt_string("true") },
+
+    { nxt_string("new Boolean(true) <= '1'"),
+      nxt_string("true") },
+
+    { nxt_string("'-1' < {valueOf: function() {return -2}}"),
+      nxt_string("false") },
+
+    /**/
 
     { nxt_string("var a; a = 1 ? 2 : 3"),
       nxt_string("2") },


More information about the nginx-devel mailing list