1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef NS_HTML5_PARSER
7 #define NS_HTML5_PARSER
9 #include "mozilla/UniquePtr.h"
10 #include "nsIParser.h"
12 #include "nsIContentSink.h"
13 #include "nsIRequest.h"
14 #include "nsIChannel.h"
15 #include "nsCOMArray.h"
16 #include "nsContentSink.h"
17 #include "nsCycleCollectionParticipant.h"
18 #include "nsHtml5OwningUTF16Buffer.h"
19 #include "nsHtml5TreeOpExecutor.h"
20 #include "nsHtml5StreamParser.h"
21 #include "nsHtml5AtomTable.h"
22 #include "nsWeakReference.h"
23 #include "nsHtml5StreamListener.h"
24 #include "nsCharsetSource.h"
26 class nsHtml5Parser final
: public nsIParser
, public nsSupportsWeakReference
{
28 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
30 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsHtml5Parser
, nsIParser
)
36 * No-op for backwards compat.
38 NS_IMETHOD_(void) SetContentSink(nsIContentSink
* aSink
) override
;
41 * Returns the tree op executor for backwards compat.
43 NS_IMETHOD_(nsIContentSink
*) GetContentSink() override
;
46 * Always returns "view" for backwards compat.
48 NS_IMETHOD_(void) GetCommand(nsCString
& aCommand
) override
;
51 * No-op for backwards compat.
53 NS_IMETHOD_(void) SetCommand(const char* aCommand
) override
;
56 * No-op for backwards compat.
58 NS_IMETHOD_(void) SetCommand(eParserCommands aParserCommand
) override
;
61 * Call this method once you've created a parser, and want to instruct it
62 * about what charset to load
64 * @param aEncoding the charset of a document
65 * @param aCharsetSource the source of the charset
67 virtual void SetDocumentCharset(NotNull
<const Encoding
*> aEncoding
,
69 bool aForceAutoDetection
) override
;
72 * Get the channel associated with this parser
73 * @param aChannel out param that will contain the result
74 * @return NS_OK if successful or NS_NOT_AVAILABLE if not
76 nsresult
GetChannel(nsIChannel
** aChannel
);
79 * Get the stream parser for this parser
81 virtual nsIStreamListener
* GetStreamListener() override
;
84 * Don't call. For interface compat only.
86 NS_IMETHOD
ContinueInterruptedParsing() override
;
91 NS_IMETHOD_(void) BlockParser() override
;
94 * Unblocks the parser.
96 NS_IMETHOD_(void) UnblockParser() override
;
99 * Asynchronously continues parsing.
101 NS_IMETHOD_(void) ContinueInterruptedParsingAsync() override
;
104 * Query whether the parser is enabled (i.e. not blocked) or not.
106 NS_IMETHOD_(bool) IsParserEnabled() override
;
109 * Query whether the parser is closed (i.e. document.closed() is called) or
112 NS_IMETHOD_(bool) IsParserClosed() override
;
115 * Query whether the parser thinks it's done with parsing.
117 NS_IMETHOD_(bool) IsComplete() override
;
120 * Set up request observer.
122 * @param aURL used for View Source title
124 NS_IMETHOD
Parse(nsIURI
* aURL
) override
;
127 * document.write and document.close
129 * @param aSourceBuffer the argument of document.write (empty for .close())
130 * @param aKey a key unique to the script element that caused this call
131 * @param aLastCall true if .close() false if .write()
133 nsresult
Parse(const nsAString
& aSourceBuffer
, void* aKey
, bool aLastCall
);
136 * Stops the parser prematurely
138 NS_IMETHOD
Terminate() override
;
141 * True if the insertion point (per HTML5) is defined.
143 virtual bool IsInsertionPointDefined() override
;
146 * Call immediately before starting to evaluate a parser-inserted script or
147 * in general when the spec says to increment the script nesting level.
149 void IncrementScriptNestingLevel() final
;
152 * Call immediately after having evaluated a parser-inserted script or
153 * generally want to restore to the state before the last
154 * IncrementScriptNestingLevel call.
156 void DecrementScriptNestingLevel() final
;
159 * True if this is an HTML5 parser whose script nesting level (in
161 * <https://html.spec.whatwg.org/multipage/parsing.html#script-nesting-level>)
164 bool HasNonzeroScriptNestingLevel() const final
;
167 * Marks the HTML5 parser as not a script-created parser: Prepares the
168 * parser to be able to read a stream.
170 * @param aCommand the parser command (Yeah, this is bad API design. Let's
171 * make this better when retiring nsIParser)
173 void MarkAsNotScriptCreated(const char* aCommand
);
176 * True if this is a script-created HTML5 parser.
178 virtual bool IsScriptCreated() override
;
182 // Not from an external interface
183 // Non-inherited methods
187 * Initializes the parser to load from a channel.
189 virtual nsresult
Initialize(mozilla::dom::Document
* aDoc
, nsIURI
* aURI
,
190 nsISupports
* aContainer
, nsIChannel
* aChannel
);
192 inline nsHtml5Tokenizer
* GetTokenizer() { return mTokenizer
.get(); }
194 void InitializeDocWriteParserState(nsAHtml5TreeBuilderState
* aState
,
197 void DropStreamParser() {
198 if (GetStreamParser()) {
199 GetStreamParser()->DropTimer();
200 mStreamListener
->DropDelegate();
201 mStreamListener
= nullptr;
205 void StartTokenizer(bool aScriptingEnabled
);
207 void ContinueAfterFailedCharsetSwitch();
209 nsHtml5StreamParser
* GetStreamParser() {
210 if (!mStreamListener
) {
213 return mStreamListener
->GetDelegate();
216 void PermanentlyUndefineInsertionPoint() {
217 mInsertionPointPermanentlyUndefined
= true;
221 * Parse until pending data is exhausted or a script blocks the parser
223 nsresult
ParseUntilBlocked();
226 * Start our executor. This is meant to be used from document.open() _only_
227 * and does some work similar to what nsHtml5StreamParser::OnStartRequest does
230 nsresult
StartExecutor();
233 virtual ~nsHtml5Parser();
238 * Whether the last character tokenized was a carriage return (for CRLF)
243 * Whether the last character tokenized was a carriage return (for CRLF)
244 * when preparsing document.write.
246 bool mDocWriteSpeculativeLastWasCR
;
249 * The parser is blocking on the load of an external script from a web
250 * page, or any number of extension content scripts.
255 * Whether the document.write() speculator is already active.
257 bool mDocWriteSpeculatorActive
;
260 * The number of IncrementScriptNestingLevel calls we've seen without a
261 * matching DecrementScriptNestingLevel.
263 int32_t mScriptNestingLevel
;
266 * True if document.close() has been called.
268 bool mDocumentClosed
;
270 bool mInDocumentWrite
;
273 * This is set when the tokenizer has seen EOF. The purpose is to
274 * keep the insertion point undefined between the time the
275 * parser has reached the point where it can't accept more input
276 * and the time the document's mParser is set to nullptr.
277 * Scripts can run during this time period due to an update
278 * batch ending and due to various end-of-parse events firing.
279 * (Setting mParser on the document to nullptr at the point
280 * where this flag gets set to true would break things that for
281 * legacy reasons assume that mParser on the document stays
282 * non-null though the end-of-parse events.)
284 bool mInsertionPointPermanentlyUndefined
;
286 // Portable parser objects
288 * The first buffer in the pending UTF-16 buffer queue
290 RefPtr
<nsHtml5OwningUTF16Buffer
> mFirstBuffer
;
293 * The last buffer in the pending UTF-16 buffer queue. Always points
294 * to a sentinel object with nullptr as its parser key.
296 nsHtml5OwningUTF16Buffer
* mLastBuffer
; // weak ref;
299 * The tree operation executor
301 RefPtr
<nsHtml5TreeOpExecutor
> mExecutor
;
304 * The HTML5 tree builder
306 const mozilla::UniquePtr
<nsHtml5TreeBuilder
> mTreeBuilder
;
309 * The HTML5 tokenizer
311 const mozilla::UniquePtr
<nsHtml5Tokenizer
> mTokenizer
;
314 * Another HTML5 tree builder for preloading document.written content.
316 mozilla::UniquePtr
<nsHtml5TreeBuilder
> mDocWriteSpeculativeTreeBuilder
;
319 * Another HTML5 tokenizer for preloading document.written content.
321 mozilla::UniquePtr
<nsHtml5Tokenizer
> mDocWriteSpeculativeTokenizer
;
324 * The stream listener holding the stream parser.
326 RefPtr
<nsHtml5StreamListener
> mStreamListener
;
331 int32_t mRootContextLineNumber
;
334 * Whether it's OK to transfer parsing back to the stream parser
336 bool mReturnToStreamParserPermitted
;
339 * The scoped atom table
341 nsHtml5AtomTable mAtomTable
;