1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/parser/html/nsHtml5TreeOperation.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,508 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#ifndef nsHtml5TreeOperation_h 1.9 +#define nsHtml5TreeOperation_h 1.10 + 1.11 +#include "nsHtml5DocumentMode.h" 1.12 +#include "nsHtml5HtmlAttributes.h" 1.13 +#include "nsXPCOMStrings.h" 1.14 +#include "mozilla/dom/FromParser.h" 1.15 + 1.16 +class nsIContent; 1.17 +class nsHtml5TreeOpExecutor; 1.18 +class nsHtml5StateSnapshot; 1.19 +class nsHtml5DocumentBuilder; 1.20 + 1.21 +enum eHtml5TreeOperation { 1.22 +#ifdef DEBUG 1.23 + eTreeOpUninitialized, 1.24 +#endif 1.25 + // main HTML5 ops 1.26 + eTreeOpAppend, 1.27 + eTreeOpDetach, 1.28 + eTreeOpAppendChildrenToNewParent, 1.29 + eTreeOpFosterParent, 1.30 + eTreeOpAppendToDocument, 1.31 + eTreeOpAddAttributes, 1.32 + eTreeOpDocumentMode, 1.33 + eTreeOpCreateElementNetwork, 1.34 + eTreeOpCreateElementNotNetwork, 1.35 + eTreeOpSetFormElement, 1.36 + eTreeOpAppendText, 1.37 + eTreeOpAppendIsindexPrompt, 1.38 + eTreeOpFosterParentText, 1.39 + eTreeOpAppendComment, 1.40 + eTreeOpAppendCommentToDocument, 1.41 + eTreeOpAppendDoctypeToDocument, 1.42 + eTreeOpGetDocumentFragmentForTemplate, 1.43 + // Gecko-specific on-pop ops 1.44 + eTreeOpMarkAsBroken, 1.45 + eTreeOpRunScript, 1.46 + eTreeOpRunScriptAsyncDefer, 1.47 + eTreeOpPreventScriptExecution, 1.48 + eTreeOpDoneAddingChildren, 1.49 + eTreeOpDoneCreatingElement, 1.50 + eTreeOpFlushPendingAppendNotifications, 1.51 + eTreeOpSetDocumentCharset, 1.52 + eTreeOpNeedsCharsetSwitchTo, 1.53 + eTreeOpUpdateStyleSheet, 1.54 + eTreeOpProcessMeta, 1.55 + eTreeOpProcessOfflineManifest, 1.56 + eTreeOpMarkMalformedIfScript, 1.57 + eTreeOpStreamEnded, 1.58 + eTreeOpSetStyleLineNumber, 1.59 + eTreeOpSetScriptLineNumberAndFreeze, 1.60 + eTreeOpSvgLoad, 1.61 + eTreeOpMaybeComplainAboutCharset, 1.62 + eTreeOpAddClass, 1.63 + eTreeOpAddViewSourceHref, 1.64 + eTreeOpAddError, 1.65 + eTreeOpAddLineNumberId, 1.66 + eTreeOpAddErrorAtom, 1.67 + eTreeOpAddErrorTwoAtoms, 1.68 + eTreeOpStartLayout 1.69 +}; 1.70 + 1.71 +class nsHtml5TreeOperationStringPair { 1.72 + private: 1.73 + nsString mPublicId; 1.74 + nsString mSystemId; 1.75 + public: 1.76 + nsHtml5TreeOperationStringPair(const nsAString& aPublicId, 1.77 + const nsAString& aSystemId) 1.78 + : mPublicId(aPublicId) 1.79 + , mSystemId(aSystemId) 1.80 + { 1.81 + MOZ_COUNT_CTOR(nsHtml5TreeOperationStringPair); 1.82 + } 1.83 + 1.84 + ~nsHtml5TreeOperationStringPair() 1.85 + { 1.86 + MOZ_COUNT_DTOR(nsHtml5TreeOperationStringPair); 1.87 + } 1.88 + 1.89 + inline void Get(nsAString& aPublicId, nsAString& aSystemId) 1.90 + { 1.91 + aPublicId.Assign(mPublicId); 1.92 + aSystemId.Assign(mSystemId); 1.93 + } 1.94 +}; 1.95 + 1.96 +class nsHtml5TreeOperation { 1.97 + 1.98 + public: 1.99 + /** 1.100 + * Atom is used inside the parser core are either static atoms that are 1.101 + * the same as Gecko-wide static atoms or they are dynamic atoms scoped by 1.102 + * both thread and parser to a particular nsHtml5AtomTable. In order to 1.103 + * such scoped atoms coming into contact with the rest of Gecko, atoms 1.104 + * that are about to exit the parser must go through this method which 1.105 + * reobtains dynamic atoms from the Gecko-global atom table. 1.106 + * 1.107 + * @param aAtom a potentially parser-scoped atom 1.108 + * @return an nsIAtom that's pointer comparable on the main thread with 1.109 + * other not-parser atoms. 1.110 + */ 1.111 + static inline already_AddRefed<nsIAtom> Reget(nsIAtom* aAtom) 1.112 + { 1.113 + if (!aAtom || aAtom->IsStaticAtom()) { 1.114 + return dont_AddRef(aAtom); 1.115 + } 1.116 + nsAutoString str; 1.117 + aAtom->ToString(str); 1.118 + return do_GetAtom(str); 1.119 + } 1.120 + 1.121 + static nsresult AppendTextToTextNode(const char16_t* aBuffer, 1.122 + uint32_t aLength, 1.123 + nsIContent* aTextNode, 1.124 + nsHtml5DocumentBuilder* aBuilder); 1.125 + 1.126 + static nsresult AppendText(const char16_t* aBuffer, 1.127 + uint32_t aLength, 1.128 + nsIContent* aParent, 1.129 + nsHtml5DocumentBuilder* aBuilder); 1.130 + 1.131 + static nsresult Append(nsIContent* aNode, 1.132 + nsIContent* aParent, 1.133 + nsHtml5DocumentBuilder* aBuilder); 1.134 + 1.135 + static nsresult AppendToDocument(nsIContent* aNode, 1.136 + nsHtml5DocumentBuilder* aBuilder); 1.137 + 1.138 + static void Detach(nsIContent* aNode, nsHtml5DocumentBuilder* aBuilder); 1.139 + 1.140 + static nsresult AppendChildrenToNewParent(nsIContent* aNode, 1.141 + nsIContent* aParent, 1.142 + nsHtml5DocumentBuilder* aBuilder); 1.143 + 1.144 + static nsresult FosterParent(nsIContent* aNode, 1.145 + nsIContent* aParent, 1.146 + nsIContent* aTable, 1.147 + nsHtml5DocumentBuilder* aBuilder); 1.148 + 1.149 + static nsresult AddAttributes(nsIContent* aNode, 1.150 + nsHtml5HtmlAttributes* aAttributes, 1.151 + nsHtml5DocumentBuilder* aBuilder); 1.152 + 1.153 + static nsIContent* CreateElement(int32_t aNs, 1.154 + nsIAtom* aName, 1.155 + nsHtml5HtmlAttributes* aAttributes, 1.156 + mozilla::dom::FromParser aFromParser, 1.157 + nsHtml5DocumentBuilder* aBuilder); 1.158 + 1.159 + static void SetFormElement(nsIContent* aNode, nsIContent* aParent); 1.160 + 1.161 + static nsresult AppendIsindexPrompt(nsIContent* parent, 1.162 + nsHtml5DocumentBuilder* aBuilder); 1.163 + 1.164 + static nsresult FosterParentText(nsIContent* aStackParent, 1.165 + char16_t* aBuffer, 1.166 + uint32_t aLength, 1.167 + nsIContent* aTable, 1.168 + nsHtml5DocumentBuilder* aBuilder); 1.169 + 1.170 + static nsresult AppendComment(nsIContent* aParent, 1.171 + char16_t* aBuffer, 1.172 + int32_t aLength, 1.173 + nsHtml5DocumentBuilder* aBuilder); 1.174 + 1.175 + static nsresult AppendCommentToDocument(char16_t* aBuffer, 1.176 + int32_t aLength, 1.177 + nsHtml5DocumentBuilder* aBuilder); 1.178 + 1.179 + static nsresult AppendDoctypeToDocument(nsIAtom* aName, 1.180 + const nsAString& aPublicId, 1.181 + const nsAString& aSystemId, 1.182 + nsHtml5DocumentBuilder* aBuilder); 1.183 + 1.184 + static nsIContent* GetDocumentFragmentForTemplate(nsIContent* aNode); 1.185 + 1.186 + static void PreventScriptExecution(nsIContent* aNode); 1.187 + 1.188 + static void DoneAddingChildren(nsIContent* aNode, 1.189 + nsHtml5DocumentBuilder* aBuilder); 1.190 + 1.191 + static void DoneCreatingElement(nsIContent* aNode); 1.192 + 1.193 + static void SvgLoad(nsIContent* aNode); 1.194 + 1.195 + static void MarkMalformedIfScript(nsIContent* aNode); 1.196 + 1.197 + nsHtml5TreeOperation(); 1.198 + 1.199 + ~nsHtml5TreeOperation(); 1.200 + 1.201 + inline void Init(eHtml5TreeOperation aOpCode) 1.202 + { 1.203 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.204 + "Op code must be uninitialized when initializing."); 1.205 + mOpCode = aOpCode; 1.206 + } 1.207 + 1.208 + inline void Init(eHtml5TreeOperation aOpCode, nsIContentHandle* aNode) 1.209 + { 1.210 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.211 + "Op code must be uninitialized when initializing."); 1.212 + NS_PRECONDITION(aNode, "Initialized tree op with null node."); 1.213 + mOpCode = aOpCode; 1.214 + mOne.node = static_cast<nsIContent**>(aNode); 1.215 + } 1.216 + 1.217 + inline void Init(eHtml5TreeOperation aOpCode, 1.218 + nsIContentHandle* aNode, 1.219 + nsIContentHandle* aParent) 1.220 + { 1.221 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.222 + "Op code must be uninitialized when initializing."); 1.223 + NS_PRECONDITION(aNode, "Initialized tree op with null node."); 1.224 + NS_PRECONDITION(aParent, "Initialized tree op with null parent."); 1.225 + mOpCode = aOpCode; 1.226 + mOne.node = static_cast<nsIContent**>(aNode); 1.227 + mTwo.node = static_cast<nsIContent**>(aParent); 1.228 + } 1.229 + 1.230 + inline void Init(eHtml5TreeOperation aOpCode, 1.231 + const nsACString& aString, 1.232 + int32_t aInt32) 1.233 + { 1.234 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.235 + "Op code must be uninitialized when initializing."); 1.236 + 1.237 + int32_t len = aString.Length(); 1.238 + char* str = new char[len + 1]; 1.239 + const char* start = aString.BeginReading(); 1.240 + for (int32_t i = 0; i < len; ++i) { 1.241 + str[i] = start[i]; 1.242 + } 1.243 + str[len] = '\0'; 1.244 + 1.245 + mOpCode = aOpCode; 1.246 + mOne.charPtr = str; 1.247 + mFour.integer = aInt32; 1.248 + } 1.249 + 1.250 + inline void Init(eHtml5TreeOperation aOpCode, 1.251 + const nsACString& aString, 1.252 + int32_t aInt32, 1.253 + int32_t aLineNumber) 1.254 + { 1.255 + Init(aOpCode, aString, aInt32); 1.256 + mTwo.integer = aLineNumber; 1.257 + } 1.258 + 1.259 + inline void Init(eHtml5TreeOperation aOpCode, 1.260 + nsIContentHandle* aNode, 1.261 + nsIContentHandle* aParent, 1.262 + nsIContentHandle* aTable) 1.263 + { 1.264 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.265 + "Op code must be uninitialized when initializing."); 1.266 + NS_PRECONDITION(aNode, "Initialized tree op with null node."); 1.267 + NS_PRECONDITION(aParent, "Initialized tree op with null parent."); 1.268 + NS_PRECONDITION(aTable, "Initialized tree op with null table."); 1.269 + mOpCode = aOpCode; 1.270 + mOne.node = static_cast<nsIContent**>(aNode); 1.271 + mTwo.node = static_cast<nsIContent**>(aParent); 1.272 + mThree.node = static_cast<nsIContent**>(aTable); 1.273 + } 1.274 + 1.275 + inline void Init(nsHtml5DocumentMode aMode) 1.276 + { 1.277 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.278 + "Op code must be uninitialized when initializing."); 1.279 + mOpCode = eTreeOpDocumentMode; 1.280 + mOne.mode = aMode; 1.281 + } 1.282 + 1.283 + inline void InitScript(nsIContentHandle* aNode) 1.284 + { 1.285 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.286 + "Op code must be uninitialized when initializing."); 1.287 + NS_PRECONDITION(aNode, "Initialized tree op with null node."); 1.288 + mOpCode = eTreeOpRunScript; 1.289 + mOne.node = static_cast<nsIContent**>(aNode); 1.290 + mTwo.state = nullptr; 1.291 + } 1.292 + 1.293 + inline void Init(int32_t aNamespace, 1.294 + nsIAtom* aName, 1.295 + nsHtml5HtmlAttributes* aAttributes, 1.296 + nsIContentHandle* aTarget, 1.297 + bool aFromNetwork) 1.298 + { 1.299 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.300 + "Op code must be uninitialized when initializing."); 1.301 + NS_PRECONDITION(aName, "Initialized tree op with null name."); 1.302 + NS_PRECONDITION(aTarget, "Initialized tree op with null target node."); 1.303 + mOpCode = aFromNetwork ? 1.304 + eTreeOpCreateElementNetwork : 1.305 + eTreeOpCreateElementNotNetwork; 1.306 + mFour.integer = aNamespace; 1.307 + mOne.node = static_cast<nsIContent**>(aTarget); 1.308 + mTwo.atom = aName; 1.309 + if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) { 1.310 + mThree.attributes = nullptr; 1.311 + } else { 1.312 + mThree.attributes = aAttributes; 1.313 + } 1.314 + } 1.315 + 1.316 + inline void Init(eHtml5TreeOperation aOpCode, 1.317 + char16_t* aBuffer, 1.318 + int32_t aLength, 1.319 + nsIContentHandle* aStackParent, 1.320 + nsIContentHandle* aTable) 1.321 + { 1.322 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.323 + "Op code must be uninitialized when initializing."); 1.324 + NS_PRECONDITION(aBuffer, "Initialized tree op with null buffer."); 1.325 + mOpCode = aOpCode; 1.326 + mOne.node = static_cast<nsIContent**>(aStackParent); 1.327 + mTwo.unicharPtr = aBuffer; 1.328 + mThree.node = static_cast<nsIContent**>(aTable); 1.329 + mFour.integer = aLength; 1.330 + } 1.331 + 1.332 + inline void Init(eHtml5TreeOperation aOpCode, 1.333 + char16_t* aBuffer, 1.334 + int32_t aLength, 1.335 + nsIContentHandle* aParent) 1.336 + { 1.337 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.338 + "Op code must be uninitialized when initializing."); 1.339 + NS_PRECONDITION(aBuffer, "Initialized tree op with null buffer."); 1.340 + mOpCode = aOpCode; 1.341 + mOne.node = static_cast<nsIContent**>(aParent); 1.342 + mTwo.unicharPtr = aBuffer; 1.343 + mFour.integer = aLength; 1.344 + } 1.345 + 1.346 + inline void Init(eHtml5TreeOperation aOpCode, 1.347 + char16_t* aBuffer, 1.348 + int32_t aLength) 1.349 + { 1.350 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.351 + "Op code must be uninitialized when initializing."); 1.352 + NS_PRECONDITION(aBuffer, "Initialized tree op with null buffer."); 1.353 + mOpCode = aOpCode; 1.354 + mTwo.unicharPtr = aBuffer; 1.355 + mFour.integer = aLength; 1.356 + } 1.357 + 1.358 + inline void Init(nsIContentHandle* aElement, 1.359 + nsHtml5HtmlAttributes* aAttributes) 1.360 + { 1.361 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.362 + "Op code must be uninitialized when initializing."); 1.363 + NS_PRECONDITION(aElement, "Initialized tree op with null element."); 1.364 + mOpCode = eTreeOpAddAttributes; 1.365 + mOne.node = static_cast<nsIContent**>(aElement); 1.366 + mTwo.attributes = aAttributes; 1.367 + } 1.368 + 1.369 + inline void Init(nsIAtom* aName, 1.370 + const nsAString& aPublicId, 1.371 + const nsAString& aSystemId) 1.372 + { 1.373 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.374 + "Op code must be uninitialized when initializing."); 1.375 + mOpCode = eTreeOpAppendDoctypeToDocument; 1.376 + mOne.atom = aName; 1.377 + mTwo.stringPair = new nsHtml5TreeOperationStringPair(aPublicId, aSystemId); 1.378 + } 1.379 + 1.380 + inline void Init(nsIContentHandle* aElement, 1.381 + const char* aMsgId, 1.382 + nsIAtom* aAtom, 1.383 + nsIAtom* aOtherAtom) 1.384 + { 1.385 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.386 + "Op code must be uninitialized when initializing."); 1.387 + mOpCode = eTreeOpAddError; 1.388 + mOne.node = static_cast<nsIContent**>(aElement); 1.389 + mTwo.charPtr = (char*)aMsgId; 1.390 + mThree.atom = aAtom; 1.391 + mFour.atom = aOtherAtom; 1.392 + } 1.393 + 1.394 + inline void Init(nsIContentHandle* aElement, 1.395 + const char* aMsgId, 1.396 + nsIAtom* aAtom) 1.397 + { 1.398 + Init(aElement, aMsgId, aAtom, nullptr); 1.399 + } 1.400 + 1.401 + inline void Init(nsIContentHandle* aElement, 1.402 + const char* aMsgId) 1.403 + { 1.404 + Init(aElement, aMsgId, nullptr, nullptr); 1.405 + } 1.406 + 1.407 + inline void Init(const char* aMsgId, 1.408 + bool aError, 1.409 + int32_t aLineNumber) 1.410 + { 1.411 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.412 + "Op code must be uninitialized when initializing."); 1.413 + mOpCode = eTreeOpMaybeComplainAboutCharset; 1.414 + mOne.charPtr = const_cast<char*>(aMsgId); 1.415 + mTwo.integer = aError; 1.416 + mThree.integer = aLineNumber; 1.417 + } 1.418 + 1.419 + inline void Init(eHtml5TreeOperation aOpCode, const nsAString& aString) 1.420 + { 1.421 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.422 + "Op code must be uninitialized when initializing."); 1.423 + 1.424 + char16_t* str = NS_StringCloneData(aString); 1.425 + mOpCode = aOpCode; 1.426 + mOne.unicharPtr = str; 1.427 + } 1.428 + 1.429 + inline void Init(eHtml5TreeOperation aOpCode, 1.430 + nsIContentHandle* aNode, 1.431 + int32_t aInt) 1.432 + { 1.433 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.434 + "Op code must be uninitialized when initializing."); 1.435 + NS_PRECONDITION(aNode, "Initialized tree op with null node."); 1.436 + mOpCode = aOpCode; 1.437 + mOne.node = static_cast<nsIContent**>(aNode); 1.438 + mFour.integer = aInt; 1.439 + } 1.440 + 1.441 + inline void Init(nsresult aRv) 1.442 + { 1.443 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.444 + "Op code must be uninitialized when initializing."); 1.445 + NS_PRECONDITION(NS_FAILED(aRv), "Initialized tree op with non-failure."); 1.446 + mOpCode = eTreeOpMarkAsBroken; 1.447 + mOne.result = aRv; 1.448 + } 1.449 + 1.450 + inline void InitAddClass(nsIContentHandle* aNode, const char16_t* aClass) 1.451 + { 1.452 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.453 + "Op code must be uninitialized when initializing."); 1.454 + NS_PRECONDITION(aNode, "Initialized tree op with null node."); 1.455 + NS_PRECONDITION(aClass, "Initialized tree op with null string."); 1.456 + // aClass must be a literal string that does not need freeing 1.457 + mOpCode = eTreeOpAddClass; 1.458 + mOne.node = static_cast<nsIContent**>(aNode); 1.459 + mTwo.unicharPtr = (char16_t*)aClass; 1.460 + } 1.461 + 1.462 + inline void InitAddLineNumberId(nsIContentHandle* aNode, 1.463 + const int32_t aLineNumber) 1.464 + { 1.465 + NS_PRECONDITION(mOpCode == eTreeOpUninitialized, 1.466 + "Op code must be uninitialized when initializing."); 1.467 + NS_PRECONDITION(aNode, "Initialized tree op with null node."); 1.468 + NS_PRECONDITION(aLineNumber > 0, "Initialized tree op with line number."); 1.469 + // aClass must be a literal string that does not need freeing 1.470 + mOpCode = eTreeOpAddLineNumberId; 1.471 + mOne.node = static_cast<nsIContent**>(aNode); 1.472 + mFour.integer = aLineNumber; 1.473 + } 1.474 + 1.475 + inline bool IsRunScript() 1.476 + { 1.477 + return mOpCode == eTreeOpRunScript; 1.478 + } 1.479 + 1.480 + inline void SetSnapshot(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine) 1.481 + { 1.482 + NS_ASSERTION(IsRunScript(), 1.483 + "Setting a snapshot for a tree operation other than eTreeOpRunScript!"); 1.484 + NS_PRECONDITION(aSnapshot, "Initialized tree op with null snapshot."); 1.485 + mTwo.state = aSnapshot; 1.486 + mFour.integer = aLine; 1.487 + } 1.488 + 1.489 + nsresult Perform(nsHtml5TreeOpExecutor* aBuilder, 1.490 + nsIContent** aScriptElement); 1.491 + 1.492 + private: 1.493 + // possible optimization: 1.494 + // Make the queue take items the size of pointer and make the op code 1.495 + // decide how many operands it dequeues after it. 1.496 + eHtml5TreeOperation mOpCode; 1.497 + union { 1.498 + nsIContent** node; 1.499 + nsIAtom* atom; 1.500 + nsHtml5HtmlAttributes* attributes; 1.501 + nsHtml5DocumentMode mode; 1.502 + char16_t* unicharPtr; 1.503 + char* charPtr; 1.504 + nsHtml5TreeOperationStringPair* stringPair; 1.505 + nsAHtml5TreeBuilderState* state; 1.506 + int32_t integer; 1.507 + nsresult result; 1.508 + } mOne, mTwo, mThree, mFour; 1.509 +}; 1.510 + 1.511 +#endif // nsHtml5TreeOperation_h