@@ -673,7 +673,7 @@ mixin _ChunkedJsonParser<T> on _ChunkedJsonParserState {
673673 *
674674 * The [start] positions is inclusive, [end] is exclusive.
675675 */
676- void addSliceToString (int start, int end);
676+ void addSliceToString (int start, int end, int bits );
677677
678678 /**
679679 * Adds a string slice to the string being built.
@@ -1251,7 +1251,7 @@ mixin _ChunkedJsonParser<T> on _ChunkedJsonParserState {
12511251 }
12521252 }
12531253 beginString ();
1254- if (start < end) addSliceToString (start, end);
1254+ if (start < end) addSliceToString (start, end, bits );
12551255 return chunkString (STR_PLAIN );
12561256 }
12571257
@@ -1298,17 +1298,19 @@ mixin _ChunkedJsonParser<T> on _ChunkedJsonParserState {
12981298 int parseStringToBuffer (int position) {
12991299 int end = chunkEnd;
13001300 int start = position;
1301+ int bits = 0 ;
13011302 while (true ) {
13021303 if (position == end) {
13031304 if (position > start) {
1304- addSliceToString (start, position);
1305+ addSliceToString (start, position, bits );
13051306 }
13061307 return chunkString (STR_PLAIN );
13071308 }
13081309
13091310 int char = 0 ;
13101311 do {
13111312 char = getChar (position);
1313+ bits | = char; // Includes final '"', but that never matters.
13121314 position++ ;
13131315 if (isUtf16Input && char > 0xFF ) {
13141316 continue ;
@@ -1327,7 +1329,7 @@ mixin _ChunkedJsonParser<T> on _ChunkedJsonParserState {
13271329 if (char == QUOTE ) {
13281330 int quotePosition = position - 1 ;
13291331 if (quotePosition > start) {
1330- addSliceToString (start, quotePosition);
1332+ addSliceToString (start, quotePosition, bits );
13311333 }
13321334 listener.handleString (endString ());
13331335 return position;
@@ -1339,13 +1341,14 @@ mixin _ChunkedJsonParser<T> on _ChunkedJsonParserState {
13391341
13401342 // Handle escape.
13411343 if (position - 1 > start) {
1342- addSliceToString (start, position - 1 );
1344+ addSliceToString (start, position - 1 , bits );
13431345 }
13441346
13451347 if (position == end) return chunkString (STR_ESCAPE );
13461348 position = parseStringEscape (position);
13471349 if (position == end) return position;
13481350 start = position;
1351+ bits = 0 ;
13491352 }
13501353 }
13511354
@@ -1656,7 +1659,7 @@ class _JsonOneByteStringParser extends _ChunkedJsonParserState
16561659 assert (stringBuffer.isEmpty);
16571660 }
16581661
1659- void addSliceToString (int start, int end) {
1662+ void addSliceToString (int start, int end, int bits ) {
16601663 addStringSliceToString (chunk.substringUnchecked (start, end));
16611664 }
16621665
@@ -1710,26 +1713,18 @@ class _JsonTwoByteStringParser extends _ChunkedJsonParserState
17101713 int length = end - start;
17111714 if (length == 0 ) return '' ;
17121715
1713- final WasmArray <WasmI16 > sourceArray = chunk.array;
1714- const int asciiBits = 0x7f ;
1715- if (bits <= asciiBits) {
1716- final result = OneByteString .withLength (length);
1717- for (int i = 0 ; i < length; ++ i) {
1718- result.array.write (i, sourceArray.readUnsigned (start++ ));
1719- }
1720- return result;
1716+ final sourceArray = chunk.array;
1717+ if (bits <= 0xff ) {
1718+ return _oneByteStringFromI16 (sourceArray, start, length);
17211719 }
1722- final result = TwoByteString .withLength (length);
1723- result.array.copy (0 , sourceArray, start, length);
1724- return result;
1720+ return _twoByteStringFromI16 (sourceArray, start, length);
17251721 }
17261722
17271723 String getStringWithHash (int start, int end, int bits, int stringHash) {
17281724 final sourceArray = chunk.array;
17291725 final length = end - start;
17301726
1731- const asciiBits = 0x7f ;
1732- if (bits <= asciiBits) {
1727+ if (bits <= 0xff ) {
17331728 return _internOneByteStringFromI16 (
17341729 sourceArray,
17351730 stringHash,
@@ -1738,8 +1733,7 @@ class _JsonTwoByteStringParser extends _ChunkedJsonParserState
17381733 );
17391734 }
17401735
1741- final result = TwoByteString .withLength (length);
1742- result.array.copy (0 , sourceArray, start, length);
1736+ final result = _twoByteStringFromI16 (sourceArray, start, length);
17431737 assert (result.hashCode.toWasmI32 () == stringHash.toWasmI32 ());
17441738 setIdentityHashField (result, stringHash);
17451739 return result;
@@ -1749,8 +1743,14 @@ class _JsonTwoByteStringParser extends _ChunkedJsonParserState
17491743 assert (stringBuffer.isEmpty);
17501744 }
17511745
1752- void addSliceToString (int start, int end) {
1753- addStringSliceToString (chunk.substringUnchecked (start, end));
1746+ void addSliceToString (int start, int end, int bits) {
1747+ final sourceArray = chunk.array;
1748+ final length = end - start;
1749+ addStringSliceToString (
1750+ bits <= 0xff
1751+ ? _oneByteStringFromI16 (sourceArray, start, length)
1752+ : _twoByteStringFromI16 (sourceArray, start, length),
1753+ );
17541754 }
17551755
17561756 void addStringSliceToString (String string) {
@@ -1812,14 +1812,24 @@ OneByteString _internOneByteStringFromI8(
18121812 }
18131813 }
18141814
1815- final result = OneByteString .withLength (length);
1816- result.array.copy (0 , array, offset, length);
1815+ final result = _oneByteStringFromI8 (array, offset, length);
18171816 assert (result.hashCode.toWasmI32 () == stringHash.toWasmI32 ());
18181817 setIdentityHashField (result, stringHash);
18191818 _oneByteStringInternCache[index] = result;
18201819 return result;
18211820}
18221821
1822+ @pragma ('wasm:prefer-inline' )
1823+ OneByteString _oneByteStringFromI8 (
1824+ WasmArray <WasmI8 > array,
1825+ int start,
1826+ int length,
1827+ ) {
1828+ final result = OneByteString .withLength (length);
1829+ result.array.copy (0 , array, start, length);
1830+ return result;
1831+ }
1832+
18231833OneByteString _internOneByteStringFromI16 (
18241834 WasmArray <WasmI16 > array,
18251835 int stringHash,
@@ -1844,16 +1854,35 @@ OneByteString _internOneByteStringFromI16(
18441854 }
18451855 }
18461856
1847- final result = OneByteString .withLength (length);
1848- for (int start = offset, i = 0 ; i < length; ++ i, start++ ) {
1849- result.array.write (i, array.readUnsigned (start));
1850- }
1857+ final result = _oneByteStringFromI16 (array, offset, length);
18511858 assert (result.hashCode.toWasmI32 () == stringHash.toWasmI32 ());
18521859 setIdentityHashField (result, stringHash);
18531860 _oneByteStringInternCache[index] = result;
18541861 return result;
18551862}
18561863
1864+ OneByteString _oneByteStringFromI16 (
1865+ WasmArray <WasmI16 > array,
1866+ int start,
1867+ int length,
1868+ ) {
1869+ final result = OneByteString .withLength (length);
1870+ for (int i = 0 ; i < length; ++ i) {
1871+ result.array.write (i, array.readUnsigned (start++ ));
1872+ }
1873+ return result;
1874+ }
1875+
1876+ TwoByteString _twoByteStringFromI16 (
1877+ WasmArray <WasmI16 > array,
1878+ int start,
1879+ int length,
1880+ ) {
1881+ final result = TwoByteString .withLength (length);
1882+ result.array.copy (0 , array, start, length);
1883+ return result;
1884+ }
1885+
18571886@patch
18581887class JsonDecoder {
18591888 @patch
@@ -1999,14 +2028,16 @@ class _JsonUtf8Parser extends _ChunkedJsonParserState
19992028 int getChar (int position) => chunk[position];
20002029
20012030 String getString (int start, int end, int bits) {
2031+ int length = end - start;
2032+ if (length == 0 ) return '' ;
2033+
20022034 const int maxAsciiChar = 0x7f ;
20032035 if (bits <= maxAsciiChar) {
20042036 return createOneByteStringFromCharacters (chunk, start, end);
20052037 }
20062038 beginString ();
2007- if (start < end) addSliceToString (start, end);
2008- String result = endString ();
2009- return result;
2039+ addSliceToString (start, end, bits);
2040+ return endString ();
20102041 }
20112042
20122043 String getStringWithHash (int start, int end, int bits, int stringHash) {
@@ -2029,8 +2060,12 @@ class _JsonUtf8Parser extends _ChunkedJsonParserState
20292060 stringBuffer.clear ();
20302061 }
20312062
2032- void addSliceToString (int start, int end) {
2033- addStringSliceToString (decoder.convertChunked (chunk, start, end));
2063+ void addSliceToString (int start, int end, int bits) {
2064+ addStringSliceToString (
2065+ ! decoder.expectsContinuation && bits <= 0x7f
2066+ ? _oneByteStringFromI8 (chunk.data, start, end - start)
2067+ : decoder.convertChunked (chunk, start, end),
2068+ );
20342069 }
20352070
20362071 void addStringSliceToString (String string) {
0 commit comments