Changeset 10867 in webkit
- Timestamp:
- Oct 17, 2005, 8:15:31 PM (20 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r10857 r10867 1 2005-10-17 Maciej Stachowiak <mjs@apple.com> 2 3 Reviewed by Geoff. Code changes by Darin. 4 5 - some micro-optimizations to FastMalloc to reduce math and branches. 6 7 * kxmlcore/FastMalloc.cpp: 8 (KXMLCore::TCMalloc_Central_FreeList::Populate): 9 (KXMLCore::fastMallocRegisterThread): 10 (KXMLCore::TCMalloc_ThreadCache::GetCache): 11 (KXMLCore::TCMalloc_ThreadCache::GetCacheIfPresent): 12 1 13 2005-10-15 Maciej Stachowiak <mjs@apple.com> 2 14 -
trunk/JavaScriptCore/kxmlcore/FastMalloc.cpp
r10703 r10867 1235 1235 const size_t size = ByteSizeForClass(size_class_); 1236 1236 int num = 0; 1237 while (ptr + size <= limit) { 1237 char* nptr; 1238 while ((nptr = ptr + size) <= limit) { 1238 1239 *tail = ptr; 1239 1240 tail = reinterpret_cast<void**>(ptr); 1240 ptr += size;1241 ptr = nptr; 1241 1242 num++; 1242 1243 } … … 1394 1395 // And other threads can't get it wrong because they must have gone through 1395 1396 // this function before allocating so they've synchronized. 1397 // Also, mainThreadCache is only set when isMultiThreaded is false, 1398 // to save a branchin some cases. 1396 1399 SpinLockHolder lock(&multiThreadedLock); 1397 1400 isMultiThreaded = true; 1398 } 1399 } 1400 1401 inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::GetCache() { 1401 mainThreadCache = 0; 1402 } 1403 } 1404 1405 ALWAYS_INLINE TCMalloc_ThreadCache* TCMalloc_ThreadCache::GetCache() { 1402 1406 void* ptr = NULL; 1403 1407 if (!tsd_inited) { 1404 1408 InitModule(); 1405 1409 } else { 1406 if ( !isMultiThreaded)1410 if (mainThreadCache) 1407 1411 ptr = mainThreadCache; 1408 1412 else … … 1417 1421 // already cleaned up the cache for this thread. 1418 1422 inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::GetCacheIfPresent() { 1419 if ( !isMultiThreaded)1423 if (mainThreadCache) 1420 1424 return mainThreadCache; 1421 1425 if (!tsd_inited) return NULL; -
trunk/WebCore/ChangeLog-2005-12-19
r10866 r10867 1 2005-10-17 Maciej Stachowiak <mjs@apple.com> 2 3 Reviewed by Geoff. 4 5 Speed up the tokenizer by keeping more state on the stack instead of in the object, 6 to avoid load-store traffic. About a .5% speedup. 7 8 * khtml/html/htmltokenizer.cpp: 9 (khtml::HTMLTokenizer::HTMLTokenizer): 10 (khtml::HTMLTokenizer::reset): 11 (khtml::HTMLTokenizer::begin): 12 (khtml::HTMLTokenizer::setForceSynchronous): 13 (khtml::HTMLTokenizer::processListing): 14 (khtml::HTMLTokenizer::parseSpecial): 15 (khtml::HTMLTokenizer::scriptHandler): 16 (khtml::HTMLTokenizer::scriptExecution): 17 (khtml::HTMLTokenizer::parseComment): 18 (khtml::HTMLTokenizer::parseServer): 19 (khtml::HTMLTokenizer::parseProcessingInstruction): 20 (khtml::HTMLTokenizer::parseText): 21 (khtml::HTMLTokenizer::parseEntity): 22 (khtml::HTMLTokenizer::parseTag): 23 (khtml::HTMLTokenizer::continueProcessing): 24 (khtml::HTMLTokenizer::write): 25 (khtml::HTMLTokenizer::allDataProcessed): 26 (khtml::HTMLTokenizer::end): 27 (khtml::HTMLTokenizer::finish): 28 (khtml::HTMLTokenizer::notifyFinished): 29 (khtml::HTMLTokenizer::isWaitingForScripts): 30 * khtml/html/htmltokenizer.h: 31 (khtml::HTMLTokenizer::): 32 (khtml::HTMLTokenizer::State::State): 33 (khtml::HTMLTokenizer::State::tagState): 34 (khtml::HTMLTokenizer::State::setTagState): 35 (khtml::HTMLTokenizer::State::entityState): 36 (khtml::HTMLTokenizer::State::setEntityState): 37 (khtml::HTMLTokenizer::State::inScript): 38 (khtml::HTMLTokenizer::State::setInScript): 39 (khtml::HTMLTokenizer::State::inStyle): 40 (khtml::HTMLTokenizer::State::setInStyle): 41 (khtml::HTMLTokenizer::State::inSelect): 42 (khtml::HTMLTokenizer::State::setInSelect): 43 (khtml::HTMLTokenizer::State::inXmp): 44 (khtml::HTMLTokenizer::State::setInXmp): 45 (khtml::HTMLTokenizer::State::inTitle): 46 (khtml::HTMLTokenizer::State::setInTitle): 47 (khtml::HTMLTokenizer::State::inPlainText): 48 (khtml::HTMLTokenizer::State::setInPlainText): 49 (khtml::HTMLTokenizer::State::inProcessingInstruction): 50 (khtml::HTMLTokenizer::State::setInProcessingInstruction): 51 (khtml::HTMLTokenizer::State::inComment): 52 (khtml::HTMLTokenizer::State::setInComment): 53 (khtml::HTMLTokenizer::State::inTextArea): 54 (khtml::HTMLTokenizer::State::setInTextArea): 55 (khtml::HTMLTokenizer::State::escaped): 56 (khtml::HTMLTokenizer::State::setEscaped): 57 (khtml::HTMLTokenizer::State::inServer): 58 (khtml::HTMLTokenizer::State::setInServer): 59 (khtml::HTMLTokenizer::State::skipLF): 60 (khtml::HTMLTokenizer::State::setSkipLF): 61 (khtml::HTMLTokenizer::State::startTag): 62 (khtml::HTMLTokenizer::State::setStartTag): 63 (khtml::HTMLTokenizer::State::discardLF): 64 (khtml::HTMLTokenizer::State::setDiscardLF): 65 (khtml::HTMLTokenizer::State::allowYield): 66 (khtml::HTMLTokenizer::State::setAllowYield): 67 (khtml::HTMLTokenizer::State::loadingExtScript): 68 (khtml::HTMLTokenizer::State::setLoadingExtScript): 69 (khtml::HTMLTokenizer::State::forceSynchronous): 70 (khtml::HTMLTokenizer::State::setForceSynchronous): 71 (khtml::HTMLTokenizer::State::inAnySpecial): 72 (khtml::HTMLTokenizer::State::hasTagState): 73 (khtml::HTMLTokenizer::State::hasEntityState): 74 (khtml::HTMLTokenizer::State::): 75 (khtml::HTMLTokenizer::State::setBit): 76 (khtml::HTMLTokenizer::State::testBit): 77 * khtml/rendering/bidi.cpp: 78 (khtml::RenderBlock::checkLinesForTextOverflow): 79 * khtml/rendering/render_block.cpp: 80 (khtml::RenderBlock::updateFirstLetter): 81 * khtml/rendering/render_flow.cpp: 82 (RenderFlow::caretRect): 83 * khtml/rendering/render_line.cpp: 84 (khtml::EllipsisBox::paint): 85 * khtml/rendering/render_object.cpp: 86 (RenderObject::firstLineStyle): 87 * khtml/rendering/render_object.h: 88 (khtml::RenderObject::style): 89 1 90 2005-10-17 Maciej Stachowiak <mjs@apple.com> 2 91 -
trunk/WebCore/khtml/html/htmltokenizer.cpp
r10854 r10867 173 173 parser = new HTMLParser(_view, _doc, includesComments); 174 174 m_executingScript = 0; 175 loadingExtScript = false;176 175 onHold = false; 177 176 timerId = 0; … … 192 191 parser = new HTMLParser(i, _doc, includesComments); 193 192 m_executingScript = 0; 194 loadingExtScript = false;195 193 onHold = false; 196 194 timerId = 0; … … 212 210 } 213 211 214 if ( buffer)212 if (buffer) 215 213 KHTML_DELETE_QCHAR_VEC(buffer); 216 214 buffer = dest = 0; 217 215 size = 0; 218 216 219 if ( scriptCode)217 if (scriptCode) 220 218 KHTML_DELETE_QCHAR_VEC(scriptCode); 221 219 scriptCode = 0; … … 227 225 } 228 226 timerId = 0; 229 allowYield = false;230 forceSynchronous = false;227 m_state.setAllowYield(false); 228 m_state.setForceSynchronous(false); 231 229 232 230 currToken.reset(); … … 236 234 { 237 235 m_executingScript = 0; 238 loadingExtScript = false;236 m_state.setLoadingExtScript(false); 239 237 onHold = false; 240 238 reset(); … … 242 240 buffer = KHTML_ALLOC_QCHAR_VEC( 255 ); 243 241 dest = buffer; 244 tag = NoTag;245 discard = NoneDiscard;246 plaintext = false;247 xmp = false;248 processingInstruction = false;249 script = false;250 escaped = false;251 style = false;252 skipLF = false;253 select = false;254 comment = false;255 server = false;256 textarea = false;257 title = false;258 startTag = false;259 242 tquote = NoQuote; 260 243 searchCount = 0; 261 Entity = NoEntity; 262 loadingExtScript = false; 244 m_state.setEntityState(NoEntity); 263 245 scriptSrc = QString::null; 264 246 pendingSrc.clear(); … … 270 252 scriptStartLineno = 0; 271 253 tagStartLineno = 0; 272 forceSynchronous = false;254 m_state.setForceSynchronous(false); 273 255 } 274 256 275 257 void HTMLTokenizer::setForceSynchronous(bool force) 276 258 { 277 forceSynchronous = force;278 } 279 280 void HTMLTokenizer::processListing(TokenizerString list)259 m_state.setForceSynchronous(force); 260 } 261 262 HTMLTokenizer::State HTMLTokenizer::processListing(TokenizerString list, State state) 281 263 { 282 264 // This function adds the listing 'list' as … … 285 267 checkBuffer(); 286 268 287 if (s kipLF&& *list != '\n')288 s kipLF = false;289 290 if (s kipLF) {291 s kipLF = false;269 if (state.skipLF() && *list != '\n') 270 state.setSkipLF(false); 271 272 if (state.skipLF()) { 273 state.setSkipLF(false); 292 274 ++list; 293 275 } else if (*list == '\n' || *list == '\r') { 294 if ( discard == LFDiscard)276 if (state.discardLF()) 295 277 // Ignore this LF 296 discard = NoneDiscard; // We have discarded 1 LF278 state.setDiscardLF(false); // We have discarded 1 LF 297 279 else 298 280 *dest++ = '\n'; … … 300 282 /* Check for MS-DOS CRLF sequence */ 301 283 if (*list == '\r') 302 s kipLF = true;284 state.setSkipLF(true); 303 285 304 286 ++list; 305 287 } else { 306 discard = NoneDiscard;288 state.setDiscardLF(false); 307 289 *dest++ = *list; 308 290 ++list; 309 291 } 310 292 } 311 } 312 313 void HTMLTokenizer::parseSpecial(TokenizerString &src) 314 { 315 assert( textarea || title || !Entity ); 316 assert( !tag ); 317 assert( xmp+textarea+title+style+script == 1 ); 318 if (script) 319 scriptStartLineno = lineno+src.lineCount(); 320 321 if ( comment ) parseComment( src ); 293 294 return state; 295 } 296 297 HTMLTokenizer::State HTMLTokenizer::parseSpecial(TokenizerString &src, State state) 298 { 299 assert(state.inTextArea() || state.inTitle() || !state.hasEntityState()); 300 assert(!state.hasTagState()); 301 assert(state.inXmp() + state.inTextArea() + state.inTitle() + state.inStyle() + state.inScript() == 1 ); 302 if (state.inScript()) 303 scriptStartLineno = lineno + src.lineCount(); 304 305 if (state.inComment()) 306 state = parseComment(src, state); 322 307 323 308 while ( !src.isEmpty() ) { 324 309 checkScriptBuffer(); 325 310 unsigned char ch = src->latin1(); 326 if ( !scriptCodeResync && !brokenComments && !textarea && !xmp && !title && ch == '-' && scriptCodeSize >= 3 && !src.escaped() && scriptCode[scriptCodeSize-3] == '<' && scriptCode[scriptCodeSize-2] == '!' && scriptCode[scriptCodeSize-1] == '-') {327 comment = true;328 parseComment( src);311 if (!scriptCodeResync && !brokenComments && !state.inTextArea() && !state.inXmp() && !state.inTitle() && ch == '-' && scriptCodeSize >= 3 && !src.escaped() && scriptCode[scriptCodeSize-3] == '<' && scriptCode[scriptCodeSize-2] == '!' && scriptCode[scriptCodeSize-1] == '-') { 312 state.setInComment(true); 313 state = parseComment(src, state); 329 314 continue; 330 315 } … … 334 319 scriptCodeResync = 0; 335 320 scriptCode[ scriptCodeSize ] = scriptCode[ scriptCodeSize + 1 ] = 0; 336 if ( script)337 s criptHandler();321 if (state.inScript()) 322 state = scriptHandler(state); 338 323 else { 339 processListing(TokenizerString(scriptCode, scriptCodeSize));324 state = processListing(TokenizerString(scriptCode, scriptCodeSize), state); 340 325 processToken(); 341 if ( style ) { currToken.tagName = styleTag.localName(); currToken.beginTag = false; } 342 else if ( textarea ) { currToken.tagName = textareaTag.localName(); currToken.beginTag = false; } 343 else if ( title ) { currToken.tagName = titleTag.localName(); currToken.beginTag = false; } 344 else if ( xmp ) { currToken.tagName = xmpTag.localName(); currToken.beginTag = false; } 326 if (state.inStyle()) { 327 currToken.tagName = styleTag.localName(); 328 currToken.beginTag = false; 329 } else if (state.inTextArea()) { 330 currToken.tagName = textareaTag.localName(); 331 currToken.beginTag = false; 332 } else if (state.inTitle()) { 333 currToken.tagName = titleTag.localName(); 334 currToken.beginTag = false; 335 } else if (state.inXmp()) { 336 currToken.tagName = xmpTag.localName(); 337 currToken.beginTag = false; 338 } 345 339 processToken(); 346 style = script = style = textarea = title = xmp = false; 340 state.setInStyle(false); 341 state.setInScript(false); 342 state.setInTextArea(false); 343 state.setInTitle(false); 344 state.setInXmp(false); 347 345 tquote = NoQuote; 348 346 scriptCodeSize = scriptCodeResync = 0; 349 347 } 350 return ;348 return state; 351 349 } 352 350 // possible end of tagname, lets check. 353 if ( !scriptCodeResync && ! escaped&& !src.escaped() && ( ch == '>' || ch == '/' || ch <= ' ' ) && ch &&351 if ( !scriptCodeResync && !state.escaped() && !src.escaped() && ( ch == '>' || ch == '/' || ch <= ' ' ) && ch && 354 352 scriptCodeSize >= searchStopperLen && 355 353 tagMatch( searchStopper, scriptCode+scriptCodeSize-searchStopperLen, searchStopperLen )) { … … 358 356 continue; 359 357 } 360 if ( scriptCodeResync && ! escaped) {358 if ( scriptCodeResync && !state.escaped() ) { 361 359 if(ch == '\"') 362 360 tquote = (tquote == NoQuote) ? DoubleQuote : ((tquote == SingleQuote) ? SingleQuote : NoQuote); … … 366 364 tquote = NoQuote; 367 365 } 368 escaped = ( !escaped && ch == '\\');369 if (!scriptCodeResync && ( textarea||title) && !src.escaped() && ch == '&') {366 state.setEscaped(!state.escaped() && ch == '\\'); 367 if (!scriptCodeResync && (state.inTextArea() || state.inTitle()) && !src.escaped() && ch == '&') { 370 368 QChar *scriptCodeDest = scriptCode+scriptCodeSize; 371 369 ++src; 372 parseEntity(src,scriptCodeDest,true);370 state = parseEntity(src, scriptCodeDest, state, m_cBufferPos, true, false); 373 371 scriptCodeSize = scriptCodeDest-scriptCode; 374 372 } … … 379 377 } 380 378 } 381 } 382 383 void HTMLTokenizer::scriptHandler() 379 380 return state; 381 } 382 383 HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state) 384 384 { 385 385 // We are inside a <script> … … 413 413 doScriptExec = true; 414 414 } 415 processListing(TokenizerString(scriptCode, scriptCodeSize));415 state = processListing(TokenizerString(scriptCode, scriptCodeSize), state); 416 416 QString exScript( buffer, dest-buffer ); 417 417 processToken(); … … 435 435 setSrc(TokenizerString()); 436 436 scriptCodeSize = scriptCodeResync = 0; 437 438 // the ref() call below may call notifyFinished if the script is already in cache, 439 // and that mucks with the state directly, so we must write it back to the object. 440 m_state = state; 437 441 cs->ref(this); 442 state = m_state; 438 443 // will be 0 if script was already loaded and ref() executed it 439 444 if (!pendingScripts.isEmpty()) 440 loadingExtScript = true;445 state.setLoadingExtScript(true); 441 446 } 442 447 else if (view && doScriptExec && javascript ) { … … 449 454 //QTime dt; 450 455 //dt.start(); 451 s criptExecution( exScript, QString::null, scriptStartLineno);456 state = scriptExecution(exScript, state, QString::null, scriptStartLineno); 452 457 //kdDebug( 6036 ) << "script execution time:" << dt.elapsed() << endl; 453 458 } 454 459 } 455 460 456 s cript = false;461 state.setInScript(false); 457 462 scriptCodeSize = scriptCodeResync = 0; 458 463 459 if ( !m_executingScript && !loadingExtScript) {464 if (!m_executingScript && !state.loadingExtScript()) { 460 465 // kdDebug( 6036 ) << "adding pending Output to parsed string" << endl; 461 466 src.append(pendingSrc); … … 469 474 // because we want to prepend to pendingSrc rather than appending 470 475 // if there's no previous prependingSrc 471 if ( loadingExtScript) {476 if (state.loadingExtScript()) { 472 477 if (currentPrependingSrc) { 473 478 currentPrependingSrc->append(prependingSrc); … … 476 481 } 477 482 } else { 483 m_state = state; 478 484 write(prependingSrc, false); 485 state = m_state; 479 486 } 480 487 } 481 488 482 489 currentPrependingSrc = savedPrependingSrc; 483 } 484 485 void HTMLTokenizer::scriptExecution( const QString& str, QString scriptURL, 486 int baseLine) 490 491 return state; 492 } 493 494 HTMLTokenizer::State HTMLTokenizer::scriptExecution(const QString& str, State state, 495 QString scriptURL, int baseLine) 487 496 { 488 497 #if APPLE_CHANGES 489 498 if (!view || !view->part()) 490 return ;491 #endif 492 bool oldscript = s cript;499 return state; 500 #endif 501 bool oldscript = state.inScript(); 493 502 m_executingScript++; 494 s cript = false;503 state.setInScript(false); 495 504 QString url; 496 505 if (scriptURL.isNull()) … … 508 517 #endif 509 518 519 m_state = state; 510 520 view->part()->executeScript(url,baseLine,0,str); 511 512 allowYield = true; 521 state = m_state; 522 523 state.setAllowYield(true); 513 524 514 525 #ifdef INSTRUMENT_LAYOUT_SCHEDULING … … 518 529 519 530 m_executingScript--; 520 s cript = oldscript;521 522 if ( !m_executingScript && !loadingExtScript) {531 state.setInScript(oldscript); 532 533 if (!m_executingScript && !state.loadingExtScript()) { 523 534 // kdDebug( 6036 ) << "adding pending Output to parsed string" << endl; 524 535 src.append(pendingSrc); … … 532 543 // because we want to prepend to pendingSrc rather than appending 533 544 // if there's no previous prependingSrc 534 if ( loadingExtScript) {545 if (state.loadingExtScript()) { 535 546 if (currentPrependingSrc) { 536 547 currentPrependingSrc->append(prependingSrc); … … 539 550 } 540 551 } else { 552 m_state = state; 541 553 write(prependingSrc, false); 554 state = m_state; 542 555 } 543 556 } 544 557 545 558 currentPrependingSrc = savedPrependingSrc; 546 } 547 548 void HTMLTokenizer::parseComment(TokenizerString &src) 559 560 return state; 561 } 562 563 HTMLTokenizer::State HTMLTokenizer::parseComment(TokenizerString &src, State state) 549 564 { 550 565 // FIXME: Why does this code even run for comments inside <script> and <style>? This seems bogus. 551 bool strict = !parser->doc()->inCompatMode() && !s cript && !style;566 bool strict = !parser->doc()->inCompatMode() && !state.inScript() && !state.inStyle(); 552 567 int delimiterCount = 0; 553 568 bool canClose = false; … … 573 588 574 589 if ((!strict || canClose) && src->unicode() == '>') { 575 bool handleBrokenComments = brokenComments && !(s cript || style);590 bool handleBrokenComments = brokenComments && !(state.inScript() || state.inStyle()); 576 591 int endCharsCount = 1; // start off with one for the '>' character 577 592 if (!strict) { … … 589 604 if (canClose || handleBrokenComments || endCharsCount > 1) { 590 605 ++src; 591 if (!( script || xmp || textarea || style)) {606 if (!(state.inScript() || state.inXmp() || state.inTextArea() || state.inStyle())) { 592 607 if (includesCommentsInDOM) { 593 608 checkScriptBuffer(); … … 596 611 currToken.tagName = commentAtom; 597 612 currToken.beginTag = true; 598 processListing(TokenizerString(scriptCode, scriptCodeSize - endCharsCount));613 state = processListing(TokenizerString(scriptCode, scriptCodeSize - endCharsCount), state); 599 614 processToken(); 600 615 currToken.tagName = commentAtom; … … 604 619 scriptCodeSize = 0; 605 620 } 606 comment = false;607 return ; // Finished parsing comment621 state.setInComment(false); 622 return state; // Finished parsing comment 608 623 } 609 624 } 610 625 ++src; 611 626 } 612 } 613 614 void HTMLTokenizer::parseServer(TokenizerString &src) 627 628 return state; 629 } 630 631 HTMLTokenizer::State HTMLTokenizer::parseServer(TokenizerString& src, State state) 615 632 { 616 633 checkScriptBuffer(src.length()); 617 while ( !src.isEmpty()) {618 scriptCode[ scriptCodeSize++] = *src;634 while (!src.isEmpty()) { 635 scriptCode[scriptCodeSize++] = *src; 619 636 if (src->unicode() == '>' && 620 637 scriptCodeSize > 1 && scriptCode[scriptCodeSize-2] == '%') { 621 638 ++src; 622 s erver = false;639 state.setInServer(false); 623 640 scriptCodeSize = 0; 624 return ; // Finished parsing server include641 return state; // Finished parsing server include 625 642 } 626 643 ++src; 627 644 } 628 } 629 630 void HTMLTokenizer::parseProcessingInstruction(TokenizerString &src) 645 return state; 646 } 647 648 HTMLTokenizer::State HTMLTokenizer::parseProcessingInstruction(TokenizerString &src, State state) 631 649 { 632 650 char oldchar = 0; … … 646 664 { 647 665 // We got a '?>' sequence 648 processingInstruction = false;666 state.setInProcessingInstruction(false); 649 667 ++src; 650 discard = LFDiscard;651 return ; // Finished parsing comment!668 state.setDiscardLF(true); 669 return state; // Finished parsing comment! 652 670 } 653 671 ++src; 654 672 oldchar = chbegin; 655 673 } 656 } 657 658 void HTMLTokenizer::parseText(TokenizerString &src) 659 { 660 while ( !src.isEmpty() ) 674 675 return state; 676 } 677 678 HTMLTokenizer::State HTMLTokenizer::parseText(TokenizerString &src, State state) 679 { 680 while (!src.isEmpty()) 661 681 { 662 682 // do we need to enlarge the buffer? … … 666 686 unsigned char chbegin = src->latin1(); 667 687 668 if (skipLF && ( chbegin != '\n' )) 688 if (state.skipLF() && (chbegin != '\n' )) 689 state.setSkipLF(false); 690 691 if (state.skipLF()) 669 692 { 670 skipLF = false; 671 } 672 673 if (skipLF) 674 { 675 skipLF = false; 693 state.setSkipLF(false); 676 694 ++src; 677 } 678 else if (( chbegin == '\n' ) || ( chbegin == '\r' )) 695 } else if ((chbegin == '\n') || (chbegin == '\r')) 679 696 { 680 697 if (chbegin == '\r') 681 s kipLF = true;698 state.setSkipLF(true); 682 699 683 700 *dest++ = '\n'; … … 691 708 } 692 709 } 693 } 694 695 696 void HTMLTokenizer::parseEntity(TokenizerString &src, QChar *&dest, bool start) 697 { 698 if( start ) 710 711 return state; 712 } 713 714 715 HTMLTokenizer::State HTMLTokenizer::parseEntity(TokenizerString &src, QChar *&dest, State state, unsigned &cBufferPos, bool start, bool parsingTag) 716 { 717 if (start) 699 718 { 700 719 cBufferPos = 0; 701 Entity = SearchEntity;720 state.setEntityState(SearchEntity); 702 721 EntityUnicodeValue = 0; 703 722 } 704 723 705 while( !src.isEmpty())724 while(!src.isEmpty()) 706 725 { 707 726 ushort cc = src->unicode(); 708 switch( Entity) {727 switch(state.entityState()) { 709 728 case NoEntity: 710 assert( Entity!= NoEntity);711 return ;729 assert(state.entityState() != NoEntity); 730 return state; 712 731 713 732 case SearchEntity: … … 715 734 cBuffer[cBufferPos++] = cc; 716 735 ++src; 717 Entity = NumericSearch;736 state.setEntityState(NumericSearch); 718 737 } 719 738 else 720 Entity = EntityName;739 state.setEntityState(EntityName); 721 740 722 741 break; … … 726 745 cBuffer[cBufferPos++] = cc; 727 746 ++src; 728 Entity = Hexadecimal;747 state.setEntityState(Hexadecimal); 729 748 } 730 749 else if(cc >= '0' && cc <= '9') 731 Entity = Decimal;750 state.setEntityState(Decimal); 732 751 else 733 Entity = SearchSemicolon;752 state.setEntityState(SearchSemicolon); 734 753 735 754 break; … … 743 762 744 763 if(csrc.row() || !((cc >= '0' && cc <= '9') || (cc >= 'a' && cc <= 'f'))) { 745 Entity = SearchSemicolon;764 state.setEntityState(SearchSemicolon); 746 765 break; 747 766 } … … 750 769 ++src; 751 770 } 752 if(cBufferPos == 10) Entity = SearchSemicolon; 771 if (cBufferPos == 10) 772 state.setEntityState(SearchSemicolon); 753 773 break; 754 774 } … … 760 780 761 781 if(src->row() || !(cc >= '0' && cc <= '9')) { 762 Entity = SearchSemicolon;782 state.setEntityState(SearchSemicolon); 763 783 break; 764 784 } … … 768 788 ++src; 769 789 } 770 if(cBufferPos == 9) Entity = SearchSemicolon; 790 if (cBufferPos == 9) 791 state.setEntityState(SearchSemicolon); 771 792 break; 772 793 } … … 780 801 if(csrc.row() || !((cc >= 'a' && cc <= 'z') || 781 802 (cc >= '0' && cc <= '9') || (cc >= 'A' && cc <= 'Z'))) { 782 Entity = SearchSemicolon;803 state.setEntityState(SearchSemicolon); 783 804 break; 784 805 } … … 787 808 ++src; 788 809 } 789 if(cBufferPos == 9) Entity = SearchSemicolon; 790 if(Entity == SearchSemicolon) { 810 if (cBufferPos == 9) 811 state.setEntityState(SearchSemicolon); 812 if (state.entityState() == SearchSemicolon) { 791 813 if(cBufferPos > 1) { 792 814 const entity *e = findEntity(cBuffer, cBufferPos); … … 795 817 796 818 // be IE compatible 797 if( tag && EntityUnicodeValue > 255 && *src != ';')819 if(parsingTag && EntityUnicodeValue > 255 && *src != ';') 798 820 EntityUnicodeValue = 0; 799 821 } … … 839 861 } 840 862 841 Entity = NoEntity; 842 return; 843 } 844 } 845 } 846 847 void HTMLTokenizer::parseTag(TokenizerString &src) 848 { 849 assert(!Entity ); 850 851 while ( !src.isEmpty() ) 863 state.setEntityState(NoEntity); 864 return state; 865 } 866 } 867 868 return state; 869 } 870 871 HTMLTokenizer::State HTMLTokenizer::parseTag(TokenizerString &src, State state) 872 { 873 assert(!state.hasEntityState()); 874 875 unsigned cBufferPos = m_cBufferPos; 876 877 while (!src.isEmpty()) 852 878 { 853 879 checkBuffer(); … … 859 885 QConstString((QChar*)src.operator->(), l).qstring().latin1(), tquote); 860 886 #endif 861 switch( tag) {887 switch(state.tagState()) { 862 888 case NoTag: 863 889 { 864 return; 890 m_cBufferPos = cBufferPos; 891 return state; 865 892 } 866 893 case TagName: … … 882 909 ++src; 883 910 dest = buffer; // ignore the previous part of this tag 884 comment = true;885 tag = NoTag;911 state.setInComment(true); 912 state.setTagState(NoTag); 886 913 887 914 // Fix bug 34302 at kde.bugs.org. Go ahead and treat … … 889 916 // can handle this case. Only do this in quirks mode. -dwh 890 917 if (!src.isEmpty() && *src == '>' && parser->doc()->inCompatMode()) { 891 comment = false;918 state.setInComment(false); 892 919 ++src; 893 920 if (!src.isEmpty()) … … 895 922 } 896 923 else 897 parseComment(src); 898 899 return; // Finished parsing tag! 924 state = parseComment(src, state); 925 926 m_cBufferPos = cBufferPos; 927 return state; // Finished parsing tag! 900 928 } 901 929 // cuts of high part, is okay … … 953 981 } 954 982 dest = buffer; 955 tag = SearchAttribute;983 state.setTagState(SearchAttribute); 956 984 cBufferPos = 0; 957 985 } … … 970 998 if (curchar > ' ' && curchar != '\'' && curchar != '"') { 971 999 if (curchar == '<' || curchar == '>') 972 tag = SearchEnd;1000 state.setTagState(SearchEnd); 973 1001 else 974 tag = AttributeName;1002 state.setTagState(AttributeName); 975 1003 976 1004 cBufferPos = 0; … … 997 1025 dest = buffer; 998 1026 *dest++ = 0; 999 tag = SearchEqual;1027 state.setTagState(SearchEqual); 1000 1028 // This is a deliberate quirk to match Mozilla and Opera. We have to do this 1001 1029 // since sites that use the "standards-compliant" path sometimes send … … 1020 1048 dest = buffer; 1021 1049 *dest++ = 0; 1022 tag = SearchEqual;1050 state.setTagState(SearchEqual); 1023 1051 } 1024 1052 break; … … 1039 1067 kdDebug(6036) << "found equal" << endl; 1040 1068 #endif 1041 tag = SearchValue;1069 state.setTagState(SearchValue); 1042 1070 ++src; 1043 1071 } … … 1045 1073 currToken.addAttribute(parser->docPtr()->document(), attrName, emptyAtom); 1046 1074 dest = buffer; 1047 tag = SearchAttribute;1075 state.setTagState(SearchAttribute); 1048 1076 } 1049 1077 break; … … 1062 1090 if(( curchar == '\'' || curchar == '\"' )) { 1063 1091 tquote = curchar == '\"' ? DoubleQuote : SingleQuote; 1064 tag = QuotedValue;1092 state.setTagState(QuotedValue); 1065 1093 ++src; 1066 1094 } else 1067 tag = Value;1095 state.setTagState(Value); 1068 1096 1069 1097 break; … … 1096 1124 attrName = v; // Just make the name/value match. (FIXME: Is this some WinIE quirk?) 1097 1125 currToken.addAttribute(parser->docPtr()->document(), attrName, v); 1098 tag = SearchAttribute;1126 state.setTagState(SearchAttribute); 1099 1127 dest = buffer; 1100 1128 tquote = NoQuote; … … 1107 1135 { 1108 1136 ++src; 1109 parseEntity(src, dest, true);1137 state = parseEntity(src, dest, state, cBufferPos, true, true); 1110 1138 break; 1111 1139 } … … 1122 1150 1123 1151 dest = buffer; 1124 tag = SearchAttribute;1152 state.setTagState(SearchAttribute); 1125 1153 tquote = NoQuote; 1126 1154 ++src; … … 1149 1177 { 1150 1178 ++src; 1151 parseEntity(src, dest, true);1179 state = parseEntity(src, dest, state, cBufferPos, true, true); 1152 1180 break; 1153 1181 } … … 1159 1187 currToken.addAttribute(parser->docPtr()->document(), attrName, v); 1160 1188 dest = buffer; 1161 tag = SearchAttribute;1189 state.setTagState(SearchAttribute); 1162 1190 break; 1163 1191 } … … 1188 1216 1189 1217 searchCount = 0; // Stop looking for '<!--' sequence 1190 tag = NoTag;1218 state.setTagState(NoTag); 1191 1219 tquote = NoQuote; 1192 1220 … … 1194 1222 ++src; 1195 1223 1196 if (currToken.tagName == nullAtom) //stop if tag is unknown 1197 return; 1224 if (currToken.tagName == nullAtom) { //stop if tag is unknown 1225 m_cBufferPos = cBufferPos; 1226 return state; 1227 } 1198 1228 1199 1229 AtomicString tagName = currToken.tagName; … … 1282 1312 1283 1313 if (tagName == preTag) { 1284 discard = LFDiscard; // Discard the first LF after we open a pre.1314 state.setDiscardLF(true); // Discard the first LF after we open a pre. 1285 1315 } else if (tagName == scriptTag) { 1286 1316 if (beginTag) { 1287 1317 searchStopper = scriptEnd; 1288 1318 searchStopperLen = 8; 1289 s cript = true;1290 parseSpecial(src);1319 state.setInScript(true); 1320 state = parseSpecial(src, state); 1291 1321 } else if (isSelfClosingScript) { // Handle <script src="foo"/> 1292 s cript = true;1293 s criptHandler();1322 state.setInScript(true); 1323 state = scriptHandler(state); 1294 1324 } 1295 1325 } else if (tagName == styleTag) { … … 1297 1327 searchStopper = styleEnd; 1298 1328 searchStopperLen = 7; 1299 st yle = true;1300 parseSpecial(src);1329 state.setInStyle(true); 1330 state = parseSpecial(src, state); 1301 1331 } 1302 1332 } else if (tagName == textareaTag) { … … 1304 1334 searchStopper = textareaEnd; 1305 1335 searchStopperLen = 10; 1306 textarea = true;1307 parseSpecial(src);1336 state.setInTextArea(true); 1337 state = parseSpecial(src, state); 1308 1338 } 1309 1339 } else if (tagName == titleTag) { … … 1311 1341 searchStopper = titleEnd; 1312 1342 searchStopperLen = 7; 1313 title = true;1314 parseSpecial(src);1343 state.setInTitle(true); 1344 state = parseSpecial(src, state); 1315 1345 } 1316 1346 } else if (tagName == xmpTag) { … … 1318 1348 searchStopper = xmpEnd; 1319 1349 searchStopperLen = 5; 1320 xmp = true;1321 parseSpecial(src);1350 state.setInXmp(true); 1351 state = parseSpecial(src, state); 1322 1352 } 1323 1353 } else if (tagName == selectTag) 1324 s elect = beginTag;1354 state.setInSelect(beginTag); 1325 1355 else if (tagName == plaintextTag) 1326 plaintext = beginTag; 1327 return; // Finished parsing tag! 1356 state.setInPlainText(beginTag); 1357 m_cBufferPos = cBufferPos; 1358 return state; // Finished parsing tag! 1328 1359 } 1329 1360 } // end switch 1330 1361 } 1331 return; 1332 } 1333 1334 void HTMLTokenizer::write(const TokenizerString &str, bool appendData) 1335 { 1336 #ifdef TOKEN_DEBUG 1337 kdDebug( 6036 ) << this << " Tokenizer::write(\"" << str.toString() << "\"," << appendData << ")" << endl; 1338 #endif 1339 1340 if (!buffer) 1341 return; 1342 1343 if (loadStopped) 1344 return; 1345 1346 if ( ( m_executingScript && appendData ) || !pendingScripts.isEmpty() ) { 1347 // don't parse; we will do this later 1348 if (currentPrependingSrc) { 1349 currentPrependingSrc->append(str); 1350 } else { 1351 pendingSrc.append(str); 1352 } 1353 return; 1354 } 1355 1356 if ( onHold ) { 1357 src.append(str); 1358 return; 1359 } 1360 1361 if (!src.isEmpty()) 1362 src.append(str); 1363 else 1364 setSrc(str); 1365 1366 // Once a timer is set, it has control of when the tokenizer continues. 1367 if (timerId) 1368 return; 1369 1370 bool wasInWrite = inWrite; 1371 inWrite = true; 1372 1373 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1374 if (!parser->doc()->ownerElement()) 1375 printf("Beginning write at time %d\n", parser->doc()->elapsedTime()); 1376 #endif 1377 1378 // if (Entity) 1379 // parseEntity(src, dest); 1380 1381 int processedCount = 0; 1382 QTime startTime; 1383 startTime.start(); 1384 KWQUIEventTime eventTime; 1385 1386 KHTMLPart* part = parser->doc()->part(); 1387 while (!src.isEmpty() && (!part || !part->isScheduledLocationChangePending())) { 1388 if (!continueProcessing(processedCount, startTime, eventTime)) 1389 break; 1390 1391 // do we need to enlarge the buffer? 1392 checkBuffer(); 1393 1394 ushort cc = src->unicode(); 1395 1396 if (skipLF && (cc != '\n')) 1397 skipLF = false; 1398 1399 if (skipLF) { 1400 skipLF = false; 1401 ++src; 1402 } 1403 else if ( Entity ) 1404 parseEntity( src, dest ); 1405 else if ( plaintext ) 1406 parseText( src ); 1407 else if (script) 1408 parseSpecial(src); 1409 else if (style) 1410 parseSpecial(src); 1411 else if (xmp) 1412 parseSpecial(src); 1413 else if (textarea) 1414 parseSpecial(src); 1415 else if (title) 1416 parseSpecial(src); 1417 else if (comment) 1418 parseComment(src); 1419 else if (server) 1420 parseServer(src); 1421 else if (processingInstruction) 1422 parseProcessingInstruction(src); 1423 else if (tag) 1424 parseTag(src); 1425 else if ( startTag ) 1426 { 1427 startTag = false; 1428 1429 switch(cc) { 1430 case '/': 1431 break; 1432 case '!': 1433 { 1434 // <!-- comment --> 1435 searchCount = 1; // Look for '<!--' sequence to start comment 1436 1437 break; 1438 } 1439 case '?': 1440 { 1441 // xml processing instruction 1442 processingInstruction = true; 1443 tquote = NoQuote; 1444 parseProcessingInstruction(src); 1445 continue; 1446 1447 break; 1448 } 1449 case '%': 1450 if (!brokenServer) { 1451 // <% server stuff, handle as comment %> 1452 server = true; 1453 tquote = NoQuote; 1454 parseServer(src); 1455 continue; 1456 } 1457 // else fall through 1458 default: 1459 { 1460 if( ((cc >= 'a') && (cc <= 'z')) || ((cc >= 'A') && (cc <= 'Z'))) 1461 { 1462 // Start of a Start-Tag 1463 } 1464 else 1465 { 1466 // Invalid tag 1467 // Add as is 1468 *dest = '<'; 1469 dest++; 1470 continue; 1471 } 1472 } 1473 }; // end case 1474 1475 processToken(); 1476 1477 cBufferPos = 0; 1478 tag = TagName; 1479 parseTag(src); 1480 } 1481 else if ( cc == '&' && !src.escaped()) 1482 { 1483 ++src; 1484 parseEntity(src, dest, true); 1485 } 1486 else if ( cc == '<' && !src.escaped()) 1487 { 1488 tagStartLineno = lineno+src.lineCount(); 1489 ++src; 1490 startTag = true; 1491 } 1492 else if (cc == '\n' || cc == '\r') { 1493 if (discard == LFDiscard) 1494 // Ignore this LF 1495 discard = NoneDiscard; // We have discarded 1 LF 1496 else 1497 // Process this LF 1498 *dest++ = '\n'; 1499 1500 /* Check for MS-DOS CRLF sequence */ 1501 if (cc == '\r') 1502 skipLF = true; 1503 ++src; 1504 } else { 1505 discard = NoneDiscard; 1506 #if QT_VERSION < 300 1507 unsigned char row = src->row(); 1508 if ( row > 0x05 && row < 0x10 || row > 0xfd ) 1509 currToken.complexText = true; 1510 #endif 1511 *dest = *src; 1512 fixUpChar(*dest); 1513 ++dest; 1514 ++src; 1515 } 1516 } 1517 1518 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1519 if (!parser->doc()->ownerElement()) 1520 printf("Ending write at time %d\n", parser->doc()->elapsedTime()); 1521 #endif 1522 1523 inWrite = wasInWrite; 1524 1525 if (noMoreData && !inWrite && !loadingExtScript && !m_executingScript && !timerId) 1526 end(); // this actually causes us to be deleted 1527 } 1528 1529 void HTMLTokenizer::stopped() 1530 { 1531 if (timerId) { 1532 killTimer(timerId); 1533 timerId = 0; 1534 } 1535 } 1536 1537 bool HTMLTokenizer::processingData() const 1538 { 1539 return timerId != 0; 1540 } 1541 1542 bool HTMLTokenizer::continueProcessing(int& processedCount, const QTime& startTime, const KWQUIEventTime& eventTime) 1362 m_cBufferPos = cBufferPos; 1363 return state; 1364 } 1365 1366 inline bool HTMLTokenizer::continueProcessing(int& processedCount, const QTime& startTime, const KWQUIEventTime& eventTime, State &state) 1543 1367 { 1544 1368 // We don't want to be checking elapsed time with every character, so we only check after we've 1545 1369 // processed a certain number of characters. 1546 bool allowedYield = allowYield;1547 allowYield = false;1548 if (! loadingExtScript && !forceSynchronous&& !m_executingScript && (processedCount > TOKENIZER_CHUNK_SIZE || allowedYield)) {1370 bool allowedYield = state.allowYield(); 1371 state.setAllowYield(false); 1372 if (!state.loadingExtScript() && !state.forceSynchronous() && !m_executingScript && (processedCount > TOKENIZER_CHUNK_SIZE || allowedYield)) { 1549 1373 processedCount = 0; 1550 1374 if (startTime.elapsed() > TOKENIZER_TIME_DELAY) { … … 1571 1395 } 1572 1396 1397 void HTMLTokenizer::write(const TokenizerString &str, bool appendData) 1398 { 1399 #ifdef TOKEN_DEBUG 1400 kdDebug( 6036 ) << this << " Tokenizer::write(\"" << str.toString() << "\"," << appendData << ")" << endl; 1401 #endif 1402 1403 if (!buffer) 1404 return; 1405 1406 if (loadStopped) 1407 return; 1408 1409 if ( ( m_executingScript && appendData ) || !pendingScripts.isEmpty() ) { 1410 // don't parse; we will do this later 1411 if (currentPrependingSrc) { 1412 currentPrependingSrc->append(str); 1413 } else { 1414 pendingSrc.append(str); 1415 } 1416 return; 1417 } 1418 1419 if (onHold) { 1420 src.append(str); 1421 return; 1422 } 1423 1424 if (!src.isEmpty()) 1425 src.append(str); 1426 else 1427 setSrc(str); 1428 1429 // Once a timer is set, it has control of when the tokenizer continues. 1430 if (timerId) 1431 return; 1432 1433 bool wasInWrite = inWrite; 1434 inWrite = true; 1435 1436 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1437 if (!parser->doc()->ownerElement()) 1438 printf("Beginning write at time %d\n", parser->doc()->elapsedTime()); 1439 #endif 1440 1441 int processedCount = 0; 1442 QTime startTime; 1443 startTime.start(); 1444 KWQUIEventTime eventTime; 1445 1446 KHTMLPart* part = parser->doc()->part(); 1447 1448 State state = m_state; 1449 1450 while (!src.isEmpty() && (!part || !part->isScheduledLocationChangePending())) { 1451 if (!continueProcessing(processedCount, startTime, eventTime, state)) 1452 break; 1453 1454 // do we need to enlarge the buffer? 1455 checkBuffer(); 1456 1457 ushort cc = src->unicode(); 1458 1459 bool wasSkipLF = state.skipLF(); 1460 if (wasSkipLF) 1461 state.setSkipLF(false); 1462 1463 if (wasSkipLF && (cc == '\n')) 1464 ++src; 1465 else if (state.needsSpecialWriteHandling()) { 1466 // it's important to keep needsSpecialWriteHandling with the flags this block tests 1467 if (state.hasEntityState()) 1468 state = parseEntity(src, dest, state, m_cBufferPos, false, state.hasTagState()); 1469 else if (state.inPlainText()) 1470 state = parseText(src, state); 1471 else if (state.inAnySpecial()) 1472 state = parseSpecial(src, state); 1473 else if (state.inComment()) 1474 state = parseComment(src, state); 1475 else if (state.inServer()) 1476 state = parseServer(src, state); 1477 else if (state.inProcessingInstruction()) 1478 state = parseProcessingInstruction(src, state); 1479 else if (state.hasTagState()) 1480 state = parseTag(src, state); 1481 else if (state.startTag()) { 1482 state.setStartTag(false); 1483 1484 switch(cc) { 1485 case '/': 1486 break; 1487 case '!': { 1488 // <!-- comment --> 1489 searchCount = 1; // Look for '<!--' sequence to start comment 1490 1491 break; 1492 } 1493 case '?': { 1494 // xml processing instruction 1495 state.setInProcessingInstruction(true); 1496 tquote = NoQuote; 1497 state = parseProcessingInstruction(src, state); 1498 continue; 1499 1500 break; 1501 } 1502 case '%': 1503 if (!brokenServer) { 1504 // <% server stuff, handle as comment %> 1505 state.setInServer(true); 1506 tquote = NoQuote; 1507 state = parseServer(src, state); 1508 continue; 1509 } 1510 // else fall through 1511 default: { 1512 if( ((cc >= 'a') && (cc <= 'z')) || ((cc >= 'A') && (cc <= 'Z'))) { 1513 // Start of a Start-Tag 1514 } else { 1515 // Invalid tag 1516 // Add as is 1517 *dest = '<'; 1518 dest++; 1519 continue; 1520 } 1521 } 1522 }; // end case 1523 1524 processToken(); 1525 1526 m_cBufferPos = 0; 1527 state.setTagState(TagName); 1528 state = parseTag(src, state); 1529 } 1530 } else if (cc == '&' && !src.escaped()) { 1531 ++src; 1532 state = parseEntity(src, dest, state, m_cBufferPos, true, state.hasTagState()); 1533 } else if (cc == '<' && !src.escaped()) { 1534 tagStartLineno = lineno+src.lineCount(); 1535 ++src; 1536 state.setStartTag(true); 1537 } else if (cc == '\n' || cc == '\r') { 1538 if (state.discardLF()) 1539 // Ignore this LF 1540 state.setDiscardLF(false); // We have discarded 1 LF 1541 else 1542 // Process this LF 1543 *dest++ = '\n'; 1544 1545 /* Check for MS-DOS CRLF sequence */ 1546 if (cc == '\r') 1547 state.setSkipLF(true); 1548 ++src; 1549 } else { 1550 state.setDiscardLF(false); 1551 #if QT_VERSION < 300 1552 unsigned char row = src->row(); 1553 if ( row > 0x05 && row < 0x10 || row > 0xfd ) 1554 currToken.complexText = true; 1555 #endif 1556 *dest = *src; 1557 fixUpChar(*dest); 1558 ++dest; 1559 ++src; 1560 } 1561 } 1562 1563 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1564 if (!parser->doc()->ownerElement()) 1565 printf("Ending write at time %d\n", parser->doc()->elapsedTime()); 1566 #endif 1567 1568 inWrite = wasInWrite; 1569 1570 m_state = state; 1571 1572 if (noMoreData && !inWrite && !state.loadingExtScript() && !m_executingScript && !timerId) 1573 end(); // this actually causes us to be deleted 1574 } 1575 1576 void HTMLTokenizer::stopped() 1577 { 1578 if (timerId) { 1579 killTimer(timerId); 1580 timerId = 0; 1581 } 1582 } 1583 1584 bool HTMLTokenizer::processingData() const 1585 { 1586 return timerId != 0; 1587 } 1588 1573 1589 void HTMLTokenizer::timerEvent(QTimerEvent* e) 1574 1590 { … … 1603 1619 void HTMLTokenizer::allDataProcessed() 1604 1620 { 1605 if (noMoreData && !inWrite && ! loadingExtScript&& !m_executingScript && !onHold && !timerId) {1621 if (noMoreData && !inWrite && !m_state.loadingExtScript() && !m_executingScript && !onHold && !timerId) { 1606 1622 QGuardedPtr<KHTMLView> savedView = view; 1607 1623 end(); … … 1631 1647 1632 1648 // parseTag is using the buffer for different matters 1633 if ( !tag)1649 if (!m_state.hasTagState()) 1634 1650 processToken(); 1635 1651 … … 1650 1666 { 1651 1667 // do this as long as we don't find matching comment ends 1652 while((comment || server) && scriptCode && scriptCodeSize) 1653 { 1668 while((m_state.inComment() || m_state.inServer()) && scriptCode && scriptCodeSize) { 1654 1669 // we've found an unmatched comment start 1655 if ( comment)1670 if (m_state.inComment()) 1656 1671 brokenComments = true; 1657 1672 else 1658 1673 brokenServer = true; 1659 1674 checkScriptBuffer(); 1660 scriptCode[ scriptCodeSize] = 0;1661 scriptCode[ scriptCodeSize + 1] = 0;1675 scriptCode[scriptCodeSize] = 0; 1676 scriptCode[scriptCodeSize + 1] = 0; 1662 1677 int pos; 1663 1678 QString food; 1664 if ( script || style) {1679 if (m_state.inScript() || m_state.inStyle()) 1665 1680 food.setUnicode(scriptCode, scriptCodeSize); 1666 } 1667 else if (server) { 1681 else if (m_state.inServer()) { 1668 1682 food = "<"; 1669 1683 food += QString(scriptCode, scriptCodeSize); 1670 } 1671 else { 1684 } else { 1672 1685 pos = QConstString(scriptCode, scriptCodeSize).string().find('>'); 1673 1686 food.setUnicode(scriptCode+pos+1, scriptCodeSize-pos-1); // deep copy … … 1676 1689 scriptCode = 0; 1677 1690 scriptCodeSize = scriptCodeMaxSize = scriptCodeResync = 0; 1678 comment = server = false; 1679 if ( !food.isEmpty() ) 1691 m_state.setInComment(false); 1692 m_state.setInServer(false); 1693 if (!food.isEmpty()) 1680 1694 write(food, true); 1681 1695 } … … 1683 1697 // an external script to load, we can't finish parsing until that is done 1684 1698 noMoreData = true; 1685 if (!inWrite && ! loadingExtScript&& !m_executingScript && !onHold && !timerId)1699 if (!inWrite && !m_state.loadingExtScript() && !m_executingScript && !onHold && !timerId) 1686 1700 end(); // this actually causes us to be deleted 1687 1701 } … … 1805 1819 #endif 1806 1820 1807 scriptExecution( scriptSource.qstring(), cachedScriptUrl);1821 m_state = scriptExecution(scriptSource.qstring(), m_state, cachedScriptUrl); 1808 1822 1809 1823 // The state of pendingScripts.isEmpty() can change inside the scriptExecution() … … 1811 1825 finished = pendingScripts.isEmpty(); 1812 1826 if (finished) { 1813 loadingExtScript = false;1827 m_state.setLoadingExtScript(false); 1814 1828 #ifdef INSTRUMENT_LAYOUT_SCHEDULING 1815 1829 if (!parser->doc()->ownerElement()) … … 1818 1832 } 1819 1833 1820 // ' script' is true when we are called synchronously from1834 // 'inScript' is true when we are called synchronously from 1821 1835 // parseScript(). In that case parseScript() will take care 1822 1836 // of 'scriptOutput'. 1823 if ( !script) {1837 if (!m_state.inScript()) { 1824 1838 TokenizerString rest = pendingSrc; 1825 1839 pendingSrc.clear(); … … 1833 1847 bool HTMLTokenizer::isWaitingForScripts() const 1834 1848 { 1835 return loadingExtScript;1849 return m_state.loadingExtScript(); 1836 1850 } 1837 1851 -
trunk/WebCore/khtml/html/htmltokenizer.h
r10843 r10867 129 129 130 130 protected: 131 class State; 132 133 // Where we are in parsing a tag 131 134 void begin(); 132 135 void end(); … … 134 137 void reset(); 135 138 void processToken(); 136 void processListing(TokenizerString list); 137 138 void parseComment(TokenizerString &str); 139 void parseServer(TokenizerString &str); 140 void parseText(TokenizerString &str); 141 void parseListing(TokenizerString &str); 142 void parseSpecial(TokenizerString &str); 143 void parseTag(TokenizerString &str); 144 void parseEntity(TokenizerString &str, QChar *&dest, bool start = false); 145 void parseProcessingInstruction(TokenizerString &str); 146 void scriptHandler(); 147 void scriptExecution(const QString& script, QString scriptURL = QString(), 148 int baseLine = 0); 139 140 State processListing(TokenizerString, State); 141 State parseComment(TokenizerString&, State); 142 State parseServer(TokenizerString&, State); 143 State parseText(TokenizerString&, State); 144 State parseSpecial(TokenizerString&, State); 145 State parseTag(TokenizerString&, State); 146 State parseEntity(TokenizerString &, QChar*& dest, State, unsigned& _cBufferPos, bool start, bool parsingTag); 147 State parseProcessingInstruction(TokenizerString&, State); 148 State scriptHandler(State); 149 State scriptExecution(const QString& script, State state, QString scriptURL = QString(), int baseLine = 0); 149 150 void setSrc(const TokenizerString &source); 150 151 … … 165 166 void enlargeScriptBuffer(int len); 166 167 167 bool continueProcessing(int& processedCount, const QTime& startTime, const KWQUIEventTime& eventTime );168 bool continueProcessing(int& processedCount, const QTime& startTime, const KWQUIEventTime& eventTime, State &state); 168 169 void timerEvent(QTimerEvent*); 169 170 void allDataProcessed(); … … 193 194 } tquote; 194 195 195 // Discard line breaks immediately after <pre> tags 196 enum 197 { 198 NoneDiscard = 0, 199 LFDiscard 200 } discard; 201 202 // Discard the LF part of CRLF sequence 203 bool skipLF; 204 205 // Flag to say that we have the '<' but not the character following it. 206 bool startTag; 207 208 // Flag to say, we are just parsing a tag, meaning, we are in the middle 209 // of <tag... 210 enum { 196 // Are we in a &... character entity description? 197 enum EntityState { 198 NoEntity = 0, 199 SearchEntity = 1, 200 NumericSearch = 2, 201 Hexadecimal = 3, 202 Decimal = 4, 203 EntityName = 5, 204 SearchSemicolon = 6 205 }; 206 unsigned EntityUnicodeValue; 207 208 enum TagState { 211 209 NoTag = 0, 212 TagName, 213 SearchAttribute, 214 AttributeName, 215 SearchEqual, 216 SearchValue, 217 QuotedValue, 218 Value, 219 SearchEnd 220 } tag; 221 222 // Are we in a &... character entity description? 223 enum { 224 NoEntity = 0, 225 SearchEntity, 226 NumericSearch, 227 Hexadecimal, 228 Decimal, 229 EntityName, 230 SearchSemicolon 231 } Entity; 232 unsigned EntityUnicodeValue; 233 234 // are we in a <script> ... </script block 235 bool script; 236 237 // Are we in a <style> ... </style> block 238 bool style; 239 240 // Are we in a <select> ... </select> block 241 bool select; 242 243 // Are we in a <xmp> ... </xmp> block 244 bool xmp; 245 246 // Are we in a <title> ... </title> block 247 bool title; 248 249 // Are we in plain textmode ? 250 bool plaintext; 251 252 // XML processing instructions. Ignored at the moment 253 bool processingInstruction; 254 255 // Area we in a <!-- comment --> block 256 bool comment; 257 258 // Are we in a <textarea> ... </textarea> block 259 bool textarea; 260 261 // was the previous character escaped ? 262 bool escaped; 263 264 // are we in a server includes statement? 265 bool server; 210 TagName = 1, 211 SearchAttribute = 2, 212 AttributeName = 3, 213 SearchEqual = 4, 214 SearchValue = 5, 215 QuotedValue = 6, 216 Value = 7, 217 SearchEnd = 8 218 }; 219 220 class State { 221 public: 222 State() : m_bits(0) {} 223 224 TagState tagState() const { return static_cast<TagState>(m_bits & TagMask); } 225 void setTagState(TagState t) { m_bits = (m_bits & ~TagMask) | t; } 226 EntityState entityState() const { return static_cast<EntityState>((m_bits & EntityMask) >> EntityShift); } 227 void setEntityState(EntityState e) { m_bits = (m_bits & ~EntityMask) | (e << EntityShift); } 228 229 bool inScript() const { return testBit(InScript); } 230 void setInScript(bool v) { setBit(InScript, v); } 231 bool inStyle() const { return testBit(InStyle); } 232 void setInStyle(bool v) { setBit(InStyle, v); } 233 bool inSelect() const { return testBit(InSelect); } 234 void setInSelect(bool v) { setBit(InSelect, v); } 235 bool inXmp() const { return testBit(InXmp); } 236 void setInXmp(bool v) { setBit(InXmp, v); } 237 bool inTitle() const { return testBit(InTitle); } 238 void setInTitle(bool v) { setBit(InTitle, v); } 239 bool inPlainText() const { return testBit(InPlainText); } 240 void setInPlainText(bool v) { setBit(InPlainText, v); } 241 bool inProcessingInstruction() const { return testBit(InProcessingInstruction); } 242 void setInProcessingInstruction(bool v) { return setBit(InProcessingInstruction, v); } 243 bool inComment() const { return testBit(InComment); } 244 void setInComment(bool v) { setBit(InComment, v); } 245 bool inTextArea() const { return testBit(InTextArea); } 246 void setInTextArea(bool v) { setBit(InTextArea, v); } 247 bool escaped() const { return testBit(Escaped); } 248 void setEscaped(bool v) { setBit(Escaped, v); } 249 bool inServer() const { return testBit(InServer); } 250 void setInServer(bool v) { setBit(InServer, v); } 251 bool skipLF() const { return testBit(SkipLF); } 252 void setSkipLF(bool v) { setBit(SkipLF, v); } 253 bool startTag() const { return testBit(StartTag); } 254 void setStartTag(bool v) { setBit(StartTag, v); } 255 bool discardLF() const { return testBit(DiscardLF); } 256 void setDiscardLF(bool v) { setBit(DiscardLF, v); } 257 bool allowYield() const { return testBit(AllowYield); } 258 void setAllowYield(bool v) { setBit(AllowYield, v); } 259 bool loadingExtScript() const { return testBit(LoadingExtScript); } 260 void setLoadingExtScript(bool v) { setBit(LoadingExtScript, v); } 261 bool forceSynchronous() const { return testBit(ForceSynchronous); } 262 void setForceSynchronous(bool v) { setBit(ForceSynchronous, v); } 263 264 bool inAnySpecial() const { return m_bits & (InScript | InStyle | InXmp | InTextArea | InTitle); } 265 bool hasTagState() const { return m_bits & TagMask; } 266 bool hasEntityState() const { return m_bits & EntityMask; } 267 268 bool needsSpecialWriteHandling() const { return m_bits & (InScript | InStyle | InXmp | InTextArea | InTitle | TagMask | EntityMask | InPlainText | InComment | InServer | InProcessingInstruction | StartTag); } 269 270 private: 271 static const int EntityShift = 4; 272 enum StateBits { 273 TagMask = (1 << 4) - 1, 274 EntityMask = (1 << 7) - (1 << 4), 275 InScript = 1 << 7, 276 InStyle = 1 << 8, 277 InSelect = 1 << 9, 278 InXmp = 1 << 10, 279 InTitle = 1 << 11, 280 InPlainText = 1 << 12, 281 InProcessingInstruction = 1 << 13, 282 InComment = 1 << 14, 283 InTextArea = 1 << 15, 284 Escaped = 1 << 16, 285 InServer = 1 << 17, 286 SkipLF = 1 << 18, 287 StartTag = 1 << 19, 288 DiscardLF = 1 << 20, // FIXME: should clarify difference between skip and discard 289 AllowYield = 1 << 21, 290 LoadingExtScript = 1 << 22, 291 ForceSynchronous = 1 << 23, 292 }; 293 294 void setBit(StateBits bit, bool value) 295 { 296 if (value) 297 m_bits |= bit; 298 else 299 m_bits &= ~bit; 300 } 301 bool testBit(StateBits bit) const { return m_bits & bit; } 302 303 unsigned m_bits; 304 }; 305 306 State m_state; 266 307 267 308 bool brokenServer; … … 289 330 // the stopper len 290 331 int searchStopperLen; 291 // true if we are waiting for an external script (<SCRIPT SRC=...) to load, i.e.292 // we don't do any parsing while this is true293 bool loadingExtScript;294 332 // if no more data is coming, just parse what we have (including ext scripts that 295 333 // may be still downloading) and finish … … 324 362 // The timer for continued processing. 325 363 int timerId; 326 bool allowYield;327 bool forceSynchronous; // disables yielding328 364 329 365 bool includesCommentsInDOM; … … 334 370 #define CBUFLEN 1024 335 371 char cBuffer[CBUFLEN+2]; 336 unsigned int cBufferPos;372 unsigned int m_cBufferPos; 337 373 338 374 TokenizerString src; -
trunk/WebCore/khtml/rendering/bidi.cpp
r10845 r10867 2524 2524 QChar ellipsis = 0x2026; // FIXME: CSS3 says this is configurable, also need to use 0x002E (FULL STOP) if 0x2026 not renderable 2525 2525 static AtomicString ellipsisStr(ellipsis); 2526 const Font& firstLineFont = style(true)->htmlFont();2526 const Font& firstLineFont = firstLineStyle()->htmlFont(); 2527 2527 const Font& font = style()->htmlFont(); 2528 2528 int firstLineEllipsisWidth = firstLineFont.width(&ellipsis, 1, 0, 0); -
trunk/WebCore/khtml/rendering/render_block.cpp
r10774 r10867 3317 3317 if (currChild->style()->styleType() == RenderStyle::FIRST_LETTER) { 3318 3318 RenderStyle* pseudo = firstLetterBlock->getPseudoStyle(RenderStyle::FIRST_LETTER, 3319 firstLetterContainer->style(true));3319 firstLetterContainer->firstLineStyle()); 3320 3320 currChild->setStyle(pseudo); 3321 3321 for (RenderObject* genChild = currChild->firstChild(); genChild; genChild = genChild->nextSibling()) { … … 3334 3334 // Create our pseudo style now that we have our firstLetterContainer determined. 3335 3335 RenderStyle* pseudoStyle = firstLetterBlock->getPseudoStyle(RenderStyle::FIRST_LETTER, 3336 firstLetterContainer-> style(true));3336 firstLetterContainer->firstLineStyle()); 3337 3337 3338 3338 // Force inline display (except for floating first-letters) -
trunk/WebCore/khtml/rendering/render_flow.cpp
r10866 r10867 601 601 // the caret size of an empty :first-line'd block is wrong, but I think we 602 602 // can live with that. 603 RenderStyle *currentStyle = style(true);603 RenderStyle *currentStyle = firstLineStyle(); 604 604 //height = currentStyle->fontMetrics().height(); 605 605 height = lineHeight(true); -
trunk/WebCore/khtml/rendering/render_line.cpp
r10755 r10867 1068 1068 { 1069 1069 QPainter* p = i.p; 1070 RenderStyle* _style = m_firstLine ? m_object-> style(true) : m_object->style();1070 RenderStyle* _style = m_firstLine ? m_object->firstLineStyle() : m_object->style(); 1071 1071 if (_style->font() != p->font()) 1072 1072 p->setFont(_style->font()); -
trunk/WebCore/khtml/rendering/render_object.cpp
r10755 r10867 2296 2296 } 2297 2297 2298 RenderStyle* RenderObject::style(bool firstLine) const { 2299 RenderStyle *s = m_style; 2300 if (firstLine) { 2301 const RenderObject* obj = isText() ? parent() : this; 2302 if (obj->isBlockFlow()) { 2303 RenderBlock* firstLineBlock = obj->firstLineBlock(); 2304 if (firstLineBlock) 2305 s = firstLineBlock->getPseudoStyle(RenderStyle::FIRST_LINE, style()); 2306 } 2307 else if (!obj->isAnonymous() && obj->isInlineFlow()) { 2308 RenderStyle* parentStyle = obj->parent()->style(true); 2309 if (parentStyle != obj->parent()->style()) { 2310 // A first-line style is in effect. We need to cache a first-line style 2311 // for ourselves. 2312 style()->setHasPseudoStyle(RenderStyle::FIRST_LINE_INHERITED); 2313 s = obj->getPseudoStyle(RenderStyle::FIRST_LINE_INHERITED, parentStyle); 2314 } 2298 RenderStyle* RenderObject::firstLineStyle() const 2299 { 2300 RenderStyle *s = m_style; 2301 const RenderObject* obj = isText() ? parent() : this; 2302 if (obj->isBlockFlow()) { 2303 RenderBlock* firstLineBlock = obj->firstLineBlock(); 2304 if (firstLineBlock) 2305 s = firstLineBlock->getPseudoStyle(RenderStyle::FIRST_LINE, style()); 2306 } else if (!obj->isAnonymous() && obj->isInlineFlow()) { 2307 RenderStyle* parentStyle = obj->parent()->firstLineStyle(); 2308 if (parentStyle != obj->parent()->style()) { 2309 // A first-line style is in effect. We need to cache a first-line style 2310 // for ourselves. 2311 style()->setHasPseudoStyle(RenderStyle::FIRST_LINE_INHERITED); 2312 s = obj->getPseudoStyle(RenderStyle::FIRST_LINE_INHERITED, parentStyle); 2315 2313 } 2316 2314 } -
trunk/WebCore/khtml/rendering/render_object.h
r10755 r10867 677 677 678 678 RenderStyle* style() const { return m_style; } 679 RenderStyle* style( bool firstLine ) const; 679 RenderStyle* firstLineStyle() const; 680 RenderStyle* style(bool firstLine) const { return firstLine ? firstLineStyle() : style(); } 681 680 682 681 683 void getTextDecorationColors(int decorations, QColor& underline, QColor& overline,
Note:
See TracChangeset
for help on using the changeset viewer.