Bug 482921 part 10 - Support parametrized error messages in new View Source. r=Olli.Pettay.
authorHenri Sivonen <hsivonen@iki.fi>
Tue, 01 Nov 2011 13:33:11 +0200
changeset 79514 775c075bd75287373a0eb4c62baa126de202deef
parent 79513 f715a1cf1e23dccfef21c039784a33a20cb21024
child 79515 378c95c9774afb9e54b1cbac65963a51182e6aa2
push id21408
push userkhuey@mozilla.com
push dateTue, 01 Nov 2011 14:32:20 +0000
treeherdermozilla-central@cd9add22f090 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersOlli.Pettay
bugs482921
milestone10.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 482921 part 10 - Support parametrized error messages in new View Source. r=Olli.Pettay.
parser/html/nsHtml5Highlighter.cpp
parser/html/nsHtml5TreeOperation.cpp
parser/html/nsHtml5TreeOperation.h
--- a/parser/html/nsHtml5Highlighter.cpp
+++ b/parser/html/nsHtml5Highlighter.cpp
@@ -811,28 +811,28 @@ nsHtml5Highlighter::AddErrorToCurrentRun
 
 void
 nsHtml5Highlighter::AddErrorToCurrentRun(const char* aMsgId,
                                          nsIAtom* aName)
 {
   NS_PRECONDITION(mCurrentRun, "Adding error to run without one!");
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
-  treeOp->Init(mCurrentRun, aMsgId);
+  treeOp->Init(mCurrentRun, aMsgId, aName);
 }
 
 void
 nsHtml5Highlighter::AddErrorToCurrentRun(const char* aMsgId,
                                          nsIAtom* aName,
                                          nsIAtom* aOther)
 {
   NS_PRECONDITION(mCurrentRun, "Adding error to run without one!");
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
-  treeOp->Init(mCurrentRun, aMsgId);
+  treeOp->Init(mCurrentRun, aMsgId, aName, aOther);
 }
 
 void
 nsHtml5Highlighter::AddErrorToCurrentAmpersand(const char* aMsgId)
 {
   NS_PRECONDITION(mAmpersand, "Adding error to ampersand without one!");
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
--- a/parser/html/nsHtml5TreeOperation.cpp
+++ b/parser/html/nsHtml5TreeOperation.cpp
@@ -367,17 +367,17 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
         }
       }
       
       return rv;
     }
     case eTreeOpCreateElementNetwork:
     case eTreeOpCreateElementNotNetwork: {
       nsIContent** target = mOne.node;
-      PRInt32 ns = mInt;
+      PRInt32 ns = mFour.integer;
       nsCOMPtr<nsIAtom> name = Reget(mTwo.atom);
       nsHtml5HtmlAttributes* attributes = mThree.attributes;
       
       bool isKeygen = (name == nsHtml5Atoms::keygen && ns == kNameSpaceID_XHTML);
       if (NS_UNLIKELY(isKeygen)) {
         name = nsHtml5Atoms::select;
       }
       
@@ -496,17 +496,17 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
           !node->HasAttr(kNameSpaceID_None, nsGkAtoms::form)) {
         formControl->SetForm(formElement);
       }
       return rv;
     }
     case eTreeOpAppendText: {
       nsIContent* parent = *mOne.node;
       PRUnichar* buffer = mTwo.unicharPtr;
-      PRUint32 length = mInt;
+      PRUint32 length = mFour.integer;
       return AppendText(buffer, length, parent, aBuilder);
     }
     case eTreeOpAppendIsindexPrompt: {
       nsIContent* parent = *mOne.node;
       nsXPIDLString prompt;
       nsresult rv =
           nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
                                              "IsIndexPromptWithSpace", prompt);
@@ -518,17 +518,17 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
         // Don't bother appending a zero-length text node.
         return NS_OK;
       }
       return AppendText(prompt.BeginReading(), len, parent, aBuilder);
     }
     case eTreeOpFosterParentText: {
       nsIContent* stackParent = *mOne.node;
       PRUnichar* buffer = mTwo.unicharPtr;
-      PRUint32 length = mInt;
+      PRUint32 length = mFour.integer;
       nsIContent* table = *mThree.node;
       
       nsIContent* foster = table->GetParent();
 
       if (foster && foster->IsElement()) {
         aBuilder->FlushPendingAppendNotifications();
 
         nsHtml5OtherDocUpdate update(foster->OwnerDoc(),
@@ -556,29 +556,29 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
         return rv;
       }
       
       return AppendText(buffer, length, stackParent, aBuilder);
     }
     case eTreeOpAppendComment: {
       nsIContent* parent = *mOne.node;
       PRUnichar* buffer = mTwo.unicharPtr;
-      PRInt32 length = mInt;
+      PRInt32 length = mFour.integer;
       
       nsCOMPtr<nsIContent> comment;
       NS_NewCommentNode(getter_AddRefs(comment), aBuilder->GetNodeInfoManager());
       NS_ASSERTION(comment, "Infallible malloc failed?");
       rv = comment->SetText(buffer, length, false);
       NS_ENSURE_SUCCESS(rv, rv);
       
       return Append(comment, parent, aBuilder);
     }
     case eTreeOpAppendCommentToDocument: {
       PRUnichar* buffer = mTwo.unicharPtr;
-      PRInt32 length = mInt;
+      PRInt32 length = mFour.integer;
       
       nsCOMPtr<nsIContent> comment;
       NS_NewCommentNode(getter_AddRefs(comment), aBuilder->GetNodeInfoManager());
       NS_ASSERTION(comment, "Infallible malloc failed?");
       rv = comment->SetText(buffer, length, false);
       NS_ENSURE_SUCCESS(rv, rv);
       
       return AppendToDocument(comment, aBuilder);
@@ -608,17 +608,17 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
     case eTreeOpMarkAsBroken: {
       aBuilder->MarkAsBroken();
       return rv;
     }
     case eTreeOpRunScript: {
       nsIContent* node = *(mOne.node);
       nsAHtml5TreeBuilderState* snapshot = mTwo.state;
       if (snapshot) {
-        aBuilder->InitializeDocWriteParserState(snapshot, mInt);
+        aBuilder->InitializeDocWriteParserState(snapshot, mFour.integer);
       }
       *aScriptElement = node;
       return rv;
     }
     case eTreeOpRunScriptAsyncDefer: {
       nsIContent* node = *(mOne.node);
       aBuilder->RunScript(node);
       return rv;
@@ -634,24 +634,24 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
       return rv;
     }
     case eTreeOpFlushPendingAppendNotifications: {
       aBuilder->FlushPendingAppendNotifications();
       return rv;
     }
     case eTreeOpSetDocumentCharset: {
       char* str = mOne.charPtr;
-      PRInt32 charsetSource = mInt;
+      PRInt32 charsetSource = mFour.integer;
       nsDependentCString dependentString(str);
       aBuilder->SetDocumentCharsetAndSource(dependentString, charsetSource);
       return rv;
     }
     case eTreeOpNeedsCharsetSwitchTo: {
       char* str = mOne.charPtr;
-      PRInt32 charsetSource = mInt;
+      PRInt32 charsetSource = mFour.integer;
       aBuilder->NeedsCharsetSwitchTo(str, charsetSource);
       return rv;    
     }
     case eTreeOpUpdateStyleSheet: {
       nsIContent* node = *(mOne.node);
       aBuilder->FlushPendingAppendNotifications();
       aBuilder->UpdateStyleSheet(node);
       return rv;
@@ -687,24 +687,24 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
     case eTreeOpDocumentMode: {
       aBuilder->SetDocumentMode(mOne.mode);
       return rv;
     }
     case eTreeOpSetStyleLineNumber: {
       nsIContent* node = *(mOne.node);
       nsCOMPtr<nsIStyleSheetLinkingElement> ssle = do_QueryInterface(node);
       NS_ASSERTION(ssle, "Node didn't QI to style.");
-      ssle->SetLineNumber(mInt);
+      ssle->SetLineNumber(mFour.integer);
       return rv;
     }
     case eTreeOpSetScriptLineNumberAndFreeze: {
       nsIContent* node = *(mOne.node);
       nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
       NS_ASSERTION(sele, "Node didn't QI to script.");
-      sele->SetScriptLineNumber(mInt);
+      sele->SetScriptLineNumber(mFour.integer);
       sele->FreezeUriAsyncDefer();
       return rv;
     }
     case eTreeOpSvgLoad: {
       nsIContent* node = *(mOne.node);
       nsCOMPtr<nsIRunnable> event = new nsHtml5SVGLoadDispatcher(node);
       if (NS_FAILED(NS_DispatchToMainThread(event))) {
         NS_WARNING("failed to dispatch svg load dispatcher");
@@ -723,26 +723,26 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
         node->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true);
       } else {
         node->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, depStr, true);
       }
       return rv;
     }
     case eTreeOpAddLineNumberId: {
       nsIContent* node = *(mOne.node);
-      PRInt32 lineNumber = mInt;
+      PRInt32 lineNumber = mFour.integer;
       nsAutoString val(NS_LITERAL_STRING("line"));
       val.AppendInt(lineNumber);
       node->SetAttr(kNameSpaceID_None, nsGkAtoms::id, val, true);
       return rv;
     }
     case eTreeOpAddViewSourceHref: {
       nsIContent* node = *mOne.node;
       PRUnichar* buffer = mTwo.unicharPtr;
-      PRInt32 length = mInt;
+      PRInt32 length = mFour.integer;
 
       nsDependentString relative(buffer, length);
 
       nsIDocument* doc = aBuilder->GetDocument();
 
       const nsCString& charset = doc->GetDocumentCharacterSet();
       nsCOMPtr<nsIURI> uri;
       rv = NS_NewURI(getter_AddRefs(uri),
@@ -788,37 +788,52 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
       CopyUTF8toUTF16(viewSourceUrl, utf16);
 
       node->SetAttr(kNameSpaceID_None, nsGkAtoms::href, utf16, true);
       return rv;
     }
     case eTreeOpAddError: {
       nsIContent* node = *(mOne.node);
       char* msgId = mTwo.charPtr;
+      nsCOMPtr<nsIAtom> atom = Reget(mThree.atom);
+      nsCOMPtr<nsIAtom> otherAtom = Reget(mFour.atom);
       nsAutoString klass;
       node->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass);
       if (!klass.IsEmpty()) {
         klass.Append(NS_LITERAL_STRING(" error"));
         node->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true);
       } else {
         node->SetAttr(kNameSpaceID_None,
                       nsGkAtoms::_class,
                       NS_LITERAL_STRING("error"),
                       true);
       }
 
       nsXPIDLString message;
-      rv = nsContentUtils::GetLocalizedString(
-        nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, message);
-      NS_ENSURE_SUCCESS(rv, rv);
+      if (otherAtom) {
+        const PRUnichar* params[] = { atom->GetUTF16String(),
+                                      otherAtom->GetUTF16String() };
+        rv = nsContentUtils::FormatLocalizedString(
+          nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, params, 2, message);
+        NS_ENSURE_SUCCESS(rv, rv);
+      } else if (atom) {
+        const PRUnichar* params[] = { atom->GetUTF16String() };
+        rv = nsContentUtils::FormatLocalizedString(
+          nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, params, 1, message);
+        NS_ENSURE_SUCCESS(rv, rv);
+      } else {
+        rv = nsContentUtils::GetLocalizedString(
+          nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, message);
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
 
       nsAutoString title;
       node->GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
       if (!title.IsEmpty()) {
-        title.Append(' ');
+        title.Append('\n');
         title.Append(message);
         node->SetAttr(kNameSpaceID_None, nsGkAtoms::title, title, true);
       } else {
         node->SetAttr(kNameSpaceID_None, nsGkAtoms::title, message, true);
       }
       return rv;
     }
     default: {
--- a/parser/html/nsHtml5TreeOperation.h
+++ b/parser/html/nsHtml5TreeOperation.h
@@ -83,16 +83,18 @@ enum eHtml5TreeOperation {
   eTreeOpStreamEnded,
   eTreeOpSetStyleLineNumber,
   eTreeOpSetScriptLineNumberAndFreeze,
   eTreeOpSvgLoad,
   eTreeOpAddClass,
   eTreeOpAddViewSourceHref,
   eTreeOpAddError,
   eTreeOpAddLineNumberId,
+  eTreeOpAddErrorAtom,
+  eTreeOpAddErrorTwoAtoms,
   eTreeOpStartLayout
 };
 
 class nsHtml5TreeOperationStringPair {
   private:
     nsString mPublicId;
     nsString mSystemId;
   public:
@@ -157,17 +159,17 @@ class nsHtml5TreeOperation {
       const char* start = aString.BeginReading();
       for (PRInt32 i = 0; i < len; ++i) {
         str[i] = start[i];
       }
       str[len] = '\0';
 
       mOpCode = aOpCode;
       mOne.charPtr = str;
-      mInt = aInt32;
+      mFour.integer = aInt32;
     }
 
     inline void Init(eHtml5TreeOperation aOpCode,
                      nsIContent** aNode,
                      nsIContent** aParent, 
                      nsIContent** aTable) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
@@ -203,17 +205,17 @@ class nsHtml5TreeOperation {
                      bool aFromNetwork) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aName, "Initialized tree op with null name.");
       NS_PRECONDITION(aTarget, "Initialized tree op with null target node.");
       mOpCode = aFromNetwork ?
                 eTreeOpCreateElementNetwork :
                 eTreeOpCreateElementNotNetwork;
-      mInt = aNamespace;
+      mFour.integer = aNamespace;
       mOne.node = aTarget;
       mTwo.atom = aName;
       if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
         mThree.attributes = nsnull;
       } else {
         mThree.attributes = aAttributes;
       }
     }
@@ -225,41 +227,41 @@ class nsHtml5TreeOperation {
                      nsIContent** aTable) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aBuffer, "Initialized tree op with null buffer.");
       mOpCode = aOpCode;
       mOne.node = aStackParent;
       mTwo.unicharPtr = aBuffer;
       mThree.node = aTable;
-      mInt = aLength;
+      mFour.integer = aLength;
     }
 
     inline void Init(eHtml5TreeOperation aOpCode, 
                      PRUnichar* aBuffer, 
                      PRInt32 aLength, 
                      nsIContent** aParent) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aBuffer, "Initialized tree op with null buffer.");
       mOpCode = aOpCode;
       mOne.node = aParent;
       mTwo.unicharPtr = aBuffer;
-      mInt = aLength;
+      mFour.integer = aLength;
     }
 
     inline void Init(eHtml5TreeOperation aOpCode, 
                      PRUnichar* aBuffer, 
                      PRInt32 aLength) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aBuffer, "Initialized tree op with null buffer.");
       mOpCode = aOpCode;
       mTwo.unicharPtr = aBuffer;
-      mInt = aLength;
+      mFour.integer = aLength;
     }
     
     inline void Init(nsIContent** aElement,
                      nsHtml5HtmlAttributes* aAttributes) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aElement, "Initialized tree op with null element.");
       mOpCode = eTreeOpAddAttributes;
@@ -273,22 +275,37 @@ class nsHtml5TreeOperation {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       mOpCode = eTreeOpAppendDoctypeToDocument;
       mOne.atom = aName;
       mTwo.stringPair = new nsHtml5TreeOperationStringPair(aPublicId, aSystemId);
     }
     
     inline void Init(nsIContent** aElement,
-                     const char* aMsgId) {
+                     const char* aMsgId,
+                     nsIAtom* aAtom,
+                     nsIAtom* aOtherAtom) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       mOpCode = eTreeOpAddError;
       mOne.node = aElement;
       mTwo.charPtr = (char*)aMsgId;
+      mThree.atom = aAtom;
+      mFour.atom = aOtherAtom;
+    }
+
+    inline void Init(nsIContent** aElement,
+                     const char* aMsgId,
+                     nsIAtom* aAtom) {
+      Init(aElement, aMsgId, aAtom, nsnull);
+    }
+
+    inline void Init(nsIContent** aElement,
+                     const char* aMsgId) {
+      Init(aElement, aMsgId, nsnull, nsnull);
     }
 
     inline void Init(eHtml5TreeOperation aOpCode, const nsAString& aString) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
 
       PRUnichar* str = NS_StringCloneData(aString);
       mOpCode = aOpCode;
@@ -298,17 +315,17 @@ class nsHtml5TreeOperation {
     inline void Init(eHtml5TreeOperation aOpCode,
                      nsIContent** aNode,
                      PRInt32 aInt) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aNode, "Initialized tree op with null node.");
       mOpCode = aOpCode;
       mOne.node = aNode;
-      mInt = aInt;
+      mFour.integer = aInt;
     }
 
     inline void InitAddClass(nsIContent** aNode, const PRUnichar* aClass) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aNode, "Initialized tree op with null node.");
       NS_PRECONDITION(aClass, "Initialized tree op with null string.");
       // aClass must be a literal string that does not need freeing
@@ -321,29 +338,29 @@ class nsHtml5TreeOperation {
                                     const PRInt32 aLineNumber) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aNode, "Initialized tree op with null node.");
       NS_PRECONDITION(aLineNumber > 0, "Initialized tree op with line number.");
       // aClass must be a literal string that does not need freeing
       mOpCode = eTreeOpAddLineNumberId;
       mOne.node = aNode;
-      mInt = aLineNumber;
+      mFour.integer = aLineNumber;
     }
 
     inline bool IsRunScript() {
       return mOpCode == eTreeOpRunScript;
     }
     
     inline void SetSnapshot(nsAHtml5TreeBuilderState* aSnapshot, PRInt32 aLine) {
       NS_ASSERTION(IsRunScript(), 
         "Setting a snapshot for a tree operation other than eTreeOpRunScript!");
       NS_PRECONDITION(aSnapshot, "Initialized tree op with null snapshot.");
       mTwo.state = aSnapshot;
-      mInt = aLine;
+      mFour.integer = aLine;
     }
 
     nsresult Perform(nsHtml5TreeOpExecutor* aBuilder, nsIContent** aScriptElement);
 
     inline already_AddRefed<nsIAtom> Reget(nsIAtom* aAtom) {
       if (!aAtom || aAtom->IsStaticAtom()) {
         return aAtom;
       }
@@ -379,16 +396,13 @@ class nsHtml5TreeOperation {
       nsIContent**                    node;
       nsIAtom*                        atom;
       nsHtml5HtmlAttributes*          attributes;
       nsHtml5DocumentMode             mode;
       PRUnichar*                      unicharPtr;
       char*                           charPtr;
       nsHtml5TreeOperationStringPair* stringPair;
       nsAHtml5TreeBuilderState*       state;
-    }                   mOne, mTwo, mThree;
-    PRInt32             mInt; // optimize this away later by using an end 
-                              // pointer instead of string length and distinct
-                              // element creation opcodes for HTML, MathML and
-                              // SVG.
+      PRInt32                         integer;
+    }                   mOne, mTwo, mThree, mFour;
 };
 
 #endif // nsHtml5TreeOperation_h__