Title: [181497] trunk
Revision
181497
Author
msab...@apple.com
Date
2015-03-14 09:29:20 -0700 (Sat, 14 Mar 2015)

Log Message

ES6: Add binary and octal literal support
https://bugs.webkit.org/show_bug.cgi?id=142681

Reviewed by Ryosuke Niwa.

Source/_javascript_Core:

Added a binary literal parser function, parseBinary(), to Lexer patterned after the octal parser.
Refactored the parseBinary, parseOctal and parseDecimal to use a constant size for the number of
characters to try and handle directly. Factored out the shifting past any prefix to be handled by
the caller. Added binary and octal parsing to toDouble() via helper functions.

* parser/Lexer.cpp:
(JSC::Lexer<T>::parseHex):
(JSC::Lexer<T>::parseBinary):
(JSC::Lexer<T>::parseOctal):
(JSC::Lexer<T>::parseDecimal):
(JSC::Lexer<T>::lex):
* parser/Lexer.h:
* parser/ParserTokens.h:
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::jsBinaryIntegerLiteral):
(JSC::jsOctalIntegerLiteral):
(JSC::toDouble):

Source/WTF:

* wtf/ASCIICType.h:
(WTF::isASCIIBinaryDigit): New support function.
(WTF::isASCIIOctalDigit): Updated to use logical and (&&) instead of binary and (&).

LayoutTests:

New tests.

* js/binary-literals-expected.txt: Added.
* js/binary-literals.html: Added.
* js/octal-literals-expected.txt: Added.
* js/octal-literals.html: Added.
* js/script-tests/binary-literals.js: Added.
* js/script-tests/octal-literals.js: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (181496 => 181497)


--- trunk/LayoutTests/ChangeLog	2015-03-14 02:57:54 UTC (rev 181496)
+++ trunk/LayoutTests/ChangeLog	2015-03-14 16:29:20 UTC (rev 181497)
@@ -1,3 +1,19 @@
+2015-03-14  Michael Saboff  <msab...@apple.com>
+
+        ES6: Add binary and octal literal support
+        https://bugs.webkit.org/show_bug.cgi?id=142681
+
+        Reviewed by Ryosuke Niwa.
+
+        New tests.
+
+        * js/binary-literals-expected.txt: Added.
+        * js/binary-literals.html: Added.
+        * js/octal-literals-expected.txt: Added.
+        * js/octal-literals.html: Added.
+        * js/script-tests/binary-literals.js: Added.
+        * js/script-tests/octal-literals.js: Added.
+
 2015-03-13  Ryosuke Niwa  <rn...@webkit.org>
 
         Class constructor should throw TypeError when "called"

Added: trunk/LayoutTests/js/binary-literals-expected.txt (0 => 181497)


--- trunk/LayoutTests/js/binary-literals-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/binary-literals-expected.txt	2015-03-14 16:29:20 UTC (rev 181497)
@@ -0,0 +1,43 @@
+Make sure that we correctly handle binary literals
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS 0b0 is 0
+PASS 0b1 is 1
+PASS 0B1 is 1
+PASS 0b00000000000000000000000000000000 is 0
+PASS 0B2 threw exception SyntaxError: No binary digits after '0b'.
+PASS 0ba threw exception SyntaxError: No binary digits after '0b'.
+PASS 0b0.0 threw exception SyntaxError: Unexpected number '.0'. Parse error..
+PASS x=0b1y=42 threw exception SyntaxError: No space between binary literal and identifier.
+PASS 0b1010 is 0xa
+PASS 0b00000001001000110100010101100111 is 0x01234567
+PASS 0b10001001101010111100110111101111 is 0x89abcdef
+PASS 0o100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 is 3.00300673152188e+256
+PASS 0b11111111111111111111111111111111111111111111111111110 is 9007199254740990
+PASS 0b11111111111111111111111111111111111111111111111111111 is 9007199254740991
+PASS 0b111111111111111111111111111111111111111111111111111110 is 18014398509481982
+PASS 0b111111111111111111111111111111111111111111111111111111 is 18014398509481984
+PASS !!0b1 is true
+PASS !!0b0 is false
+PASS Number('0b0') is 0
+PASS Number('0b1') is 1
+PASS Number('0B1') is 1
+PASS Number('0b00000000000000000000000000000000') is 0
+PASS Number('0B2') is NaN
+PASS Number('0ba') is NaN
+PASS Number('0b0.0') is NaN
+PASS Number('0b1010') is 0xa
+PASS Number('0b00000001001000110100010101100111') is 0x01234567
+PASS Number('0b10001001101010111100110111101111') is 0x89abcdef
+PASS Number('0b11111111111111111111111111111111111111111111111111110') is 9007199254740990
+PASS Number('0b11111111111111111111111111111111111111111111111111111') is 9007199254740991
+PASS Number('0b111111111111111111111111111111111111111111111111111110') is 18014398509481982
+PASS Number('0b111111111111111111111111111111111111111111111111111111') is 18014398509481984
+PASS !!Number('0b1') is true
+PASS !!Number('0b0') is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/binary-literals.html (0 => 181497)


--- trunk/LayoutTests/js/binary-literals.html	                        (rev 0)
+++ trunk/LayoutTests/js/binary-literals.html	2015-03-14 16:29:20 UTC (rev 181497)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/octal-literals-expected.txt (0 => 181497)


--- trunk/LayoutTests/js/octal-literals-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/octal-literals-expected.txt	2015-03-14 16:29:20 UTC (rev 181497)
@@ -0,0 +1,43 @@
+Make sure that we correctly handle octal literals
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS 0o0 is 0
+PASS 0o1 is 1
+PASS 0O1 is 1
+PASS 0o000000000000 is 0
+PASS 0O8 threw exception SyntaxError: No octal digits after '0o'.
+PASS 0oa threw exception SyntaxError: No octal digits after '0o'.
+PASS 0o0.0 threw exception SyntaxError: Unexpected number '.0'. Parse error..
+PASS x=0o1y=42 threw exception SyntaxError: No space between octal literal and identifier.
+PASS 0o12 is 0xa
+PASS 0o110642547 is 0x01234567
+PASS 0o21152746757 is 0x89abcdef
+FAIL 0o70000000000000000000000000000000000000000000000000000000 should be 3.00300673152188e+256. Was 3.2737636676212225e+50.
+PASS 0o377777777777777776 is 9007199254740990
+PASS 0o377777777777777777 is 9007199254740991
+PASS 0o777777777777777776 is 18014398509481982
+PASS 0o777777777777777777 is 18014398509481984
+PASS !!0o1 is true
+PASS !!0o0 is false
+PASS Number('0o0') is 0
+PASS Number('0o1') is 1
+PASS Number('0O1') is 1
+PASS Number('0o00000000000000000') is 0
+PASS Number('0O8') is NaN
+PASS Number('0oa') is NaN
+PASS Number('0o0.0') is NaN
+PASS Number('0o77') is 0x3f
+PASS Number('0o110642547') is 0x01234567
+PASS Number('0o21152746757') is 0x89abcdef
+PASS Number('0o377777777777777776') is 9007199254740990
+PASS Number('0o377777777777777777') is 9007199254740991
+PASS Number('0o777777777777777776') is 18014398509481982
+PASS Number('0o777777777777777777') is 18014398509481984
+PASS !!Number('0o1') is true
+PASS !!Number('0o0') is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/octal-literals.html (0 => 181497)


--- trunk/LayoutTests/js/octal-literals.html	                        (rev 0)
+++ trunk/LayoutTests/js/octal-literals.html	2015-03-14 16:29:20 UTC (rev 181497)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/script-tests/binary-literals.js (0 => 181497)


--- trunk/LayoutTests/js/script-tests/binary-literals.js	                        (rev 0)
+++ trunk/LayoutTests/js/script-tests/binary-literals.js	2015-03-14 16:29:20 UTC (rev 181497)
@@ -0,0 +1,47 @@
+description("Make sure that we correctly handle binary literals");
+
+shouldBe("0b0", "0");
+shouldBe("0b1", "1");
+shouldBe("0B1", "1");
+shouldBe("0b00000000000000000000000000000000", "0");
+shouldThrow("0B2");
+shouldThrow("0ba");
+shouldThrow("0b0.0");
+shouldThrow("x=0b1y=42");
+shouldBe("0b1010", "0xa");
+shouldBe("0b00000001001000110100010101100111", "0x01234567");
+shouldBe("0b10001001101010111100110111101111", "0x89abcdef");
+shouldBe("0o100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "3.00300673152188e+256");
+
+// Try 53 bits
+shouldBe("0b11111111111111111111111111111111111111111111111111110", "9007199254740990");
+shouldBe("0b11111111111111111111111111111111111111111111111111111", "9007199254740991");
+
+// 54 bits and above should add zeroes
+shouldBe("0b111111111111111111111111111111111111111111111111111110", "18014398509481982");
+shouldBe("0b111111111111111111111111111111111111111111111111111111", "18014398509481984");
+
+shouldBeTrue("!!0b1");
+shouldBeFalse("!!0b0");
+
+shouldBe("Number('0b0')", "0");
+shouldBe("Number('0b1')", "1");
+shouldBe("Number('0B1')", "1");
+shouldBe("Number('0b00000000000000000000000000000000')", "0");
+shouldBeNaN("Number('0B2')");
+shouldBeNaN("Number('0ba')");
+shouldBeNaN("Number('0b0.0')");
+shouldBe("Number('0b1010')", "0xa");
+shouldBe("Number('0b00000001001000110100010101100111')", "0x01234567");
+shouldBe("Number('0b10001001101010111100110111101111')", "0x89abcdef");
+
+// Try 53 bits
+shouldBe("Number('0b11111111111111111111111111111111111111111111111111110')", "9007199254740990");
+shouldBe("Number('0b11111111111111111111111111111111111111111111111111111')", "9007199254740991");
+
+// 54 bits and above should add zeroes
+shouldBe("Number('0b111111111111111111111111111111111111111111111111111110')", "18014398509481982");
+shouldBe("Number('0b111111111111111111111111111111111111111111111111111111')", "18014398509481984");
+
+shouldBeTrue("!!Number('0b1')");
+shouldBeFalse("!!Number('0b0')");

Added: trunk/LayoutTests/js/script-tests/octal-literals.js (0 => 181497)


--- trunk/LayoutTests/js/script-tests/octal-literals.js	                        (rev 0)
+++ trunk/LayoutTests/js/script-tests/octal-literals.js	2015-03-14 16:29:20 UTC (rev 181497)
@@ -0,0 +1,47 @@
+description("Make sure that we correctly handle octal literals");
+
+shouldBe("0o0", "0");
+shouldBe("0o1", "1");
+shouldBe("0O1", "1");
+shouldBe("0o000000000000", "0");
+shouldThrow("0O8");
+shouldThrow("0oa");
+shouldThrow("0o0.0");
+shouldThrow("x=0o1y=42");
+shouldBe("0o12", "0xa");
+shouldBe("0o110642547", "0x01234567");
+shouldBe("0o21152746757", "0x89abcdef");
+shouldBe("0o70000000000000000000000000000000000000000000000000000000", "3.00300673152188e+256");
+
+// Try 53 bits
+shouldBe("0o377777777777777776", "9007199254740990");
+shouldBe("0o377777777777777777", "9007199254740991");
+
+// 54 bits and above should add zeroes
+shouldBe("0o777777777777777776", "18014398509481982");
+shouldBe("0o777777777777777777", "18014398509481984");
+
+shouldBeTrue("!!0o1");
+shouldBeFalse("!!0o0");
+
+shouldBe("Number('0o0')", "0");
+shouldBe("Number('0o1')", "1");
+shouldBe("Number('0O1')", "1");
+shouldBe("Number('0o00000000000000000')", "0");
+shouldBeNaN("Number('0O8')");
+shouldBeNaN("Number('0oa')");
+shouldBeNaN("Number('0o0.0')");
+shouldBe("Number('0o77')", "0x3f");
+shouldBe("Number('0o110642547')", "0x01234567");
+shouldBe("Number('0o21152746757')", "0x89abcdef");
+
+// Try 53 bits
+shouldBe("Number('0o377777777777777776')", "9007199254740990");
+shouldBe("Number('0o377777777777777777')", "9007199254740991");
+
+// 54 bits and above should add zeroes
+shouldBe("Number('0o777777777777777776')", "18014398509481982");
+shouldBe("Number('0o777777777777777777')", "18014398509481984");
+
+shouldBeTrue("!!Number('0o1')");
+shouldBeFalse("!!Number('0o0')");

Modified: trunk/Source/_javascript_Core/ChangeLog (181496 => 181497)


--- trunk/Source/_javascript_Core/ChangeLog	2015-03-14 02:57:54 UTC (rev 181496)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-03-14 16:29:20 UTC (rev 181497)
@@ -1,3 +1,28 @@
+2015-03-14  Michael Saboff  <msab...@apple.com>
+
+        ES6: Add binary and octal literal support
+        https://bugs.webkit.org/show_bug.cgi?id=142681
+
+        Reviewed by Ryosuke Niwa.
+
+        Added a binary literal parser function, parseBinary(), to Lexer patterned after the octal parser.
+        Refactored the parseBinary, parseOctal and parseDecimal to use a constant size for the number of
+        characters to try and handle directly. Factored out the shifting past any prefix to be handled by
+        the caller. Added binary and octal parsing to toDouble() via helper functions.
+
+        * parser/Lexer.cpp:
+        (JSC::Lexer<T>::parseHex):
+        (JSC::Lexer<T>::parseBinary):
+        (JSC::Lexer<T>::parseOctal):
+        (JSC::Lexer<T>::parseDecimal):
+        (JSC::Lexer<T>::lex):
+        * parser/Lexer.h:
+        * parser/ParserTokens.h:
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::jsBinaryIntegerLiteral):
+        (JSC::jsOctalIntegerLiteral):
+        (JSC::toDouble):
+
 2015-03-13  Alex Christensen  <achristen...@webkit.org>
 
         Progress towards CMake on Mac.

Modified: trunk/Source/_javascript_Core/parser/Lexer.cpp (181496 => 181497)


--- trunk/Source/_javascript_Core/parser/Lexer.cpp	2015-03-14 02:57:54 UTC (rev 181496)
+++ trunk/Source/_javascript_Core/parser/Lexer.cpp	2015-03-14 16:29:20 UTC (rev 181497)
@@ -1222,9 +1222,6 @@
     uint32_t hexValue = 0;
     int maximumDigits = 7;
 
-    // Shift out the 'x' prefix.
-    shift();
-
     do {
         hexValue = (hexValue << 4) + toASCIIHexValue(m_current);
         shift();
@@ -1256,28 +1253,67 @@
 }
 
 template <typename T>
+ALWAYS_INLINE bool Lexer<T>::parseBinary(double& returnValue)
+{
+    // Optimization: most binary values fit into 4 bytes.
+    uint32_t binaryValue = 0;
+    const unsigned maximumDigits = 32;
+    int digit = maximumDigits - 1;
+    // Temporary buffer for the digits. Makes easier
+    // to reconstruct the input characters when needed.
+    LChar digits[maximumDigits];
+
+    do {
+        binaryValue = (binaryValue << 1) + (m_current - '0');
+        digits[digit] = m_current;
+        shift();
+        --digit;
+    } while (isASCIIBinaryDigit(m_current) && digit >= 0);
+
+    if (!isASCIIDigit(m_current) && digit >= 0) {
+        returnValue = binaryValue;
+        return true;
+    }
+
+    for (int i = maximumDigits - 1; i > digit; --i)
+        record8(digits[i]);
+
+    while (isASCIIBinaryDigit(m_current)) {
+        record8(m_current);
+        shift();
+    }
+
+    if (isASCIIDigit(m_current))
+        return false;
+
+    returnValue = parseIntOverflow(m_buffer8.data(), m_buffer8.size(), 2);
+    return true;
+}
+
+template <typename T>
 ALWAYS_INLINE bool Lexer<T>::parseOctal(double& returnValue)
 {
     // Optimization: most octal values fit into 4 bytes.
     uint32_t octalValue = 0;
-    int maximumDigits = 9;
+    const unsigned maximumDigits = 10;
+    int digit = maximumDigits - 1;
     // Temporary buffer for the digits. Makes easier
     // to reconstruct the input characters when needed.
-    LChar digits[10];
+    LChar digits[maximumDigits];
 
     do {
         octalValue = octalValue * 8 + (m_current - '0');
-        digits[maximumDigits] = m_current;
+        digits[digit] = m_current;
         shift();
-        --maximumDigits;
-    } while (isASCIIOctalDigit(m_current) && maximumDigits >= 0);
+        --digit;
+    } while (isASCIIOctalDigit(m_current) && digit >= 0);
 
-    if (!isASCIIDigit(m_current) && maximumDigits >= 0) {
+    if (!isASCIIDigit(m_current) && digit >= 0) {
         returnValue = octalValue;
         return true;
     }
 
-    for (int i = 9; i > maximumDigits; --i)
+    for (int i = maximumDigits - 1; i > digit; --i)
          record8(digits[i]);
 
     while (isASCIIOctalDigit(m_current)) {
@@ -1301,24 +1337,25 @@
     // Since parseOctal may be executed before parseDecimal,
     // the m_buffer8 may hold ascii digits.
     if (!m_buffer8.size()) {
-        int maximumDigits = 9;
+        const unsigned maximumDigits = 10;
+        int digit = maximumDigits - 1;
         // Temporary buffer for the digits. Makes easier
         // to reconstruct the input characters when needed.
-        LChar digits[10];
+        LChar digits[maximumDigits];
 
         do {
             decimalValue = decimalValue * 10 + (m_current - '0');
-            digits[maximumDigits] = m_current;
+            digits[digit] = m_current;
             shift();
-            --maximumDigits;
-        } while (isASCIIDigit(m_current) && maximumDigits >= 0);
+            --digit;
+        } while (isASCIIDigit(m_current) && digit >= 0);
 
-        if (maximumDigits >= 0 && m_current != '.' && (m_current | 0x20) != 'e') {
+        if (digit >= 0 && m_current != '.' && (m_current | 0x20) != 'e') {
             returnValue = decimalValue;
             return true;
         }
 
-        for (int i = 9; i > maximumDigits; --i)
+        for (int i = maximumDigits - 1; i > digit; --i)
             record8(digits[i]);
     }
 
@@ -1688,6 +1725,10 @@
                 token = INVALID_HEX_NUMBER_ERRORTOK;
                 goto returnError;
             }
+
+            // Shift out the 'x' prefix.
+            shift();
+
             parseHex(tokenData->doubleValue);
             if (isIdentStart(m_current)) {
                 m_lexErrorMessage = ASCIILiteral("No space between hexadecimal literal and identifier");
@@ -1698,7 +1739,48 @@
             m_buffer8.resize(0);
             break;
         }
+        if ((m_current | 0x20) == 'b') {
+            if (!isASCIIBinaryDigit(peek(1))) {
+                m_lexErrorMessage = ASCIILiteral("No binary digits after '0b'");
+                token = INVALID_BINARY_NUMBER_ERRORTOK;
+                goto returnError;
+            }
 
+            // Shift out the 'b' prefix.
+            shift();
+
+            parseBinary(tokenData->doubleValue);
+            if (isIdentStart(m_current)) {
+                m_lexErrorMessage = ASCIILiteral("No space between binary literal and identifier");
+                token = INVALID_BINARY_NUMBER_ERRORTOK;
+                goto returnError;
+            }
+            token = tokenTypeForIntegerLikeToken(tokenData->doubleValue);
+            m_buffer8.resize(0);
+            break;
+        }
+
+        if ((m_current | 0x20) == 'o') {
+            if (!isASCIIOctalDigit(peek(1))) {
+                m_lexErrorMessage = ASCIILiteral("No octal digits after '0o'");
+                token = INVALID_OCTAL_NUMBER_ERRORTOK;
+                goto returnError;
+            }
+
+            // Shift out the 'o' prefix.
+            shift();
+
+            parseOctal(tokenData->doubleValue);
+            if (isIdentStart(m_current)) {
+                m_lexErrorMessage = ASCIILiteral("No space between octal literal and identifier");
+                token = INVALID_OCTAL_NUMBER_ERRORTOK;
+                goto returnError;
+            }
+            token = tokenTypeForIntegerLikeToken(tokenData->doubleValue);
+            m_buffer8.resize(0);
+            break;
+        }
+
         record8('0');
         if (strictMode && isASCIIDigit(m_current)) {
             m_lexErrorMessage = ASCIILiteral("Decimal integer literals with a leading zero are forbidden in strict mode");

Modified: trunk/Source/_javascript_Core/parser/Lexer.h (181496 => 181497)


--- trunk/Source/_javascript_Core/parser/Lexer.h	2015-03-14 02:57:54 UTC (rev 181496)
+++ trunk/Source/_javascript_Core/parser/Lexer.h	2015-03-14 16:29:20 UTC (rev 181497)
@@ -203,6 +203,7 @@
     template <bool shouldBuildStrings> ALWAYS_INLINE StringParseResult parseString(JSTokenData*, bool strictMode);
     template <bool shouldBuildStrings> NEVER_INLINE StringParseResult parseStringSlowCase(JSTokenData*, bool strictMode);
     ALWAYS_INLINE void parseHex(double& returnValue);
+    ALWAYS_INLINE bool parseBinary(double& returnValue);
     ALWAYS_INLINE bool parseOctal(double& returnValue);
     ALWAYS_INLINE bool parseDecimal(double& returnValue);
     ALWAYS_INLINE void parseNumberAfterDecimalPoint();

Modified: trunk/Source/_javascript_Core/parser/ParserTokens.h (181496 => 181497)


--- trunk/Source/_javascript_Core/parser/ParserTokens.h	2015-03-14 02:57:54 UTC (rev 181496)
+++ trunk/Source/_javascript_Core/parser/ParserTokens.h	2015-03-14 16:29:20 UTC (rev 181497)
@@ -160,7 +160,8 @@
     UNTERMINATED_STRING_LITERAL_ERRORTOK = 8 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
     INVALID_STRING_LITERAL_ERRORTOK = 9 | ErrorTokenFlag,
     INVALID_PRIVATE_NAME_ERRORTOK = 10 | ErrorTokenFlag,
-    INVALID_HEX_NUMBER_ERRORTOK = 11 | ErrorTokenFlag
+    INVALID_HEX_NUMBER_ERRORTOK = 11 | ErrorTokenFlag,
+    INVALID_BINARY_NUMBER_ERRORTOK = 12 | ErrorTokenFlag
 };
 
 struct JSTextPosition {

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp (181496 => 181497)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2015-03-14 02:57:54 UTC (rev 181496)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2015-03-14 16:29:20 UTC (rev 181497)
@@ -343,8 +343,52 @@
         && data[7] == 'y';
 }
 
-// See ecma-262 9.3.1
+// See ecma-262 6th 11.8.3
 template <typename CharType>
+static double jsBinaryIntegerLiteral(const CharType*& data, const CharType* end)
+{
+    // Binary number.
+    data += 2;
+    const CharType* firstDigitPosition = data;
+    double number = 0;
+    while (true) {
+        number = number * 2 + (*data - '0');
+        ++data;
+        if (data == end)
+            break;
+        if (!isASCIIBinaryDigit(*data))
+            break;
+    }
+    if (number >= mantissaOverflowLowerBound)
+        number = parseIntOverflow(firstDigitPosition, data - firstDigitPosition, 2);
+
+    return number;
+}
+
+// See ecma-262 6th 11.8.3
+template <typename CharType>
+static double jsOctalIntegerLiteral(const CharType*& data, const CharType* end)
+{
+    // Octal number.
+    data += 2;
+    const CharType* firstDigitPosition = data;
+    double number = 0;
+    while (true) {
+        number = number * 8 + (*data - '0');
+        ++data;
+        if (data == end)
+            break;
+        if (!isASCIIOctalDigit(*data))
+            break;
+    }
+    if (number >= mantissaOverflowLowerBound)
+        number = parseIntOverflow(firstDigitPosition, data - firstDigitPosition, 8);
+    
+    return number;
+}
+
+// See ecma-262 6th 11.8.3
+template <typename CharType>
 static double jsHexIntegerLiteral(const CharType*& data, const CharType* end)
 {
     // Hex number.
@@ -365,7 +409,7 @@
     return number;
 }
 
-// See ecma-262 9.3.1
+// See ecma-262 6th 11.8.3
 template <typename CharType>
 static double jsStrDecimalLiteral(const CharType*& data, const CharType* end)
 {
@@ -422,9 +466,16 @@
         return 0.0;
     
     double number;
-    if (characters[0] == '0' && characters + 2 < endCharacters && (characters[1] | 0x20) == 'x' && isASCIIHexDigit(characters[2]))
-        number = jsHexIntegerLiteral(characters, endCharacters);
-    else
+    if (characters[0] == '0' && characters + 2 < endCharacters) {
+        if ((characters[1] | 0x20) == 'x' && isASCIIHexDigit(characters[2]))
+            number = jsHexIntegerLiteral(characters, endCharacters);
+        else if ((characters[1] | 0x20) == 'o' && isASCIIOctalDigit(characters[2]))
+            number = jsOctalIntegerLiteral(characters, endCharacters);
+        else if ((characters[1] | 0x20) == 'b' && isASCIIBinaryDigit(characters[2]))
+            number = jsBinaryIntegerLiteral(characters, endCharacters);
+        else
+            number = jsStrDecimalLiteral(characters, endCharacters);
+    } else
         number = jsStrDecimalLiteral(characters, endCharacters);
     
     // Allow trailing white space.
@@ -438,7 +489,7 @@
     return number;
 }
 
-// See ecma-262 9.3.1
+// See ecma-262 6th 11.8.3
 double jsToNumber(const String& s)
 {
     unsigned size = s.length();

Modified: trunk/Source/WTF/ChangeLog (181496 => 181497)


--- trunk/Source/WTF/ChangeLog	2015-03-14 02:57:54 UTC (rev 181496)
+++ trunk/Source/WTF/ChangeLog	2015-03-14 16:29:20 UTC (rev 181497)
@@ -1,3 +1,14 @@
+2015-03-14  Michael Saboff  <msab...@apple.com>
+
+        ES6: Add binary and octal literal support
+        https://bugs.webkit.org/show_bug.cgi?id=142681
+
+        Reviewed by Ryosuke Niwa.
+
+        * wtf/ASCIICType.h:
+        (WTF::isASCIIBinaryDigit): New support function.
+        (WTF::isASCIIOctalDigit): Updated to use logical and (&&) instead of binary and (&).
+
 2015-03-13  Mark Lam  <mark....@apple.com>
 
         Replace TCSpinLock with a new WTF::SpinLock based on WTF::Atomic.

Modified: trunk/Source/WTF/wtf/ASCIICType.h (181496 => 181497)


--- trunk/Source/WTF/wtf/ASCIICType.h	2015-03-14 02:57:54 UTC (rev 181496)
+++ trunk/Source/WTF/wtf/ASCIICType.h	2015-03-14 16:29:20 UTC (rev 181497)
@@ -73,9 +73,14 @@
     return c >= 'a' && c <= 'z';
 }
 
+template<typename CharType> inline bool isASCIIBinaryDigit(CharType c)
+{
+    return (c == '0') || (c == '1');
+}
+
 template<typename CharType> inline bool isASCIIOctalDigit(CharType c)
 {
-    return (c >= '0') & (c <= '7');
+    return (c >= '0') && (c <= '7');
 }
 
 template<typename CharType> inline bool isASCIIPrintable(CharType c)
@@ -166,6 +171,7 @@
 using WTF::isASCIIDigit;
 using WTF::isASCIIHexDigit;
 using WTF::isASCIILower;
+using WTF::isASCIIBinaryDigit;
 using WTF::isASCIIOctalDigit;
 using WTF::isASCIIPrintable;
 using WTF::isASCIISpace;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to