1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=2 et tw=79: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsHtml5Parser.h"
9 #include "mozilla/AutoRestore.h"
10 #include "nsContentUtils.h" // for kLoadAsData
11 #include "nsHtml5Tokenizer.h"
12 #include "nsHtml5TreeBuilder.h"
13 #include "nsHtml5AtomTable.h"
14 #include "nsHtml5DependentUTF16Buffer.h"
15 #include "nsNetUtil.h"
17 NS_INTERFACE_TABLE_HEAD(nsHtml5Parser
)
18 NS_INTERFACE_TABLE(nsHtml5Parser
, nsIParser
, nsISupportsWeakReference
)
19 NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsHtml5Parser
)
22 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHtml5Parser
)
23 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHtml5Parser
)
25 NS_IMPL_CYCLE_COLLECTION_CLASS(nsHtml5Parser
)
27 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsHtml5Parser
)
28 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExecutor
)
29 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(GetStreamParser())
30 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
32 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsHtml5Parser
)
33 NS_IMPL_CYCLE_COLLECTION_UNLINK(mExecutor
)
34 tmp
->DropStreamParser();
35 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
37 nsHtml5Parser::nsHtml5Parser()
38 : mFirstBuffer(new nsHtml5OwningUTF16Buffer((void*)nullptr))
39 , mLastBuffer(mFirstBuffer
)
40 , mExecutor(new nsHtml5TreeOpExecutor())
41 , mTreeBuilder(new nsHtml5TreeBuilder(mExecutor
, nullptr))
42 , mTokenizer(new nsHtml5Tokenizer(mTreeBuilder
, false))
43 , mRootContextLineNumber(1)
45 mTokenizer
->setInterner(&mAtomTable
);
46 // There's a zeroing operator new for everything else
49 nsHtml5Parser::~nsHtml5Parser()
52 if (mDocWriteSpeculativeTokenizer
) {
53 mDocWriteSpeculativeTokenizer
->end();
58 nsHtml5Parser::SetContentSink(nsIContentSink
* aSink
)
60 NS_ASSERTION(aSink
== static_cast<nsIContentSink
*> (mExecutor
),
61 "Attempt to set a foreign sink.");
64 NS_IMETHODIMP_(nsIContentSink
*)
65 nsHtml5Parser::GetContentSink()
67 return static_cast<nsIContentSink
*> (mExecutor
);
71 nsHtml5Parser::GetCommand(nsCString
& aCommand
)
73 aCommand
.AssignLiteral("view");
77 nsHtml5Parser::SetCommand(const char* aCommand
)
79 NS_ASSERTION(!strcmp(aCommand
, "view") ||
80 !strcmp(aCommand
, "view-source") ||
81 !strcmp(aCommand
, "external-resource") ||
82 !strcmp(aCommand
, "import") ||
83 !strcmp(aCommand
, kLoadAsData
),
84 "Unsupported parser command");
88 nsHtml5Parser::SetCommand(eParserCommands aParserCommand
)
90 NS_ASSERTION(aParserCommand
== eViewNormal
,
91 "Parser command was not eViewNormal.");
95 nsHtml5Parser::SetDocumentCharset(const nsACString
& aCharset
,
96 int32_t aCharsetSource
)
98 NS_PRECONDITION(!mExecutor
->HasStarted(),
99 "Document charset set too late.");
100 NS_PRECONDITION(GetStreamParser(), "Setting charset on a script-only parser.");
101 nsAutoCString trimmed
;
102 trimmed
.Assign(aCharset
);
103 trimmed
.Trim(" \t\r\n\f");
104 GetStreamParser()->SetDocumentCharset(trimmed
, aCharsetSource
);
105 mExecutor
->SetDocumentCharsetAndSource(trimmed
,
110 nsHtml5Parser::GetChannel(nsIChannel
** aChannel
)
112 if (GetStreamParser()) {
113 return GetStreamParser()->GetChannel(aChannel
);
115 return NS_ERROR_NOT_AVAILABLE
;
120 nsHtml5Parser::GetDTD(nsIDTD
** aDTD
)
127 nsHtml5Parser::GetStreamListener()
129 return mStreamListener
;
133 nsHtml5Parser::ContinueInterruptedParsing()
135 NS_NOTREACHED("Don't call. For interface compat only.");
136 return NS_ERROR_NOT_IMPLEMENTED
;
140 nsHtml5Parser::BlockParser()
146 nsHtml5Parser::UnblockParser()
149 mExecutor
->ContinueInterruptedParsingAsync();
153 nsHtml5Parser::ContinueInterruptedParsingAsync()
155 mExecutor
->ContinueInterruptedParsingAsync();
159 nsHtml5Parser::IsParserEnabled()
165 nsHtml5Parser::IsComplete()
167 return mExecutor
->IsComplete();
171 nsHtml5Parser::Parse(nsIURI
* aURL
,
172 nsIRequestObserver
* aObserver
,
173 void* aKey
, // legacy; ignored
174 nsDTDMode aMode
) // legacy; ignored
177 * Do NOT cause WillBuildModel to be called synchronously from here!
178 * The document won't be ready for it until OnStartRequest!
180 NS_PRECONDITION(!mExecutor
->HasStarted(),
181 "Tried to start parse without initializing the parser.");
182 NS_PRECONDITION(GetStreamParser(),
183 "Can't call this Parse() variant on script-created parser");
184 GetStreamParser()->SetObserver(aObserver
);
185 GetStreamParser()->SetViewSourceTitle(aURL
); // In case we're viewing source
186 mExecutor
->SetStreamParser(GetStreamParser());
187 mExecutor
->SetParser(this);
192 nsHtml5Parser::Parse(const nsAString
& aSourceBuffer
,
194 const nsACString
& aContentType
,
196 nsDTDMode aMode
) // ignored
199 if (NS_FAILED(rv
= mExecutor
->IsBroken())) {
202 if (aSourceBuffer
.Length() > INT32_MAX
) {
203 return mExecutor
->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY
);
206 // Maintain a reference to ourselves so we don't go away
207 // till we're completely done. The old parser grips itself in this method.
208 nsCOMPtr
<nsIParser
> kungFuDeathGrip(this);
210 // Gripping the other objects just in case, since the other old grip
211 // required grips to these, too.
212 nsRefPtr
<nsHtml5StreamParser
> streamKungFuDeathGrip(GetStreamParser());
213 nsRefPtr
<nsHtml5TreeOpExecutor
> treeOpKungFuDeathGrip(mExecutor
);
215 if (!mExecutor
->HasStarted()) {
216 NS_ASSERTION(!GetStreamParser(),
217 "Had stream parser but document.write started life cycle.");
218 // This is the first document.write() on a document.open()ed document
219 mExecutor
->SetParser(this);
220 mTreeBuilder
->setScriptingEnabled(mExecutor
->IsScriptEnabled());
222 bool isSrcdoc
= false;
223 nsCOMPtr
<nsIChannel
> channel
;
224 rv
= GetChannel(getter_AddRefs(channel
));
225 if (NS_SUCCEEDED(rv
)) {
226 isSrcdoc
= NS_IsSrcdocChannel(channel
);
228 mTreeBuilder
->setIsSrcdocDocument(isSrcdoc
);
232 if (!aContentType
.EqualsLiteral("text/html")) {
233 mTreeBuilder
->StartPlainText();
234 mTokenizer
->StartPlainText();
237 * If you move the following line, be very careful not to cause
238 * WillBuildModel to be called before the document has had its
239 * script global object set.
241 rv
= mExecutor
->WillBuildModel(eDTDMode_unknown
);
242 NS_ENSURE_SUCCESS(rv
, rv
);
245 // Return early if the parser has processed EOF
246 if (mExecutor
->IsComplete()) {
250 if (aLastCall
&& aSourceBuffer
.IsEmpty() && !aKey
) {
252 NS_ASSERTION(!GetStreamParser(),
253 "Had stream parser but got document.close().");
254 if (mDocumentClosed
) {
258 mDocumentClosed
= true;
259 if (!mBlocked
&& !mInDocumentWrite
) {
260 return ParseUntilBlocked();
265 // If we got this far, we are dealing with a document.write or
266 // document.writeln call--not document.close().
268 NS_ASSERTION(IsInsertionPointDefined(),
269 "Doc.write reached parser with undefined insertion point.");
271 NS_ASSERTION(!(GetStreamParser() && !aKey
),
272 "Got a null key in a non-script-created parser");
274 // XXX is this optimization bogus?
275 if (aSourceBuffer
.IsEmpty()) {
279 // This guard is here to prevent document.close from tokenizing synchronously
280 // while a document.write (that wrote the script that called document.close!)
281 // is still on the call stack.
282 mozilla::AutoRestore
<bool> guard(mInDocumentWrite
);
283 mInDocumentWrite
= true;
285 // The script is identified by aKey. If there's nothing in the buffer
286 // chain for that key, we'll insert at the head of the queue.
287 // When the script leaves something in the queue, a zero-length
288 // key-holder "buffer" is inserted in the queue. If the same script
289 // leaves something in the chain again, it will be inserted immediately
290 // before the old key holder belonging to the same script.
292 // We don't do the actual data insertion yet in the hope that the data gets
293 // tokenized and there no data or less data to copy to the heap after
294 // tokenization. Also, this way, we avoid inserting one empty data buffer
295 // per document.write, which matters for performance when the parser isn't
296 // blocked and a badly-authored script calls document.write() once per
297 // input character. (As seen in a benchmark!)
299 // The insertion into the input stream happens conceptually before anything
300 // gets tokenized. To make sure multi-level document.write works right,
301 // it's necessary to establish the location of our parser key up front
302 // in case this is the first write with this key.
304 // In a document.open() case, the first write level has a null key, so that
305 // case is handled separately, because normal buffers containing data
308 // These don't need to be owning references, because they always point to
309 // the buffer queue and buffers can't be removed from the buffer queue
310 // before document.write() returns. The buffer queue clean-up happens the
311 // next time ParseUntilBlocked() is called.
312 // However, they are made owning just in case the reasoning above is flawed
313 // and a flaw would lead to worse problems with plain pointers. If this
314 // turns out to be a perf problem, it's worthwhile to consider making
315 // prevSearchbuf a plain pointer again.
316 nsRefPtr
<nsHtml5OwningUTF16Buffer
> prevSearchBuf
;
317 nsRefPtr
<nsHtml5OwningUTF16Buffer
> firstLevelMarker
;
320 if (mFirstBuffer
== mLastBuffer
) {
321 nsHtml5OwningUTF16Buffer
* keyHolder
= new nsHtml5OwningUTF16Buffer(aKey
);
322 keyHolder
->next
= mLastBuffer
;
323 mFirstBuffer
= keyHolder
;
324 } else if (mFirstBuffer
->key
!= aKey
) {
325 prevSearchBuf
= mFirstBuffer
;
327 if (prevSearchBuf
->next
== mLastBuffer
) {
329 nsHtml5OwningUTF16Buffer
* keyHolder
=
330 new nsHtml5OwningUTF16Buffer(aKey
);
331 keyHolder
->next
= mFirstBuffer
;
332 mFirstBuffer
= keyHolder
;
333 prevSearchBuf
= nullptr;
336 if (prevSearchBuf
->next
->key
== aKey
) {
337 // found a key holder
340 prevSearchBuf
= prevSearchBuf
->next
;
342 } // else mFirstBuffer is the keyholder
344 // prevSearchBuf is the previous buffer before the keyholder or null if
347 // We have a first-level write in the document.open() case. We insert before
348 // mLastBuffer, effectively, by making mLastBuffer be a new sentinel object
349 // and redesignating the previous mLastBuffer as our firstLevelMarker. We
350 // need to put a marker there, because otherwise additional document.writes
351 // from nested event loops would insert in the wrong place. Sigh.
352 mLastBuffer
->next
= new nsHtml5OwningUTF16Buffer((void*)nullptr);
353 firstLevelMarker
= mLastBuffer
;
354 mLastBuffer
= mLastBuffer
->next
;
357 nsHtml5DependentUTF16Buffer
stackBuffer(aSourceBuffer
);
359 while (!mBlocked
&& stackBuffer
.hasMore()) {
360 stackBuffer
.adjust(mLastWasCR
);
362 if (stackBuffer
.hasMore()) {
363 int32_t lineNumberSave
;
364 bool inRootContext
= (!GetStreamParser() && !aKey
);
366 mTokenizer
->setLineNumber(mRootContextLineNumber
);
368 // we aren't the root context, so save the line number on the
369 // *stack* so that we can restore it.
370 lineNumberSave
= mTokenizer
->getLineNumber();
373 mLastWasCR
= mTokenizer
->tokenizeBuffer(&stackBuffer
);
376 mRootContextLineNumber
= mTokenizer
->getLineNumber();
378 mTokenizer
->setLineNumber(lineNumberSave
);
381 if (mTreeBuilder
->HasScript()) {
382 mTreeBuilder
->Flush(); // Move ops to the executor
383 rv
= mExecutor
->FlushDocumentWrite(); // run the ops
384 NS_ENSURE_SUCCESS(rv
, rv
);
385 // Flushing tree ops can cause all sorts of things.
386 // Return early if the parser got terminated.
387 if (mExecutor
->IsComplete()) {
391 // Ignore suspension requests
395 nsRefPtr
<nsHtml5OwningUTF16Buffer
> heapBuffer
;
396 if (stackBuffer
.hasMore()) {
397 // The buffer wasn't tokenized to completion. Create a copy of the tail
399 heapBuffer
= stackBuffer
.FalliblyCopyAsOwningBuffer();
401 // Allocation failed. The parser is now broken.
402 return mExecutor
->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY
);
407 // We have something to insert before the keyholder holding in the non-null
408 // aKey case and we have something to swap into firstLevelMarker in the
411 NS_ASSERTION(mFirstBuffer
!= mLastBuffer
,
412 "Where's the keyholder?");
413 // the key holder is still somewhere further down the list from
414 // prevSearchBuf (which may be null)
415 if (mFirstBuffer
->key
== aKey
) {
416 NS_ASSERTION(!prevSearchBuf
,
417 "Non-null prevSearchBuf when mFirstBuffer is the key holder?");
418 heapBuffer
->next
= mFirstBuffer
;
419 mFirstBuffer
= heapBuffer
;
421 if (!prevSearchBuf
) {
422 prevSearchBuf
= mFirstBuffer
;
424 // We created a key holder earlier, so we will find it without walking
425 // past the end of the list.
426 while (prevSearchBuf
->next
->key
!= aKey
) {
427 prevSearchBuf
= prevSearchBuf
->next
;
429 heapBuffer
->next
= prevSearchBuf
->next
;
430 prevSearchBuf
->next
= heapBuffer
;
433 NS_ASSERTION(firstLevelMarker
, "How come we don't have a marker.");
434 firstLevelMarker
->Swap(heapBuffer
);
438 if (!mBlocked
) { // buffer was tokenized to completion
439 NS_ASSERTION(!stackBuffer
.hasMore(),
440 "Buffer wasn't tokenized to completion?");
441 // Scripting semantics require a forced tree builder flush here
442 mTreeBuilder
->Flush(); // Move ops to the executor
443 rv
= mExecutor
->FlushDocumentWrite(); // run the ops
444 NS_ENSURE_SUCCESS(rv
, rv
);
445 } else if (stackBuffer
.hasMore()) {
446 // The buffer wasn't tokenized to completion. Tokenize the untokenized
447 // content in order to preload stuff. This content will be retokenized
448 // later for normal parsing.
449 if (!mDocWriteSpeculatorActive
) {
450 mDocWriteSpeculatorActive
= true;
451 if (!mDocWriteSpeculativeTreeBuilder
) {
452 // Lazily initialize if uninitialized
453 mDocWriteSpeculativeTreeBuilder
=
454 new nsHtml5TreeBuilder(nullptr, mExecutor
->GetStage());
455 mDocWriteSpeculativeTreeBuilder
->setScriptingEnabled(
456 mTreeBuilder
->isScriptingEnabled());
457 mDocWriteSpeculativeTokenizer
=
458 new nsHtml5Tokenizer(mDocWriteSpeculativeTreeBuilder
, false);
459 mDocWriteSpeculativeTokenizer
->setInterner(&mAtomTable
);
460 mDocWriteSpeculativeTokenizer
->start();
462 mDocWriteSpeculativeTokenizer
->resetToDataState();
463 mDocWriteSpeculativeTreeBuilder
->loadState(mTreeBuilder
, &mAtomTable
);
464 mDocWriteSpeculativeLastWasCR
= false;
467 // Note that with multilevel document.write if we didn't just activate the
468 // speculator, it's possible that the speculator is now in the wrong state.
469 // That's OK for the sake of simplicity. The worst that can happen is
470 // that the speculative loads aren't exactly right. The content will be
471 // reparsed anyway for non-preload purposes.
473 // The buffer position for subsequent non-speculative parsing now lives
474 // in heapBuffer, so it's ok to let the buffer position of stackBuffer
475 // to be overwritten and not restored below.
476 while (stackBuffer
.hasMore()) {
477 stackBuffer
.adjust(mDocWriteSpeculativeLastWasCR
);
478 if (stackBuffer
.hasMore()) {
479 mDocWriteSpeculativeLastWasCR
=
480 mDocWriteSpeculativeTokenizer
->tokenizeBuffer(&stackBuffer
);
484 mDocWriteSpeculativeTreeBuilder
->Flush();
485 mDocWriteSpeculativeTreeBuilder
->DropHandles();
486 mExecutor
->FlushSpeculativeLoads();
493 nsHtml5Parser::Terminate()
495 // We should only call DidBuildModel once, so don't do anything if this is
496 // the second time that Terminate has been called.
497 if (mExecutor
->IsComplete()) {
500 // XXX - [ until we figure out a way to break parser-sink circularity ]
501 // Hack - Hold a reference until we are completely done...
502 nsCOMPtr
<nsIParser
> kungFuDeathGrip(this);
503 nsRefPtr
<nsHtml5StreamParser
> streamKungFuDeathGrip(GetStreamParser());
504 nsRefPtr
<nsHtml5TreeOpExecutor
> treeOpKungFuDeathGrip(mExecutor
);
505 if (GetStreamParser()) {
506 GetStreamParser()->Terminate();
508 return mExecutor
->DidBuildModel(true);
512 nsHtml5Parser::ParseFragment(const nsAString
& aSourceBuffer
,
513 nsTArray
<nsString
>& aTagStack
)
515 return NS_ERROR_NOT_IMPLEMENTED
;
519 nsHtml5Parser::BuildModel()
521 NS_NOTREACHED("Don't call this!");
522 return NS_ERROR_NOT_IMPLEMENTED
;
526 nsHtml5Parser::CancelParsingEvents()
528 NS_NOTREACHED("Don't call this!");
529 return NS_ERROR_NOT_IMPLEMENTED
;
533 nsHtml5Parser::Reset()
535 NS_NOTREACHED("Don't call this!");
539 nsHtml5Parser::CanInterrupt()
541 // nsContentSink needs this to let nsContentSink::DidProcessATokenImpl
547 nsHtml5Parser::IsInsertionPointDefined()
549 return !mExecutor
->IsFlushing() &&
550 (!GetStreamParser() || mParserInsertedScriptsBeingEvaluated
);
554 nsHtml5Parser::BeginEvaluatingParserInsertedScript()
556 ++mParserInsertedScriptsBeingEvaluated
;
560 nsHtml5Parser::EndEvaluatingParserInsertedScript()
562 --mParserInsertedScriptsBeingEvaluated
;
566 nsHtml5Parser::MarkAsNotScriptCreated(const char* aCommand
)
568 NS_PRECONDITION(!mStreamListener
, "Must not call this twice.");
569 eParserMode mode
= NORMAL
;
570 if (!nsCRT::strcmp(aCommand
, "view-source")) {
571 mode
= VIEW_SOURCE_HTML
;
572 } else if (!nsCRT::strcmp(aCommand
, "view-source-xml")) {
573 mode
= VIEW_SOURCE_XML
;
574 } else if (!nsCRT::strcmp(aCommand
, "view-source-plain")) {
575 mode
= VIEW_SOURCE_PLAIN
;
576 } else if (!nsCRT::strcmp(aCommand
, "plain-text")) {
578 } else if (!nsCRT::strcmp(aCommand
, kLoadAsData
)) {
583 NS_ASSERTION(!nsCRT::strcmp(aCommand
, "view") ||
584 !nsCRT::strcmp(aCommand
, "external-resource") ||
585 !nsCRT::strcmp(aCommand
, "import"),
586 "Unsupported parser command!");
590 new nsHtml5StreamListener(new nsHtml5StreamParser(mExecutor
, this, mode
));
594 nsHtml5Parser::IsScriptCreated()
596 return !GetStreamParser();
601 // not from interface
603 nsHtml5Parser::ParseUntilBlocked()
605 nsresult rv
= mExecutor
->IsBroken();
606 NS_ENSURE_SUCCESS(rv
, rv
);
607 if (mBlocked
|| mExecutor
->IsComplete()) {
610 NS_ASSERTION(mExecutor
->HasStarted(), "Bad life cycle.");
611 NS_ASSERTION(!mInDocumentWrite
,
612 "ParseUntilBlocked entered while in doc.write!");
614 mDocWriteSpeculatorActive
= false;
617 if (!mFirstBuffer
->hasMore()) {
618 if (mFirstBuffer
== mLastBuffer
) {
619 if (mExecutor
->IsComplete()) {
620 // something like cache manisfests stopped the parse in mid-flight
623 if (mDocumentClosed
) {
624 NS_ASSERTION(!GetStreamParser(),
625 "This should only happen with script-created parser.");
627 mTreeBuilder
->StreamEnded();
628 mTreeBuilder
->Flush();
629 mExecutor
->FlushDocumentWrite();
630 // The below call does memory cleanup, so call it even if the
631 // parser has been marked as broken.
635 // never release the last buffer.
636 NS_ASSERTION(!mLastBuffer
->getStart() && !mLastBuffer
->getEnd(),
637 "Sentinel buffer had its indeces changed.");
638 if (GetStreamParser()) {
639 if (mReturnToStreamParserPermitted
&&
640 !mExecutor
->IsScriptExecuting()) {
641 mTreeBuilder
->Flush();
642 mReturnToStreamParserPermitted
= false;
643 GetStreamParser()->ContinueAfterScripts(mTokenizer
,
648 // Script-created parser
649 mTreeBuilder
->Flush();
650 // No need to flush the executor, because the executor is already
652 NS_ASSERTION(mExecutor
->IsInFlushLoop(),
653 "How did we come here without being in the flush loop?");
655 return NS_OK
; // no more data for now but expecting more
657 mFirstBuffer
= mFirstBuffer
->next
;
661 if (mBlocked
|| mExecutor
->IsComplete()) {
665 // now we have a non-empty buffer
666 mFirstBuffer
->adjust(mLastWasCR
);
668 if (mFirstBuffer
->hasMore()) {
669 bool inRootContext
= (!GetStreamParser() && !mFirstBuffer
->key
);
671 mTokenizer
->setLineNumber(mRootContextLineNumber
);
673 mLastWasCR
= mTokenizer
->tokenizeBuffer(mFirstBuffer
);
675 mRootContextLineNumber
= mTokenizer
->getLineNumber();
677 if (mTreeBuilder
->HasScript()) {
678 mTreeBuilder
->Flush();
679 nsresult rv
= mExecutor
->FlushDocumentWrite();
680 NS_ENSURE_SUCCESS(rv
, rv
);
691 nsHtml5Parser::Initialize(nsIDocument
* aDoc
,
693 nsISupports
* aContainer
,
694 nsIChannel
* aChannel
)
696 return mExecutor
->Init(aDoc
, aURI
, aContainer
, aChannel
);
700 nsHtml5Parser::StartTokenizer(bool aScriptingEnabled
) {
702 bool isSrcdoc
= false;
703 nsCOMPtr
<nsIChannel
> channel
;
704 nsresult rv
= GetChannel(getter_AddRefs(channel
));
705 if (NS_SUCCEEDED(rv
)) {
706 isSrcdoc
= NS_IsSrcdocChannel(channel
);
708 mTreeBuilder
->setIsSrcdocDocument(isSrcdoc
);
710 mTreeBuilder
->SetPreventScriptExecution(!aScriptingEnabled
);
711 mTreeBuilder
->setScriptingEnabled(aScriptingEnabled
);
716 nsHtml5Parser::InitializeDocWriteParserState(nsAHtml5TreeBuilderState
* aState
,
719 mTokenizer
->resetToDataState();
720 mTokenizer
->setLineNumber(aLine
);
721 mTreeBuilder
->loadState(aState
, &mAtomTable
);
723 mReturnToStreamParserPermitted
= true;
727 nsHtml5Parser::ContinueAfterFailedCharsetSwitch()
729 NS_PRECONDITION(GetStreamParser(),
730 "Tried to continue after failed charset switch without a stream parser");
731 GetStreamParser()->ContinueAfterFailedCharsetSwitch();