michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #define NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH 512 michael@0: michael@0: private: michael@0: nsHtml5OplessBuilder* mBuilder; michael@0: // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! michael@0: // If mBuilder is not null, the tree op machinery is not in use and michael@0: // the fields below aren't in use, either. michael@0: // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! michael@0: nsHtml5Highlighter* mViewSource; michael@0: nsTArray mOpQueue; michael@0: nsTArray mSpeculativeLoadQueue; michael@0: nsAHtml5TreeOpSink* mOpSink; michael@0: nsAutoArrayPtr mHandles; michael@0: int32_t mHandlesUsed; michael@0: nsTArray > mOldHandles; michael@0: nsHtml5TreeOpStage* mSpeculativeLoadStage; michael@0: bool mCurrentHtmlScriptIsAsyncOrDefer; michael@0: bool mPreventScriptExecution; michael@0: #ifdef DEBUG michael@0: bool mActive; michael@0: #endif michael@0: michael@0: // DocumentModeHandler michael@0: /** michael@0: * Tree builder uses this to report quirkiness of the document michael@0: */ michael@0: void documentMode(nsHtml5DocumentMode m); michael@0: michael@0: nsIContentHandle* getDocumentFragmentForTemplate(nsIContentHandle* aTemplate); michael@0: michael@0: nsIContentHandle* getFormPointerForContext(nsIContentHandle* aContext); michael@0: michael@0: /** michael@0: * Using nsIContent** instead of nsIContent* is the parser deals with DOM michael@0: * nodes in a way that works off the main thread. Non-main-thread code michael@0: * can't refcount or otherwise touch nsIContent objects in any way. michael@0: * Yet, the off-the-main-thread code needs to have a way to hold onto a michael@0: * particular node and repeatedly operate on the same node. michael@0: * michael@0: * The way this works is that the off-the-main-thread code has an michael@0: * nsIContent** for each DOM node and a given nsIContent** is only ever michael@0: * actually dereferenced into an actual nsIContent* on the main thread. michael@0: * When the off-the-main-thread code requests a new node, it gets an michael@0: * nsIContent** immediately and a tree op is enqueued for later allocating michael@0: * an actual nsIContent object and writing a pointer to it into the memory michael@0: * location pointed to by the nsIContent**. michael@0: * michael@0: * Since tree ops are in a queue, the node creating tree op will always michael@0: * run before tree ops that try to further operate on the node that the michael@0: * nsIContent** is a handle to. michael@0: * michael@0: * On-the-main-thread parts of the parser use nsIContent* instead of michael@0: * nsIContent**. Since both cases share the same parser core, the parser michael@0: * core casts both to nsIContentHandle*. michael@0: */ michael@0: nsIContentHandle* AllocateContentHandle(); michael@0: michael@0: void accumulateCharactersForced(const char16_t* aBuf, int32_t aStart, int32_t aLength) michael@0: { michael@0: accumulateCharacters(aBuf, aStart, aLength); michael@0: } michael@0: michael@0: void MarkAsBrokenAndRequestSuspension(nsresult aRv) michael@0: { michael@0: mBuilder->MarkAsBroken(aRv); michael@0: requestSuspension(); michael@0: } michael@0: michael@0: public: michael@0: michael@0: nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder); michael@0: michael@0: nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink, michael@0: nsHtml5TreeOpStage* aStage); michael@0: michael@0: ~nsHtml5TreeBuilder(); michael@0: michael@0: void StartPlainTextViewSource(const nsAutoString& aTitle); michael@0: michael@0: void StartPlainText(); michael@0: michael@0: void StartPlainTextBody(); michael@0: michael@0: bool HasScript(); michael@0: michael@0: void SetOpSink(nsAHtml5TreeOpSink* aOpSink) michael@0: { michael@0: mOpSink = aOpSink; michael@0: } michael@0: michael@0: void ClearOps() michael@0: { michael@0: mOpQueue.Clear(); michael@0: } michael@0: michael@0: bool Flush(bool aDiscretionary = false); michael@0: michael@0: void FlushLoads(); michael@0: michael@0: void SetDocumentCharset(nsACString& aCharset, int32_t aCharsetSource); michael@0: michael@0: void StreamEnded(); michael@0: michael@0: void NeedsCharsetSwitchTo(const nsACString& aEncoding, michael@0: int32_t aSource, michael@0: int32_t aLineNumber); michael@0: michael@0: void MaybeComplainAboutCharset(const char* aMsgId, michael@0: bool aError, michael@0: int32_t aLineNumber); michael@0: michael@0: void AddSnapshotToScript(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine); michael@0: michael@0: void DropHandles(); michael@0: michael@0: void SetPreventScriptExecution(bool aPrevent) michael@0: { michael@0: mPreventScriptExecution = aPrevent; michael@0: } michael@0: michael@0: bool HasBuilder() michael@0: { michael@0: return mBuilder; michael@0: } michael@0: michael@0: void EnableViewSource(nsHtml5Highlighter* aHighlighter); michael@0: michael@0: void errStrayStartTag(nsIAtom* aName); michael@0: michael@0: void errStrayEndTag(nsIAtom* aName); michael@0: michael@0: void errUnclosedElements(int32_t aIndex, nsIAtom* aName); michael@0: michael@0: void errUnclosedElementsImplied(int32_t aIndex, nsIAtom* aName); michael@0: michael@0: void errUnclosedElementsCell(int32_t aIndex); michael@0: michael@0: void errStrayDoctype(); michael@0: michael@0: void errAlmostStandardsDoctype(); michael@0: michael@0: void errQuirkyDoctype(); michael@0: michael@0: void errNonSpaceInTrailer(); michael@0: michael@0: void errNonSpaceAfterFrameset(); michael@0: michael@0: void errNonSpaceInFrameset(); michael@0: michael@0: void errNonSpaceAfterBody(); michael@0: michael@0: void errNonSpaceInColgroupInFragment(); michael@0: michael@0: void errNonSpaceInNoscriptInHead(); michael@0: michael@0: void errFooBetweenHeadAndBody(nsIAtom* aName); michael@0: michael@0: void errStartTagWithoutDoctype(); michael@0: michael@0: void errNoSelectInTableScope(); michael@0: michael@0: void errStartSelectWhereEndSelectExpected(); michael@0: michael@0: void errStartTagWithSelectOpen(nsIAtom* aName); michael@0: michael@0: void errBadStartTagInHead(nsIAtom* aName); michael@0: michael@0: void errImage(); michael@0: michael@0: void errIsindex(); michael@0: michael@0: void errFooSeenWhenFooOpen(nsIAtom* aName); michael@0: michael@0: void errHeadingWhenHeadingOpen(); michael@0: michael@0: void errFramesetStart(); michael@0: michael@0: void errNoCellToClose(); michael@0: michael@0: void errStartTagInTable(nsIAtom* aName); michael@0: michael@0: void errFormWhenFormOpen(); michael@0: michael@0: void errTableSeenWhileTableOpen(); michael@0: michael@0: void errStartTagInTableBody(nsIAtom* aName); michael@0: michael@0: void errEndTagSeenWithoutDoctype(); michael@0: michael@0: void errEndTagAfterBody(); michael@0: michael@0: void errEndTagSeenWithSelectOpen(nsIAtom* aName); michael@0: michael@0: void errGarbageInColgroup(); michael@0: michael@0: void errEndTagBr(); michael@0: michael@0: void errNoElementToCloseButEndTagSeen(nsIAtom* aName); michael@0: michael@0: void errHtmlStartTagInForeignContext(nsIAtom* aName); michael@0: michael@0: void errTableClosedWhileCaptionOpen(); michael@0: michael@0: void errNoTableRowToClose(); michael@0: michael@0: void errNonSpaceInTable(); michael@0: michael@0: void errUnclosedChildrenInRuby(); michael@0: michael@0: void errStartTagSeenWithoutRuby(nsIAtom* aName); michael@0: michael@0: void errSelfClosing(); michael@0: michael@0: void errNoCheckUnclosedElementsOnStack(); michael@0: michael@0: void errEndTagDidNotMatchCurrentOpenElement(nsIAtom* aName, nsIAtom* aOther); michael@0: michael@0: void errEndTagViolatesNestingRules(nsIAtom* aName); michael@0: michael@0: void errEndWithUnclosedElements(nsIAtom* aName); michael@0: michael@0: void MarkAsBroken(nsresult aRv);