|
Lines 388-393
void HTMLTreeBuilder::detach()
a/WebCore/html/parser/HTMLTreeBuilder.cpp_sec1
|
| 388 |
m_tree.detach(); |
388 |
m_tree.detach(); |
| 389 |
} |
389 |
} |
| 390 |
|
390 |
|
|
|
391 |
// NOTE: HTML5 requires that we use a dummy document when parsing |
| 392 |
// document fragments. However, creating a new Document element |
| 393 |
// for each fragment is very slow (Document() does too much work, and |
| 394 |
// innerHTML is a common call). So we use a shared dummy document. |
| 395 |
// This sharing works because there can only ever be one fragment |
| 396 |
// parser at any time. Fragment parsing is synchronous and done |
| 397 |
// only from the main thread. It should be impossible for javascript |
| 398 |
// (or anything else) to ever hold a reference to the dummy document. |
| 399 |
// See https://bugs.webkit.org/show_bug.cgi?id=48719 |
| 400 |
class DummyDocumentFactory : Noncopyable { |
| 401 |
public: |
| 402 |
// Use an explicit create/release here to ASSERT this sharing is safe. |
| 403 |
static HTMLDocument* createDummyDocument(); |
| 404 |
static void releaseDocument(HTMLDocument*); |
| 405 |
|
| 406 |
private: |
| 407 |
static HTMLDocument* s_sharedDummyDocument; |
| 408 |
static int s_sharedDummyDocumentMutex; |
| 409 |
}; |
| 410 |
|
| 411 |
HTMLDocument* DummyDocumentFactory::createDummyDocument() |
| 412 |
{ |
| 413 |
if (!s_sharedDummyDocument) { |
| 414 |
s_sharedDummyDocument = HTMLDocument::create(0, KURL()).releaseRef(); |
| 415 |
s_sharedDummyDocumentMutex = 0; |
| 416 |
} |
| 417 |
ASSERT(!s_sharedDummyDocumentMutex); |
| 418 |
ASSERT(!s_sharedDummyDocument->hasChildNodes()); |
| 419 |
s_sharedDummyDocumentMutex++; |
| 420 |
return s_sharedDummyDocument; |
| 421 |
} |
| 422 |
|
| 423 |
void DummyDocumentFactory::releaseDocument(HTMLDocument* dummyDocument) |
| 424 |
{ |
| 425 |
ASSERT(s_sharedDummyDocument == dummyDocument); |
| 426 |
s_sharedDummyDocumentMutex--; |
| 427 |
ASSERT(!s_sharedDummyDocumentMutex); |
| 428 |
dummyDocument->removeAllChildren(); |
| 429 |
} |
| 430 |
|
| 431 |
HTMLDocument* DummyDocumentFactory::s_sharedDummyDocument = 0; |
| 432 |
int DummyDocumentFactory::s_sharedDummyDocumentMutex = 0; |
| 433 |
|
| 391 |
HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext() |
434 |
HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext() |
| 392 |
: m_fragment(0) |
435 |
: m_fragment(0) |
| 393 |
, m_contextElement(0) |
436 |
, m_contextElement(0) |
|
Lines 396-422
HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext()
a/WebCore/html/parser/HTMLTreeBuilder.cpp_sec2
|
| 396 |
} |
439 |
} |
| 397 |
|
440 |
|
| 398 |
HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext(DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission) |
441 |
HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext(DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission) |
| 399 |
: m_dummyDocumentForFragmentParsing(HTMLDocument::create(0, KURL(), fragment->document()->baseURI())) |
442 |
: m_dummyDocumentForFragmentParsing(DummyDocumentFactory::createDummyDocument()) |
| 400 |
, m_fragment(fragment) |
443 |
, m_fragment(fragment) |
| 401 |
, m_contextElement(contextElement) |
444 |
, m_contextElement(contextElement) |
| 402 |
, m_scriptingPermission(scriptingPermission) |
445 |
, m_scriptingPermission(scriptingPermission) |
| 403 |
{ |
446 |
{ |
| 404 |
m_dummyDocumentForFragmentParsing->setCompatibilityMode(fragment->document()->compatibilityMode()); |
447 |
m_dummyDocumentForFragmentParsing->setCompatibilityMode(fragment->document()->compatibilityMode()); |
|
|
448 |
// Setting the baseURL should work the same as it would have had we passed |
| 449 |
// it during HTMLDocument() construction, since the new document is empty. |
| 450 |
m_dummyDocumentForFragmentParsing->setURL(fragment->document()->baseURI()); |
| 405 |
} |
451 |
} |
| 406 |
|
452 |
|
| 407 |
Document* HTMLTreeBuilder::FragmentParsingContext::document() const |
453 |
Document* HTMLTreeBuilder::FragmentParsingContext::document() const |
| 408 |
{ |
454 |
{ |
| 409 |
ASSERT(m_fragment); |
455 |
ASSERT(m_fragment); |
| 410 |
return m_dummyDocumentForFragmentParsing.get(); |
456 |
return m_dummyDocumentForFragmentParsing; |
| 411 |
} |
457 |
} |
| 412 |
|
458 |
|
| 413 |
void HTMLTreeBuilder::FragmentParsingContext::finished() |
459 |
void HTMLTreeBuilder::FragmentParsingContext::finished() |
| 414 |
{ |
460 |
{ |
| 415 |
// Populate the DocumentFragment with the parsed content now that we're done. |
461 |
// Populate the DocumentFragment with the parsed content now that we're done. |
| 416 |
ContainerNode* root = m_dummyDocumentForFragmentParsing.get(); |
462 |
ContainerNode* root = m_dummyDocumentForFragmentParsing; |
| 417 |
if (m_contextElement) |
463 |
if (m_contextElement) |
| 418 |
root = m_dummyDocumentForFragmentParsing->documentElement(); |
464 |
root = m_dummyDocumentForFragmentParsing->documentElement(); |
| 419 |
m_fragment->takeAllChildrenFrom(root); |
465 |
m_fragment->takeAllChildrenFrom(root); |
|
|
466 |
ASSERT(!m_dummyDocumentForFragmentParsing->hasChildNodes()); |
| 467 |
DummyDocumentFactory::releaseDocument(m_dummyDocumentForFragmentParsing); |
| 468 |
m_dummyDocumentForFragmentParsing = 0; |
| 420 |
} |
469 |
} |
| 421 |
|
470 |
|
| 422 |
HTMLTreeBuilder::FragmentParsingContext::~FragmentParsingContext() |
471 |
HTMLTreeBuilder::FragmentParsingContext::~FragmentParsingContext() |