parser/html/nsHtml5DocumentBuilder.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/parser/html/nsHtml5DocumentBuilder.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,198 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim: set ts=2 sw=2 et tw=78: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef nsHtml5DocumentBuilder_h
    1.11 +#define nsHtml5DocumentBuilder_h
    1.12 +
    1.13 +#include "nsHtml5PendingNotification.h"
    1.14 +#include "nsContentSink.h"
    1.15 +#include "nsHtml5DocumentMode.h"
    1.16 +#include "nsIDocument.h"
    1.17 +
    1.18 +typedef nsIContent* nsIContentPtr;
    1.19 +
    1.20 +enum eHtml5FlushState {
    1.21 +  eNotFlushing = 0,  // not flushing
    1.22 +  eInFlush = 1,      // the Flush() method is on the call stack
    1.23 +  eInDocUpdate = 2,  // inside an update batch on the document
    1.24 +  eNotifying = 3     // flushing pending append notifications
    1.25 +};
    1.26 +
    1.27 +class nsHtml5DocumentBuilder : public nsContentSink
    1.28 +{
    1.29 +public:
    1.30 +  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHtml5DocumentBuilder,
    1.31 +                                           nsContentSink)
    1.32 +
    1.33 +  NS_DECL_ISUPPORTS_INHERITED
    1.34 +
    1.35 +  inline void HoldElement(nsIContent* aContent)
    1.36 +  {
    1.37 +    mOwnedElements.AppendElement(aContent);
    1.38 +  }
    1.39 +
    1.40 +  inline bool HaveNotified(nsIContent* aNode)
    1.41 +  {
    1.42 +    NS_PRECONDITION(aNode, "HaveNotified called with null argument.");
    1.43 +    const nsHtml5PendingNotification* start = mPendingNotifications.Elements();
    1.44 +    const nsHtml5PendingNotification* end = start + mPendingNotifications.Length();
    1.45 +    for (;;) {
    1.46 +      nsIContent* parent = aNode->GetParent();
    1.47 +      if (!parent) {
    1.48 +        return true;
    1.49 +      }
    1.50 +      for (nsHtml5PendingNotification* iter = (nsHtml5PendingNotification*)start; iter < end; ++iter) {
    1.51 +        if (iter->Contains(parent)) {
    1.52 +          return iter->HaveNotifiedIndex(parent->IndexOf(aNode));
    1.53 +        }
    1.54 +      }
    1.55 +      aNode = parent;
    1.56 +    }
    1.57 +  }
    1.58 +
    1.59 +  void PostPendingAppendNotification(nsIContent* aParent, nsIContent* aChild)
    1.60 +  {
    1.61 +    bool newParent = true;
    1.62 +    const nsIContentPtr* first = mElementsSeenInThisAppendBatch.Elements();
    1.63 +    const nsIContentPtr* last = first + mElementsSeenInThisAppendBatch.Length() - 1;
    1.64 +    for (const nsIContentPtr* iter = last; iter >= first; --iter) {
    1.65 +#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
    1.66 +      sAppendBatchSlotsExamined++;
    1.67 +#endif
    1.68 +      if (*iter == aParent) {
    1.69 +        newParent = false;
    1.70 +        break;
    1.71 +      }
    1.72 +    }
    1.73 +    if (aChild->IsElement()) {
    1.74 +      mElementsSeenInThisAppendBatch.AppendElement(aChild);
    1.75 +    }
    1.76 +    mElementsSeenInThisAppendBatch.AppendElement(aParent);
    1.77 +    if (newParent) {
    1.78 +      mPendingNotifications.AppendElement(aParent);
    1.79 +    }
    1.80 +#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
    1.81 +    sAppendBatchExaminations++;
    1.82 +#endif
    1.83 +  }
    1.84 +
    1.85 +  void FlushPendingAppendNotifications()
    1.86 +  {
    1.87 +    NS_PRECONDITION(mFlushState == eInDocUpdate, "Notifications flushed outside update");
    1.88 +    mFlushState = eNotifying;
    1.89 +    const nsHtml5PendingNotification* start = mPendingNotifications.Elements();
    1.90 +    const nsHtml5PendingNotification* end = start + mPendingNotifications.Length();
    1.91 +    for (nsHtml5PendingNotification* iter = (nsHtml5PendingNotification*)start; iter < end; ++iter) {
    1.92 +      iter->Fire();
    1.93 +    }
    1.94 +    mPendingNotifications.Clear();
    1.95 +#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
    1.96 +    if (mElementsSeenInThisAppendBatch.Length() > sAppendBatchMaxSize) {
    1.97 +      sAppendBatchMaxSize = mElementsSeenInThisAppendBatch.Length();
    1.98 +    }
    1.99 +#endif
   1.100 +    mElementsSeenInThisAppendBatch.Clear();
   1.101 +    NS_ASSERTION(mFlushState == eNotifying, "mFlushState out of sync");
   1.102 +    mFlushState = eInDocUpdate;
   1.103 +  }
   1.104 +
   1.105 +  nsresult Init(nsIDocument* aDoc, nsIURI* aURI,
   1.106 +                nsISupports* aContainer, nsIChannel* aChannel);
   1.107 +
   1.108 +  // Getters and setters for fields from nsContentSink
   1.109 +  nsIDocument* GetDocument()
   1.110 +  {
   1.111 +    return mDocument;
   1.112 +  }
   1.113 +
   1.114 +  nsNodeInfoManager* GetNodeInfoManager()
   1.115 +  {
   1.116 +    return mNodeInfoManager;
   1.117 +  }
   1.118 +
   1.119 +  /**
   1.120 +   * Marks this parser as broken and tells the stream parser (if any) to
   1.121 +   * terminate.
   1.122 +   *
   1.123 +   * @return aReason for convenience
   1.124 +   */
   1.125 +  virtual nsresult MarkAsBroken(nsresult aReason);
   1.126 +
   1.127 +  /**
   1.128 +   * Checks if this parser is broken. Returns a non-NS_OK (i.e. non-0)
   1.129 +   * value if broken.
   1.130 +   */
   1.131 +  inline nsresult IsBroken()
   1.132 +  {
   1.133 +    return mBroken;
   1.134 +  }
   1.135 +
   1.136 +  inline void BeginDocUpdate()
   1.137 +  {
   1.138 +    NS_PRECONDITION(mFlushState == eInFlush, "Tried to double-open update.");
   1.139 +    NS_PRECONDITION(mParser, "Started update without parser.");
   1.140 +    mFlushState = eInDocUpdate;
   1.141 +    mDocument->BeginUpdate(UPDATE_CONTENT_MODEL);
   1.142 +  }
   1.143 +
   1.144 +  inline void EndDocUpdate()
   1.145 +  {
   1.146 +    NS_PRECONDITION(mFlushState != eNotifying, "mFlushState out of sync");
   1.147 +    if (mFlushState == eInDocUpdate) {
   1.148 +      FlushPendingAppendNotifications();
   1.149 +      mFlushState = eInFlush;
   1.150 +      mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
   1.151 +    }
   1.152 +  }
   1.153 +
   1.154 +  void SetDocumentCharsetAndSource(nsACString& aCharset, int32_t aCharsetSource);
   1.155 +
   1.156 +  /**
   1.157 +   * Sets up style sheet load / parse
   1.158 +   */
   1.159 +  void UpdateStyleSheet(nsIContent* aElement);
   1.160 +
   1.161 +  void SetDocumentMode(nsHtml5DocumentMode m);
   1.162 +
   1.163 +  void SetNodeInfoManager(nsNodeInfoManager* aManager)
   1.164 +  {
   1.165 +    mNodeInfoManager = aManager;
   1.166 +  }
   1.167 +
   1.168 +  // nsContentSink methods
   1.169 +  virtual void UpdateChildCounts();
   1.170 +  virtual nsresult FlushTags();
   1.171 +
   1.172 +protected:
   1.173 +  inline void SetAppendBatchCapacity(uint32_t aCapacity)
   1.174 +  {
   1.175 +    mElementsSeenInThisAppendBatch.SetCapacity(aCapacity);
   1.176 +  }
   1.177 +
   1.178 +  nsHtml5DocumentBuilder(bool aRunsToCompletion);
   1.179 +  virtual ~nsHtml5DocumentBuilder();
   1.180 +
   1.181 +private:
   1.182 +  nsTArray<nsHtml5PendingNotification> mPendingNotifications;
   1.183 +  nsTArray<nsIContentPtr>              mElementsSeenInThisAppendBatch;
   1.184 +protected:
   1.185 +  nsTArray<nsCOMPtr<nsIContent> >      mOwnedElements;
   1.186 +  /**
   1.187 +   * Non-NS_OK if this parser should refuse to process any more input.
   1.188 +   * For example, the parser needs to be marked as broken if it drops some
   1.189 +   * input due to a memory allocation failure. In such a case, the whole
   1.190 +   * parser needs to be marked as broken, because some input has been lost
   1.191 +   * and parsing more input could lead to a DOM where pieces of HTML source
   1.192 +   * that weren't supposed to become scripts become scripts.
   1.193 +   *
   1.194 +   * Since NS_OK is actually 0, zeroing operator new takes care of
   1.195 +   * initializing this.
   1.196 +   */
   1.197 +  nsresult                             mBroken;
   1.198 +  eHtml5FlushState                     mFlushState;
   1.199 +};
   1.200 +
   1.201 +#endif // nsHtml5DocumentBuilder_h

mercurial