WebKit Bugzilla
Attachment 341243 Details for
Bug 185929
: [ESNext][BigInt] Implement support for "=<" and ">=" relational operation
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP - Patch
big-int-less-than-or-equal.diff (text/plain), 37.09 KB, created by
Caio Lima
on 2018-05-24 20:13:25 PDT
(
hide
)
Description:
WIP - Patch
Filename:
MIME Type:
Creator:
Caio Lima
Created:
2018-05-24 20:13:25 PDT
Size:
37.09 KB
patch
obsolete
>diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog >index 18ac558..d42f989 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,19 @@ >+2018-05-14 Caio Lima <ticaiolima@gmail.com> >+ >+ [ESNext][BigInt] Implement support for "<" and ">" relational operation >+ https://bugs.webkit.org/show_bug.cgi?id=185379 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * stress/big-int-greater-than-general.js: Added. >+ * stress/big-int-greater-than-jit.js: Added. >+ * stress/big-int-greater-than-order-of-evaluation.js: Added. >+ * stress/big-int-greater-than-wrapped-values.js: Added. >+ * stress/big-int-less-than-general.js: Added. >+ * stress/big-int-less-than-jit.js: Added. >+ * stress/big-int-less-than-order-of-evaluation.js: Added. >+ * stress/big-int-less-than-wrapped-values.js: Added. >+ > 2018-05-24 Caio Lima <ticaiolima@gmail.com> > > [ESNext][BigInt] Implement support for "<" and ">" relational operation >diff --git a/JSTests/bigIntTests.yaml b/JSTests/bigIntTests.yaml >index 1b05d69..924cc9a 100644 >--- a/JSTests/bigIntTests.yaml >+++ b/JSTests/bigIntTests.yaml >@@ -138,3 +138,28 @@ > > - path: stress/big-int-no-conversion-to-number.js > cmd: runBigIntEnabled >+ >+- path: stress/big-int-greater-than-or-equal-general.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-greater-than-or-equal-jit.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-greater-than-or-equal-order-of-evaluation.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-greater-than-or-equal-wrapped-values.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-less-than-or-equal-jit.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-less-than-or-equal-order-of-evaluation.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-less-than-or-equal-wrapped-values.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-less-than-or-equal-general.js >+ cmd: runBigIntEnabled >+ >diff --git a/JSTests/stress/big-int-greater-than-general.js b/JSTests/stress/big-int-greater-than-general.js >index 0979dbe..8f2f86b 100644 >--- a/JSTests/stress/big-int-greater-than-general.js >+++ b/JSTests/stress/big-int-greater-than-general.js >@@ -137,4 +137,3 @@ try { > } catch(e) { > assert(e instanceof TypeError, true, "Comparison with Symbol shoud throw TypeError, but throwed something else"); > } >- >diff --git a/JSTests/stress/big-int-greater-than-or-equal-jit.js b/JSTests/stress/big-int-greater-than-or-equal-jit.js >new file mode 100644 >index 0000000..d37fe51 >--- /dev/null >+++ b/JSTests/stress/big-int-greater-than-or-equal-jit.js >@@ -0,0 +1,24 @@ >+//@ runBigIntEnabled >+ >+function assert(a) { >+ if (!a) >+ throw new Error("Bad assertion"); >+} >+ >+function greaterThanOrEqualTest(a, b) { >+ return a >= b; >+} >+noInline(greaterThanOrEqualTest); >+ >+for (let i = 0; i < 100000; i++) { >+ assert(greaterThanOrEqualTest(3n, 4) === false); >+} >+ >+for (let i = 0; i < 100000; i++) { >+ assert(greaterThanOrEqualTest(3n, 4n) === false); >+} >+ >+for (let i = 0; i < 100000; i++) { >+ assert(greaterThanOrEqualTest(3n, "4") === false); >+} >+ >diff --git a/JSTests/stress/big-int-greater-than-or-equal-order-of-evaluation.js b/JSTests/stress/big-int-greater-than-or-equal-order-of-evaluation.js >new file mode 100644 >index 0000000..0e8ac85 >--- /dev/null >+++ b/JSTests/stress/big-int-greater-than-or-equal-order-of-evaluation.js >@@ -0,0 +1,55 @@ >+//@ runBigIntEnabled >+ >+function assert(v, e, m) { >+ if (v !== e) >+ throw new Error(m); >+} >+ >+let o = { >+ [Symbol.toPrimitive]: function() { >+ throw new Error("Calling @toPrimitive"); >+ } >+} >+ >+try { >+ o >= Symbol(2); >+ assert(true, false, "") >+} catch(e) { >+ assert(e.message, "Calling @toPrimitive", "Bad Exception when object is left operand"); >+} >+ >+try { >+ Symbol(2) >= o; >+ assert(true, false, "") >+} catch(e) { >+ assert(e instanceof TypeError, true, "Bad Exception when Symbol is left operand"); >+} >+ >+o = { >+ [Symbol.toPrimitive]: function() { >+ return 2n; >+ }, >+ >+ toString: function() { >+ throw new Error("Should never call toString"); >+ }, >+ >+ valueOf: function() { >+ throw new Error("Should never call valueOf"); >+ } >+} >+ >+assert(o >= 3n, false, "ToPrimitive(2n) > 3n"); >+ >+o = { >+ toString: function() { >+ throw new Error("Should never call toString"); >+ }, >+ >+ valueOf: function() { >+ return 2n; >+ } >+} >+ >+assert(o >= 3n, false, "valueOf(2n) > 3n"); >+ >diff --git a/JSTests/stress/big-int-greater-than-or-equal-wrapped-values.js b/JSTests/stress/big-int-greater-than-or-equal-wrapped-values.js >new file mode 100644 >index 0000000..597b2cf >--- /dev/null >+++ b/JSTests/stress/big-int-greater-than-or-equal-wrapped-values.js >@@ -0,0 +1,63 @@ >+//@ runBigIntEnabled >+ >+function assert(v, e, m) { >+ if (v !== e) >+ throw new Error(m); >+} >+ >+assert(Object(2n) >= 1n, true, "Object(2n) >= 1n"); >+assert(1n >= Object(2n), false, "1n >= Object(2n)"); >+assert(Object(2n) >= Object(1n), true, "Object(2n) >= Object(1n)"); >+assert(Object(1n) >= Object(2n), false, "Object(1n) >= Object(2n)"); >+ >+let o = { >+ [Symbol.toPrimitive]: function() { >+ return 2n; >+ } >+} >+ >+let o2 = { >+ [Symbol.toPrimitive]: function() { >+ return 1n; >+ } >+} >+ >+assert(o >= 1n, true, "ToPrimitive(2n) >= 1n"); >+assert(1n >= o, false, "1n >= ToPrimitive(2n)"); >+assert(o >= o2, true, "ToPrimitive(2n) >= ToPrimitive(1n)"); >+assert(o2 >= o, false, "ToPrimitive(1n) >= ToPrimitive(2n)"); >+ >+o = { >+ valueOf: function() { >+ return 2n; >+ } >+} >+ >+o2 = { >+ valueOf: function() { >+ return 1n; >+ } >+} >+ >+assert(o >= 1n, true, "valueOf(2n) >= 1n"); >+assert(1n >= o, false, "1n >= valueOf(2n)"); >+assert(o >= o2, true, "valueOf(2n) >= valueOf(1n)"); >+assert(o2 >= o, false, "valueOf(1n) >= valueOf(2n)"); >+ >+o = { >+ toString: function() { >+ return 2n; >+ } >+} >+ >+o2 = { >+ toString: function() { >+ return 1n; >+ } >+} >+ >+assert(o >= 1n, true, "toString(2n) >= 1n"); >+assert(1n >= o, false, "1n >= ToPrimitive(2n)"); >+assert(o >= o2, true, "toString(2n) < toString(1n)"); >+assert(o2 >= o, false, "toString(1n) < toString(2n)"); >+ >diff --git a/JSTests/stress/big-int-greater-than-or-equal.js b/JSTests/stress/big-int-greater-than-or-equal.js >new file mode 100644 >index 0000000..7fb523a >--- /dev/null >+++ b/JSTests/stress/big-int-greater-than-or-equal.js >@@ -0,0 +1,140 @@ >+//@ runBigIntEnabled >+ >+// Copyright (C) 2017 Josh Wolfe. All rights reserved. >+// Copyright (C) 2018 Igalia, S.L. All rights reserved. >+// This code is governed by the BSD license found in the LICENSE file. >+ >+function assert(v, e, m) { >+ if (v !== e) >+ throw new Error(m); >+} >+ >+assert(0n >= 0n, true, "0n >= 0n"); >+assert(1n >= 1n, true, "1n >= 1n"); >+assert(BigInt("-1") >= BigInt("-1"), true, "-1n >= -1n"); >+assert(0n >= BigInt("-0"), true, "0n >= -0n"); >+assert(BigInt("-0") >= 0n, true, "-0n >= 0n"); >+assert(0n >= 1n, false, "0n >= 1n"); >+assert(1n >= 0n, true, "1n >= 0n"); >+assert(0n >= BigInt("-1"), true, "0n >= -1n"); >+assert(BigInt("-1") >= 0n, false, "-1n >= 0n"); >+assert(1n >= BigInt("-1"), true, "1n >= -1n"); >+assert(BigInt("-1") >= 1n, false, "-1n >= 1n"); >+assert(0x1fffffffffffff01n >= 0x1fffffffffffff02n, false, "0x1fffffffffffff01n >= 0x1fffffffffffff02n"); >+assert(0x1fffffffffffff02n >= 0x1fffffffffffff01n, true, "0x1fffffffffffff02n >= 0x1fffffffffffff01n"); >+assert(BigInt("-2305843009213693697") >= BigInt("-2305843009213693698"), true, "-2305843009213693697n >= -2305843009213693698n"); >+assert(BigInt("-2305843009213693698") >= BigInt("-2305843009213693697"), false, "-2305843009213693698n >= -2305843009213693697n"); >+assert(0x10000000000000000n >= 0n, true, "0x10000000000000000n >= 0n"); >+assert(0n >= 0x10000000000000000n, false, "0n >= 0x10000000000000000n"); >+assert(0x10000000000000000n >= 1n, true, "0x10000000000000000n >= 1n"); >+assert(1n >= 0x10000000000000000n, false, "1n >= 0x10000000000000000n"); >+assert(0x10000000000000000n >= BigInt("-1"), true, "0x10000000000000000n >= -1n"); >+assert(BigInt("-1") >= 0x10000000000000000n, false, "-1n >= 0x10000000000000000n"); >+assert(0x10000000000000001n >= 0n, true, "0x10000000000000001n >= 0n"); >+assert(0n >= 0x10000000000000001n, false, "0n >= 0x10000000000000001n"); >+assert(BigInt("-18446744073709551616") >= 0n, false, "-18446744073709551616n >= 0n"); >+assert(0n >= BigInt("-18446744073709551616"), true, "0n >= -18446744073709551616n"); >+assert(BigInt("-18446744073709551616") >= 1n, false, "-18446744073709551616n >= 1n"); >+assert(1n >= BigInt("-18446744073709551616"), true, "1n >= -18446744073709551616n"); >+assert(BigInt("-18446744073709551616") >= BigInt("-1"), false, "-18446744073709551616n >= -1n"); >+assert(BigInt("-1") >= BigInt("-18446744073709551616"), true, "-1n >= -18446744073709551616n"); >+assert(BigInt("-18446744073709551617") >= 0n, false, "-18446744073709551617n >= 0n"); >+assert(0n >= BigInt("-18446744073709551617"), true, "0n >= -18446744073709551617n"); >+assert(0x10000000000000000n >= 0x100000000n, true, "0x10000000000000000n >= 0x100000000n"); >+assert(0x100000000n >= 0x10000000000000000n, false, "0x100000000n >= 0x10000000000000000n"); >+ >+// BigInt - String >+ >+assert(0n >= "0", true, "0n >= '0'"); >+assert("0" >= 0n, true, "'0' >= 0n"); >+assert(0n >= "1", false, "0n >= '1'"); >+assert("0" >= 1n, false, "'0' >= 1n"); >+assert(1n >= "0", true, "1n >= '0'"); >+assert("1" >= 0n, true, "'1' >= 0n"); >+assert(0n >= "", true, "0n >= ''"); >+assert("" >= 0n, true, "'' >= 0n"); >+assert(0n >= "1", false, "0n >= '1'"); >+assert("" >= 1n, false, "'' >= 1n"); >+assert(1n >= "", true, "1n >= ''"); >+assert(1n >= "1", true, "1n >= '1'"); >+assert("1" >= 1n, true, "'1' >= 1n"); >+assert(1n >= "-1", true, "1n >= '-1'"); >+assert("1" >= BigInt("-1"), true, "'1' >= -1n"); >+assert(BigInt("-1") >= "1", false, "-1n >= '1'"); >+assert("-1" >= 1n, false, "'-1' >= 1n"); >+assert(BigInt("-1") >= "-1", true, "-1n >= '-1'"); >+assert("-1" >= BigInt("-1"), true, "'-1' >= -1n"); >+assert(9007199254740993n >= "9007199254740992", true, "9007199254740993n >= '9007199254740992'"); >+assert("9007199254740993" >= 9007199254740992n, true, "'9007199254740993' >= 9007199254740992n"); >+assert(BigInt("-9007199254740992") >= "-9007199254740993", true, "-9007199254740992n >= '-9007199254740993'"); >+assert("-9007199254740992" >= BigInt("-9007199254740993"), true, "'-9007199254740992' >= -9007199254740993n"); >+assert("0x10" >= 14n, true, "'0x10' >= 3n"); >+assert("0b10" >= 2n, true, "'0b10' >= 2n"); >+assert("0b10" >= 1n, true, "'0b10' >= 1n"); >+ >+// Invalid String >+ >+assert("b10" >= 2n, false, "'b10' >= 2n"); >+assert("bbb10" >= 2n, false, "'bbb10' >= 2n"); >+ >+// BigInt - Number >+ >+assert(0n >= 0, true, "0n >= 0"); >+assert(0 >= 0n, true, "0 >= 0n"); >+assert(0n >= -0, true, "0n >= -0"); >+assert(-0 >= 0n, true, "-0 >= 0n"); >+assert(0n >= 0.000000000001, false, "0n >= 0.000000000001"); >+assert(0.000000000001 >= 0n, true, "0.000000000001 >= 0n"); >+assert(0n >= 1, false, "0n >= 1"); >+assert(1 >= 0n, true, "1 >= 0n"); >+assert(1n >= 0, true, "1n >= 0"); >+assert(0 >= 1n, false, "0 >= 1n"); >+assert(1n >= 0.999999999999, true, "1n >= 0.999999999999"); >+assert(0.999999999999 >= 1n, false, "0.999999999999 >= 1n"); >+assert(1n >= 1, true, "1n >= 1"); >+assert(1 >= 1n, true, "1 >= 1n"); >+assert(0n >= Number.MIN_VALUE, false, "0n >= Number.MIN_VALUE"); >+assert(Number.MIN_VALUE >= 0n, true, "Number.MIN_VALUE >= 0n"); >+assert(0n >= -Number.MIN_VALUE, true, "0n >= -Number.MIN_VALUE"); >+assert(-Number.MIN_VALUE >= 0n, false, "-Number.MIN_VALUE >= 0n"); >+assert(BigInt("-10") >= Number.MIN_VALUE, false, "-10n >= Number.MIN_VALUE"); >+assert(Number.MIN_VALUE >= BigInt("-10"), true, "Number.MIN_VALUE >= -10n"); >+assert(1n >= Number.MAX_VALUE, false, "1n >= Number.MAX_VALUE"); >+assert(Number.MAX_VALUE >= 1n, true, "Number.MAX_VALUE >= 1n"); >+assert(1n >= -Number.MAX_VALUE, true, "1n >= -Number.MAX_VALUE"); >+assert(-Number.MAX_VALUE >= 1n, false, "-Number.MAX_VALUE >= 1n"); >+assert(0xfffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn >= Number.MAX_VALUE, false, "0xfffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn >= Number.MAX_VALUE"); >+assert(Number.MAX_VALUE >= 0xfffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn, true, "Number.MAX_VALUE >= 0xfffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn"); >+assert(0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001n >= Number.MAX_VALUE, true, "0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001n >= Number.MAX_VALUE"); >+assert(Number.MAX_VALUE >= 0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001n, false, "Number.MAX_VALUE >= 0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001n"); >+assert(1n >= Infinity, false, "1n >= Infinity"); >+assert(Infinity >= 1n, true, "Infinity >= 1n"); >+assert(BigInt("-1") >= Infinity, false, "-1n >= Infinity"); >+assert(Infinity >= BigInt("-1"), true, "Infinity >= -1n"); >+assert(1n >= -Infinity, true, "1n >= -Infinity"); >+assert(-Infinity >= 1n, false, "-Infinity >= 1n"); >+assert(BigInt("-1") >= -Infinity, true, "-1n >= -Infinity"); >+assert(-Infinity >= BigInt("-1"), false, "-Infinity >= -1n"); >+assert(0n >= NaN, false, "0n >= NaN"); >+assert(NaN >= 0n, false, "NaN >= 0n"); >+ >+// BigInt - Boolean >+ >+assert(false >= 1n, false, "false >= 1n"); >+assert(1n >= false, true, "1n >= false"); >+assert(false >= 0n, true, "false >= 0n"); >+assert(0n >= false, true, "0n >= false"); >+assert(true >= 1n, true, "true >= 1n"); >+assert(1n >= true, true, "1n >= true"); >+assert(true >= 2n, false, "true >= 2n"); >+assert(2n >= true, true, "2n >= true"); >+ >+// BigInt - Symbol >+ >+try { >+ 1n >= Symbol("1"); >+ assert(false, true, "Comparison with Symbol shoud throw TypeError, but executed without exception"); >+} catch(e) { >+ assert(e instanceof TypeError, true, "Comparison with Symbol shoud throw TypeError, but throwed something else"); >+} >+ >diff --git a/JSTests/stress/big-int-less-than-general.js b/JSTests/stress/big-int-less-than-general.js >index afa191c..bf589f0 100644 >--- a/JSTests/stress/big-int-less-than-general.js >+++ b/JSTests/stress/big-int-less-than-general.js >@@ -145,4 +145,3 @@ try { > } catch(e) { > assert(e instanceof TypeError, true, "Comparison with Symbol shoud throw TypeError, but throwed something else"); > } >- >diff --git a/JSTests/stress/big-int-less-than-or-equal-general.js b/JSTests/stress/big-int-less-than-or-equal-general.js >new file mode 100644 >index 0000000..44ffa57 >--- /dev/null >+++ b/JSTests/stress/big-int-less-than-or-equal-general.js >@@ -0,0 +1,148 @@ >+//@ runBigIntEnabled >+ >+// Copyright (C) 2017 Josh Wolfe. All rights reserved. >+// Copyright (C) 2017 Robin Templeton. All rights reserved. >+// Copyright (C) 2018 Igalia, S.L. All rights reserved. >+// This code is governed by the BSD license found in the LICENSE file. >+ >+function assert(v, e, m) { >+ if (v !== e) >+ throw new Error(m); >+} >+ >+assert(0n <= 0n, true, "0n <= 0n"); >+assert(1n <= 1n, true, "1n <= 1n"); >+assert(BigInt("-1") <= BigInt("-1"), true, "-1n <= -1n"); >+assert(0n <= BigInt("-0"), true, "0n <= -0n"); >+assert(BigInt("-0") <= 0n, true, "-0n <= 0n"); >+assert(0n <= 1n, true, "0n <= 1n"); >+assert(1n <= 0n, false, "1n <= 0n"); >+assert(0n <= BigInt("-1"), false, "0n <= -1n"); >+assert(BigInt("-1") <= 0n, true, "-1n <= 0n"); >+assert(1n <= BigInt("-1"), false, "1n <= -1n"); >+assert(BigInt("-1") <= 1n, true, "-1n <= 1n"); >+assert(0x1fffffffffffff01n <= 0x1fffffffffffff02n, true, "0x1fffffffffffff01n <= 0x1fffffffffffff02n"); >+assert(0x1fffffffffffff02n <= 0x1fffffffffffff01n, false, "0x1fffffffffffff02n <= 0x1fffffffffffff01n"); >+assert(BigInt("-2305843009213693697") <= BigInt("-2305843009213693698"), false, "-2305843009213693697n <= -2305843009213693698n"); >+assert(BigInt("-2305843009213693698") <= BigInt("-2305843009213693697"), true, "-2305843009213693698n <= -2305843009213693697n"); >+assert(0x10000000000000000n <= 0n, false, "0x10000000000000000n <= 0n"); >+assert(0n <= 0x10000000000000000n, true, "0n <= 0x10000000000000000n"); >+assert(0x10000000000000000n <= 1n, false, "0x10000000000000000n <= 1n"); >+assert(1n <= 0x10000000000000000n, true, "1n <= 0x10000000000000000n"); >+assert(0x10000000000000000n <= BigInt("-1"), false, "0x10000000000000000n <= -1n"); >+assert(BigInt("-1") <= 0x10000000000000000n, true, "-1n <= 0x10000000000000000n"); >+assert(0x10000000000000001n <= 0n, false, "0x10000000000000001n <= 0n"); >+assert(0n <= 0x10000000000000001n, true, "0n <= 0x10000000000000001n"); >+assert(BigInt("-18446744073709551616") <= 0n, true, "-18446744073709551616n <= 0n"); >+assert(0n <= BigInt("-18446744073709551616"), false, "0n <= -18446744073709551616n"); >+assert(BigInt("-18446744073709551616") <= 1n, true, "-18446744073709551616n <= 1n"); >+assert(1n <= BigInt("-18446744073709551616"), false, "1n <= -18446744073709551616n"); >+assert(BigInt("-18446744073709551616") <= BigInt("-1"), true, "-18446744073709551616n <= -1n"); >+assert(BigInt("-1") <= BigInt("-18446744073709551616"), false, "-1n <= -18446744073709551616n"); >+assert(BigInt("-18446744073709551617") <= 0n, true, "-18446744073709551617n <= 0n"); >+assert(0n <= BigInt("-18446744073709551617"), false, "0n <= -18446744073709551617n"); >+assert(0x10000000000000000n <= 0x100000000n, false, "0x10000000000000000n <= 0x100000000n"); >+assert(0x100000000n <= 0x10000000000000000n, true, "0x100000000n <= 0x10000000000000000n"); >+ >+// BigInt - String >+ >+assert(0n <= "0", true, "0n <= '0'"); >+assert("0" <= 0n, true, "'0' <= 0n"); >+assert(0n <= "1", true, "0n <= '1'"); >+assert("0" <= 1n, true, "'0' <= 1n"); >+assert(1n <= "0", false, "1n <= '0'"); >+assert("1" <= 0n, false, "'1' <= 0n"); >+assert(0n <= "", true, "0n <= ''"); >+assert("" <= 0n, true, "'' <= 0n"); >+assert(0n <= "1", true, "0n <= '1'"); >+assert("" <= 1n, true, "'' <= 1n"); >+assert(1n <= "", false, "1n <= ''"); >+assert("1" <= 0n, false, "'1' <= 0n"); >+assert(1n <= "1", true, "1n <= '1'"); >+assert("1" <= 1n, true, "'1' <= 1n"); >+assert(1n <= "-1", false, "1n <= '-1'"); >+assert("1" <= BigInt("-1"), false, "'1' <= -1n"); >+assert(BigInt("-1") <= "1", true, "-1n <= '1'"); >+assert("-1" <= 1n, true, "'-1' <= 1n"); >+assert(BigInt("-1") <= "-1", true, "-1n <= '-1'"); >+assert("-1" <= BigInt("-1"), true, "'-1' <= -1n"); >+assert(9007199254740993n <= "9007199254740992", false, "9007199254740993n <= '9007199254740992'"); >+assert("9007199254740993" <= 9007199254740992n, false, "'9007199254740993' <= 9007199254740992n"); >+assert(BigInt("-9007199254740992") <= "-9007199254740993", false, "-9007199254740992n <= '-9007199254740993'"); >+assert("-9007199254740992" <= BigInt("-9007199254740993"), false, "'-9007199254740992' <= -9007199254740993n"); >+assert("0x10" <= 3n, false, "'0x10' <= 3n"); >+assert("0x10" <= 2n, false, "'0x10' <= 2n"); >+assert("0x10" <= 1n, false, "'0x10' <= 1n"); >+assert("0o10" <= 7n, false, "'0o10' <= 7n"); >+assert("0o10" <= 8n, true, "'0o10' <= 8n"); >+assert("0o10" <= 9n, true, "'0o10' <= 9n"); >+assert("0b10" <= 3n, true, "'0b10' <= 3n"); >+assert("0b10" <= 2n, true, "'0b10' <= 2n"); >+assert("0b10" <= 1n, false, "'0b10' <= 1n"); >+ >+// Invalid String >+ >+assert("b10" <= 2n, false, "'b10' > 2n"); >+assert("bbb10" <= 2n, false, "'bbb10' > 2n"); >+ >+// BigInt - Number >+ >+assert(0n <= 0, true, "0n <= 0"); >+assert(0 <= 0n, true, "0 <= 0n"); >+assert(0n <= -0, true, "0n <= -0"); >+assert(-0 <= 0n, true, "-0 <= 0n"); >+assert(0n <= 0.000000000001, true, "0n <= 0.000000000001"); >+assert(0.000000000001 <= 0n, false, "0.000000000001 <= 0n"); >+assert(0n <= 1, true, "0n <= 1"); >+assert(1 <= 0n, false, "1 <= 0n"); >+assert(1n <= 0, false, "1n <= 0"); >+assert(0 <= 1n, true, "0 <= 1n"); >+assert(1n <= 0.999999999999, false, "1n <= 0.999999999999"); >+assert(0.999999999999 <= 1n, true, "0.999999999999 <= 1n"); >+assert(1n <= 1, true, "1n <= 1"); >+assert(1 <= 1n, true, "1 <= 1n"); >+assert(0n <= Number.MIN_VALUE, true, "0n <= Number.MIN_VALUE"); >+assert(Number.MIN_VALUE <= 0n, false, "Number.MIN_VALUE <= 0n"); >+assert(0n <= -Number.MIN_VALUE, false, "0n <= -Number.MIN_VALUE"); >+assert(-Number.MIN_VALUE <= 0n, true, "-Number.MIN_VALUE <= 0n"); >+assert(BigInt("-10") <= Number.MIN_VALUE, true, "-10n <= Number.MIN_VALUE"); >+assert(Number.MIN_VALUE <= BigInt("-10"), false, "Number.MIN_VALUE <= -10n"); >+assert(1n <= Number.MAX_VALUE, true, "1n <= Number.MAX_VALUE"); >+assert(Number.MAX_VALUE <= 1n, false, "Number.MAX_VALUE <= 1n"); >+assert(1n <= -Number.MAX_VALUE, false, "1n <= -Number.MAX_VALUE"); >+assert(-Number.MAX_VALUE <= 1n, true, "-Number.MAX_VALUE <= 1n"); >+assert(0xfffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn <= Number.MAX_VALUE, true, "0xfffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn <= Number.MAX_VALUE"); >+assert(Number.MAX_VALUE <= 0xfffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn, false, "Number.MAX_VALUE <= 0xfffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn"); >+assert(0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001n <= Number.MAX_VALUE, false, "0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001n <= Number.MAX_VALUE"); >+assert(Number.MAX_VALUE <= 0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001n, true, "Number.MAX_VALUE <= 0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001n"); >+assert(1n <= Infinity, true, "1n <= Infinity"); >+assert(Infinity <= 1n, false, "Infinity <= 1n"); >+assert(BigInt("-1") <= Infinity, true, "-1n <= Infinity"); >+assert(Infinity <= BigInt("-1"), false, "Infinity <= -1n"); >+assert(1n <= -Infinity, false, "1n <= -Infinity"); >+assert(-Infinity <= 1n, true, "-Infinity <= 1n"); >+assert(BigInt("-1") <= -Infinity, false, "-1n <= -Infinity"); >+assert(-Infinity <= BigInt("-1"), true, "-Infinity <= -1n"); >+assert(0n <= NaN, false, "0n <= NaN"); >+assert(NaN <= 0n, false, "NaN <= 0n"); >+ >+// BigInt - Boolean >+ >+assert(false <= 1n, true, "false <= 1n"); >+assert(1n <= false, false, "1n <= false"); >+assert(false <= 0n, true, "false <= 0n"); >+assert(0n <= false, true, "0n <= false"); >+assert(true <= 1n, true, "true <= 1n"); >+assert(1n <= true, true, "1n <= true"); >+assert(true <= 2n, true, "true <= 2n"); >+assert(2n <= true, false, "2n <= true"); >+ >+// BigInt - Symbol >+ >+try { >+ 1n <= Symbol("1"); >+ assert(false, true, "Comparison with Symbol shoud throw TypeError, but executed without exception"); >+} catch(e) { >+ assert(e instanceof TypeError, true, "Comparison with Symbol shoud throw TypeError, but throwed something else"); >+} >+ >diff --git a/JSTests/stress/big-int-less-than-or-equal-jit.js b/JSTests/stress/big-int-less-than-or-equal-jit.js >new file mode 100644 >index 0000000..f356844 >--- /dev/null >+++ b/JSTests/stress/big-int-less-than-or-equal-jit.js >@@ -0,0 +1,24 @@ >+//@ runBigIntEnabled >+ >+function assert(a) { >+ if (!a) >+ throw new Error("Bad assertion"); >+} >+ >+function lessThanOrEqualTest(a, b) { >+ return a <= b; >+} >+noInline(lessThanOrEqualTest); >+ >+for (let i = 0; i < 100000; i++) { >+ assert(lessThanOrEqualTest(3n, 4) === true); >+} >+ >+for (let i = 0; i < 100000; i++) { >+ assert(lessThanOrEqualTest(3n, 4n) === true); >+} >+ >+for (let i = 0; i < 100000; i++) { >+ assert(lessThanOrEqualTest(3n, "4") === true); >+} >+ >diff --git a/JSTests/stress/big-int-less-than-or-equal-order-of-evaluation.js b/JSTests/stress/big-int-less-than-or-equal-order-of-evaluation.js >new file mode 100644 >index 0000000..64ea754 >--- /dev/null >+++ b/JSTests/stress/big-int-less-than-or-equal-order-of-evaluation.js >@@ -0,0 +1,55 @@ >+//@ runBigIntEnabled >+ >+function assert(v, e, m) { >+ if (v !== e) >+ throw new Error(m); >+} >+ >+let o = { >+ [Symbol.toPrimitive]: function() { >+ throw new Error("Calling @toPrimitive"); >+ } >+} >+ >+try { >+ o <= Symbol(2); >+ assert(true, false, "") >+} catch(e) { >+ assert(e.message, "Calling @toPrimitive", "Bad Exception when object is left operand"); >+} >+ >+try { >+ Symbol(2) <= o; >+ assert(true, false, "") >+} catch(e) { >+ assert(e instanceof TypeError, true, "Bad Exception when Symbol is left operand"); >+} >+ >+o = { >+ [Symbol.toPrimitive]: function() { >+ return 2n; >+ }, >+ >+ toString: function() { >+ throw new Error("Should never call toString"); >+ }, >+ >+ valueOf: function() { >+ throw new Error("Should never call valueOf"); >+ } >+} >+ >+assert(o <= 3n, true, "ToPrimitive(2n) <= 3n"); >+ >+o = { >+ toString: function() { >+ throw new Error("Should never call toString"); >+ }, >+ >+ valueOf: function() { >+ return 2n; >+ } >+} >+ >+assert(o <= 3n, true, "valueOf(2n) <= 3n"); >+ >diff --git a/JSTests/stress/big-int-less-than-or-equal-wrapped-values.js b/JSTests/stress/big-int-less-than-or-equal-wrapped-values.js >new file mode 100644 >index 0000000..237c56a >--- /dev/null >+++ b/JSTests/stress/big-int-less-than-or-equal-wrapped-values.js >@@ -0,0 +1,63 @@ >+//@ runBigIntEnabled >+ >+function assert(v, e, m) { >+ if (v !== e) >+ throw new Error(m); >+} >+ >+assert(Object(2n) <= 1n, false, "Object(2n) <= 1n"); >+assert(1n <= Object(2n), true, "1n <= Object(2n)"); >+assert(Object(2n) <= Object(1n), false, "Object(2n) <= Object(1n)"); >+assert(Object(1n) <= Object(2n), true, "Object(1n) <= Object(2n)"); >+ >+let o = { >+ [Symbol.toPrimitive]: function() { >+ return 2n; >+ } >+} >+ >+let o2 = { >+ [Symbol.toPrimitive]: function() { >+ return 1n; >+ } >+} >+ >+assert(o <= 1n, false, "ToPrimitive(2n) <= 1n"); >+assert(1n <= o, true, "1n <= ToPrimitive(2n)"); >+assert(o <= o2, false, "ToPrimitive(2n) <= ToPrimitive(1n)"); >+assert(o2 <= o, true, "ToPrimitive(1n) <= ToPrimitive(2n)"); >+ >+o = { >+ valueOf: function() { >+ return 2n; >+ } >+} >+ >+o2 = { >+ valueOf: function() { >+ return 1n; >+ } >+} >+ >+assert(o <= 1n, false, "ToPrimitive(2n) <= 1n"); >+assert(1n <= o, true, "1n <= ToPrimitive(2n)"); >+assert(o <= o2, false, "ToPrimitive(2n) <= ToPrimitive(1n)"); >+assert(o2 <= o, true, "ToPrimitive(1n) <= ToPrimitive(2n)"); >+ >+o = { >+ toString: function() { >+ return 2n; >+ } >+} >+ >+o2 = { >+ toString: function() { >+ return 1n; >+ } >+} >+ >+assert(o <= 1n, false, "ToPrimitive(2n) <= 1n"); >+assert(1n <= o, true, "1n <= ToPrimitive(2n)"); >+assert(o <= o2, false, "ToPrimitive(2n) <= ToPrimitive(1n)"); >+assert(o2 <= o, true, "ToPrimitive(1n) <= ToPrimitive(2n)"); >+ >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index dbfecb1..7fe0d09 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,32 @@ >+2018-05-14 Caio Lima <ticaiolima@gmail.com> >+ >+ [ESNext][BigInt] Implement support for "<" and ">" relational operation >+ https://bugs.webkit.org/show_bug.cgi?id=185379 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch is changing the ``jsLess``` operation to follow the >+ semantics of Abstract Relational Comparison[1] that supports BigInt. >+ For that, we create 2 new helper functions ```bigIntCompareLess``` and >+ ```toPrimitiveNumeric``` that considers BigInt as a valid type to be >+ compared. >+ >+ [1] - https://tc39.github.io/proposal-bigint/#sec-abstract-relational-comparison >+ >+ * runtime/JSBigInt.cpp: >+ (JSC::JSBigInt::unequalSign): >+ (JSC::JSBigInt::absoluteGreater): >+ (JSC::JSBigInt::absoluteLess): >+ (JSC::JSBigInt::compare): >+ (JSC::JSBigInt::absoluteCompare): >+ * runtime/JSBigInt.h: >+ * runtime/JSCJSValueInlines.h: >+ (JSC::JSValue::isPrimitive const): >+ * runtime/Operations.h: >+ (JSC::bigIntCompareLess): >+ (JSC::toPrimitiveNumeric): >+ (JSC::jsLess): >+ > 2018-05-24 Caio Lima <ticaiolima@gmail.com> > > [ESNext][BigInt] Implement support for "<" and ">" relational operation >diff --git a/Source/JavaScriptCore/runtime/JSBigInt.h b/Source/JavaScriptCore/runtime/JSBigInt.h >index 3cb1ddf..07e8074 100644 >--- a/Source/JavaScriptCore/runtime/JSBigInt.h >+++ b/Source/JavaScriptCore/runtime/JSBigInt.h >@@ -84,6 +84,11 @@ public: > std::optional<uint8_t> singleDigitValueForString(); > String toString(ExecState*, unsigned radix); > >+ enum class ComparisonMode { >+ LessThan, >+ LessThanOrEqual >+ }; >+ > enum class ComparisonResult { > Equal, > Undefined, >@@ -124,6 +129,10 @@ private: > > static uint64_t calculateMaximumCharactersRequired(unsigned length, unsigned radix, Digit lastDigit, bool sign); > >+ static ComparisonResult unequalSign(bool leftNegative); >+ static ComparisonResult absoluteGreater(bool bothNegative); >+ static ComparisonResult absoluteLess(bool bothNegative); >+ > static ComparisonResult absoluteCompare(JSBigInt* x, JSBigInt* y); > static void absoluteDivWithDigitDivisor(VM&, JSBigInt* x, Digit divisor, JSBigInt** quotient, Digit& remainder); > static void internalMultiplyAdd(JSBigInt* source, Digit factor, Digit summand, unsigned, JSBigInt* result); >diff --git a/Source/JavaScriptCore/runtime/Operations.h b/Source/JavaScriptCore/runtime/Operations.h >index f69d9ca..d0aed0c 100644 >--- a/Source/JavaScriptCore/runtime/Operations.h >+++ b/Source/JavaScriptCore/runtime/Operations.h >@@ -157,7 +157,16 @@ ALWAYS_INLINE JSValue jsStringFromArguments(ExecState* exec, JSValue thisValue) > return ropeBuilder.release(); > } > >-ALWAYS_INLINE bool bigIntCompareLess(CallFrame* callFrame, JSValue v1, JSValue v2) >+ALWAYS_INLINE bool bigIntCompareResult(JSBigInt::ComparisonResult comparisonResult, JSBigInt::ComparisonMode comparisonMode) >+{ >+ if (comparisonMode == JSBigInt::ComparisonMode::LessThan) >+ return comparisonResult == JSBigInt::ComparisonResult::LessThan; >+ >+ ASSERT(comparisonMode == JSBigInt::ComparisonMode::LessThanOrEqual); >+ return comparisonResult == JSBigInt::ComparisonResult::LessThan || comparisonResult == JSBigInt::ComparisonResult::Equal; >+} >+ >+ALWAYS_INLINE bool bigIntCompare(CallFrame* callFrame, JSValue v1, JSValue v2, JSBigInt::ComparisonMode comparisonMode) > { > ASSERT(v1.isBigInt() || v2.isBigInt()); > ASSERT(v1.isPrimitive() && v2.isPrimitive()); >@@ -166,7 +175,7 @@ ALWAYS_INLINE bool bigIntCompareLess(CallFrame* callFrame, JSValue v1, JSValue v > auto scope = DECLARE_THROW_SCOPE(vm); > > if (v1.isBigInt() && v2.isBigInt()) >- return JSBigInt::compare(asBigInt(v1), asBigInt(v2)) == JSBigInt::ComparisonResult::LessThan; >+ return bigIntCompareResult(JSBigInt::compare(asBigInt(v1), asBigInt(v2)), comparisonMode); > > if (v1.isBigInt()) { > JSValue primValue = v2; >@@ -176,15 +185,15 @@ ALWAYS_INLINE bool bigIntCompareLess(CallFrame* callFrame, JSValue v1, JSValue v > if (!bigIntValue) > return false; > >- return JSBigInt::compare(asBigInt(v1), bigIntValue) == JSBigInt::ComparisonResult::LessThan; >+ return bigIntCompareResult(JSBigInt::compare(asBigInt(v1), bigIntValue), comparisonMode); > } > > if (primValue.isBigInt()) >- return JSBigInt::compare(asBigInt(v1), asBigInt(primValue)) == JSBigInt::ComparisonResult::LessThan; >+ return bigIntCompareResult(JSBigInt::compare(asBigInt(v1), asBigInt(primValue)), comparisonMode); > > double numberValue = primValue.toNumber(callFrame); > RETURN_IF_EXCEPTION(scope, false); >- return JSBigInt::compareToDouble(asBigInt(v1), numberValue) == JSBigInt::ComparisonResult::LessThan; >+ return bigIntCompareResult(JSBigInt::compareToDouble(asBigInt(v1), numberValue), comparisonMode); > } > > JSValue primValue = v1; >@@ -194,15 +203,21 @@ ALWAYS_INLINE bool bigIntCompareLess(CallFrame* callFrame, JSValue v1, JSValue v > if (!bigIntValue) > return false; > >- return JSBigInt::compare(bigIntValue, asBigInt(v2)) == JSBigInt::ComparisonResult::LessThan; >+ return bigIntCompareResult(JSBigInt::compare(bigIntValue, asBigInt(v2)), comparisonMode); > } > > if (primValue.isBigInt()) >- return JSBigInt::compare(asBigInt(primValue), asBigInt(v2)) == JSBigInt::ComparisonResult::LessThan; >+ return bigIntCompareResult(JSBigInt::compare(asBigInt(primValue), asBigInt(v2)), comparisonMode); > > double numberValue = primValue.toNumber(callFrame); > RETURN_IF_EXCEPTION(scope, false); >- return JSBigInt::compareToDouble(asBigInt(v2), numberValue) == JSBigInt::ComparisonResult::GreaterThan; >+ >+ // Here we check inverted because BigInt is the v2 >+ JSBigInt::ComparisonResult comparisonResult = JSBigInt::compareToDouble(asBigInt(v2), numberValue); >+ if (comparisonMode == JSBigInt::ComparisonMode::LessThan) >+ return comparisonResult == JSBigInt::ComparisonResult::GreaterThan; >+ >+ return comparisonResult == JSBigInt::ComparisonResult::GreaterThan || comparisonResult == JSBigInt::ComparisonResult::Equal; > } > > ALWAYS_INLINE bool toPrimitiveNumeric(CallFrame* callFrame, JSValue v, JSValue& p, double& n) >@@ -257,13 +272,14 @@ ALWAYS_INLINE bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2) > > if (wasNotString1 | wasNotString2) { > if (p1.isBigInt() || p2.isBigInt()) { >- bool result = bigIntCompareLess(callFrame, p1, p2); >+ bool result = bigIntCompare(callFrame, p1, p2, JSBigInt::ComparisonMode::LessThan); > RETURN_IF_EXCEPTION(scope, false); > return result; > } > > return n1 < n2; > } >+ > return codePointCompareLessThan(asString(p1)->value(callFrame), asString(p2)->value(callFrame)); > } > >@@ -292,18 +308,25 @@ ALWAYS_INLINE bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2) > bool wasNotString1; > bool wasNotString2; > if (leftFirst) { >- wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1); >+ wasNotString1 = toPrimitiveNumeric(callFrame, v1, p1, n1); > RETURN_IF_EXCEPTION(scope, false); >- wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2); >+ wasNotString2 = toPrimitiveNumeric(callFrame, v2, p2, n2); > } else { >- wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2); >+ wasNotString2 = toPrimitiveNumeric(callFrame, v2, p2, n2); > RETURN_IF_EXCEPTION(scope, false); >- wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1); >+ wasNotString1 = toPrimitiveNumeric(callFrame, v1, p1, n1); > } > RETURN_IF_EXCEPTION(scope, false); > >- if (wasNotString1 | wasNotString2) >+ if (wasNotString1 | wasNotString2) { >+ if (p1.isBigInt() || p2.isBigInt()) { >+ bool result = bigIntCompare(callFrame, p1, p2, JSBigInt::ComparisonMode::LessThanOrEqual); >+ RETURN_IF_EXCEPTION(scope, false); >+ return result; >+ } >+ > return n1 <= n2; >+ } > return !codePointCompareLessThan(asString(p2)->value(callFrame), asString(p1)->value(callFrame)); > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 185929
:
341243
|
341638
|
341722