]> git.kaiwu.me - njs.git/commitdiff
Fixed comparison of objects and strings.
authorDmitry Volyntsev <xeioex@nginx.com>
Thu, 30 Aug 2018 17:21:18 +0000 (20:21 +0300)
committerDmitry Volyntsev <xeioex@nginx.com>
Thu, 30 Aug 2018 17:21:18 +0000 (20:21 +0300)
njs/njs_vm.c
njs/test/njs_unit_test.c

index 7ca111106f12dbf514e35942c6fb314c5297b3c9..0c68234ea466d7be09dc89e87f38976c2f3876d0 100644 (file)
@@ -1814,6 +1814,7 @@ njs_vmcode_greater_or_equal(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
 
 
 /*
+ * 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))) {
+    double  num1, num2;
 
-        if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
+    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;
 
-            /* NaN and void values are not comparable with anything. */
-            if (isnan(val1->data.u.number) || isnan(val2->data.u.number)) {
-                return -1;
+            } 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);
-    }
+        /* NaN and void values are not comparable with anything. */
+        if (isnan(num1) || isnan(num2)) {
+            return -1;
+        }
 
-    if (nxt_fast_path(njs_is_string(val1) && njs_is_string(val2))) {
-        return (njs_string_cmp(val1, val2) < 0) ? 1 : 0;
+        /* Infinities are handled correctly by comparision. */
+        return (num1 < num2);
     }
 
     return njs_trap(vm, NJS_TRAP_COMPARISON);
index 842d5afd59104d6878be73d3fdc5e23006e4969b..e30f23314fe9143120e4a4059f9b264ef17d4589 100644 (file)
@@ -1527,6 +1527,34 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("[0] >= ({})"),
       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"),