Bug 1890793: Assert CallArgs::newTarget is not gray. r=spidermonkey-reviewers,sfink...
[gecko.git] / parser / html / nsHtml5StringParser.cpp
blob69e2806ce5eb69f75cbaddfd930322855226d630
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "nsHtml5StringParser.h"
6 #include "nsHtml5DependentUTF16Buffer.h"
7 #include "nsHtml5Tokenizer.h"
8 #include "nsHtml5TreeBuilder.h"
9 #include "nsHtml5TreeOpExecutor.h"
10 #include "nsIContent.h"
11 #include "mozilla/dom/Document.h"
12 #include "mozilla/dom/DocumentFragment.h"
14 using mozilla::dom::Document;
16 NS_IMPL_ISUPPORTS0(nsHtml5StringParser)
18 nsHtml5StringParser::nsHtml5StringParser()
19 : mBuilder(new nsHtml5OplessBuilder()),
20 mTreeBuilder(new nsHtml5TreeBuilder(mBuilder)),
21 mTokenizer(new nsHtml5Tokenizer(mTreeBuilder.get(), false)) {
22 mTokenizer->setInterner(&mAtomTable);
23 mTokenizer->setKeepBuffer(true);
24 mTreeBuilder->setKeepBuffer(true);
27 nsHtml5StringParser::~nsHtml5StringParser() { ClearCaches(); }
29 nsresult nsHtml5StringParser::ParseFragment(
30 const nsAString& aSourceBuffer, nsIContent* aTargetNode,
31 nsAtom* aContextLocalName, int32_t aContextNamespace, bool aQuirks,
32 bool aPreventScriptExecution, bool aAllowDeclarativeShadowRoots) {
33 NS_ENSURE_TRUE(aSourceBuffer.Length() <= INT32_MAX, NS_ERROR_OUT_OF_MEMORY);
35 Document* doc = aTargetNode->OwnerDoc();
36 nsIURI* uri = doc->GetDocumentURI();
37 NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE);
39 mTreeBuilder->setFragmentContext(aContextLocalName, aContextNamespace,
40 aTargetNode, aQuirks);
42 #ifdef DEBUG
43 if (!aPreventScriptExecution) {
44 NS_ASSERTION(!aTargetNode->IsInUncomposedDoc(),
45 "If script execution isn't prevented, "
46 "the target node must not be in doc.");
47 NS_ASSERTION(
48 aTargetNode->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE,
49 "If script execution isn't prevented, must parse to DOM fragment.");
51 #endif
53 mTreeBuilder->SetPreventScriptExecution(aPreventScriptExecution);
55 return Tokenize(aSourceBuffer, doc, true, aAllowDeclarativeShadowRoots);
58 nsresult nsHtml5StringParser::ParseDocument(
59 const nsAString& aSourceBuffer, Document* aTargetDoc,
60 bool aScriptingEnabledForNoscriptParsing) {
61 MOZ_ASSERT(!aTargetDoc->GetFirstChild());
63 NS_ENSURE_TRUE(aSourceBuffer.Length() <= INT32_MAX, NS_ERROR_OUT_OF_MEMORY);
65 mTreeBuilder->setFragmentContext(nullptr, kNameSpaceID_None, nullptr, false);
67 mTreeBuilder->SetPreventScriptExecution(true);
69 return Tokenize(aSourceBuffer, aTargetDoc,
70 aScriptingEnabledForNoscriptParsing,
71 aTargetDoc->AllowsDeclarativeShadowRoots());
74 void nsHtml5StringParser::ClearCaches() {
75 mTokenizer->dropBufferIfLongerThan(0);
76 mTreeBuilder->dropBufferIfLongerThan(0);
77 if (mCacheClearer) {
78 mCacheClearer->Disconnect();
79 mCacheClearer = nullptr;
83 void nsHtml5StringParser::TryCache() {
84 const int32_t kMaxBuffer = 1024 * 1024;
85 bool didDrop = mTokenizer->dropBufferIfLongerThan(kMaxBuffer);
86 didDrop |= mTreeBuilder->dropBufferIfLongerThan(kMaxBuffer);
87 if (didDrop) {
88 return;
91 if (!mCacheClearer) {
92 mCacheClearer = new CacheClearer(this);
93 nsCOMPtr<nsIRunnable> runnable = mCacheClearer.get();
94 NS_DispatchToMainThreadQueue(runnable.forget(),
95 mozilla::EventQueuePriority::Idle);
99 nsresult nsHtml5StringParser::Tokenize(const nsAString& aSourceBuffer,
100 Document* aDocument,
101 bool aScriptingEnabledForNoscriptParsing,
102 bool aDeclarativeShadowRootsAllowed) {
103 nsIURI* uri = aDocument->GetDocumentURI();
105 mBuilder->Init(aDocument, uri, nullptr, nullptr);
107 mBuilder->SetParser(this);
108 mBuilder->SetNodeInfoManager(aDocument->NodeInfoManager());
110 // Mark the parser as *not* broken by passing NS_OK
111 nsresult rv = mBuilder->MarkAsBroken(NS_OK);
113 mTreeBuilder->setScriptingEnabled(aScriptingEnabledForNoscriptParsing);
114 mTreeBuilder->setIsSrcdocDocument(aDocument->IsSrcdocDocument());
115 mTreeBuilder->setAllowDeclarativeShadowRoots(aDeclarativeShadowRootsAllowed);
116 mBuilder->Start();
117 mTokenizer->start();
118 if (!aSourceBuffer.IsEmpty()) {
119 bool lastWasCR = false;
120 nsHtml5DependentUTF16Buffer buffer(aSourceBuffer);
121 while (buffer.hasMore()) {
122 buffer.adjust(lastWasCR);
123 lastWasCR = false;
124 if (buffer.hasMore()) {
125 if (!mTokenizer->EnsureBufferSpace(buffer.getLength())) {
126 rv = mBuilder->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
127 break;
129 lastWasCR = mTokenizer->tokenizeBuffer(&buffer);
130 if (NS_FAILED(rv = mBuilder->IsBroken())) {
131 break;
136 if (NS_SUCCEEDED(rv)) {
137 mTokenizer->eof();
140 mTokenizer->end();
141 mBuilder->Finish();
142 mAtomTable.Clear();
143 TryCache();
144 return rv;