Title: [244828] trunk
Revision
244828
Author
[email protected]
Date
2019-05-01 10:33:03 -0700 (Wed, 01 May 2019)

Log Message

WebKit has too much of its own UTF-8 code and should rely more on ICU's UTF-8 support
https://bugs.webkit.org/show_bug.cgi?id=195535

Patch by Darin Adler <[email protected]> on 2019-05-01
Reviewed by Alexey Proskuryakov.

LayoutTests/imported/w3c:

* web-platform-tests/encoding/textdecoder-utf16-surrogates-expected.txt:
Updated expected results to have the Unicode replacement character in cases where the
text contains unpaired surrogates. The tests are still doing the same operations, and
still getting the same results, but the text output no longer includes illegal UTF-8.

Source/_javascript_Core:

* API/JSClassRef.cpp: Removed uneeded include of UTF8Conversion.h.

* API/JSStringRef.cpp:
(JSStringCreateWithUTF8CString): Updated for changes to convertUTF8ToUTF16.
(JSStringGetUTF8CString): Updated for changes to convertLatin1ToUTF8.
Removed unneeded "true" to get the strict version of convertUTF16ToUTF8,
since that is the default. Also updated for changes to CompletionResult.

* runtime/JSGlobalObjectFunctions.cpp:
(JSC::decode): Stop using UTF8SequenceLength, and instead use U8_COUNT_TRAIL_BYTES
and U8_MAX_LENGTH. Instead of decodeUTF8Sequence, use U8_NEXT. Also use U_IS_BMP,
U_IS_SUPPLEMENTARY, U16_LEAD, U16_TRAIL, and U_IS_SURROGATE instead of our own
equivalents, since these macros from ICU are correct and efficient.

* wasm/WasmParser.h:
(JSC::Wasm::Parser<SuccessType>::consumeUTF8String): Updated for changes to
convertUTF8ToUTF16.

Source/WebCore:

* platform/SharedBuffer.cpp:
(WebCore::utf8Buffer): Removed unnecessary "strict" argument to convertUTF16ToUTF8 since
that is the default behavior. Also updated for changes to return values.

* xml/XSLTProcessorLibxslt.cpp:
(WebCore::writeToStringBuilder): Removed unnecessary use of StringBuffer for a temporary
buffer for characters. Rewrote to use U8_NEXT and U16_APPEND directly.

* xml/parser/XMLDocumentParserLibxml2.cpp:
(WebCore::convertUTF16EntityToUTF8): Updated for changes to CompletionResult.

Source/WebKit:

* Shared/API/APIString.h: Removed uneeded includes and also switched to #pragma once.

* Shared/API/c/WKString.cpp: Moved include of UTF8Conversion.h here.
(WKStringGetUTF8CStringImpl): Updated for changes to return values.

Source/WTF:

* wtf/text/AtomicString.cpp:
(WTF::AtomicString::fromUTF8Internal): Added code to compute string length when the
end is nullptr; this behavior used to be implemented inside the
calculateStringHashAndLengthFromUTF8MaskingTop8Bits function.

* wtf/text/AtomicStringImpl.cpp:
(WTF::HashAndUTF8CharactersTranslator::translate): Updated for change to
convertUTF8ToUTF16.

* wtf/text/AtomicStringImpl.h: Took the WTF_EXPORT_PRIVATE off of the
AtomicStringImpl::addUTF8 function. This is used only inside a non-inlined function in
the AtomicString class and its behavior changed subtly in this patch; it's helpful
to document that it's not exported.

* wtf/text/StringImpl.cpp:
(WTF::StringImpl::utf8Impl): Don't pass "true" for strictness to convertUTF16ToUTF8
since strict is the default. Also updated for changes to ConversionResult.
(WTF::StringImpl::utf8ForCharacters): Updated for change to convertLatin1ToUTF8.
(WTF::StringImpl::tryGetUtf8ForRange const): Ditto.

* wtf/text/StringView.cpp: Removed uneeded include of UTF8Conversion.h.

* wtf/text/WTFString.cpp:
(WTF::String::fromUTF8): Updated for change to convertUTF8ToUTF16.

* wtf/unicode/UTF8Conversion.cpp:
(WTF::Unicode::inlineUTF8SequenceLengthNonASCII): Deleted.
(WTF::Unicode::inlineUTF8SequenceLength): Deleted.
(WTF::Unicode::UTF8SequenceLength): Deleted.
(WTF::Unicode::decodeUTF8Sequence): Deleted.
(WTF::Unicode::convertLatin1ToUTF8): Use U8_APPEND, enabling us to remove
almost everything in the function. Also changed resturn value to be a boolean
to indicate success since there is only one possible failure (target exhausted).
There is room for further simplification, since most callers have lengths rather
than end pointers for the source buffer, and all but one caller supplies a buffer
size known to be sufficient, so those don't need a return value, nor do they need
to pass an end of buffer pointer.
(WTF::Unicode::convertUTF16ToUTF8): Use U_IS_LEAD, U_IS_TRAIL,
U16_GET_SUPPLEMENTARY, U_IS_SURROGATE, and U8_APPEND. Also changed behavior
for non-strict mode so that unpaired surrogates will be turned into the
replacement character instead of invalid UTF-8 sequences, because U8_APPEND
won't create an invalid UTF-8 sequence, and because we don't need to do that
for any good reason at any call site.
(WTF::Unicode::isLegalUTF8): Deleted.
(WTF::Unicode::readUTF8Sequence): Deleted.
(WTF::Unicode::convertUTF8ToUTF16): Use U8_NEXT instead of
inlineUTF8SequenceLength, isLegalUTF8, and readUTF8Sequence. Use
U16_APPEND instead of lots of code that does the same thing. There is
room for further simplification since most callers don't need the "all ASCII"
feature and could probably pass the arguments in a more natural way.
(WTF::Unicode::calculateStringHashAndLengthFromUTF8MaskingTop8Bits):
Use U8_NEXT instead of isLegalUTF8, readUTF8Sequence, and various
error handling checks for things that are handled by U8_NEXT. Also removed
support for passing nullptr for end to specify a null-terminated string.
(WTF::Unicode::equalUTF16WithUTF8): Ditto.

* wtf/unicode/UTF8Conversion.h: Removed UTF8SequenceLength and
decodeUTF8Sequence. Changed the ConversionResult to match WebKit coding
style, with an eye toward perhaps removing it in the future. Changed
the convertUTF8ToUTF16 return value to a boolean and removed the "strict"
argument since no caller was passing false. Changed the convertLatin1ToUTF8
return value to a boolean. Tweaked comments.

LayoutTests:

* css3/escape-dom-api-expected.txt:
* fast/text/dangling-surrogates-expected.txt:
* js/dom/webidl-type-mapping-expected.txt:
* js/invalid-utf8-in-syntax-error-expected.txt:
Updated expected results to have the Unicode replacement character in cases where the
text contains unpaired surrogates. The tests are still doing the same operations, and
still getting the same results, but the text output no longer includes illegal UTF-8.

* js/invalid-utf8-in-syntax-error.html: Added. Before adding this, the test was
run, but unlike the rest of the tests in this directory, was only run as part of
run-_javascript_core-tests. There are two reasons for adding this. One is to be
consistent with the rest of the tests here and run a second time as part of the
broader WebKit tests. The second is that we can now use "--reset-results" to generate
new expected results, something that run-webkit-tests has but run-_javascript_core-tests
does not have.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (244827 => 244828)


--- trunk/LayoutTests/ChangeLog	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/LayoutTests/ChangeLog	2019-05-01 17:33:03 UTC (rev 244828)
@@ -1,3 +1,26 @@
+2019-05-01  Darin Adler  <[email protected]>
+
+        WebKit has too much of its own UTF-8 code and should rely more on ICU's UTF-8 support
+        https://bugs.webkit.org/show_bug.cgi?id=195535
+
+        Reviewed by Alexey Proskuryakov.
+
+        * css3/escape-dom-api-expected.txt:
+        * fast/text/dangling-surrogates-expected.txt:
+        * js/dom/webidl-type-mapping-expected.txt:
+        * js/invalid-utf8-in-syntax-error-expected.txt:
+        Updated expected results to have the Unicode replacement character in cases where the
+        text contains unpaired surrogates. The tests are still doing the same operations, and
+        still getting the same results, but the text output no longer includes illegal UTF-8.
+
+        * js/invalid-utf8-in-syntax-error.html: Added. Before adding this, the test was
+        run, but unlike the rest of the tests in this directory, was only run as part of
+        run-_javascript_core-tests. There are two reasons for adding this. One is to be
+        consistent with the rest of the tests here and run a second time as part of the
+        broader WebKit tests. The second is that we can now use "--reset-results" to generate
+        new expected results, something that run-webkit-tests has but run-_javascript_core-tests
+        does not have.
+
 2019-05-01  Shawn Roberts  <[email protected]>
 
         Unreviewed, rolling out r244821.

Modified: trunk/LayoutTests/css3/escape-dom-api-expected.txt (244827 => 244828)


--- trunk/LayoutTests/css3/escape-dom-api-expected.txt	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/LayoutTests/css3/escape-dom-api-expected.txt	2019-05-01 17:33:03 UTC (rev 244828)
@@ -4,14 +4,14 @@
 
 
 PASS CSS.escape.length is 1
-PASS CSS.escape('\0') is "�"
-PASS CSS.escape('a\0') is "a�"
-PASS CSS.escape('\0b') is "�b"
-PASS CSS.escape('a\0b') is "a�b"
-PASS CSS.escape('�') is "�"
-PASS CSS.escape('a�') is "a�"
-PASS CSS.escape('�b') is "�b"
-PASS CSS.escape('a�b') is "a�b"
+PASS CSS.escape('\0') is "�"
+PASS CSS.escape('a\0') is "a�"
+PASS CSS.escape('\0b') is "�b"
+PASS CSS.escape('a\0b') is "a�b"
+PASS CSS.escape('�') is "�"
+PASS CSS.escape('a�') is "a�"
+PASS CSS.escape('�b') is "�b"
+PASS CSS.escape('a�b') is "a�b"
 PASS CSS.escape() threw exception TypeError: Not enough arguments.
 PASS CSS.escape(undefined) is "undefined"
 PASS CSS.escape(true) is "true"
@@ -53,16 +53,16 @@
 PASS CSS.escape('-a') is "-a"
 PASS CSS.escape('--') is "--"
 PASS CSS.escape('--a') is "--a"
-PASS CSS.escape('€-_©') is "€-_©"
-PASS CSS.escape('€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ') is "\\7f €‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ"
-PASS CSS.escape(' ¡¢') is " ¡¢"
+PASS CSS.escape('€-_©') is "€-_©"
+PASS CSS.escape('€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ') is "\\7f €‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ"
+PASS CSS.escape(' ¡¢') is " ¡¢"
 PASS CSS.escape('a0123456789b') is "a0123456789b"
 PASS CSS.escape('abcdefghijklmnopqrstuvwxyz') is "abcdefghijklmnopqrstuvwxyz"
 PASS CSS.escape('ABCDEFGHIJKLMNOPQRSTUVWXYZ') is "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 PASS CSS.escape(' !xy') is "\\ \\!xy"
-PASS CSS.escape('𝌆') is "𝌆"
-PASS CSS.escape('í¼†') is "\udf06"
-PASS CSS.escape('í ´') is "\ud834"
+PASS CSS.escape('𝌆') is "𝌆"
+PASS CSS.escape('�') is "\udf06"
+PASS CSS.escape('�') is "\ud834"
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/fast/text/dangling-surrogates-expected.txt (244827 => 244828)


--- trunk/LayoutTests/fast/text/dangling-surrogates-expected.txt	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/LayoutTests/fast/text/dangling-surrogates-expected.txt	2019-05-01 17:33:03 UTC (rev 244828)
@@ -3,8 +3,8 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS danglingFirst is "í ƒ"
-PASS danglingSecond is "í°"
+PASS danglingFirst is "�"
+PASS danglingSecond is "�"
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (244827 => 244828)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2019-05-01 17:33:03 UTC (rev 244828)
@@ -1,3 +1,15 @@
+2019-05-01  Darin Adler  <[email protected]>
+
+        WebKit has too much of its own UTF-8 code and should rely more on ICU's UTF-8 support
+        https://bugs.webkit.org/show_bug.cgi?id=195535
+
+        Reviewed by Alexey Proskuryakov.
+
+        * web-platform-tests/encoding/textdecoder-utf16-surrogates-expected.txt:
+        Updated expected results to have the Unicode replacement character in cases where the
+        text contains unpaired surrogates. The tests are still doing the same operations, and
+        still getting the same results, but the text output no longer includes illegal UTF-8.
+
 2019-05-01  Shawn Roberts  <[email protected]>
 
         Unreviewed, rolling out r244821.

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/encoding/textdecoder-utf16-surrogates-expected.txt (244827 => 244828)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/encoding/textdecoder-utf16-surrogates-expected.txt	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/encoding/textdecoder-utf16-surrogates-expected.txt	2019-05-01 17:33:03 UTC (rev 244828)
@@ -1,21 +1,21 @@
 
-FAIL utf-16le - lone surrogate lead assert_equals: expected "\ufffd" but got "í €"
+FAIL utf-16le - lone surrogate lead assert_equals: expected "\ufffd" but got "�"
 FAIL utf-16le - lone surrogate lead (fatal flag set) assert_throws: function "function () {
             new TextDecoder(t.encoding, {fatal: true}).decode(new Uint8Array(t.input))
         }" did not throw
-FAIL utf-16le - lone surrogate trail assert_equals: expected "\ufffd" but got "í°€"
+FAIL utf-16le - lone surrogate trail assert_equals: expected "\ufffd" but got "�"
 FAIL utf-16le - lone surrogate trail (fatal flag set) assert_throws: function "function () {
             new TextDecoder(t.encoding, {fatal: true}).decode(new Uint8Array(t.input))
         }" did not throw
-FAIL utf-16le - unmatched surrogate lead assert_equals: expected "\ufffd\0" but got "í €\0"
+FAIL utf-16le - unmatched surrogate lead assert_equals: expected "\ufffd\0" but got "�\0"
 FAIL utf-16le - unmatched surrogate lead (fatal flag set) assert_throws: function "function () {
             new TextDecoder(t.encoding, {fatal: true}).decode(new Uint8Array(t.input))
         }" did not throw
-FAIL utf-16le - unmatched surrogate trail assert_equals: expected "\ufffd\0" but got "í°€\0"
+FAIL utf-16le - unmatched surrogate trail assert_equals: expected "\ufffd\0" but got "�\0"
 FAIL utf-16le - unmatched surrogate trail (fatal flag set) assert_throws: function "function () {
             new TextDecoder(t.encoding, {fatal: true}).decode(new Uint8Array(t.input))
         }" did not throw
-FAIL utf-16le - swapped surrogate pair assert_equals: expected "\ufffd\ufffd" but got "í°€í €"
+FAIL utf-16le - swapped surrogate pair assert_equals: expected "\ufffd\ufffd" but got "��"
 FAIL utf-16le - swapped surrogate pair (fatal flag set) assert_throws: function "function () {
             new TextDecoder(t.encoding, {fatal: true}).decode(new Uint8Array(t.input))
         }" did not throw

Modified: trunk/LayoutTests/js/dom/webidl-type-mapping-expected.txt (244827 => 244828)


--- trunk/LayoutTests/js/dom/webidl-type-mapping-expected.txt	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/LayoutTests/js/dom/webidl-type-mapping-expected.txt	2019-05-01 17:33:03 UTC (rev 244828)
@@ -1009,48 +1009,48 @@
 
 converter.testUSVString = '!@#123ABCabc\x00\x80\xFF\r\n\t'
 converter.testString = '!@#123ABCabc\x00\x80\xFF\r\n\t'
-PASS converter.testUSVString is "!@#123ABCabc\u0000€ÿ\r\n\t"
-PASS converter.testString is "!@#123ABCabc\u0000€ÿ\r\n\t"
+PASS converter.testUSVString is "!@#123ABCabc\u0000€ÿ\r\n\t"
+PASS converter.testString is "!@#123ABCabc\u0000€ÿ\r\n\t"
 converter.testUSVString = '\u0100'
 converter.testString = '\u0100'
-PASS converter.testUSVString is "Ā"
-PASS converter.testString is "Ā"
+PASS converter.testUSVString is "Ā"
+PASS converter.testString is "Ā"
 PASS converter.testUSVString = {toString: function() { throw Error(); }} threw exception Error.
 PASS converter.testString = {toString: function() { throw Error(); }} threw exception Error.
-PASS converter.testUSVString is "Ā"
-PASS converter.testString is "Ā"
+PASS converter.testUSVString is "Ā"
+PASS converter.testString is "Ā"
 converter.testUSVString = "\ud800"
 converter.testString = "\ud800"
-PASS converter.testUSVString is "�"
+PASS converter.testUSVString is "�"
 PASS converter.testString is "\ud800"
 converter.testUSVString = "\udc00"
 converter.testString = "\udc00"
-PASS converter.testUSVString is "�"
+PASS converter.testUSVString is "�"
 PASS converter.testString is "\udc00"
 converter.testUSVString = "\ud800\u0000"
 converter.testString = "\ud800\u0000"
-PASS converter.testUSVString is "�\u0000"
+PASS converter.testUSVString is "�\u0000"
 PASS converter.testString is "\ud800\u0000"
 converter.testUSVString = "\udc00\u0000"
 converter.testString = "\udc00\u0000"
-PASS converter.testUSVString is "�\u0000"
+PASS converter.testUSVString is "�\u0000"
 PASS converter.testString is "\udc00\u0000"
 converter.testUSVString = "\udc00\ud800"
 converter.testString = "\udc00\ud800"
-PASS converter.testUSVString is "��"
+PASS converter.testUSVString is "��"
 PASS converter.testString is "\udc00\ud800"
-converter.testUSVString = "𝄞"
-converter.testString = "𝄞"
-PASS converter.testUSVString is "𝄞"
-PASS converter.testString is "𝄞"
+converter.testUSVString = "𝄞"
+converter.testString = "𝄞"
+PASS converter.testUSVString is "𝄞"
+PASS converter.testString is "𝄞"
 converter.testByteString = '!@#123ABCabc\x00\x80\xFF\r\n\t'
-PASS converter.testByteString is "!@#123ABCabc\u0000€ÿ\r\n\t"
+PASS converter.testByteString is "!@#123ABCabc\u0000€ÿ\r\n\t"
 converter.testByteString = '\u00FF'
-PASS converter.testByteString is "ÿ"
+PASS converter.testByteString is "ÿ"
 PASS converter.testByteString = '\u0100' threw exception TypeError: Type error.
-PASS converter.testByteString is "ÿ"
+PASS converter.testByteString is "ÿ"
 PASS converter.testByteString = {toString: function() { throw Error(); }} threw exception Error.
-PASS converter.testByteString is "ÿ"
+PASS converter.testByteString is "ÿ"
 converter.testUSVString = true
 converter.testString = true
 converter.testByteString = true
@@ -1180,37 +1180,37 @@
 PASS 'key2' in converter.testNodeRecord() is true
 PASS converter.testNodeRecord()['key2'] is document.documentElement
 PASS converter.setTestNodeRecord({ key: 'hello' }) threw exception TypeError: Type error.
-converter.setTestLongRecord({'í €': 1 })
-PASS converter.testLongRecord()['í €'] is 1
-converter.setTestNodeRecord({'í €': document })
-PASS converter.testNodeRecord()['�'] is document
-converter.setTestLongRecord({'í°€': 1 })
-PASS converter.testLongRecord()['í°€'] is 1
-converter.setTestNodeRecord({'í°€': document })
-PASS converter.testNodeRecord()['�'] is document
-converter.setTestLongRecord({'í €': 1 })
-PASS converter.testLongRecord()['í €\0'] is 1
-converter.setTestNodeRecord({'í €': document })
-PASS converter.testNodeRecord()['�\0'] is document
-converter.setTestLongRecord({'í°€': 1 })
-PASS converter.testLongRecord()['í°€\0'] is 1
-converter.setTestNodeRecord({'í°€': document })
-PASS converter.testNodeRecord()['�\0'] is document
-converter.setTestLongRecord({'í°€í €': 1 })
-PASS converter.testLongRecord()['í°€í €'] is 1
-converter.setTestNodeRecord({'í°€í €': document })
-PASS converter.testNodeRecord()['��'] is document
-converter.setTestLongRecord({'𝄞': 1 })
-PASS converter.testLongRecord()['𝄞'] is 1
-converter.setTestNodeRecord({'𝄞': document })
-PASS converter.testNodeRecord()['𝄞'] is document
+converter.setTestLongRecord({'�': 1 })
+PASS converter.testLongRecord()['�'] is 1
+converter.setTestNodeRecord({'�': document })
+PASS converter.testNodeRecord()['�'] is document
+converter.setTestLongRecord({'�': 1 })
+PASS converter.testLongRecord()['�'] is 1
+converter.setTestNodeRecord({'�': document })
+PASS converter.testNodeRecord()['�'] is document
+converter.setTestLongRecord({'�': 1 })
+PASS converter.testLongRecord()['�\0'] is 1
+converter.setTestNodeRecord({'�': document })
+PASS converter.testNodeRecord()['�\0'] is document
+converter.setTestLongRecord({'�': 1 })
+PASS converter.testLongRecord()['�\0'] is 1
+converter.setTestNodeRecord({'�': document })
+PASS converter.testNodeRecord()['�\0'] is document
+converter.setTestLongRecord({'��': 1 })
+PASS converter.testLongRecord()['��'] is 1
+converter.setTestNodeRecord({'��': document })
+PASS converter.testNodeRecord()['��'] is document
+converter.setTestLongRecord({'𝄞': 1 })
+PASS converter.testLongRecord()['𝄞'] is 1
+converter.setTestNodeRecord({'𝄞': document })
+PASS converter.testNodeRecord()['𝄞'] is document
 converter.setTestSequenceRecord({ key: ['value', 'other value'] })
 PASS converter.testSequenceRecord().hasOwnProperty('key') is true
 PASS 'key' in converter.testSequenceRecord() is true
 PASS converter.testSequenceRecord()['key'] is ['value', 'other value']
-PASS converter.setTestSequenceRecord({ 'Ā': ['value'] }) threw exception TypeError: Type error.
-converter.setTestSequenceRecord({ 'ÿ': ['value'] })
-PASS converter.testSequenceRecord()['ÿ'] is ['value']
+PASS converter.setTestSequenceRecord({ 'Ā': ['value'] }) threw exception TypeError: Type error.
+converter.setTestSequenceRecord({ 'ÿ': ['value'] })
+PASS converter.testSequenceRecord()['ÿ'] is ['value']
 PASS converter.testImpureNaNUnrestrictedDouble is NaN
 PASS converter.testImpureNaN2UnrestrictedDouble is NaN
 PASS converter.testQuietNaNUnrestrictedDouble is NaN

Modified: trunk/LayoutTests/js/invalid-utf8-in-syntax-error-expected.txt (244827 => 244828)


--- trunk/LayoutTests/js/invalid-utf8-in-syntax-error-expected.txt	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/LayoutTests/js/invalid-utf8-in-syntax-error-expected.txt	2019-05-01 17:33:03 UTC (rev 244828)
@@ -3,7 +3,7 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS ({f("\x{DEAD}")}) threw exception SyntaxError: Unexpected string literal "íº­". Expected a parameter pattern or a ')' in parameter list..
+PASS ({f("�")}) threw exception SyntaxError: Unexpected string literal "�". Expected a parameter pattern or a ')' in parameter list..
 PASS successfullyParsed is true
 
 TEST COMPLETE

Added: trunk/LayoutTests/js/invalid-utf8-in-syntax-error.html (0 => 244828)


--- trunk/LayoutTests/js/invalid-utf8-in-syntax-error.html	                        (rev 0)
+++ trunk/LayoutTests/js/invalid-utf8-in-syntax-error.html	2019-05-01 17:33:03 UTC (rev 244828)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Modified: trunk/Source/_javascript_Core/API/JSClassRef.cpp (244827 => 244828)


--- trunk/Source/_javascript_Core/API/JSClassRef.cpp	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/_javascript_Core/API/JSClassRef.cpp	2019-05-01 17:33:03 UTC (rev 244828)
@@ -35,10 +35,8 @@
 #include "ObjectPrototype.h"
 #include "JSCInlines.h"
 #include <wtf/text/StringHash.h>
-#include <wtf/unicode/UTF8Conversion.h>
 
 using namespace JSC;
-using namespace WTF::Unicode;
 
 const JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 

Modified: trunk/Source/_javascript_Core/API/JSStringRef.cpp (244827 => 244828)


--- trunk/Source/_javascript_Core/API/JSStringRef.cpp	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/_javascript_Core/API/JSStringRef.cpp	2019-05-01 17:33:03 UTC (rev 244828)
@@ -49,7 +49,7 @@
         UChar* p = buffer.data();
         bool sourceIsAllASCII;
         const LChar* stringStart = reinterpret_cast<const LChar*>(string);
-        if (conversionOK == convertUTF8ToUTF16(&string, string + length, &p, p + length, &sourceIsAllASCII)) {
+        if (convertUTF8ToUTF16(string, string + length, &p, p + length, &sourceIsAllASCII)) {
             if (sourceIsAllASCII)
                 return &OpaqueJSString::create(stringStart, length).leakRef();
             return &OpaqueJSString::create(buffer.data(), p - buffer.data()).leakRef();
@@ -102,20 +102,18 @@
         return 0;
 
     char* destination = buffer;
-    ConversionResult result;
+    bool failed = false;
     if (string->is8Bit()) {
         const LChar* source = string->characters8();
-        result = convertLatin1ToUTF8(&source, source + string->length(), &destination, destination + bufferSize - 1);
+        convertLatin1ToUTF8(&source, source + string->length(), &destination, destination + bufferSize - 1);
     } else {
         const UChar* source = string->characters16();
-        result = convertUTF16ToUTF8(&source, source + string->length(), &destination, destination + bufferSize - 1, true);
+        auto result = convertUTF16ToUTF8(&source, source + string->length(), &destination, destination + bufferSize - 1);
+        failed = result != ConversionOK && result != TargetExhausted;
     }
 
     *destination++ = '\0';
-    if (result != conversionOK && result != targetExhausted)
-        return 0;
-
-    return destination - buffer;
+    return failed ? 0 : destination - buffer;
 }
 
 bool JSStringIsEqual(JSStringRef a, JSStringRef b)

Modified: trunk/Source/_javascript_Core/ChangeLog (244827 => 244828)


--- trunk/Source/_javascript_Core/ChangeLog	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-05-01 17:33:03 UTC (rev 244828)
@@ -1,3 +1,28 @@
+2019-05-01  Darin Adler  <[email protected]>
+
+        WebKit has too much of its own UTF-8 code and should rely more on ICU's UTF-8 support
+        https://bugs.webkit.org/show_bug.cgi?id=195535
+
+        Reviewed by Alexey Proskuryakov.
+
+        * API/JSClassRef.cpp: Removed uneeded include of UTF8Conversion.h.
+
+        * API/JSStringRef.cpp:
+        (JSStringCreateWithUTF8CString): Updated for changes to convertUTF8ToUTF16.
+        (JSStringGetUTF8CString): Updated for changes to convertLatin1ToUTF8.
+        Removed unneeded "true" to get the strict version of convertUTF16ToUTF8,
+        since that is the default. Also updated for changes to CompletionResult.
+
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::decode): Stop using UTF8SequenceLength, and instead use U8_COUNT_TRAIL_BYTES
+        and U8_MAX_LENGTH. Instead of decodeUTF8Sequence, use U8_NEXT. Also use U_IS_BMP,
+        U_IS_SUPPLEMENTARY, U16_LEAD, U16_TRAIL, and U_IS_SURROGATE instead of our own
+        equivalents, since these macros from ICU are correct and efficient.
+
+        * wasm/WasmParser.h:
+        (JSC::Wasm::Parser<SuccessType>::consumeUTF8String): Updated for changes to
+        convertUTF8ToUTF16.
+
 2019-05-01  Shawn Roberts  <[email protected]>
 
         Unreviewed, rolling out r244821.

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp (244827 => 244828)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2019-05-01 17:33:03 UTC (rev 244828)
@@ -58,12 +58,9 @@
 #include <wtf/MathExtras.h>
 #include <wtf/dtoa.h>
 #include <wtf/text/StringBuilder.h>
-#include <wtf/unicode/UTF8Conversion.h>
 
 namespace JSC {
 
-using namespace WTF::Unicode;
-
 const ASCIILiteral ObjectProtoCalledOnNullOrUndefinedError { "Object.prototype.__proto__ called on null or undefined"_s };
 
 template<unsigned charactersCount>
@@ -184,10 +181,10 @@
             int charLen = 0;
             if (k <= length - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) {
                 const char b0 = Lexer<CharType>::convertHex(p[1], p[2]);
-                const int sequenceLen = UTF8SequenceLength(b0);
-                if (sequenceLen && k <= length - sequenceLen * 3) {
+                const int sequenceLen = 1 + U8_COUNT_TRAIL_BYTES(b0);
+                if (k <= length - sequenceLen * 3) {
                     charLen = sequenceLen * 3;
-                    char sequence[5];
+                    uint8_t sequence[U8_MAX_LENGTH];
                     sequence[0] = b0;
                     for (int i = 1; i < sequenceLen; ++i) {
                         const CharType* q = p + i * 3;
@@ -199,16 +196,20 @@
                         }
                     }
                     if (charLen != 0) {
-                        sequence[sequenceLen] = 0;
-                        const int character = decodeUTF8Sequence(sequence);
-                        if (character < 0 || character >= 0x110000)
+                        UChar32 character;
+                        int32_t offset = 0;
+                        U8_NEXT(sequence, offset, sequenceLen, character);
+                        if (character < 0)
                             charLen = 0;
-                        else if (character >= 0x10000) {
+                        else if (!U_IS_BMP(character)) {
                             // Convert to surrogate pair.
-                            builder.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10)));
-                            u = static_cast<UChar>(0xDC00 | ((character - 0x10000) & 0x3FF));
-                        } else
+                            ASSERT(U_IS_SUPPLEMENTARY(character));
+                            builder.append(U16_LEAD(character));
+                            u = U16_TRAIL(character);
+                        } else {
+                            ASSERT(!U_IS_SURROGATE(character));
                             u = static_cast<UChar>(character);
+                        }
                     }
                 }
             }

Modified: trunk/Source/_javascript_Core/wasm/WasmParser.h (244827 => 244828)


--- trunk/Source/_javascript_Core/wasm/WasmParser.h	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/_javascript_Core/wasm/WasmParser.h	2019-05-01 17:33:03 UTC (rev 244828)
@@ -162,7 +162,7 @@
 
         UChar* bufferCurrent = bufferStart;
         const char* stringCurrent = reinterpret_cast<const char*>(stringStart);
-        if (WTF::Unicode::convertUTF8ToUTF16(&stringCurrent, reinterpret_cast<const char *>(stringStart + stringLength), &bufferCurrent, bufferCurrent + buffer.size()) != WTF::Unicode::conversionOK)
+        if (!WTF::Unicode::convertUTF8ToUTF16(stringCurrent, reinterpret_cast<const char *>(stringStart + stringLength), &bufferCurrent, bufferCurrent + buffer.size()))
             return false;
     }
 

Modified: trunk/Source/WTF/ChangeLog (244827 => 244828)


--- trunk/Source/WTF/ChangeLog	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WTF/ChangeLog	2019-05-01 17:33:03 UTC (rev 244828)
@@ -1,3 +1,73 @@
+2019-05-01  Darin Adler  <[email protected]>
+
+        WebKit has too much of its own UTF-8 code and should rely more on ICU's UTF-8 support
+        https://bugs.webkit.org/show_bug.cgi?id=195535
+
+        Reviewed by Alexey Proskuryakov.
+
+        * wtf/text/AtomicString.cpp:
+        (WTF::AtomicString::fromUTF8Internal): Added code to compute string length when the
+        end is nullptr; this behavior used to be implemented inside the
+        calculateStringHashAndLengthFromUTF8MaskingTop8Bits function.
+
+        * wtf/text/AtomicStringImpl.cpp:
+        (WTF::HashAndUTF8CharactersTranslator::translate): Updated for change to
+        convertUTF8ToUTF16.
+
+        * wtf/text/AtomicStringImpl.h: Took the WTF_EXPORT_PRIVATE off of the
+        AtomicStringImpl::addUTF8 function. This is used only inside a non-inlined function in
+        the AtomicString class and its behavior changed subtly in this patch; it's helpful
+        to document that it's not exported.
+
+        * wtf/text/StringImpl.cpp:
+        (WTF::StringImpl::utf8Impl): Don't pass "true" for strictness to convertUTF16ToUTF8
+        since strict is the default. Also updated for changes to ConversionResult.
+        (WTF::StringImpl::utf8ForCharacters): Updated for change to convertLatin1ToUTF8.
+        (WTF::StringImpl::tryGetUtf8ForRange const): Ditto.
+
+        * wtf/text/StringView.cpp: Removed uneeded include of UTF8Conversion.h.
+
+        * wtf/text/WTFString.cpp:
+        (WTF::String::fromUTF8): Updated for change to convertUTF8ToUTF16.
+
+        * wtf/unicode/UTF8Conversion.cpp:
+        (WTF::Unicode::inlineUTF8SequenceLengthNonASCII): Deleted.
+        (WTF::Unicode::inlineUTF8SequenceLength): Deleted.
+        (WTF::Unicode::UTF8SequenceLength): Deleted.
+        (WTF::Unicode::decodeUTF8Sequence): Deleted.
+        (WTF::Unicode::convertLatin1ToUTF8): Use U8_APPEND, enabling us to remove
+        almost everything in the function. Also changed resturn value to be a boolean
+        to indicate success since there is only one possible failure (target exhausted).
+        There is room for further simplification, since most callers have lengths rather
+        than end pointers for the source buffer, and all but one caller supplies a buffer
+        size known to be sufficient, so those don't need a return value, nor do they need
+        to pass an end of buffer pointer.
+        (WTF::Unicode::convertUTF16ToUTF8): Use U_IS_LEAD, U_IS_TRAIL,
+        U16_GET_SUPPLEMENTARY, U_IS_SURROGATE, and U8_APPEND. Also changed behavior
+        for non-strict mode so that unpaired surrogates will be turned into the
+        replacement character instead of invalid UTF-8 sequences, because U8_APPEND
+        won't create an invalid UTF-8 sequence, and because we don't need to do that
+        for any good reason at any call site.
+        (WTF::Unicode::isLegalUTF8): Deleted.
+        (WTF::Unicode::readUTF8Sequence): Deleted.
+        (WTF::Unicode::convertUTF8ToUTF16): Use U8_NEXT instead of
+        inlineUTF8SequenceLength, isLegalUTF8, and readUTF8Sequence. Use
+        U16_APPEND instead of lots of code that does the same thing. There is
+        room for further simplification since most callers don't need the "all ASCII"
+        feature and could probably pass the arguments in a more natural way.
+        (WTF::Unicode::calculateStringHashAndLengthFromUTF8MaskingTop8Bits):
+        Use U8_NEXT instead of isLegalUTF8, readUTF8Sequence, and various
+        error handling checks for things that are handled by U8_NEXT. Also removed
+        support for passing nullptr for end to specify a null-terminated string.
+        (WTF::Unicode::equalUTF16WithUTF8): Ditto.
+
+        * wtf/unicode/UTF8Conversion.h: Removed UTF8SequenceLength and
+        decodeUTF8Sequence. Changed the ConversionResult to match WebKit coding
+        style, with an eye toward perhaps removing it in the future. Changed
+        the convertUTF8ToUTF16 return value to a boolean and removed the "strict"
+        argument since no caller was passing false. Changed the convertLatin1ToUTF8
+        return value to a boolean. Tweaked comments.
+
 2019-05-01  Shawn Roberts  <[email protected]>
 
         Unreviewed, rolling out r244821.

Modified: trunk/Source/WTF/wtf/text/AtomicString.cpp (244827 => 244828)


--- trunk/Source/WTF/wtf/text/AtomicString.cpp	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WTF/wtf/text/AtomicString.cpp	2019-05-01 17:33:03 UTC (rev 244828)
@@ -113,19 +113,24 @@
     return numberToString(number, buffer);
 }
 
-AtomicString AtomicString::fromUTF8Internal(const char* charactersStart, const char* charactersEnd)
+AtomicString AtomicString::fromUTF8Internal(const char* start, const char* end)
 {
-    auto impl = AtomicStringImpl::addUTF8(charactersStart, charactersEnd);
-    if (!impl)
-        return nullAtom();
-    return impl.get();
+    ASSERT(start);
+
+    // Caller needs to handle empty string.
+    ASSERT(!end || end > start);
+    ASSERT(end || start[0]);
+
+    return AtomicStringImpl::addUTF8(start, end ? end : start + std::strlen(start));
 }
 
 #ifndef NDEBUG
+
 void AtomicString::show() const
 {
     m_string.show();
 }
+
 #endif
 
 WTF_EXPORT_PRIVATE LazyNeverDestroyed<AtomicString> nullAtomData;

Modified: trunk/Source/WTF/wtf/text/AtomicStringImpl.cpp (244827 => 244828)


--- trunk/Source/WTF/wtf/text/AtomicStringImpl.cpp	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WTF/wtf/text/AtomicStringImpl.cpp	2019-05-01 17:33:03 UTC (rev 244828)
@@ -219,7 +219,7 @@
 
         bool isAllASCII;
         const char* source = buffer.characters;
-        if (convertUTF8ToUTF16(&source, source + buffer.length, &target, target + buffer.utf16Length, &isAllASCII) != conversionOK)
+        if (!convertUTF8ToUTF16(source, source + buffer.length, &target, target + buffer.utf16Length, &isAllASCII))
             ASSERT_NOT_REACHED();
 
         if (isAllASCII)

Modified: trunk/Source/WTF/wtf/text/AtomicStringImpl.h (244827 => 244828)


--- trunk/Source/WTF/wtf/text/AtomicStringImpl.h	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WTF/wtf/text/AtomicStringImpl.h	2019-05-01 17:33:03 UTC (rev 244828)
@@ -56,7 +56,8 @@
     WTF_EXPORT_PRIVATE static Ref<AtomicStringImpl> addLiteral(const char* characters, unsigned length);
 
     // Returns null if the input data contains an invalid UTF-8 sequence.
-    WTF_EXPORT_PRIVATE static RefPtr<AtomicStringImpl> addUTF8(const char* start, const char* end);
+    static RefPtr<AtomicStringImpl> addUTF8(const char* start, const char* end);
+
 #if USE(CF)
     WTF_EXPORT_PRIVATE static RefPtr<AtomicStringImpl> add(CFStringRef);
 #endif

Modified: trunk/Source/WTF/wtf/text/StringImpl.cpp (244827 => 244828)


--- trunk/Source/WTF/wtf/text/StringImpl.cpp	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WTF/wtf/text/StringImpl.cpp	2019-05-01 17:33:03 UTC (rev 244828)
@@ -1756,11 +1756,11 @@
         char* bufferEnd = buffer + bufferSize;
         while (characters < charactersEnd) {
             // Use strict conversion to detect unpaired surrogates.
-            ConversionResult result = convertUTF16ToUTF8(&characters, charactersEnd, &buffer, bufferEnd, true);
-            ASSERT(result != targetExhausted);
+            auto result = convertUTF16ToUTF8(&characters, charactersEnd, &buffer, bufferEnd);
+            ASSERT(result != TargetExhausted);
             // Conversion fails when there is an unpaired surrogate.
             // Put replacement character (U+FFFD) instead of the unpaired surrogate.
-            if (result != conversionOK) {
+            if (result != ConversionOK) {
                 ASSERT((0xD800 <= *characters && *characters <= 0xDFFF));
                 // There should be room left, since one UChar hasn't been converted.
                 ASSERT((buffer + 3) <= bufferEnd);
@@ -1771,17 +1771,17 @@
     } else {
         bool strict = mode == StrictConversion;
         const UChar* originalCharacters = characters;
-        ConversionResult result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferSize, strict);
-        ASSERT(result != targetExhausted); // (length * 3) should be sufficient for any conversion
+        auto result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferSize, strict);
+        ASSERT(result != TargetExhausted); // (length * 3) should be sufficient for any conversion
 
         // Only produced from strict conversion.
-        if (result == sourceIllegal) {
+        if (result == SourceIllegal) {
             ASSERT(strict);
             return UTF8ConversionError::IllegalSource;
         }
 
         // Check for an unconverted high surrogate.
-        if (result == sourceExhausted) {
+        if (result == SourceExhausted) {
             if (strict)
                 return UTF8ConversionError::SourceExhausted;
             // This should be one unpaired high surrogate. Treat it the same
@@ -1809,8 +1809,8 @@
     Vector<char, 1024> bufferVector(length * 3);
     char* buffer = bufferVector.data();
     const LChar* source = characters;
-    ConversionResult result = convertLatin1ToUTF8(&source, source + length, &buffer, buffer + bufferVector.size());
-    ASSERT_UNUSED(result, result != targetExhausted); // (length * 3) should be sufficient for any conversion
+    bool success = convertLatin1ToUTF8(&source, source + length, &buffer, buffer + bufferVector.size());
+    ASSERT_UNUSED(success, success); // (length * 3) should be sufficient for any conversion
     return CString(bufferVector.data(), buffer - bufferVector.data());
 }
 
@@ -1854,9 +1854,8 @@
 
     if (is8Bit()) {
         const LChar* characters = this->characters8() + offset;
-
-        ConversionResult result = convertLatin1ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size());
-        ASSERT_UNUSED(result, result != targetExhausted); // (length * 3) should be sufficient for any conversion
+        auto success = convertLatin1ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size());
+        ASSERT_UNUSED(success, success); // (length * 3) should be sufficient for any conversion
     } else {
         UTF8ConversionError error = utf8Impl(this->characters16() + offset, length, buffer, bufferVector.size(), mode);
         if (error != UTF8ConversionError::None)

Modified: trunk/Source/WTF/wtf/text/StringView.cpp (244827 => 244828)


--- trunk/Source/WTF/wtf/text/StringView.cpp	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WTF/wtf/text/StringView.cpp	2019-05-01 17:33:03 UTC (rev 244828)
@@ -35,12 +35,9 @@
 #include <wtf/NeverDestroyed.h>
 #include <wtf/Optional.h>
 #include <wtf/text/TextBreakIterator.h>
-#include <wtf/unicode/UTF8Conversion.h>
 
 namespace WTF {
 
-using namespace Unicode;
-
 bool StringView::containsIgnoringASCIICase(const StringView& matchString) const
 {
     return findIgnoringASCIICase(matchString) != notFound;

Modified: trunk/Source/WTF/wtf/text/WTFString.cpp (244827 => 244828)


--- trunk/Source/WTF/wtf/text/WTFString.cpp	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WTF/wtf/text/WTFString.cpp	2019-05-01 17:33:03 UTC (rev 244828)
@@ -859,7 +859,7 @@
  
     UChar* bufferCurrent = bufferStart;
     const char* stringCurrent = reinterpret_cast<const char*>(stringStart);
-    if (convertUTF8ToUTF16(&stringCurrent, reinterpret_cast<const char *>(stringStart + length), &bufferCurrent, bufferCurrent + buffer.size()) != conversionOK)
+    if (!convertUTF8ToUTF16(stringCurrent, reinterpret_cast<const char *>(stringStart + length), &bufferCurrent, bufferCurrent + buffer.size()))
         return String();
 
     unsigned utf16Length = bufferCurrent - bufferStart;

Modified: trunk/Source/WTF/wtf/unicode/UTF8Conversion.cpp (244827 => 244828)


--- trunk/Source/WTF/wtf/unicode/UTF8Conversion.cpp	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WTF/wtf/unicode/UTF8Conversion.cpp	2019-05-01 17:33:03 UTC (rev 244828)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2019 Apple Inc. All rights reserved.
  * Copyright (C) 2010 Patrick Gansterer <[email protected]>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,389 +34,107 @@
 namespace WTF {
 namespace Unicode {
 
-inline int inlineUTF8SequenceLengthNonASCII(char b0)
+bool convertLatin1ToUTF8(const LChar** sourceStart, const LChar* sourceEnd, char** targetStart, char* targetEnd)
 {
-    if ((b0 & 0xC0) != 0xC0)
-        return 0;
-    if ((b0 & 0xE0) == 0xC0)
-        return 2;
-    if ((b0 & 0xF0) == 0xE0)
-        return 3;
-    if ((b0 & 0xF8) == 0xF0)
-        return 4;
-    return 0;
-}
-
-inline int inlineUTF8SequenceLength(char b0)
-{
-    return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0);
-}
-
-int UTF8SequenceLength(char b0)
-{
-    return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0);
-}
-
-int decodeUTF8Sequence(const char* sequence)
-{
-    // Handle 0-byte sequences (never valid).
-    const unsigned char b0 = sequence[0];
-    const int length = inlineUTF8SequenceLength(b0);
-    if (length == 0)
-        return -1;
-
-    // Handle 1-byte sequences (plain ASCII).
-    const unsigned char b1 = sequence[1];
-    if (length == 1) {
-        if (b1)
-            return -1;
-        return b0;
-    }
-
-    // Handle 2-byte sequences.
-    if ((b1 & 0xC0) != 0x80)
-        return -1;
-    const unsigned char b2 = sequence[2];
-    if (length == 2) {
-        if (b2)
-            return -1;
-        const int c = ((b0 & 0x1F) << 6) | (b1 & 0x3F);
-        if (c < 0x80)
-            return -1;
-        return c;
-    }
-
-    // Handle 3-byte sequences.
-    if ((b2 & 0xC0) != 0x80)
-        return -1;
-    const unsigned char b3 = sequence[3];
-    if (length == 3) {
-        if (b3)
-            return -1;
-        const int c = ((b0 & 0xF) << 12) | ((b1 & 0x3F) << 6) | (b2 & 0x3F);
-        if (c < 0x800)
-            return -1;
-        // UTF-16 surrogates should never appear in UTF-8 data.
-        if (c >= 0xD800 && c <= 0xDFFF)
-            return -1;
-        return c;
-    }
-
-    // Handle 4-byte sequences.
-    if ((b3 & 0xC0) != 0x80)
-        return -1;
-    const unsigned char b4 = sequence[4];
-    if (length == 4) {
-        if (b4)
-            return -1;
-        const int c = ((b0 & 0x7) << 18) | ((b1 & 0x3F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F);
-        if (c < 0x10000 || c > 0x10FFFF)
-            return -1;
-        return c;
-    }
-
-    return -1;
-}
-
-// Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
-// into the first byte, depending on how many bytes follow.  There are
-// as many entries in this table as there are UTF-8 sequence types.
-// (I.e., one byte sequence, two byte... etc.). Remember that sequencs
-// for *legal* UTF-8 will be 4 or fewer bytes total.
-static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
-
-ConversionResult convertLatin1ToUTF8(
-    const LChar** sourceStart, const LChar* sourceEnd, 
-    char** targetStart, char* targetEnd)
-{
-    ConversionResult result = conversionOK;
-    const LChar* source = *sourceStart;
+    const LChar* source;
     char* target = *targetStart;
-    while (source < sourceEnd) {
-        UChar32 ch;
-        unsigned short bytesToWrite = 0;
-        const UChar32 byteMask = 0xBF;
-        const UChar32 byteMark = 0x80; 
-        const LChar* oldSource = source; // In case we have to back up because of target overflow.
-        ch = static_cast<unsigned short>(*source++);
-
-        // Figure out how many bytes the result will require
-        if (ch < (UChar32)0x80)
-            bytesToWrite = 1;
-        else
-            bytesToWrite = 2;
-
-        target += bytesToWrite;
-        if (target > targetEnd) {
-            source = oldSource; // Back up source pointer!
-            target -= bytesToWrite;
-            result = targetExhausted;
-            break;
-        }
-        switch (bytesToWrite) { // note: everything falls through.
-        case 2:
-            *--target = (char)((ch | byteMark) & byteMask);
-            ch >>= 6;
-            FALLTHROUGH;
-        case 1:
-            *--target =  (char)(ch | firstByteMark[bytesToWrite]);
-        }
-        target += bytesToWrite;
+    int i = 0;
+    for (source = *sourceStart; source < sourceEnd; ++source) {
+        UBool sawError = false;
+        // Work around bug in either Windows compiler or old version of ICU, where passing a uint8_t to
+        // U8_APPEND warns, by converting from uint8_t to a wider type.
+        UChar32 character = *source;
+        U8_APPEND(reinterpret_cast<uint8_t*>(target), i, targetEnd - *targetStart, character, sawError);
+        if (sawError)
+            return false;
     }
     *sourceStart = source;
-    *targetStart = target;
-    return result;
+    *targetStart = target + i;
+    return true;
 }
 
-ConversionResult convertUTF16ToUTF8(
-    const UChar** sourceStart, const UChar* sourceEnd, 
-    char** targetStart, char* targetEnd, bool strict)
+ConversionResult convertUTF16ToUTF8(const UChar** sourceStart, const UChar* sourceEnd, char** targetStart, char* targetEnd, bool strict)
 {
-    ConversionResult result = conversionOK;
+    ConversionResult result = ConversionOK;
     const UChar* source = *sourceStart;
     char* target = *targetStart;
+    UBool sawError = false;
+    int i = 0;
     while (source < sourceEnd) {
         UChar32 ch;
-        unsigned short bytesToWrite = 0;
-        const UChar32 byteMask = 0xBF;
-        const UChar32 byteMark = 0x80; 
-        const UChar* oldSource = source; // In case we have to back up because of target overflow.
-        ch = static_cast<unsigned short>(*source++);
-        // If we have a surrogate pair, convert to UChar32 first.
-        if (ch >= 0xD800 && ch <= 0xDBFF) {
-            // If the 16 bits following the high surrogate are in the source buffer...
-            if (source < sourceEnd) {
-                UChar32 ch2 = static_cast<unsigned short>(*source);
-                // If it's a low surrogate, convert to UChar32.
-                if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) {
-                    ch = ((ch - 0xD800) << 10) + (ch2 - 0xDC00) + 0x0010000;
-                    ++source;
-                } else if (strict) { // it's an unpaired high surrogate
-                    --source; // return to the illegal value itself
-                    result = sourceIllegal;
-                    break;
-                }
-            } else { // We don't have the 16 bits following the high surrogate.
-                --source; // return to the high surrogate
-                result = sourceExhausted;
+        int j = 0;
+        U16_NEXT(source, j, sourceEnd - source, ch);
+        if (U_IS_SURROGATE(ch)) {
+            if (source + j == sourceEnd && U_IS_SURROGATE_LEAD(ch)) {
+                result = SourceExhausted;
                 break;
             }
-        } else if (strict) {
-            // UTF-16 surrogate values are illegal in UTF-32
-            if (ch >= 0xDC00 && ch <= 0xDFFF) {
-                --source; // return to the illegal value itself
-                result = sourceIllegal;
+            if (strict) {
+                result = SourceIllegal;
                 break;
             }
-        }
-        // Figure out how many bytes the result will require
-        if (ch < (UChar32)0x80) {
-            bytesToWrite = 1;
-        } else if (ch < (UChar32)0x800) {
-            bytesToWrite = 2;
-        } else if (ch < (UChar32)0x10000) {
-            bytesToWrite = 3;
-        } else if (ch < (UChar32)0x110000) {
-            bytesToWrite = 4;
-        } else {
-            bytesToWrite = 3;
             ch = replacementCharacter;
         }
-
-        target += bytesToWrite;
-        if (target > targetEnd) {
-            source = oldSource; // Back up source pointer!
-            target -= bytesToWrite;
-            result = targetExhausted;
+        U8_APPEND(reinterpret_cast<uint8_t*>(target), i, targetEnd - target, ch, sawError);
+        if (sawError) {
+            result = TargetExhausted;
             break;
         }
-        switch (bytesToWrite) { // note: everything falls through.
-            case 4: *--target = (char)((ch | byteMark) & byteMask); ch >>= 6; FALLTHROUGH;
-            case 3: *--target = (char)((ch | byteMark) & byteMask); ch >>= 6; FALLTHROUGH;
-            case 2: *--target = (char)((ch | byteMark) & byteMask); ch >>= 6; FALLTHROUGH;
-            case 1: *--target =  (char)(ch | firstByteMark[bytesToWrite]);
-        }
-        target += bytesToWrite;
+        source += j;
     }
     *sourceStart = source;
-    *targetStart = target;
+    *targetStart = target + i;
     return result;
 }
 
-// This must be called with the length pre-determined by the first byte.
-// If presented with a length > 4, this returns false.  The Unicode
-// definition of UTF-8 goes up to 4-byte sequences.
-static bool isLegalUTF8(const unsigned char* source, int length)
+bool convertUTF8ToUTF16(const char* source, const char* sourceEnd, UChar** targetStart, UChar* targetEnd, bool* sourceAllASCII)
 {
-    unsigned char a;
-    const unsigned char* srcptr = source + length;
-    switch (length) {
-        default: return false;
-        // Everything else falls through when "true"...
-        case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; FALLTHROUGH;
-        case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; FALLTHROUGH;
-        case 2: if ((a = (*--srcptr)) > 0xBF) return false;
-
-        switch (*source) {
-            // no fall-through in this inner switch
-            case 0xE0: if (a < 0xA0) return false; break;
-            case 0xED: if (a > 0x9F) return false; break;
-            case 0xF0: if (a < 0x90) return false; break;
-            case 0xF4: if (a > 0x8F) return false; break;
-            default:   if (a < 0x80) return false;
-        }
-        FALLTHROUGH;
-
-        case 1: if (*source >= 0x80 && *source < 0xC2) return false;
-    }
-    if (*source > 0xF4)
-        return false;
-    return true;
-}
-
-// Magic values subtracted from a buffer value during UTF8 conversion.
-// This table contains as many values as there might be trailing bytes
-// in a UTF-8 sequence.
-static const UChar32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, static_cast<UChar32>(0xFA082080UL), static_cast<UChar32>(0x82082080UL) };
-
-static inline UChar32 readUTF8Sequence(const char*& sequence, unsigned length)
-{
-    UChar32 character = 0;
-
-    // The cases all fall through.
-    switch (length) {
-        case 6: character += static_cast<unsigned char>(*sequence++); character <<= 6; FALLTHROUGH;
-        case 5: character += static_cast<unsigned char>(*sequence++); character <<= 6; FALLTHROUGH;
-        case 4: character += static_cast<unsigned char>(*sequence++); character <<= 6; FALLTHROUGH;
-        case 3: character += static_cast<unsigned char>(*sequence++); character <<= 6; FALLTHROUGH;
-        case 2: character += static_cast<unsigned char>(*sequence++); character <<= 6; FALLTHROUGH;
-        case 1: character += static_cast<unsigned char>(*sequence++);
-    }
-
-    return character - offsetsFromUTF8[length - 1];
-}
-
-ConversionResult convertUTF8ToUTF16(
-    const char** sourceStart, const char* sourceEnd, 
-    UChar** targetStart, UChar* targetEnd, bool* sourceAllASCII, bool strict)
-{
-    ConversionResult result = conversionOK;
-    const char* source = *sourceStart;
+    RELEASE_ASSERT(sourceEnd - source <= std::numeric_limits<int>::max());
+    UBool error = false;
     UChar* target = *targetStart;
-    UChar orAllData = 0;
-    while (source < sourceEnd) {
-        int utf8SequenceLength = inlineUTF8SequenceLength(*source);
-        if (sourceEnd - source < utf8SequenceLength)  {
-            result = sourceExhausted;
-            break;
-        }
-        // Do this check whether lenient or strict
-        if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(source), utf8SequenceLength)) {
-            result = sourceIllegal;
-            break;
-        }
-
-        UChar32 character = readUTF8Sequence(source, utf8SequenceLength);
-
-        if (target >= targetEnd) {
-            source -= utf8SequenceLength; // Back up source pointer!
-            result = targetExhausted;
-            break;
-        }
-
-        if (U_IS_BMP(character)) {
-            // UTF-16 surrogate values are illegal in UTF-32
-            if (U_IS_SURROGATE(character)) {
-                if (strict) {
-                    source -= utf8SequenceLength; // return to the illegal value itself
-                    result = sourceIllegal;
-                    break;
-                } else {
-                    *target++ = replacementCharacter;
-                    orAllData |= replacementCharacter;
-                }
-            } else {
-                *target++ = character; // normal case
-                orAllData |= character;
-            }
-        } else if (U_IS_SUPPLEMENTARY(character)) {
-            // target is a character in range 0xFFFF - 0x10FFFF
-            if (target + 1 >= targetEnd) {
-                source -= utf8SequenceLength; // Back up source pointer!
-                result = targetExhausted;
-                break;
-            }
-            *target++ = U16_LEAD(character);
-            *target++ = U16_TRAIL(character);
-            orAllData = 0xffff;
-        } else {
-            if (strict) {
-                source -= utf8SequenceLength; // return to the start
-                result = sourceIllegal;
-                break; // Bail out; shouldn't continue
-            } else {
-                *target++ = replacementCharacter;
-                orAllData |= replacementCharacter;
-            }
-        }
+    UChar32 orAllData = 0;
+    int targetOffset = 0;
+    for (int sourceOffset = 0; sourceOffset < sourceEnd - source; ) {
+        UChar32 character;
+        U8_NEXT(reinterpret_cast<const uint8_t*>(source), sourceOffset, sourceEnd - source, character);
+        if (character < 0)
+            return false;
+        U16_APPEND(target, targetOffset, targetEnd - target, character, error);
+        if (error)
+            return false;
+        orAllData |= character;
     }
-    *sourceStart = source;
-    *targetStart = target;
-
+    *targetStart = target + targetOffset;
     if (sourceAllASCII)
-        *sourceAllASCII = !(orAllData & ~0x7f);
-
-    return result;
+        *sourceAllASCII = isASCII(orAllData);
+    return true;
 }
 
 unsigned calculateStringHashAndLengthFromUTF8MaskingTop8Bits(const char* data, const char* dataEnd, unsigned& dataLength, unsigned& utf16Length)
 {
-    if (!data)
-        return 0;
-
     StringHasher stringHasher;
-    dataLength = 0;
     utf16Length = 0;
 
-    while (data < dataEnd || (!dataEnd && *data)) {
-        if (isASCII(*data)) {
-            stringHasher.addCharacter(*data++);
-            dataLength++;
-            utf16Length++;
-            continue;
-        }
-
-        int utf8SequenceLength = inlineUTF8SequenceLengthNonASCII(*data);
-        dataLength += utf8SequenceLength;
-
-        if (!dataEnd) {
-            for (int i = 1; i < utf8SequenceLength; ++i) {
-                if (!data[i])
-                    return 0;
-            }
-        } else if (dataEnd - data < utf8SequenceLength)
+    int inputOffset = 0;
+    int inputLength = dataEnd - data;
+    while (inputOffset < inputLength) {
+        UChar32 character;
+        U8_NEXT(reinterpret_cast<const uint8_t*>(data), inputOffset, inputLength, character);
+        if (character < 0)
             return 0;
 
-        if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(data), utf8SequenceLength))
-            return 0;
-
-        UChar32 character = readUTF8Sequence(data, utf8SequenceLength);
-        ASSERT(!isASCII(character));
-
         if (U_IS_BMP(character)) {
-            // UTF-16 surrogate values are illegal in UTF-32
-            if (U_IS_SURROGATE(character))
-                return 0;
-            stringHasher.addCharacter(static_cast<UChar>(character)); // normal case
+            ASSERT(!U_IS_SURROGATE(character));
+            stringHasher.addCharacter(character);
             utf16Length++;
-        } else if (U_IS_SUPPLEMENTARY(character)) {
-            stringHasher.addCharacters(static_cast<UChar>(U16_LEAD(character)),
-                                       static_cast<UChar>(U16_TRAIL(character)));
+        } else {
+            ASSERT(U_IS_SUPPLEMENTARY(character));
+            stringHasher.addCharacters(U16_LEAD(character), U16_TRAIL(character));
             utf16Length += 2;
-        } else
-            return 0;
+        }
     }
 
+    dataLength = inputOffset;
     return stringHasher.hashWithTop8BitsMasked();
 }
 
@@ -423,36 +141,24 @@
 bool equalUTF16WithUTF8(const UChar* a, const char* b, const char* bEnd)
 {
     while (b < bEnd) {
-        if (isASCII(*a) || isASCII(*b)) {
-            if (*a++ != *b++)
-                return false;
-            continue;
-        }
-
-        int utf8SequenceLength = inlineUTF8SequenceLengthNonASCII(*b);
-
-        if (bEnd - b < utf8SequenceLength)
+        int offset = 0;
+        UChar32 character;
+        U8_NEXT(reinterpret_cast<const uint8_t*>(b), offset, bEnd - b, character);
+        if (character < 0)
             return false;
+        b += offset;
 
-        if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(b), utf8SequenceLength))
-            return false;
-
-        UChar32 character = readUTF8Sequence(b, utf8SequenceLength);
-        ASSERT(!isASCII(character));
-
         if (U_IS_BMP(character)) {
-            // UTF-16 surrogate values are illegal in UTF-32
-            if (U_IS_SURROGATE(character))
-                return false;
+            ASSERT(!U_IS_SURROGATE(character));
             if (*a++ != character)
                 return false;
-        } else if (U_IS_SUPPLEMENTARY(character)) {
+        } else {
+            ASSERT(U_IS_SUPPLEMENTARY(character));
             if (*a++ != U16_LEAD(character))
                 return false;
             if (*a++ != U16_TRAIL(character))
                 return false;
-        } else
-            return false;
+        }
     }
 
     return true;

Modified: trunk/Source/WTF/wtf/unicode/UTF8Conversion.h (244827 => 244828)


--- trunk/Source/WTF/wtf/unicode/UTF8Conversion.h	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WTF/wtf/unicode/UTF8Conversion.h	2019-05-01 17:33:03 UTC (rev 244828)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2007-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,54 +31,28 @@
 namespace WTF {
 namespace Unicode {
 
-    // Given a first byte, gives the length of the UTF-8 sequence it begins.
-    // Returns 0 for bytes that are not legal starts of UTF-8 sequences.
-    // Only allows sequences of up to 4 bytes, since that works for all Unicode characters (U-00000000 to U-0010FFFF).
-    WTF_EXPORT_PRIVATE int UTF8SequenceLength(char);
+enum ConversionResult {
+    ConversionOK, // conversion successful
+    SourceExhausted, // partial character in source, but hit end
+    TargetExhausted, // insufficient room in target for conversion
+    SourceIllegal // source sequence is illegal/malformed
+};
 
-    // Takes a null-terminated C-style string with a UTF-8 sequence in it and converts it to a character.
-    // Only allows Unicode characters (U-00000000 to U-0010FFFF).
-    // Returns -1 if the sequence is not valid (including presence of extra bytes).
-    WTF_EXPORT_PRIVATE int decodeUTF8Sequence(const char*);
+// Conversion functions are strict, except for convertUTF16ToUTF8, which takes
+// "strict" argument. When strict, both illegal sequences and unpaired surrogates
+// will cause an error. When not, illegal sequences and unpaired surrogates are
+// converted to the replacement character, except for an unpaired lead surrogate
+// at the end of the source, which will instead cause a SourceExhausted error.
 
-    typedef enum {
-            conversionOK,       // conversion successful
-            sourceExhausted,    // partial character in source, but hit end
-            targetExhausted,    // insuff. room in target for conversion
-            sourceIllegal       // source sequence is illegal/malformed
-    } ConversionResult;
+WTF_EXPORT_PRIVATE bool convertUTF8ToUTF16(const char* sourceStart, const char* sourceEnd, UChar** targetStart, UChar* targetEnd, bool* isSourceAllASCII = nullptr);
+WTF_EXPORT_PRIVATE bool convertLatin1ToUTF8(const LChar** sourceStart, const LChar* sourceEnd, char** targetStart, char* targetEnd);
+WTF_EXPORT_PRIVATE ConversionResult convertUTF16ToUTF8(const UChar** sourceStart, const UChar* sourceEnd, char** targetStart, char* targetEnd, bool strict = true);
 
-    // These conversion functions take a "strict" argument. When this
-    // flag is set to strict, both irregular sequences and isolated surrogates
-    // will cause an error.  When the flag is set to lenient, both irregular
-    // sequences and isolated surrogates are converted.
-    // 
-    // Whether the flag is strict or lenient, all illegal sequences will cause
-    // an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
-    // or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
-    // must check for illegal sequences.
-    // 
-    // When the flag is set to lenient, characters over 0x10FFFF are converted
-    // to the replacement character; otherwise (when the flag is set to strict)
-    // they constitute an error.
+WTF_EXPORT_PRIVATE unsigned calculateStringHashAndLengthFromUTF8MaskingTop8Bits(const char* data, const char* dataEnd, unsigned& dataLength, unsigned& utf16Length);
 
-    WTF_EXPORT_PRIVATE ConversionResult convertUTF8ToUTF16(
-                    const char** sourceStart, const char* sourceEnd, 
-                    UChar** targetStart, UChar* targetEnd, bool* isSourceAllASCII = 0, bool strict = true);
+// Callers of these functions must check that the lengths are the same; accordingly we omit an end argument for UTF-16 and Latin-1.
+bool equalUTF16WithUTF8(const UChar* stringInUTF16, const char* stringInUTF8, const char* stringInUTF8End);
+bool equalLatin1WithUTF8(const LChar* stringInLatin1, const char* stringInUTF8, const char* stringInUTF8End);
 
-    WTF_EXPORT_PRIVATE ConversionResult convertLatin1ToUTF8(
-                    const LChar** sourceStart, const LChar* sourceEnd, 
-                    char** targetStart, char* targetEnd);
-
-    WTF_EXPORT_PRIVATE ConversionResult convertUTF16ToUTF8(
-                    const UChar** sourceStart, const UChar* sourceEnd, 
-                    char** targetStart, char* targetEnd, bool strict = true);
-
-    WTF_EXPORT_PRIVATE unsigned calculateStringHashAndLengthFromUTF8MaskingTop8Bits(const char* data, const char* dataEnd, unsigned& dataLength, unsigned& utf16Length);
-
-    // The caller of these functions already knows that the lengths are the same, so we omit an end argument for UTF-16 and Latin-1.
-    bool equalUTF16WithUTF8(const UChar* stringInUTF16, const char* stringInUTF8, const char* stringInUTF8End);
-    bool equalLatin1WithUTF8(const LChar* stringInLatin1, const char* stringInUTF8, const char* stringInUTF8End);
-
 } // namespace Unicode
 } // namespace WTF

Modified: trunk/Source/WebCore/ChangeLog (244827 => 244828)


--- trunk/Source/WebCore/ChangeLog	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WebCore/ChangeLog	2019-05-01 17:33:03 UTC (rev 244828)
@@ -1,3 +1,21 @@
+2019-05-01  Darin Adler  <[email protected]>
+
+        WebKit has too much of its own UTF-8 code and should rely more on ICU's UTF-8 support
+        https://bugs.webkit.org/show_bug.cgi?id=195535
+
+        Reviewed by Alexey Proskuryakov.
+
+        * platform/SharedBuffer.cpp:
+        (WebCore::utf8Buffer): Removed unnecessary "strict" argument to convertUTF16ToUTF8 since
+        that is the default behavior. Also updated for changes to return values.
+
+        * xml/XSLTProcessorLibxslt.cpp:
+        (WebCore::writeToStringBuilder): Removed unnecessary use of StringBuffer for a temporary
+        buffer for characters. Rewrote to use U8_NEXT and U16_APPEND directly.
+
+        * xml/parser/XMLDocumentParserLibxml2.cpp:
+        (WebCore::convertUTF16EntityToUTF8): Updated for changes to CompletionResult.
+
 2019-05-01  Shawn Roberts  <[email protected]>
 
         Unreviewed, rolling out r244821.

Modified: trunk/Source/WebCore/ChangeLog-2010-12-06 (244827 => 244828)


--- trunk/Source/WebCore/ChangeLog-2010-12-06	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WebCore/ChangeLog-2010-12-06	2019-05-01 17:33:03 UTC (rev 244828)
@@ -95190,7 +95190,7 @@
         [chromium] fast/forms/input-file-directory-upload.html fails on win after r63454
         https://bugs.webkit.org/show_bug.cgi?id=42768
 
-        Normalize path separators for the script API by convering \'s to /'s.
+        Normalize path separators for the script API by converting \'s to /'s.
 
         Covered by input-file-directory-upload.html
 

Modified: trunk/Source/WebCore/ChangeLog-2013-04-24 (244827 => 244828)


--- trunk/Source/WebCore/ChangeLog-2013-04-24	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WebCore/ChangeLog-2013-04-24	2019-05-01 17:33:03 UTC (rev 244828)
@@ -42510,7 +42510,7 @@
 
         * platform/graphics/chromium/GraphicsLayerChromium.cpp:
         (WebCore::transformToSkMatrix44):
-          Utility for convering a WebCore::TransformationMatrix to an SkMatrix44.
+          Utility for converting a WebCore::TransformationMatrix to an SkMatrix44.
           Will move to a more common location once it gets more callers.
         (WebCore::GraphicsLayerChromium::updateTransform):
         (WebCore::GraphicsLayerChromium::updateChildrenTransform):

Modified: trunk/Source/WebCore/platform/SharedBuffer.cpp (244827 => 244828)


--- trunk/Source/WebCore/platform/SharedBuffer.cpp	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WebCore/platform/SharedBuffer.cpp	2019-05-01 17:33:03 UTC (rev 244828)
@@ -334,17 +334,16 @@
 
     // Convert to runs of 8-bit characters.
     char* p = buffer.data();
-    WTF::Unicode::ConversionResult result;
     if (length) {
         if (string.is8Bit()) {
             const LChar* d = string.characters8();
-            result = WTF::Unicode::convertLatin1ToUTF8(&d, d + length, &p, p + buffer.size());
+            if (!WTF::Unicode::convertLatin1ToUTF8(&d, d + length, &p, p + buffer.size()))
+                return nullptr;
         } else {
             const UChar* d = string.characters16();
-            result = WTF::Unicode::convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size(), true);
+            if (WTF::Unicode::convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size()) != WTF::Unicode::ConversionOK)
+                return nullptr;
         }
-        if (result != WTF::Unicode::conversionOK)
-            return nullptr;
     }
 
     buffer.shrink(p - buffer.data());

Modified: trunk/Source/WebCore/xml/XSLTProcessorLibxslt.cpp (244827 => 244828)


--- trunk/Source/WebCore/xml/XSLTProcessorLibxslt.cpp	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WebCore/xml/XSLTProcessorLibxslt.cpp	2019-05-01 17:33:03 UTC (rev 244828)
@@ -48,8 +48,6 @@
 #include <libxslt/xslt.h>
 #include <libxslt/xsltutils.h>
 #include <wtf/Assertions.h>
-#include <wtf/text/StringBuffer.h>
-#include <wtf/unicode/UTF8Conversion.h>
 
 #if OS(DARWIN) && !PLATFORM(GTK)
 #include "SoftLinkLibxslt.h"
@@ -159,27 +157,41 @@
     globalCachedResourceLoader = cachedResourceLoader;
 }
 
-static int writeToStringBuilder(void* context, const char* buffer, int len)
+static int writeToStringBuilder(void* context, const char* buffer, int length)
 {
     StringBuilder& resultOutput = *static_cast<StringBuilder*>(context);
 
-    if (!len)
-        return 0;
+    // FIXME: Consider ways to make this more efficient by moving it into a
+    // StringBuilder::appendUTF8 function, and then optimizing to not need a
+    // Vector<UChar> and possibly optimize cases that can produce 8-bit Latin-1
+    // strings, but that would need to be sophisticated about not processing
+    // trailing incomplete sequences and communicating that to the caller.
 
-    StringBuffer<UChar> stringBuffer(len);
-    UChar* bufferUChar = stringBuffer.characters();
-    UChar* bufferUCharEnd = bufferUChar + len;
+    Vector<UChar> outputBuffer(length);
 
-    const char* stringCurrent = buffer;
-    WTF::Unicode::ConversionResult result = WTF::Unicode::convertUTF8ToUTF16(&stringCurrent, buffer + len, &bufferUChar, bufferUCharEnd);
-    if (result != WTF::Unicode::conversionOK && result != WTF::Unicode::sourceExhausted) {
-        ASSERT_NOT_REACHED();
-        return -1;
+    UBool error = false;
+    int inputOffset = 0;
+    int outputOffset = 0;
+    while (inputOffset < length) {
+        UChar32 character;
+        int nextInputOffset = inputOffset;
+        U8_NEXT(reinterpret_cast<const uint8_t*>(buffer), nextInputOffset, length, character);
+        if (character < 0) {
+            if (nextInputOffset == length)
+                break;
+            ASSERT_NOT_REACHED();
+            return -1;
+        }
+        inputOffset = nextInputOffset;
+        U16_APPEND(outputBuffer.data(), outputOffset, length, character, error);
+        if (error) {
+            ASSERT_NOT_REACHED();
+            return -1;
+        }
     }
 
-    int utf16Length = bufferUChar - stringBuffer.characters();
-    resultOutput.append(stringBuffer.characters(), utf16Length);
-    return stringCurrent - buffer;
+    resultOutput.append(outputBuffer.data(), outputOffset);
+    return inputOffset;
 }
 
 static bool saveResultToString(xmlDocPtr resultDoc, xsltStylesheetPtr sheet, String& resultString)

Modified: trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp (244827 => 244828)


--- trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp	2019-05-01 17:33:03 UTC (rev 244828)
@@ -1154,7 +1154,7 @@
 {
     const char* originalTarget = target;
     auto conversionResult = WTF::Unicode::convertUTF16ToUTF8(&utf16Entity, utf16Entity + numberOfCodeUnits, &target, target + targetSize);
-    if (conversionResult != WTF::Unicode::conversionOK)
+    if (conversionResult != WTF::Unicode::ConversionOK)
         return 0;
 
     // Even though we must pass the length, libxml expects the entity string to be null terminated.

Modified: trunk/Source/WebKit/ChangeLog (244827 => 244828)


--- trunk/Source/WebKit/ChangeLog	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WebKit/ChangeLog	2019-05-01 17:33:03 UTC (rev 244828)
@@ -1,3 +1,15 @@
+2019-05-01  Darin Adler  <[email protected]>
+
+        WebKit has too much of its own UTF-8 code and should rely more on ICU's UTF-8 support
+        https://bugs.webkit.org/show_bug.cgi?id=195535
+
+        Reviewed by Alexey Proskuryakov.
+
+        * Shared/API/APIString.h: Removed uneeded includes and also switched to #pragma once.
+
+        * Shared/API/c/WKString.cpp: Moved include of UTF8Conversion.h here.
+        (WKStringGetUTF8CStringImpl): Updated for changes to return values.
+
 2019-05-01  Shawn Roberts  <[email protected]>
 
         Unreviewed, rolling out r244821.

Modified: trunk/Source/WebKit/Shared/API/APIString.h (244827 => 244828)


--- trunk/Source/WebKit/Shared/API/APIString.h	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WebKit/Shared/API/APIString.h	2019-05-01 17:33:03 UTC (rev 244828)
@@ -23,14 +23,10 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef APIString_h
-#define APIString_h
+#pragma once
 
 #include "APIObject.h"
-#include <wtf/Ref.h>
 #include <wtf/text/StringView.h>
-#include <wtf/text/WTFString.h>
-#include <wtf/unicode/UTF8Conversion.h>
 
 namespace API {
 
@@ -75,5 +71,3 @@
 };
 
 } // namespace WebKit
-
-#endif // APIString_h

Modified: trunk/Source/WebKit/Shared/API/c/WKString.cpp (244827 => 244828)


--- trunk/Source/WebKit/Shared/API/c/WKString.cpp	2019-05-01 17:13:58 UTC (rev 244827)
+++ trunk/Source/WebKit/Shared/API/c/WKString.cpp	2019-05-01 17:33:03 UTC (rev 244828)
@@ -30,6 +30,7 @@
 #include "WKAPICast.h"
 #include <_javascript_Core/InitializeThreading.h>
 #include <_javascript_Core/OpaqueJSString.h>
+#include <wtf/unicode/UTF8Conversion.h>
 
 WKTypeID WKStringGetTypeID()
 {
@@ -78,19 +79,18 @@
     auto stringView = WebKit::toImpl(stringRef)->stringView();
 
     char* p = buffer;
-    WTF::Unicode::ConversionResult result;
 
     if (stringView.is8Bit()) {
         const LChar* characters = stringView.characters8();
-        result = WTF::Unicode::convertLatin1ToUTF8(&characters, characters + stringView.length(), &p, p + bufferSize - 1);
+        if (!WTF::Unicode::convertLatin1ToUTF8(&characters, characters + stringView.length(), &p, p + bufferSize - 1))
+            return 0;
     } else {
         const UChar* characters = stringView.characters16();
-        result = WTF::Unicode::convertUTF16ToUTF8(&characters, characters + stringView.length(), &p, p + bufferSize - 1, strict);
+        auto result = WTF::Unicode::convertUTF16ToUTF8(&characters, characters + stringView.length(), &p, p + bufferSize - 1, strict);
+        if (result != WTF::Unicode::ConversionOK && result != WTF::Unicode::TargetExhausted)
+            return 0;
     }
 
-    if (result != WTF::Unicode::conversionOK && result != WTF::Unicode::targetExhausted)
-        return 0;
-
     *p++ = '\0';
     return p - buffer;
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to