Changeset 99812 in webkit
- Timestamp:
- Nov 9, 2011 8:49:01 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/API/JSValueRef.cpp
r99312 r99812 236 236 APIEntryShim entryShim(exec); 237 237 UString str = string->ustring(); 238 LiteralParser parser(exec, str.characters(), str.length(), LiteralParser::StrictJSON); 238 if (str.is8Bit()) { 239 LiteralParser<LChar> parser(exec, str.characters8(), str.length(), StrictJSON); 240 return toRef(exec, parser.tryLiteralParse()); 241 } 242 LiteralParser<UChar> parser(exec, str.characters16(), str.length(), StrictJSON); 239 243 return toRef(exec, parser.tryLiteralParse()); 240 244 } -
trunk/Source/JavaScriptCore/ChangeLog
r99810 r99812 1 2011-11-09 Michael Saboff <msaboff@apple.com> 2 3 Towards 8 Bit Strings: Templatize JSC::LiteralParser class by character type 4 https://bugs.webkit.org/show_bug.cgi?id=71862 5 6 Changed LiteralParser to be templatized of character type. 7 8 Moved five enums out of class definition to work around a clang compiler defect. 9 10 Added lexIdentifier templated method to break out character specific versions. 11 Added static setParserTokenString templated method to handle setting approriately 12 sized string pointer. 13 14 To keep code in LiteralParser.cpp and keep LiteralParser.h small, the two 15 flavors of LiteralParser are explicitly instantiated at the end of 16 LiteralParser.cpp. 17 18 Reviewed by Oliver Hunt. 19 20 * API/JSValueRef.cpp: 21 (JSValueMakeFromJSONString): 22 * JavaScriptCore.exp: 23 * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: 24 * interpreter/Interpreter.cpp: 25 (JSC::Interpreter::callEval): 26 (JSC::Interpreter::execute): 27 * runtime/JSGlobalObjectFunctions.cpp: 28 (JSC::globalFuncEval): 29 * runtime/JSONObject.cpp: 30 (JSC::JSONProtoFuncParse): 31 * runtime/LiteralParser.cpp: 32 (JSC::isJSONWhiteSpace): 33 (JSC::::tryJSONPParse): 34 (JSC::::makeIdentifier): 35 (JSC::::Lexer::lex): 36 (JSC::::Lexer::lexIdentifier): 37 (JSC::::Lexer::next): 38 (JSC::LChar): 39 (JSC::UChar): 40 (JSC::isSafeStringCharacter): 41 (JSC::::Lexer::lexString): 42 (JSC::::Lexer::lexNumber): 43 (JSC::::parse): 44 * runtime/LiteralParser.h: 45 (JSC::LiteralParser::LiteralParser): 46 (JSC::LiteralParser::getErrorMessage): 47 (JSC::LiteralParser::tryLiteralParse): 48 (JSC::LiteralParser::Lexer::Lexer): 49 (JSC::LiteralParser::Lexer::currentToken): 50 (JSC::LiteralParser::Lexer::getErrorMessage): 51 * runtime/UString.h: 52 (JSC::LChar): 53 (JSC::UChar): 54 * wtf/text/StringBuilder.cpp: 55 (WTF::StringBuilder::append): 56 * wtf/text/StringBuilder.h: 57 (WTF::StringBuilder::append): 58 1 59 2011-11-09 Filip Pizlo <fpizlo@apple.com> 2 60 -
trunk/Source/JavaScriptCore/JavaScriptCore.exp
r99779 r99812 411 411 __ZN3WTF13StringBuilder11shrinkToFitEv 412 412 __ZN3WTF13StringBuilder15reserveCapacityEj 413 __ZN3WTF13StringBuilder6appendEPK cj413 __ZN3WTF13StringBuilder6appendEPKhj 414 414 __ZN3WTF13StringBuilder6appendEPKtj 415 415 __ZN3WTF13StringBuilder6resizeEj -
trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
r99779 r99812 63 63 ?allocatePropertyStorage@JSObject@JSC@@QAEXAAVJSGlobalData@2@II@Z 64 64 ?allocateSlowCase@AllocationSpace@JSC@@AAEPAXAAUSizeClass@MarkedSpace@2@@Z 65 ?append@StringBuilder@WTF@@QAEXPB DI@Z65 ?append@StringBuilder@WTF@@QAEXPBEI@Z 66 66 ?append@StringBuilder@WTF@@QAEXPB_WI@Z 67 67 ?ascii@UString@JSC@@QBE?AVCString@WTF@@XZ -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r99618 r99812 446 446 // FIXME: We can use the preparser in strict mode, we just need additional logic 447 447 // to prevent duplicates. 448 LiteralParser preparser(callFrame, programSource.characters(), programSource.length(), LiteralParser::NonStrictJSON); 449 if (JSValue parsedObject = preparser.tryLiteralParse()) 450 return parsedObject; 448 if (programSource.is8Bit()) { 449 LiteralParser<LChar> preparser(callFrame, programSource.characters8(), programSource.length(), NonStrictJSON); 450 if (JSValue parsedObject = preparser.tryLiteralParse()) 451 return parsedObject; 452 } else { 453 LiteralParser<UChar> preparser(callFrame, programSource.characters16(), programSource.length(), NonStrictJSON); 454 if (JSValue parsedObject = preparser.tryLiteralParse()) 455 return parsedObject; 456 } 451 457 } 452 458 … … 780 786 781 787 DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get()); 782 LiteralParser literalParser(callFrame, program->source().data(), program->source().length(), LiteralParser::JSONP); 783 Vector<LiteralParser::JSONPData> JSONPData; 784 if (literalParser.tryJSONPParse(JSONPData, scopeChain->globalObject->supportsRichSourceInfo())) { 788 Vector<JSONPData> JSONPData; 789 bool parseResult; 790 const UString programSource = program->source().toString(); 791 if (programSource.is8Bit()) { 792 LiteralParser<LChar> literalParser(callFrame, programSource.characters8(), programSource.length(), JSONP); 793 parseResult = literalParser.tryJSONPParse(JSONPData, scopeChain->globalObject->supportsRichSourceInfo()); 794 } else { 795 LiteralParser<UChar> literalParser(callFrame, programSource.characters16(), programSource.length(), JSONP); 796 parseResult = literalParser.tryJSONPParse(JSONPData, scopeChain->globalObject->supportsRichSourceInfo()); 797 } 798 799 if (parseResult) { 785 800 JSGlobalObject* globalObject = scopeChain->globalObject.get(); 786 801 JSValue result; 787 802 for (unsigned entry = 0; entry < JSONPData.size(); entry++) { 788 Vector< LiteralParser::JSONPPathEntry> JSONPPath;803 Vector<JSONPPathEntry> JSONPPath; 789 804 JSONPPath.swap(JSONPData[entry].m_path); 790 805 JSValue JSONPValue = JSONPData[entry].m_value.get(); 791 if (JSONPPath.size() == 1 && JSONPPath[0].m_type == LiteralParser::JSONPPathEntryTypeDeclare) {806 if (JSONPPath.size() == 1 && JSONPPath[0].m_type == JSONPPathEntryTypeDeclare) { 792 807 if (globalObject->hasProperty(callFrame, JSONPPath[0].m_pathEntryName)) { 793 808 PutPropertySlot slot; … … 801 816 JSValue baseObject(globalObject); 802 817 for (unsigned i = 0; i < JSONPPath.size() - 1; i++) { 803 ASSERT(JSONPPath[i].m_type != LiteralParser::JSONPPathEntryTypeDeclare);818 ASSERT(JSONPPath[i].m_type != JSONPPathEntryTypeDeclare); 804 819 switch (JSONPPath[i].m_type) { 805 case LiteralParser::JSONPPathEntryTypeDot: {820 case JSONPPathEntryTypeDot: { 806 821 if (i == 0) { 807 822 PropertySlot slot(globalObject); … … 818 833 continue; 819 834 } 820 case LiteralParser::JSONPPathEntryTypeLookup: {835 case JSONPPathEntryTypeLookup: { 821 836 baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex); 822 837 if (callFrame->hadException()) … … 831 846 PutPropertySlot slot; 832 847 switch (JSONPPath.last().m_type) { 833 case LiteralParser::JSONPPathEntryTypeCall: {848 case JSONPPathEntryTypeCall: { 834 849 JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName); 835 850 if (callFrame->hadException()) … … 847 862 break; 848 863 } 849 case LiteralParser::JSONPPathEntryTypeDot: {864 case JSONPPathEntryTypeDot: { 850 865 baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot); 851 866 if (callFrame->hadException()) … … 853 868 break; 854 869 } 855 case LiteralParser::JSONPPathEntryTypeLookup: {870 case JSONPPathEntryTypeLookup: { 856 871 baseObject.put(callFrame, JSONPPath.last().m_pathIndex, JSONPValue); 857 872 if (callFrame->hadException()) -
trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
r99436 r99812 446 446 UString s = x.toString(exec); 447 447 448 LiteralParser preparser(exec, s.characters(), s.length(), LiteralParser::NonStrictJSON); 449 if (JSValue parsedObject = preparser.tryLiteralParse()) 450 return JSValue::encode(parsedObject); 448 if (s.is8Bit()) { 449 LiteralParser<LChar> preparser(exec, s.characters8(), s.length(), NonStrictJSON); 450 if (JSValue parsedObject = preparser.tryLiteralParse()) 451 return JSValue::encode(parsedObject); 452 } else { 453 LiteralParser<UChar> preparser(exec, s.characters16(), s.length(), NonStrictJSON); 454 if (JSValue parsedObject = preparser.tryLiteralParse()) 455 return JSValue::encode(parsedObject); 456 } 451 457 452 458 EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false); -
trunk/Source/JavaScriptCore/runtime/JSONObject.cpp
r99754 r99812 820 820 return JSValue::encode(jsNull()); 821 821 822 JSValue unfiltered; 822 823 LocalScope scope(exec->globalData()); 823 LiteralParser jsonParser(exec, source.characters(), source.length(), LiteralParser::StrictJSON); 824 JSValue unfiltered = jsonParser.tryLiteralParse(); 825 if (!unfiltered) 826 return throwVMError(exec, createSyntaxError(exec, jsonParser.getErrorMessage())); 824 if (source.is8Bit()) { 825 LiteralParser<LChar> jsonParser(exec, source.characters8(), source.length(), StrictJSON); 826 unfiltered = jsonParser.tryLiteralParse(); 827 if (!unfiltered) 828 return throwVMError(exec, createSyntaxError(exec, jsonParser.getErrorMessage())); 829 } else { 830 LiteralParser<UChar> jsonParser(exec, source.characters16(), source.length(), StrictJSON); 831 unfiltered = jsonParser.tryLiteralParse(); 832 if (!unfiltered) 833 return throwVMError(exec, createSyntaxError(exec, jsonParser.getErrorMessage())); 834 } 827 835 828 836 if (exec->argumentCount() < 2) -
trunk/Source/JavaScriptCore/runtime/LiteralParser.cpp
r99436 r99812 37 37 namespace JSC { 38 38 39 static inline bool isJSONWhiteSpace(const UChar& c) 39 template <typename CharType> 40 static inline bool isJSONWhiteSpace(const CharType& c) 40 41 { 41 42 // The JSON RFC 4627 defines a list of allowed characters to be considered … … 44 45 } 45 46 46 bool LiteralParser::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSourceInfo) 47 template <typename CharType> 48 bool LiteralParser<CharType>::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSourceInfo) 47 49 { 48 50 if (m_lexer.next() != TokIdentifier) … … 121 123 } 122 124 123 ALWAYS_INLINE const Identifier LiteralParser::makeIdentifier(const UChar* characters, size_t length) 125 template <typename CharType> 126 ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const LChar* characters, size_t length) 124 127 { 125 128 if (!length) … … 140 143 } 141 144 142 template <LiteralParser::ParserMode mode> LiteralParser::TokenType LiteralParser::Lexer::lex(LiteralParserToken& token) 145 template <typename CharType> 146 ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const UChar* characters, size_t length) 147 { 148 if (!length) 149 return m_exec->globalData().propertyNames->emptyIdentifier; 150 if (characters[0] >= MaximumCachableCharacter) 151 return Identifier(&m_exec->globalData(), characters, length); 152 153 if (length == 1) { 154 if (!m_shortIdentifiers[characters[0]].isNull()) 155 return m_shortIdentifiers[characters[0]]; 156 m_shortIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length); 157 return m_shortIdentifiers[characters[0]]; 158 } 159 if (!m_recentIdentifiers[characters[0]].isNull() && Identifier::equal(m_recentIdentifiers[characters[0]].impl(), characters, length)) 160 return m_recentIdentifiers[characters[0]]; 161 m_recentIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length); 162 return m_recentIdentifiers[characters[0]]; 163 } 164 165 template <typename CharType> 166 template <ParserMode mode> TokenType LiteralParser<CharType>::Lexer::lex(LiteralParserToken<CharType>& token) 143 167 { 144 168 while (m_ptr < m_end && isJSONWhiteSpace(*m_ptr)) … … 241 265 return TokAssign; 242 266 } 243 if (isASCIIAlpha(*m_ptr) || *m_ptr == '_' || *m_ptr == '$') { 244 while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$')) 245 m_ptr++; 246 token.stringToken = token.start; 247 token.stringLength = m_ptr - token.start; 248 token.type = TokIdentifier; 249 token.end = m_ptr; 250 return TokIdentifier; 251 } 267 if (isASCIIAlpha(*m_ptr) || *m_ptr == '_' || *m_ptr == '$') 268 return lexIdentifier(token); 252 269 if (*m_ptr == '\'') { 253 270 if (mode == StrictJSON) { … … 262 279 } 263 280 264 LiteralParser::TokenType LiteralParser::Lexer::next() 281 template <> 282 ALWAYS_INLINE TokenType LiteralParser<LChar>::Lexer::lexIdentifier(LiteralParserToken<LChar>& token) 283 { 284 while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$')) 285 m_ptr++; 286 token.stringIs8Bit = 1; 287 token.stringToken8 = token.start; 288 token.stringLength = m_ptr - token.start; 289 token.type = TokIdentifier; 290 token.end = m_ptr; 291 return TokIdentifier; 292 } 293 294 template <> 295 ALWAYS_INLINE TokenType LiteralParser<UChar>::Lexer::lexIdentifier(LiteralParserToken<UChar>& token) 296 { 297 while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$')) 298 m_ptr++; 299 token.stringIs8Bit = 0; 300 token.stringToken16 = token.start; 301 token.stringLength = m_ptr - token.start; 302 token.type = TokIdentifier; 303 token.end = m_ptr; 304 return TokIdentifier; 305 } 306 307 template <typename CharType> 308 TokenType LiteralParser<CharType>::Lexer::next() 265 309 { 266 310 if (m_mode == NonStrictJSON) … … 271 315 } 272 316 273 template <LiteralParser::ParserMode mode, UChar terminator> static inline bool isSafeStringCharacter(UChar c) 274 { 275 return (c >= ' ' && (mode == LiteralParser::StrictJSON || c <= 0xff) && c != '\\' && c != terminator) || c == '\t'; 317 template <> 318 ALWAYS_INLINE void setParserTokenString<LChar>(LiteralParserToken<LChar>& token, const LChar* string) 319 { 320 token.stringIs8Bit = 1; 321 token.stringToken8 = string; 322 } 323 324 template <> 325 ALWAYS_INLINE void setParserTokenString<UChar>(LiteralParserToken<UChar>& token, const UChar* string) 326 { 327 token.stringIs8Bit = 0; 328 token.stringToken16 = string; 329 } 330 331 template <ParserMode mode, typename CharType, LChar terminator> static inline bool isSafeStringCharacter(LChar c) 332 { 333 return (c >= ' ' && c != '\\' && c != terminator) || c == '\t'; 334 } 335 336 template <ParserMode mode, typename CharType, UChar terminator> static inline bool isSafeStringCharacter(UChar c) 337 { 338 return (c >= ' ' && (mode == StrictJSON || c <= 0xff) && c != '\\' && c != terminator) || c == '\t'; 276 339 } 277 340 278 341 // "inline" is required here to help WINSCW compiler resolve specialized argument in templated functions. 279 template <LiteralParser::ParserMode mode, UChar terminator> inline LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token) 342 template <typename CharType> 343 template <ParserMode mode, char terminator> ALWAYS_INLINE TokenType LiteralParser<CharType>::Lexer::lexString(LiteralParserToken<CharType>& token) 280 344 { 281 345 ++m_ptr; 282 const UChar* runStart = m_ptr;346 const CharType* runStart = m_ptr; 283 347 UStringBuilder builder; 284 348 do { 285 349 runStart = m_ptr; 286 while (m_ptr < m_end && isSafeStringCharacter<mode, terminator>(*m_ptr))350 while (m_ptr < m_end && isSafeStringCharacter<mode, CharType, terminator>(*m_ptr)) 287 351 ++m_ptr; 288 352 if (builder.length()) … … 341 405 } 342 406 } 343 builder.append(JSC::Lexer< UChar>::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4]));407 builder.append(JSC::Lexer<CharType>::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4])); 344 408 m_ptr += 5; 345 409 break; … … 364 428 if (builder.isEmpty()) { 365 429 token.stringBuffer = UString(); 366 token.stringToken = runStart;430 setParserTokenString<CharType>(token, runStart); 367 431 token.stringLength = m_ptr - runStart; 368 432 } else { 369 433 token.stringBuffer = builder.toUString(); 370 token.stringToken = token.stringBuffer.characters(); 434 if (token.stringBuffer.is8Bit()) { 435 token.stringIs8Bit = 1; 436 token.stringToken8 = token.stringBuffer.characters8(); 437 } else { 438 token.stringIs8Bit = 0; 439 token.stringToken16 = token.stringBuffer.characters16(); 440 } 371 441 token.stringLength = token.stringBuffer.length(); 372 442 } … … 376 446 } 377 447 378 LiteralParser::TokenType LiteralParser::Lexer::lexNumber(LiteralParserToken& token) 448 template <typename CharType> 449 TokenType LiteralParser<CharType>::Lexer::lexNumber(LiteralParserToken<CharType>& token) 379 450 { 380 451 // ES5 and json.org define numbers as … … 424 495 token.type = TokNumber; 425 496 token.end = m_ptr; 426 const UChar* digit = token.start;497 const CharType* digit = token.start; 427 498 int negative = 1; 428 499 if (*digit == '-') { … … 472 543 } 473 544 474 JSValue LiteralParser::parse(ParserState initialState) 545 template <typename CharType> 546 JSValue LiteralParser<CharType>::parse(ParserState initialState) 475 547 { 476 548 ParserState state = initialState; … … 527 599 TokenType type = m_lexer.next(); 528 600 if (type == TokString || (m_mode != StrictJSON && type == TokIdentifier)) { 529 L exer::LiteralParserTokenidentifierToken = m_lexer.currentToken();601 LiteralParserToken<CharType> identifierToken = m_lexer.currentToken(); 530 602 531 603 // Check for colon … … 536 608 537 609 m_lexer.next(); 538 identifierStack.append(makeIdentifier(identifierToken.stringToken, identifierToken.stringLength)); 610 if (identifierToken.stringIs8Bit) 611 identifierStack.append(makeIdentifier(identifierToken.stringToken8, identifierToken.stringLength)); 612 else 613 identifierStack.append(makeIdentifier(identifierToken.stringToken16, identifierToken.stringLength)); 539 614 stateStack.append(DoParseObjectEndExpression); 540 615 goto startParseExpression; … … 556 631 return JSValue(); 557 632 } 558 L exer::LiteralParserTokenidentifierToken = m_lexer.currentToken();633 LiteralParserToken<CharType> identifierToken = m_lexer.currentToken(); 559 634 560 635 // Check for colon … … 565 640 566 641 m_lexer.next(); 567 identifierStack.append(makeIdentifier(identifierToken.stringToken, identifierToken.stringLength)); 642 if (identifierToken.stringIs8Bit) 643 identifierStack.append(makeIdentifier(identifierToken.stringToken8, identifierToken.stringLength)); 644 else 645 identifierStack.append(makeIdentifier(identifierToken.stringToken16, identifierToken.stringLength)); 568 646 stateStack.append(DoParseObjectEndExpression); 569 647 goto startParseExpression; … … 592 670 goto startParseObject; 593 671 case TokString: { 594 L exer::LiteralParserTokenstringToken = m_lexer.currentToken();672 LiteralParserToken<CharType> stringToken = m_lexer.currentToken(); 595 673 m_lexer.next(); 596 lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken, stringToken.stringLength).ustring()); 674 if (stringToken.stringIs8Bit) 675 lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken8, stringToken.stringLength).ustring()); 676 else 677 lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken16, stringToken.stringLength).ustring()); 597 678 break; 598 679 } 599 680 case TokNumber: { 600 L exer::LiteralParserTokennumberToken = m_lexer.currentToken();681 LiteralParserToken<CharType> numberToken = m_lexer.currentToken(); 601 682 m_lexer.next(); 602 683 lastValue = jsNumber(numberToken.numberToken); … … 623 704 m_parseErrorMessage = "Unexpected token '}'"; 624 705 return JSValue(); 625 case TokIdentifier: 626 m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", UString(m_lexer.currentToken().stringToken, m_lexer.currentToken().stringLength).ascii().data()).impl(); 627 return JSValue(); 706 case TokIdentifier: { 707 const LiteralParserToken<CharType>& token = m_lexer.currentToken(); 708 if (token.stringIs8Bit) 709 m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", UString(m_lexer.currentToken().stringToken8, m_lexer.currentToken().stringLength).ascii().data()).impl(); 710 else 711 m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", UString(m_lexer.currentToken().stringToken16, m_lexer.currentToken().stringLength).ascii().data()).impl(); 712 return JSValue(); 713 } 628 714 case TokColon: 629 715 m_parseErrorMessage = "Unexpected token ':'"; … … 738 824 } 739 825 740 } 826 // Instantiate the two flavors of LiteralParser we need instead of putting most of this file in LiteralParser.h 827 template class LiteralParser<LChar>; 828 template class LiteralParser<UChar>; 829 830 } -
trunk/Source/JavaScriptCore/runtime/LiteralParser.h
r95901 r99812 34 34 namespace JSC { 35 35 36 class LiteralParser { 36 typedef enum { StrictJSON, NonStrictJSON, JSONP } ParserMode; 37 38 enum JSONPPathEntryType { 39 JSONPPathEntryTypeDeclare, // var pathEntryName = JSON 40 JSONPPathEntryTypeDot, // <prior entries>.pathEntryName = JSON 41 JSONPPathEntryTypeLookup, // <prior entries>[pathIndex] = JSON 42 JSONPPathEntryTypeCall // <prior entries>(JSON) 43 }; 44 45 enum ParserState { StartParseObject, StartParseArray, StartParseExpression, 46 StartParseStatement, StartParseStatementEndStatement, 47 DoParseObjectStartExpression, DoParseObjectEndExpression, 48 DoParseArrayStartExpression, DoParseArrayEndExpression }; 49 enum TokenType { TokLBracket, TokRBracket, TokLBrace, TokRBrace, 50 TokString, TokIdentifier, TokNumber, TokColon, 51 TokLParen, TokRParen, TokComma, TokTrue, TokFalse, 52 TokNull, TokEnd, TokDot, TokAssign, TokSemi, TokError }; 53 54 struct JSONPPathEntry { 55 JSONPPathEntryType m_type; 56 Identifier m_pathEntryName; 57 int m_pathIndex; 58 }; 59 60 struct JSONPData { 61 Vector<JSONPPathEntry> m_path; 62 Strong<Unknown> m_value; 63 }; 64 65 template <typename CharType> 66 struct LiteralParserToken { 67 TokenType type; 68 const CharType* start; 69 const CharType* end; 70 UString stringBuffer; 71 union { 72 double numberToken; 73 struct { 74 union { 75 const LChar* stringToken8; 76 const UChar* stringToken16; 77 }; 78 unsigned stringIs8Bit : 1; 79 unsigned stringLength : 31; 80 }; 81 }; 82 }; 83 84 template <typename CharType> 85 ALWAYS_INLINE void setParserTokenString(LiteralParserToken<CharType>&, const CharType* string); 86 87 template <typename CharType> 88 class LiteralParser { 89 public: 90 LiteralParser(ExecState* exec, const CharType* characters, unsigned length, ParserMode mode) 91 : m_exec(exec) 92 , m_lexer(characters, length, mode) 93 , m_mode(mode) 94 { 95 } 96 97 UString getErrorMessage() 98 { 99 if (!m_lexer.getErrorMessage().isEmpty()) 100 return String::format("JSON Parse error: %s", m_lexer.getErrorMessage().ascii().data()).impl(); 101 if (!m_parseErrorMessage.isEmpty()) 102 return String::format("JSON Parse error: %s", m_parseErrorMessage.ascii().data()).impl(); 103 return "JSON Parse error: Unable to parse JSON string"; 104 } 105 106 JSValue tryLiteralParse() 107 { 108 m_lexer.next(); 109 JSValue result = parse(m_mode == StrictJSON ? StartParseExpression : StartParseStatement); 110 if (m_lexer.currentToken().type == TokSemi) 111 m_lexer.next(); 112 if (m_lexer.currentToken().type != TokEnd) 113 return JSValue(); 114 return result; 115 } 116 117 bool tryJSONPParse(Vector<JSONPData>&, bool needsFullSourceInfo); 118 119 private: 120 class Lexer { 37 121 public: 38 typedef enum { StrictJSON, NonStrictJSON, JSONP } ParserMode; 39 LiteralParser(ExecState* exec, const UChar* characters, unsigned length, ParserMode mode) 40 : m_exec(exec) 41 , m_lexer(characters, length, mode) 42 , m_mode(mode) 122 Lexer(const CharType* characters, unsigned length, ParserMode mode) 123 : m_mode(mode) 124 , m_ptr(characters) 125 , m_end(characters + length) 43 126 { 44 127 } 45 128 46 UString getErrorMessage() 47 { 48 if (!m_lexer.getErrorMessage().isEmpty()) 49 return String::format("JSON Parse error: %s", m_lexer.getErrorMessage().ascii().data()).impl(); 50 if (!m_parseErrorMessage.isEmpty()) 51 return String::format("JSON Parse error: %s", m_parseErrorMessage.ascii().data()).impl(); 52 return "JSON Parse error: Unable to parse JSON string"; 129 TokenType next(); 130 131 const LiteralParserToken<CharType>& currentToken() 132 { 133 return m_currentToken; 53 134 } 54 135 55 JSValue tryLiteralParse() 56 { 57 m_lexer.next(); 58 JSValue result = parse(m_mode == StrictJSON ? StartParseExpression : StartParseStatement); 59 if (m_lexer.currentToken().type == TokSemi) 60 m_lexer.next(); 61 if (m_lexer.currentToken().type != TokEnd) 62 return JSValue(); 63 return result; 64 } 136 UString getErrorMessage() { return m_lexErrorMessage; } 65 137 66 enum JSONPPathEntryType { 67 JSONPPathEntryTypeDeclare, // var pathEntryName = JSON 68 JSONPPathEntryTypeDot, // <prior entries>.pathEntryName = JSON 69 JSONPPathEntryTypeLookup, // <prior entries>[pathIndex] = JSON 70 JSONPPathEntryTypeCall // <prior entries>(JSON) 71 }; 138 private: 139 UString m_lexErrorMessage; 140 template <ParserMode mode> TokenType lex(LiteralParserToken<CharType>&); 141 ALWAYS_INLINE TokenType lexIdentifier(LiteralParserToken<CharType>&); 142 template <ParserMode mode, char terminator> ALWAYS_INLINE TokenType lexString(LiteralParserToken<CharType>&); 143 ALWAYS_INLINE TokenType lexNumber(LiteralParserToken<CharType>&); 144 LiteralParserToken<CharType> m_currentToken; 145 UString m_string; 146 ParserMode m_mode; 147 const CharType* m_ptr; 148 const CharType* m_end; 149 }; 150 151 class StackGuard; 152 JSValue parse(ParserState); 72 153 73 struct JSONPPathEntry { 74 JSONPPathEntryType m_type; 75 Identifier m_pathEntryName; 76 int m_pathIndex; 77 }; 78 79 struct JSONPData { 80 Vector<JSONPPathEntry> m_path; 81 Strong<Unknown> m_value; 82 }; 83 84 bool tryJSONPParse(Vector<JSONPData>&, bool needsFullSourceInfo); 85 86 private: 87 enum ParserState { StartParseObject, StartParseArray, StartParseExpression, 88 StartParseStatement, StartParseStatementEndStatement, 89 DoParseObjectStartExpression, DoParseObjectEndExpression, 90 DoParseArrayStartExpression, DoParseArrayEndExpression }; 91 enum TokenType { TokLBracket, TokRBracket, TokLBrace, TokRBrace, 92 TokString, TokIdentifier, TokNumber, TokColon, 93 TokLParen, TokRParen, TokComma, TokTrue, TokFalse, 94 TokNull, TokEnd, TokDot, TokAssign, TokSemi, TokError }; 95 96 class Lexer { 97 public: 98 struct LiteralParserToken { 99 TokenType type; 100 const UChar* start; 101 const UChar* end; 102 UString stringBuffer; 103 union { 104 double numberToken; 105 struct { 106 const UChar* stringToken; 107 int stringLength; 108 }; 109 }; 110 }; 111 Lexer(const UChar* characters, unsigned length, ParserMode mode) 112 : m_mode(mode) 113 , m_ptr(characters) 114 , m_end(characters + length) 115 { 116 } 117 118 TokenType next(); 119 120 const LiteralParserToken& currentToken() 121 { 122 return m_currentToken; 123 } 124 125 UString getErrorMessage() { return m_lexErrorMessage; } 126 127 private: 128 UString m_lexErrorMessage; 129 template <ParserMode mode> TokenType lex(LiteralParserToken&); 130 template <ParserMode mode, UChar terminator> ALWAYS_INLINE TokenType lexString(LiteralParserToken&); 131 ALWAYS_INLINE TokenType lexNumber(LiteralParserToken&); 132 LiteralParserToken m_currentToken; 133 UString m_string; 134 ParserMode m_mode; 135 const UChar* m_ptr; 136 const UChar* m_end; 137 }; 138 139 class StackGuard; 140 JSValue parse(ParserState); 141 142 ExecState* m_exec; 143 LiteralParser::Lexer m_lexer; 144 ParserMode m_mode; 145 UString m_parseErrorMessage; 146 static unsigned const MaximumCachableCharacter = 128; 147 FixedArray<Identifier, MaximumCachableCharacter> m_shortIdentifiers; 148 FixedArray<Identifier, MaximumCachableCharacter> m_recentIdentifiers; 149 ALWAYS_INLINE const Identifier makeIdentifier(const UChar* characters, size_t length); 154 ExecState* m_exec; 155 typename LiteralParser<CharType>::Lexer m_lexer; 156 ParserMode m_mode; 157 UString m_parseErrorMessage; 158 static unsigned const MaximumCachableCharacter = 128; 159 FixedArray<Identifier, MaximumCachableCharacter> m_shortIdentifiers; 160 FixedArray<Identifier, MaximumCachableCharacter> m_recentIdentifiers; 161 ALWAYS_INLINE const Identifier makeIdentifier(const LChar* characters, size_t length); 162 ALWAYS_INLINE const Identifier makeIdentifier(const UChar* characters, size_t length); 150 163 }; 151 164 -
trunk/Source/JavaScriptCore/runtime/UString.h
r98643 r99812 94 94 return m_impl->characters16(); 95 95 } 96 97 template <typename CharType> 98 inline const CharType* getCharacters() const; 96 99 97 100 bool is8Bit() const { return m_impl->is8Bit(); } … … 135 138 RefPtr<StringImpl> m_impl; 136 139 }; 140 141 template<> 142 inline const LChar* UString::getCharacters<LChar>() const 143 { 144 ASSERT(is8Bit()); 145 return characters8(); 146 } 147 148 template<> 149 inline const UChar* UString::getCharacters<UChar>() const 150 { 151 ASSERT(!is8Bit()); 152 return characters16(); 153 } 137 154 138 155 NEVER_INLINE bool equalSlowCase(const UString& s1, const UString& s2); -
trunk/Source/JavaScriptCore/wtf/text/StringBuilder.cpp
r97371 r99812 159 159 } 160 160 161 void StringBuilder::append(const char* characters, unsigned length)161 void StringBuilder::append(const LChar* characters, unsigned length) 162 162 { 163 163 if (!length) … … 166 166 167 167 UChar* dest = appendUninitialized(length); 168 const char* end = characters + length;168 const LChar* end = characters + length; 169 169 while (characters < end) 170 *(dest++) = *(c onst unsigned char*)(characters++);170 *(dest++) = *(characters++); 171 171 } 172 172 -
trunk/Source/JavaScriptCore/wtf/text/StringBuilder.h
r97371 r99812 40 40 41 41 void append(const UChar*, unsigned); 42 void append(const char*, unsigned); 42 void append(const LChar*, unsigned); 43 44 ALWAYS_INLINE void append(const char* characters, unsigned length) { append(reinterpret_cast<const LChar*>(characters), length); } 43 45 44 46 void append(const String& string)
Note: See TracChangeset
for help on using the changeset viewer.