Changeset 211319 in webkit for trunk/Source/JavaScriptCore/parser/Lexer.cpp
- Timestamp:
- Jan 27, 2017, 7:09:12 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/parser/Lexer.cpp
r209632 r211319 634 634 }; 635 635 636 template<typename CharacterType> ParsedUnicodeEscapeValue Lexer<CharacterType>::parseUnicodeEscape() 636 template<typename CharacterType> 637 ParsedUnicodeEscapeValue Lexer<CharacterType>::parseUnicodeEscape() 637 638 { 638 639 if (m_current == '{') { … … 643 644 return m_current ? ParsedUnicodeEscapeValue::Invalid : ParsedUnicodeEscapeValue::Incomplete; 644 645 codePoint = (codePoint << 4) | toASCIIHexValue(m_current); 645 if (codePoint > UCHAR_MAX_VALUE) 646 return ParsedUnicodeEscapeValue::Invalid; 646 if (codePoint > UCHAR_MAX_VALUE) { 647 // For raw template literal syntax, we consume `NotEscapeSequence`. 648 // Here, we consume NotCodePoint's HexDigits. 649 // 650 // NotEscapeSequence :: 651 // u { [lookahread not one of HexDigit] 652 // u { NotCodePoint 653 // u { CodePoint [lookahead != }] 654 // 655 // NotCodePoint :: 656 // HexDigits but not if MV of HexDigits <= 0x10FFFF 657 // 658 // CodePoint :: 659 // HexDigits but not if MV of HexDigits > 0x10FFFF 660 shift(); 661 while (isASCIIHexDigit(m_current)) 662 shift(); 663 664 return atEnd() ? ParsedUnicodeEscapeValue::Incomplete : ParsedUnicodeEscapeValue::Invalid; 665 } 647 666 shift(); 648 667 } while (m_current != '}'); … … 654 673 auto character3 = peek(2); 655 674 auto character4 = peek(3); 656 if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(character2) || !isASCIIHexDigit(character3) || !isASCIIHexDigit(character4))) 657 return (m_code + 4) >= m_codeEnd ? ParsedUnicodeEscapeValue::Incomplete : ParsedUnicodeEscapeValue::Invalid; 675 if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(character2) || !isASCIIHexDigit(character3) || !isASCIIHexDigit(character4))) { 676 auto result = (m_code + 4) >= m_codeEnd ? ParsedUnicodeEscapeValue::Incomplete : ParsedUnicodeEscapeValue::Invalid; 677 678 // For raw template literal syntax, we consume `NotEscapeSequence`. 679 // 680 // NotEscapeSequence :: 681 // u [lookahead not one of HexDigit][lookahead != {] 682 // u HexDigit [lookahead not one of HexDigit] 683 // u HexDigit HexDigit [lookahead not one of HexDigit] 684 // u HexDigit HexDigit HexDigit [lookahead not one of HexDigit] 685 while (isASCIIHexDigit(m_current)) 686 shift(); 687 688 return result; 689 } 690 658 691 auto result = convertUnicode(m_current, character2, character3, character4); 659 692 shift(); … … 1182 1215 1183 1216 template <typename T> 1184 template <bool shouldBuildStrings > ALWAYS_INLINE auto Lexer<T>::parseComplexEscape(EscapeParseMode escapeParseMode,bool strictMode, T stringQuoteCharacter) -> StringParseResult1217 template <bool shouldBuildStrings, LexerEscapeParseMode escapeParseMode> ALWAYS_INLINE auto Lexer<T>::parseComplexEscape(bool strictMode, T stringQuoteCharacter) -> StringParseResult 1185 1218 { 1186 1219 if (m_current == 'x') { 1187 1220 shift(); 1188 1221 if (!isASCIIHexDigit(m_current) || !isASCIIHexDigit(peek(1))) { 1222 // For raw template literal syntax, we consume `NotEscapeSequence`. 1223 // 1224 // NotEscapeSequence :: 1225 // x [lookahread not one of HexDigit] 1226 // x HexDigit [lookahread not one of HexDigit] 1227 if (isASCIIHexDigit(m_current)) 1228 shift(); 1229 ASSERT(!isASCIIHexDigit(m_current)); 1230 1189 1231 m_lexErrorMessage = ASCIILiteral("\\x can only be followed by a hex character sequence"); 1190 return StringCannotBeParsed; 1191 } 1232 return atEnd() ? StringUnterminated : StringCannotBeParsed; 1233 } 1234 1192 1235 T prev = m_current; 1193 1236 shift(); … … 1195 1238 record16(convertHex(prev, m_current)); 1196 1239 shift(); 1240 1197 1241 return StringParsedSuccessfully; 1198 1242 } … … 1201 1245 shift(); 1202 1246 1203 if (escapeParseMode == EscapeParseMode::String && m_current == stringQuoteCharacter) {1247 if (escapeParseMode == LexerEscapeParseMode::String && m_current == stringQuoteCharacter) { 1204 1248 if (shouldBuildStrings) 1205 1249 record16('u'); … … 1215 1259 1216 1260 m_lexErrorMessage = ASCIILiteral("\\u can only be followed by a Unicode character sequence"); 1217 return character.isIncomplete() ? StringUnterminated : StringCannotBeParsed;1261 return atEnd() ? StringUnterminated : StringCannotBeParsed; 1218 1262 } 1219 1263 … … 1224 1268 shift(); 1225 1269 if (character1 != '0' || isASCIIDigit(m_current)) { 1270 // For raw template literal syntax, we consume `NotEscapeSequence`. 1271 // 1272 // NotEscapeSequence :: 1273 // 0 DecimalDigit 1274 // DecimalDigit but not 0 1275 if (character1 == '0') 1276 shift(); 1277 1226 1278 m_lexErrorMessage = ASCIILiteral("The only valid numeric escape in strict mode is '\\0'"); 1227 return StringCannotBeParsed;1279 return atEnd() ? StringUnterminated : StringCannotBeParsed; 1228 1280 } 1229 1281 if (shouldBuildStrings) … … 1291 1343 shiftLineTerminator(); 1292 1344 else { 1293 StringParseResult result = parseComplexEscape<shouldBuildStrings >(EscapeParseMode::String,strictMode, stringQuoteCharacter);1345 StringParseResult result = parseComplexEscape<shouldBuildStrings, LexerEscapeParseMode::String>(strictMode, stringQuoteCharacter); 1294 1346 if (result != StringParsedSuccessfully) 1295 1347 return result; … … 1373 1425 1374 1426 template <typename T> 1375 template <bool shouldBuildStrings> typename Lexer<T>::StringParseResult Lexer<T>::parseTemplateLiteral(JSTokenData* tokenData, RawStringsBuildMode rawStringsBuildMode) 1376 { 1427 typename Lexer<T>::StringParseResult Lexer<T>::parseTemplateLiteral(JSTokenData* tokenData, RawStringsBuildMode rawStringsBuildMode) 1428 { 1429 bool parseCookedFailed = false; 1377 1430 const T* stringStart = currentSourcePtr(); 1378 1431 const T* rawStringStart = currentSourcePtr(); … … 1383 1436 if (UNLIKELY(m_current == '\\')) { 1384 1437 lineNumberAdder.clear(); 1385 if (stringStart != currentSourcePtr() && shouldBuildStrings)1438 if (stringStart != currentSourcePtr()) 1386 1439 append16(stringStart, currentSourcePtr() - stringStart); 1387 1440 shift(); … … 1391 1444 // Most common escape sequences first. 1392 1445 if (escape) { 1393 if (shouldBuildStrings) 1394 record16(escape); 1446 record16(escape); 1395 1447 shift(); 1396 1448 } else if (UNLIKELY(isLineTerminator(m_current))) { 1397 1449 // Normalize <CR>, <CR><LF> to <LF>. 1398 1450 if (m_current == '\r') { 1399 if (shouldBuildStrings) { 1400 ASSERT_WITH_MESSAGE(rawStringStart != currentSourcePtr(), "We should have at least shifted the escape."); 1401 1402 if (rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings) { 1403 m_bufferForRawTemplateString16.append(rawStringStart, currentSourcePtr() - rawStringStart); 1404 m_bufferForRawTemplateString16.append('\n'); 1405 } 1451 ASSERT_WITH_MESSAGE(rawStringStart != currentSourcePtr(), "We should have at least shifted the escape."); 1452 1453 if (rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings) { 1454 m_bufferForRawTemplateString16.append(rawStringStart, currentSourcePtr() - rawStringStart); 1455 m_bufferForRawTemplateString16.append('\n'); 1406 1456 } 1407 1457 … … 1420 1470 } else { 1421 1471 bool strictMode = true; 1422 StringParseResult result = parseComplexEscape<shouldBuildStrings>(EscapeParseMode::Template, strictMode, '`'); 1423 if (result != StringParsedSuccessfully) 1424 return result; 1472 StringParseResult result = parseComplexEscape<true, LexerEscapeParseMode::Template>(strictMode, '`'); 1473 if (result != StringParsedSuccessfully) { 1474 if (rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings && result == StringCannotBeParsed) 1475 parseCookedFailed = true; 1476 else 1477 return result; 1478 } 1425 1479 } 1426 1480 … … 1446 1500 if (m_current == '\r') { 1447 1501 // Normalize <CR>, <CR><LF> to <LF>. 1448 if (shouldBuildStrings) { 1449 if (stringStart != currentSourcePtr()) 1450 append16(stringStart, currentSourcePtr() - stringStart); 1451 if (rawStringStart != currentSourcePtr() && rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings) 1452 m_bufferForRawTemplateString16.append(rawStringStart, currentSourcePtr() - rawStringStart); 1453 1454 record16('\n'); 1455 if (rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings) 1456 m_bufferForRawTemplateString16.append('\n'); 1457 } 1502 if (stringStart != currentSourcePtr()) 1503 append16(stringStart, currentSourcePtr() - stringStart); 1504 if (rawStringStart != currentSourcePtr() && rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings) 1505 m_bufferForRawTemplateString16.append(rawStringStart, currentSourcePtr() - rawStringStart); 1506 1507 record16('\n'); 1508 if (rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings) 1509 m_bufferForRawTemplateString16.append('\n'); 1458 1510 lineNumberAdder.add(m_current); 1459 1511 shift(); … … 1479 1531 bool isTail = m_current == '`'; 1480 1532 1481 if (shouldBuildStrings) { 1482 if (currentSourcePtr() != stringStart) 1483 append16(stringStart, currentSourcePtr() - stringStart); 1484 if (rawStringStart != currentSourcePtr() && rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings) 1485 m_bufferForRawTemplateString16.append(rawStringStart, currentSourcePtr() - rawStringStart); 1486 } 1487 1488 if (shouldBuildStrings) { 1533 if (currentSourcePtr() != stringStart) 1534 append16(stringStart, currentSourcePtr() - stringStart); 1535 if (rawStringStart != currentSourcePtr() && rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings) 1536 m_bufferForRawTemplateString16.append(rawStringStart, currentSourcePtr() - rawStringStart); 1537 1538 if (!parseCookedFailed) 1489 1539 tokenData->cooked = makeIdentifier(m_buffer16.data(), m_buffer16.size()); 1490 // Line terminator normalization (e.g. <CR> => <LF>) should be applied to both the raw and cooked representations.1491 if (rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings)1492 tokenData->raw = makeIdentifier(m_bufferForRawTemplateString16.data(), m_bufferForRawTemplateString16.size()); 1493 else1494 tokenData->raw = makeEmptyIdentifier();1495 } else {1496 tokenData->cooked = makeEmptyIdentifier();1497 tokenData->raw = makeEmptyIdentifier();1498 } 1540 else 1541 tokenData->cooked = nullptr; 1542 1543 // Line terminator normalization (e.g. <CR> => <LF>) should be applied to both the raw and cooked representations. 1544 if (rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings) 1545 tokenData->raw = makeIdentifier(m_bufferForRawTemplateString16.data(), m_bufferForRawTemplateString16.size()); 1546 else 1547 tokenData->raw = nullptr; 1548 1499 1549 tokenData->isTail = isTail; 1500 1550 … … 2082 2132 shift(); 2083 2133 token = SEMICOLON; 2134 break; 2135 case CharacterBackQuote: 2136 shift(); 2137 token = BACKQUOTE; 2084 2138 break; 2085 2139 case CharacterOpenBrace: … … 2235 2289 break; 2236 2290 } 2237 case CharacterBackQuote: {2238 // Skip backquote.2239 shift();2240 StringParseResult result = StringCannotBeParsed;2241 if (lexerFlags & LexerFlagsDontBuildStrings)2242 result = parseTemplateLiteral<false>(tokenData, RawStringsBuildMode::BuildRawStrings);2243 else2244 result = parseTemplateLiteral<true>(tokenData, RawStringsBuildMode::BuildRawStrings);2245 2246 if (UNLIKELY(result != StringParsedSuccessfully)) {2247 token = result == StringUnterminated ? UNTERMINATED_TEMPLATE_LITERAL_ERRORTOK : INVALID_TEMPLATE_LITERAL_ERRORTOK;2248 goto returnError;2249 }2250 token = TEMPLATE;2251 break;2252 }2253 2291 case CharacterIdentifierStart: 2254 2292 ASSERT(isIdentStart(m_current)); … … 2421 2459 2422 2460 template <typename T> 2423 JSTokenType Lexer<T>::scanT railingTemplateString(JSToken* tokenRecord, RawStringsBuildMode rawStringsBuildMode)2461 JSTokenType Lexer<T>::scanTemplateString(JSToken* tokenRecord, RawStringsBuildMode rawStringsBuildMode) 2424 2462 { 2425 2463 JSTokenData* tokenData = &tokenRecord->m_data; … … 2427 2465 ASSERT(m_buffer16.isEmpty()); 2428 2466 2429 // Leading closing brace } isalready shifted in the previous token scan.2467 // Leading backquote ` (for template head) or closing brace } (for template trailing) are already shifted in the previous token scan. 2430 2468 // So in this re-scan phase, shift() is not needed here. 2431 StringParseResult result = parseTemplateLiteral <true>(tokenData, rawStringsBuildMode);2469 StringParseResult result = parseTemplateLiteral(tokenData, rawStringsBuildMode); 2432 2470 JSTokenType token = ERRORTOK; 2433 2471 if (UNLIKELY(result != StringParsedSuccessfully)) {
Note:
See TracChangeset
for help on using the changeset viewer.