Merge from mozilla-inbound to mozilla-central
authorMatt Brubeck <mbrubeck@mozilla.com>
Tue, 13 Sep 2011 06:31:47 -0700
changeset 76907 c9479e3f6c54a969f32add6c87b06acc8530dc9e
parent 76885 da2f5b63ba1e7c9c0b7efccbc7a5ca1608d792e4 (current diff)
parent 76906 3950656acf1bbca750db300bc00b03bba4dfd657 (diff)
child 76908 15183b3e7d1846557fcc7134185a1777a1da9a9c
child 76951 1f8902ba7731616990ae200cca4912faef16b6f2
child 77258 384a64b6afe1b68fa409973da2eb69f7beef82c0
push id21152
push usermbrubeck@mozilla.com
push dateTue, 13 Sep 2011 13:34:26 +0000
treeherdermozilla-central@c9479e3f6c54 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone9.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
Merge from mozilla-inbound to mozilla-central
--- a/.hgignore
+++ b/.hgignore
@@ -2,16 +2,20 @@
 
 # Filenames that should be ignored wherever they appear
 ~$
 \.py(c|o)$
 (?i)(^|/)TAGS$
 (^|/)ID$
 (^|/)\.DS_Store$
 
+# Vim swap files.
+^\.sw.$
+.[^/]*\.sw.$
+
 # User files that may appear at the root
 ^\.mozconfig
 ^mozconfig$
 ^configure$
 ^config\.cache$
 ^config\.log$
 
 # Empty marker file that's generated when we check out NSS
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -1607,17 +1607,17 @@ nsHTMLEditRules::WillInsertBreak(nsISele
     res = mHTMLEditor->GetLengthOfDOMNode(blockParent, blockLen);
     NS_ENSURE_SUCCESS(res, res);
     nsCOMPtr<nsIDOMNode> brNode;
     res = mHTMLEditor->CreateBR(blockParent, blockLen, address_of(brNode));
     NS_ENSURE_SUCCESS(res, res);
   }
   
   nsCOMPtr<nsIDOMNode> listItem = IsInListItem(blockParent);
-  if (listItem)
+  if (listItem && listItem != hostNode)
   {
     res = ReturnInListItem(aSelection, listItem, node, offset);
     *aHandled = PR_TRUE;
     return NS_OK;
   }
   
   // headers: close (or split) header
   else if (nsHTMLEditUtils::IsHeader(blockParent))
@@ -6502,29 +6502,31 @@ nsHTMLEditRules::MakeTransitionList(nsCO
 
 /********************************************************
  *  main implementation methods 
  ********************************************************/
  
 ///////////////////////////////////////////////////////////////////////////
 // IsInListItem: if aNode is the descendant of a listitem, return that li.
 //               But table element boundaries are stoppers on the search.
+//               Also stops on the active editor host (contenteditable).
 //               Also test if aNode is an li itself.
 //                       
 nsCOMPtr<nsIDOMNode> 
 nsHTMLEditRules::IsInListItem(nsIDOMNode *aNode)
 {
   NS_ENSURE_TRUE(aNode, nsnull);  
   if (nsHTMLEditUtils::IsListItem(aNode)) return aNode;
   
   nsCOMPtr<nsIDOMNode> parent, tmp;
   aNode->GetParentNode(getter_AddRefs(parent));
   
   while (parent)
   {
+    if (!mHTMLEditor->IsNodeInActiveEditor(parent)) return nsnull;
     if (nsHTMLEditUtils::IsTableElement(parent)) return nsnull;
     if (nsHTMLEditUtils::IsListItem(parent)) return parent;
     tmp=parent; tmp->GetParentNode(getter_AddRefs(parent));
   }
   return nsnull;
 }
 
 
--- a/editor/libeditor/html/tests/Makefile.in
+++ b/editor/libeditor/html/tests/Makefile.in
@@ -68,16 +68,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug487524.html \
 		test_bug520189.html \
 		test_bug525389.html \
 		test_bug537046.html \
 		test_bug549262.html \
 		file_bug549262.html \
 		test_bug550434.html \
 		test_bug551704.html \
+		test_bug570144.html \
 		test_bug592592.html \
 		test_bug597784.html \
 		test_bug599322.html \
 		test_bug607584.html \
 		test_bug611182.html \
 		test_bug612447.html \
 		test_bug620906.html \
 		test_bug622371.html \
--- a/editor/libeditor/html/tests/test_bug460740.html
+++ b/editor/libeditor/html/tests/test_bug460740.html
@@ -79,18 +79,18 @@ function split(element, caretPos) {
     case CARET_END:
       pos = len;
       break;
   }
 
   // put the caret on the requested position
   var range = document.createRange();
   var sel = window.getSelection();
-  range.setStart(element.firstChild, len);
-  range.setEnd(element.firstChild, len);
+  range.setStart(element.firstChild, pos);
+  range.setEnd(element.firstChild, pos);
   sel.addRange(range);
   
   // simulates a [Return] keypress
   synthesizeKey("VK_RETURN", {});
 }
 
 // count the number of non-BR elements in #content
 function getBlockCount() {
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/html/tests/test_bug570144.html
@@ -0,0 +1,123 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=570144
+-->
+<head>
+  <title>Test for Bug 570144</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=570144">Mozilla Bug 570144</a>
+<p id="display"></p>
+<div id="content">
+  <!-- editable paragraphs in list item -->
+  <section id="test1">
+    <ol>
+      <li><p contenteditable>foo</p></li>
+    </ol>
+    <ul>
+      <li><p contenteditable>foo</p></li>
+    </ul>
+    <dl>
+      <dt>foo</dt>
+      <dd><p contenteditable>bar</p></dd>
+    </dl>
+  </section>
+  <!-- paragraphs in editable list item -->
+  <section id="test2">
+    <ol>
+      <li contenteditable><p>foo</p></li>
+    </ol>
+    <ul>
+      <li contenteditable><p>foo</p></li>
+    </ul>
+    <dl>
+      <dt>foo</dt>
+      <dd contenteditable><p>bar</p></dd>
+    </dl>
+  </section>
+  <!-- paragraphs in editable list -->
+  <section id="test3">
+    <ol contenteditable>
+      <li><p>foo</p></li>
+    </ol>
+    <ul contenteditable>
+      <li><p>foo</p></li>
+    </ul>
+    <dl contenteditable>
+      <dt>foo</dt>
+      <dd><p>bar</p></dd>
+    </dl>
+  </section>
+</div>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 570144 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTests);
+
+function try2split(list) {
+  var editor = list.hasAttribute("contenteditable")
+             ? list : list.querySelector("*[contenteditable]");
+  editor.focus();
+  // put the caret at the end of the paragraph
+  var selection = window.getSelection();
+  if (editor.nodeName.toLowerCase() == "p")
+    selection.selectAllChildren(editor);
+  else
+    selection.selectAllChildren(editor.querySelector("p"));
+  selection.collapseToEnd();
+  // simulate a [Return] keypress
+  synthesizeKey("VK_RETURN", {});
+}
+
+function testSection(element, context, shouldCreateLI, shouldCreateP) {
+  var nbLI = shouldCreateLI ? 2 : 1; // number of expected list items
+  var nbP  = shouldCreateP  ? 2 : 1; // number of expected paragraphs
+
+  function message(nodeName, dup) {
+    return context + ":[Return] should " + (dup ? "" : "not ")
+                   + "create another <" + nodeName + ">."
+  }
+  var msgP  = message("p",  shouldCreateP);
+  var msgLI = message("li", shouldCreateLI);
+  var msgDT = message("dt", shouldCreateLI);
+  var msgDD = message("dd", false);
+
+  const ol = element.querySelector("ol");
+  try2split(ol);
+  is(ol.querySelectorAll("li").length, nbLI, msgLI);
+  is(ol.querySelectorAll("p").length, nbP, msgP);
+
+  const ul = element.querySelector("ul");
+  try2split(ul);
+  is(ul.querySelectorAll("li").length, nbLI, msgLI);
+  is(ul.querySelectorAll("p").length, nbP, msgP);
+
+  const dl = element.querySelector("dl");
+  try2split(dl);
+  is(dl.querySelectorAll("dt").length, nbLI, msgDT);
+  is(dl.querySelectorAll("dd").length, 1, msgDD);
+  is(dl.querySelectorAll("p").length, nbP, msgP);
+}
+
+function runTests() {
+  testSection(document.getElementById("test1"), "editable paragraph in list item", false, false);
+  testSection(document.getElementById("test2"), "paragraph in editable list item", false, true);
+  testSection(document.getElementById("test3"), "paragraph in editable list",      true,  false);
+  /* Note: concerning #test3, it would be preferrable that [Return] creates
+   * another paragraph in another list item (i.e. last argument = 'true').
+   * Currently it just creates an empty list item, which is acceptable.
+   */
+  SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/gfx/tests/crashtests/686190-1.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<head>
+<style type="text/css">
+@font-face {
+  font-family: foo;
+  src: url(Prototype.ttf);
+}
+body {
+  font-family: foo;
+  font-size: 2000px;
+  font-weight: 900;
+}
+</style>
+</head>
+<body>
+xyzzy
+</body>
+</html>
copy from layout/reftests/fonts/Prototype.ttf
copy to gfx/tests/crashtests/Prototype.ttf
--- a/gfx/tests/crashtests/crashtests.list
+++ b/gfx/tests/crashtests/crashtests.list
@@ -79,8 +79,9 @@ load balinese-letter-spacing.html
 load 580100-1.html
 load 580212-1.html
 load 580233-1.html
 load 580719-1.html
 load 594654-1.xhtml
 load 595727-1.html
 load 633453-1.html
 load 633322-1.html
+load 686190-1.html
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -1106,20 +1106,20 @@ struct GlyphBuffer {
         : mNumGlyphs(0) { }
 
     cairo_glyph_t *AppendGlyph() {
         return &mGlyphBuffer[mNumGlyphs++];
     }
 
     void Flush(cairo_t *aCR, PRBool aDrawToPath, PRBool aReverse,
                PRBool aFinish = PR_FALSE) {
-        // Ensure there's enough room for at least two glyphs in the
-        // buffer (because we may allocate two glyphs between flushes)
-        if (!aFinish && mNumGlyphs + 2 <= GLYPH_BUFFER_SIZE)
+        // Ensure there's enough room for a glyph to be added to the buffer
+        if (!aFinish && mNumGlyphs < GLYPH_BUFFER_SIZE) {
             return;
+        }
 
         if (aReverse) {
             for (PRUint32 i = 0; i < mNumGlyphs/2; ++i) {
                 cairo_glyph_t tmp = mGlyphBuffer[i];
                 mGlyphBuffer[i] = mGlyphBuffer[mNumGlyphs - 1 - i];
                 mGlyphBuffer[mNumGlyphs - 1 - i] = tmp;
             }
         }
@@ -1217,35 +1217,35 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUi
                 x -= advance;
                 glyphX = x;
             } else {
                 glyphX = x;
                 x += advance;
             }
             glyph->x = ToDeviceUnits(glyphX, devUnitsPerAppUnit);
             glyph->y = ToDeviceUnits(y, devUnitsPerAppUnit);
+            glyphs.Flush(cr, aDrawToPath, isRTL);
             
             // synthetic bolding by multi-striking with 1-pixel offsets
             // at least once, more if there's room (large font sizes)
             if (IsSyntheticBold()) {
                 double strikeOffset = synBoldOnePixelOffset;
                 PRInt32 strikeCount = strikes;
                 do {
                     cairo_glyph_t *doubleglyph;
                     doubleglyph = glyphs.AppendGlyph();
                     doubleglyph->index = glyph->index;
                     doubleglyph->x =
                         ToDeviceUnits(glyphX + strikeOffset * appUnitsPerDevUnit,
                                       devUnitsPerAppUnit);
                     doubleglyph->y = glyph->y;
                     strikeOffset += synBoldOnePixelOffset;
+                    glyphs.Flush(cr, aDrawToPath, isRTL);
                 } while (--strikeCount > 0);
             }
-            
-            glyphs.Flush(cr, aDrawToPath, isRTL);
         } else {
             PRUint32 glyphCount = glyphData->GetGlyphCount();
             if (glyphCount > 0) {
                 const gfxTextRun::DetailedGlyph *details =
                     aTextRun->GetDetailedGlyphs(i);
                 NS_ASSERTION(details, "detailedGlyph should not be missing!");
                 for (PRUint32 j = 0; j < glyphCount; ++j, ++details) {
                     double advance = details->mAdvance;
@@ -1270,34 +1270,34 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUi
                         glyph = glyphs.AppendGlyph();
                         glyph->index = details->mGlyphID;
                         double glyphX = x + details->mXOffset;
                         if (isRTL) {
                             glyphX -= advance;
                         }
                         glyph->x = ToDeviceUnits(glyphX, devUnitsPerAppUnit);
                         glyph->y = ToDeviceUnits(y + details->mYOffset, devUnitsPerAppUnit);
+                        glyphs.Flush(cr, aDrawToPath, isRTL);
 
                         if (IsSyntheticBold()) {
                             double strikeOffset = synBoldOnePixelOffset;
                             PRInt32 strikeCount = strikes;
                             do {
                                 cairo_glyph_t *doubleglyph;
                                 doubleglyph = glyphs.AppendGlyph();
                                 doubleglyph->index = glyph->index;
                                 doubleglyph->x =
                                     ToDeviceUnits(glyphX + strikeOffset *
                                                       appUnitsPerDevUnit,
                                                   devUnitsPerAppUnit);
                                 doubleglyph->y = glyph->y;
                                 strikeOffset += synBoldOnePixelOffset;
+                                glyphs.Flush(cr, aDrawToPath, isRTL);
                             } while (--strikeCount > 0);
                         }
-
-                        glyphs.Flush(cr, aDrawToPath, isRTL);
                     }
                     x += direction*advance;
                 }
             }
         }
 
         if (aSpacing) {
             double space = aSpacing[i - aStart].mAfter;
--- a/js/src/assembler/assembler/X86Assembler.h
+++ b/js/src/assembler/assembler/X86Assembler.h
@@ -984,17 +984,19 @@ public:
     void imull_mr(int offset, RegisterID base, RegisterID dst)
     {
         FIXME_INSN_PRINTING;
         m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, base, offset);
     }
 
     void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
     {
-        FIXME_INSN_PRINTING;
+        js::JaegerSpew(js::JSpew_Insns,
+                       IPFX "imull      %d, %s, %s\n",
+                       MAYBE_PAD, value, nameIReg(4, src), nameIReg(4, dst));
         m_formatter.oneByteOp(OP_IMUL_GvEvIz, dst, src);
         m_formatter.immediate32(value);
     }
 
     void idivl_r(RegisterID dst)
     {
         js::JaegerSpew(js::JSpew_Insns,
                        IPFX "idivl      %s\n", MAYBE_PAD, 
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -4348,17 +4348,17 @@ MaybeEmitGroupAssignment(JSContext *cx, 
 }
 
 #endif /* JS_HAS_DESTRUCTURING */
 
 static JSBool
 EmitVariables(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
               JSBool inLetHead, ptrdiff_t *headNoteIndex)
 {
-    bool let, forInVar, first;
+    bool forInVar, first;
     ptrdiff_t off, noteIndex, tmp;
     JSParseNode *pn2, *pn3, *next;
     JSOp op;
     jsatomid atomIndex;
     uintN oldflags;
 
     /* Default in case of JS_HAS_BLOCK_SCOPE early return, below. */
     *headNoteIndex = -1;
@@ -4370,17 +4370,17 @@ EmitVariables(JSContext *cx, JSCodeGener
      * block from any calls to BindNameToSlot hiding in pn2->pn_expr so that
      * it won't find any names in the new let block.
      *
      * The same goes for let declarations in the head of any kind of for loop.
      * Unlike a let declaration 'let x = i' within a block, where x is hoisted
      * to the start of the block, a 'for (let x = i...) ...' loop evaluates i
      * in the containing scope, and puts x in the loop body's scope.
      */
-    let = (pn->pn_op == JSOP_NOP);
+    DebugOnly<bool> let = (pn->pn_op == JSOP_NOP);
     forInVar = (pn->pn_xflags & PNX_FORINVAR) != 0;
 
     off = noteIndex = -1;
     for (pn2 = pn->pn_head; ; pn2 = next) {
         first = pn2 == pn->pn_head;
         next = pn2->pn_next;
 
         if (pn2->pn_type != TOK_NAME) {
@@ -5949,27 +5949,25 @@ js_EmitTree(JSContext *cx, JSCodeGenerat
             return JS_FALSE;
         }
         break;
       }
 
       case TOK_CATCH:
       {
         ptrdiff_t catchStart, guardJump;
-        JSObject *blockObj;
 
         /*
          * Morph STMT_BLOCK to STMT_CATCH, note the block entry code offset,
          * and save the block object atom.
          */
         stmt = cg->topStmt;
         JS_ASSERT(stmt->type == STMT_BLOCK && (stmt->flags & SIF_SCOPE));
         stmt->type = STMT_CATCH;
         catchStart = stmt->update;
-        blockObj = stmt->blockBox->object;
 
         /* Go up one statement info record to the TRY or FINALLY record. */
         stmt = stmt->down;
         JS_ASSERT(stmt->type == STMT_TRY || stmt->type == STMT_FINALLY);
 
         /* Pick up the pending exception and bind it to the catch variable. */
         if (js_Emit1(cx, cg, JSOP_EXCEPTION) < 0)
             return JS_FALSE;
--- a/js/src/jslock.cpp
+++ b/js/src/jslock.cpp
@@ -587,27 +587,25 @@ ThinUnlock(JSThinLock *tl, jsword /*me*/
  * Invariants:
  * (i)  global lock is held
  * (ii) fl->susp >= 0
  */
 static int
 js_SuspendThread(JSThinLock *tl)
 {
     JSFatLock *fl;
-    PRStatus stat;
-
     if (tl->fat == NULL)
         fl = tl->fat = GetFatlock(tl);
     else
         fl = tl->fat;
     JS_ASSERT(fl->susp >= 0);
     fl->susp++;
     PR_Lock(fl->slock);
     js_UnlockGlobal(tl);
-    stat = PR_WaitCondVar(fl->svar, PR_INTERVAL_NO_TIMEOUT);
+    DebugOnly<PRStatus> stat = PR_WaitCondVar(fl->svar, PR_INTERVAL_NO_TIMEOUT);
     JS_ASSERT(stat != PR_FAILURE);
     PR_Unlock(fl->slock);
     js_LockGlobal(tl);
     fl->susp--;
     if (fl->susp == 0) {
         PutFatlock(fl, tl);
         tl->fat = NULL;
     }
@@ -617,23 +615,21 @@ js_SuspendThread(JSThinLock *tl)
 /*
  * (i)  global lock is held
  * (ii) fl->susp > 0
  */
 static void
 js_ResumeThread(JSThinLock *tl)
 {
     JSFatLock *fl = tl->fat;
-    PRStatus stat;
-
     JS_ASSERT(fl != NULL);
     JS_ASSERT(fl->susp > 0);
     PR_Lock(fl->slock);
     js_UnlockGlobal(tl);
-    stat = PR_NotifyCondVar(fl->svar);
+    DebugOnly<PRStatus> stat = PR_NotifyCondVar(fl->svar);
     JS_ASSERT(stat != PR_FAILURE);
     PR_Unlock(fl->slock);
 }
 
 static void
 js_Enqueue(JSThinLock *tl, jsword me)
 {
     jsword o, n;
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -1670,17 +1670,17 @@ DecompileDestructuringLHS(SprintStack *s
  * immediately and return endpc.
  */
 static jsbytecode *
 DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
 {
     ptrdiff_t head;
     JSContext *cx;
     JSPrinter *jp;
-    JSOp op, saveop;
+    JSOp op;
     const JSCodeSpec *cs;
     uintN oplen;
     jsint i, lasti;
     jsdouble d;
     const char *lval;
     JSAtom *atom;
     jssrcnote *sn;
     JSBool hole;
@@ -1705,17 +1705,16 @@ DecompileDestructuring(SprintStack *ss, 
     lasti = -1;
 
     while (pc < endpc) {
 #if JS_HAS_DESTRUCTURING_SHORTHAND
         ptrdiff_t nameoff = -1;
 #endif
 
         LOAD_OP_DATA(pc);
-        saveop = op;
 
         switch (op) {
           case JSOP_POP:
             pc += oplen;
             goto out;
 
           /* Handle the optimized number-pushing opcodes. */
           case JSOP_ZERO:   d = i = 0; goto do_getelem;
--- a/js/src/methodjit/FastArithmetic.cpp
+++ b/js/src/methodjit/FastArithmetic.cpp
@@ -657,38 +657,45 @@ mjit::Compiler::jsop_binary_full(FrameEn
                 overflow = masm.branchSub32(Assembler::Overflow, reg.reg(), regs.result);
             else
                 overflow = masm.branchSub32(Assembler::Overflow, Imm32(value), regs.result);
         }
         break;
 
       case JSOP_MUL:
       {
-        JS_ASSERT(reg.isSet());
-
         MaybeJump storeNegZero;
         bool maybeNegZero = !ignoreOverflow;
         bool hasConstant = (lhs->isConstant() || rhs->isConstant());
 
         if (hasConstant && maybeNegZero) {
             value = (lhs->isConstant() ? lhs : rhs)->getValue().toInt32();
             RegisterID nonConstReg = lhs->isConstant() ? regs.rhsData.reg() : regs.lhsData.reg();
 
             if (value > 0)
                 maybeNegZero = false;
             else if (value < 0)
                 storeNegZero = masm.branchTest32(Assembler::Zero, nonConstReg);
             else
                 storeNegZero = masm.branch32(Assembler::LessThan, nonConstReg, Imm32(0));
         }
 
-        if (cannotOverflow)
-            masm.mul32(reg.reg(), regs.result);
-        else
-            overflow = masm.branchMul32(Assembler::Overflow, reg.reg(), regs.result);
+        if (cannotOverflow) {
+            if (reg.isSet())
+                masm.mul32(reg.reg(), regs.result);
+            else
+                masm.mul32(Imm32(value), regs.result, regs.result);
+        } else {
+            if (reg.isSet()) {
+                overflow = masm.branchMul32(Assembler::Overflow, reg.reg(), regs.result);
+            } else {
+                overflow = masm.branchMul32(Assembler::Overflow, Imm32(value), regs.result,
+                                            regs.result);
+            }
+        }
 
         if (maybeNegZero) {
             if (hasConstant) {
                 stubcc.linkExit(storeNegZero.get(), Uses(2));
             } else {
                 Jump isZero = masm.branchTest32(Assembler::Zero, regs.result);
                 stubcc.linkExitDirect(isZero, stubcc.masm.label());
 
--- a/js/src/methodjit/FrameState.cpp
+++ b/js/src/methodjit/FrameState.cpp
@@ -2648,44 +2648,36 @@ FrameState::allocForBinary(FrameEntry *l
         break;
 
       default:
         JS_NOT_REACHED("unknown op");
         return;
     }
 
     /*
-     * Data is a little more complicated. If the op is MUL, not all CPUs
-     * have multiplication on immediates, so a register is needed. Also,
-     * if the op is not commutative, the LHS _must_ be in a register.
+     * Allocate data registers. If the op is not commutative, the LHS
+     * _must_ be in a register.
      */
     JS_ASSERT_IF(lhs->isConstant(), !rhs->isConstant());
     JS_ASSERT_IF(rhs->isConstant(), !lhs->isConstant());
 
     if (!alloc.lhsData.isSet()) {
         if (backingLeft->data.inMemory()) {
             alloc.lhsData = tempRegForData(lhs);
             pinReg(alloc.lhsData.reg());
-        } else if (op == JSOP_MUL || !commu) {
+        } else if (!commu) {
             JS_ASSERT(lhs->isConstant());
             alloc.lhsData = allocReg();
             alloc.extraFree = alloc.lhsData;
             masm.move(Imm32(lhs->getValue().toInt32()), alloc.lhsData.reg());
         }
     }
-    if (!alloc.rhsData.isSet()) {
-        if (backingRight->data.inMemory()) {
-            alloc.rhsData = tempRegForData(rhs);
-            pinReg(alloc.rhsData.reg());
-        } else if (op == JSOP_MUL) {
-            JS_ASSERT(rhs->isConstant());
-            alloc.rhsData = allocReg();
-            alloc.extraFree = alloc.rhsData;
-            masm.move(Imm32(rhs->getValue().toInt32()), alloc.rhsData.reg());
-        }
+    if (!alloc.rhsData.isSet() && backingRight->data.inMemory()) {
+        alloc.rhsData = tempRegForData(rhs);
+        pinReg(alloc.rhsData.reg());
     }
 
     alloc.lhsNeedsRemat = false;
     alloc.rhsNeedsRemat = false;
     alloc.resultHasRhs = false;
     alloc.undoResult = false;
 
     if (!needsResult)
--- a/js/src/xpconnect/src/xpc.msg
+++ b/js/src/xpconnect/src/xpc.msg
@@ -170,16 +170,17 @@ XPC_MSG_DEF(NS_BINDING_REDIRECTED       
 XPC_MSG_DEF(NS_BINDING_RETARGETED                   , "The async request has been retargeted to a different handler")
 XPC_MSG_DEF(NS_ERROR_MALFORMED_URI                  , "The URI is malformed")
 XPC_MSG_DEF(NS_ERROR_UNKNOWN_PROTOCOL               , "The URI scheme corresponds to an unknown protocol handler")
 XPC_MSG_DEF(NS_ERROR_NO_CONTENT                     , "Channel opened successfully but no data will be returned")
 XPC_MSG_DEF(NS_ERROR_IN_PROGRESS                    , "The requested action could not be completed while the object is busy")
 XPC_MSG_DEF(NS_ERROR_ALREADY_OPENED                 , "Channel is already open")
 XPC_MSG_DEF(NS_ERROR_INVALID_CONTENT_ENCODING       , "The content encoding of the source document is incorrect")
 XPC_MSG_DEF(NS_ERROR_CORRUPTED_CONTENT              , "Corrupted content was received from server")
+XPC_MSG_DEF(NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY, "Couldn't extract first component from potentially corrupted header field")
 XPC_MSG_DEF(NS_ERROR_ALREADY_CONNECTED              , "The connection is already established")
 XPC_MSG_DEF(NS_ERROR_NOT_CONNECTED                  , "The connection does not exist")
 XPC_MSG_DEF(NS_ERROR_CONNECTION_REFUSED             , "The connection was refused")
 XPC_MSG_DEF(NS_ERROR_PROXY_CONNECTION_REFUSED       , "The connection to the proxy server was refused")
 XPC_MSG_DEF(NS_ERROR_NET_TIMEOUT                    , "The connection has timed out")
 XPC_MSG_DEF(NS_ERROR_OFFLINE                        , "The requested action could not be completed in the offline state")
 XPC_MSG_DEF(NS_ERROR_PORT_ACCESS_NOT_ALLOWED        , "Establishing a connection to an unsafe or otherwise banned port was prohibited")
 XPC_MSG_DEF(NS_ERROR_NET_RESET                      , "The connection was established, but no data was ever received")
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1904,17 +1904,22 @@ nsCSSFrameConstructor::ConstructTable(ns
   InitAndRestoreFrame(aState, content, geometricParent, nsnull, newFrame);  
 
   // Create the inner table frame
   nsIFrame* innerFrame;
   if (kNameSpaceID_MathML == nameSpaceID)
     innerFrame = NS_NewMathMLmtableFrame(mPresShell, styleContext);
   else
     innerFrame = NS_NewTableFrame(mPresShell, styleContext);
- 
+
+  if (!innerFrame) {
+    newFrame->Destroy();
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
   InitAndRestoreFrame(aState, content, newFrame, nsnull, innerFrame);
 
   // Put the newly created frames into the right child list
   SetInitialSingleChild(newFrame, innerFrame);
 
   rv = aState.AddChild(newFrame, aFrameItems, content, styleContext,
                        aParentFrame);
   if (NS_FAILED(rv)) {
@@ -2474,19 +2479,19 @@ nsCSSFrameConstructor::ConstructDocEleme
   NS_ASSERTION(processChildren ? !mRootElementFrame :
                  mRootElementFrame == contentFrame,
                "unexpected mRootElementFrame");
   mRootElementFrame = contentFrame;
 
   // Figure out which frame has the main style for the document element,
   // assigning it to mRootElementStyleFrame.
   // Backgrounds should be propagated from that frame to the viewport.
-  PRBool isChild;
-  contentFrame->GetParentStyleContextFrame(state.mPresContext,
-          &mRootElementStyleFrame, &isChild);
+  mRootElementStyleFrame = contentFrame->GetParentStyleContextFrame();
+  bool isChild = mRootElementStyleFrame &&
+                 mRootElementStyleFrame->GetParent() == contentFrame;
   if (!isChild) {
     mRootElementStyleFrame = mRootElementFrame;
   }
 
   if (processChildren) {
     // Still need to process the child content
     nsFrameItems childItems;
 
@@ -5783,23 +5788,18 @@ nsCSSFrameConstructor::IsValidSibling(ns
       (NS_STYLE_DISPLAY_TABLE_CAPTION      == siblingDisplay) ||
       (NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == siblingDisplay) ||
       (NS_STYLE_DISPLAY_TABLE_ROW_GROUP    == siblingDisplay) ||
       (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == siblingDisplay) ||
       nsGkAtoms::menuFrame == parentType) {
     // if we haven't already, construct a style context to find the display type of aContent
     if (UNSET_DISPLAY == aDisplay) {
       nsRefPtr<nsStyleContext> styleContext;
-      nsIFrame* styleParent;
-      PRBool providerIsChild;
-      if (NS_FAILED(aSibling->
-                      GetParentStyleContextFrame(aSibling->PresContext(),
-                                                 &styleParent,
-                                                 &providerIsChild)) ||
-          !styleParent) {
+      nsIFrame* styleParent = aSibling->GetParentStyleContextFrame();
+      if (!styleParent) {
         NS_NOTREACHED("Shouldn't happen");
         return PR_FALSE;
       }
       // XXXbz when this code is killed, the state argument to
       // ResolveStyleContext can be made non-optional.
       styleContext = ResolveStyleContext(styleParent, aContent, nsnull);
       if (!styleContext) return PR_FALSE;
       const nsStyleDisplay* display = styleContext->GetStyleDisplay();
@@ -6675,20 +6675,18 @@ nsCSSFrameConstructor::ContentAppended(n
   }
 
   // Notify the parent frame passing it the list of new frames
   // Append the flowed frames to the principal child list; captions
   // need special treatment
   if (captionItems.NotEmpty()) { // append the caption to the outer table
     NS_ASSERTION(nsGkAtoms::tableFrame == frameType, "how did that happen?");
     nsIFrame* outerTable = parentFrame->GetParent();
-    if (outerTable) {
-      state.mFrameManager->AppendFrames(outerTable, nsIFrame::kCaptionList,
-                                        captionItems);
-    }
+    state.mFrameManager->AppendFrames(outerTable, nsIFrame::kCaptionList,
+                                      captionItems);
   }
 
   if (frameItems.NotEmpty()) { // append the in-flow kids
     AppendFrames(state, parentFrame, frameItems, prevSibling);
   }
 
   // Recover first-letter frames
   if (haveFirstLetterStyle) {
--- a/layout/base/nsFrameManager.cpp
+++ b/layout/base/nsFrameManager.cpp
@@ -263,17 +263,17 @@ nsFrameManager::Destroy()
 
   mPresShell = nsnull;
 }
 
 //----------------------------------------------------------------------
 
 // Placeholder frame functions
 nsPlaceholderFrame*
-nsFrameManager::GetPlaceholderFrameFor(nsIFrame*  aFrame)
+nsFrameManager::GetPlaceholderFrameFor(nsIFrame* aFrame)
 {
   NS_PRECONDITION(aFrame, "null param unexpected");
 
   if (mPlaceholderMap.ops) {
     PlaceholderMapEntry *entry = static_cast<PlaceholderMapEntry*>
                                             (PL_DHashTableOperate(const_cast<PLDHashTable*>(&mPlaceholderMap),
                                 aFrame, PL_DHASH_LOOKUP));
     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
@@ -582,20 +582,17 @@ VerifyContextParent(nsPresContext* aPres
   }
 
   if (!aParentContext) {
     // Get the correct parent context from the frame
     //  - if the frame is a placeholder, we get the out of flow frame's context 
     //    as the parent context instead of asking the frame
 
     // get the parent context from the frame (indirectly)
-    nsIFrame* providerFrame = nsnull;
-    PRBool providerIsChild;
-    aFrame->GetParentStyleContextFrame(aPresContext,
-                                       &providerFrame, &providerIsChild);
+    nsIFrame* providerFrame = aFrame->GetParentStyleContextFrame();
     if (providerFrame)
       aParentContext = providerFrame->GetStyleContext();
     // aParentContext could still be null
   }
 
   NS_ASSERTION(aContext, "Failure to get required contexts");
   nsStyleContext* actualParentContext = aContext->GetParent();
 
@@ -803,23 +800,21 @@ nsFrameManager::ReparentStyleContext(nsI
   }
 
   // DO NOT verify the style tree before reparenting.  The frame
   // tree has already been changed, so this check would just fail.
   nsStyleContext* oldContext = aFrame->GetStyleContext();
   // XXXbz can oldContext really ever be null?
   if (oldContext) {
     nsRefPtr<nsStyleContext> newContext;
-    nsIFrame* providerFrame = nsnull;
-    PRBool providerIsChild = PR_FALSE;
+    nsIFrame* providerFrame = aFrame->GetParentStyleContextFrame();
+    bool isChild = providerFrame && providerFrame->GetParent() == aFrame;
+    nsStyleContext* newParentContext = nsnull;
     nsIFrame* providerChild = nsnull;
-    aFrame->GetParentStyleContextFrame(GetPresContext(), &providerFrame,
-                                       &providerIsChild);
-    nsStyleContext* newParentContext = nsnull;
-    if (providerIsChild) {
+    if (isChild) {
       ReparentStyleContext(providerFrame);
       newParentContext = providerFrame->GetStyleContext();
       providerChild = providerFrame;
     } else if (providerFrame) {
       newParentContext = providerFrame->GetStyleContext();
     } else {
       NS_NOTREACHED("Reparenting something that has no usable parent? "
                     "Shouldn't happen!");
@@ -1102,21 +1097,19 @@ nsFrameManager::ReResolveStyleContext(ns
     if (childRestyleHint == eRestyle_Self) {
       childRestyleHint = nsRestyleHint(0);
     }
 
     nsStyleContext* parentContext;
     nsIFrame* resolvedChild = nsnull;
     // Get the frame providing the parent style context.  If it is a
     // child, then resolve the provider first.
-    nsIFrame* providerFrame = nsnull;
-    PRBool providerIsChild = PR_FALSE;
-    aFrame->GetParentStyleContextFrame(aPresContext,
-                                       &providerFrame, &providerIsChild); 
-    if (!providerIsChild) {
+    nsIFrame* providerFrame = aFrame->GetParentStyleContextFrame();
+    bool isChild = providerFrame && providerFrame->GetParent() == aFrame;
+    if (!isChild) {
       if (providerFrame)
         parentContext = providerFrame->GetStyleContext();
       else
         parentContext = nsnull;
     }
     else {
       // resolve the provider here (before aFrame below).
 
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -6515,25 +6515,16 @@ nsFrame::ConsiderChildOverflow(nsOverflo
   // FIXME: Why do we check this here rather than in
   // FinishAndStoreOverflow (where we check NS_STYLE_OVERFLOW_CLIP)?
   if (!disp->IsTableClip()) {
     aOverflowAreas.UnionWith(aChildFrame->GetOverflowAreas() +
                              aChildFrame->GetPosition());
   }
 }
 
-NS_IMETHODIMP 
-nsFrame::GetParentStyleContextFrame(nsPresContext* aPresContext,
-                                    nsIFrame**      aProviderFrame,
-                                    PRBool*         aIsChild)
-{
-  return DoGetParentStyleContextFrame(aPresContext, aProviderFrame, aIsChild);
-}
-
-
 /**
  * This function takes a "special" frame and _if_ that frame is an anonymous
  * block created by an ib split it returns the block's preceding inline.  This
  * is needed because the split inline's style context is the parent of the
  * anonymous block's style context.
  *
  * If aFrame is not an anonymous block, null is returned.
  */
@@ -6570,36 +6561,32 @@ GetIBSpecialSiblingForAnonymousBlock(nsI
  * having a block within an inline.  The result only differs from the
  * result of |GetParent| when |GetParent| returns an anonymous block
  * that was created for an element that was 'display: inline' because
  * that element contained a block.
  *
  * Also skip anonymous scrolled-content parents; inherit directly from the
  * outer scroll frame.
  */
-static nsresult
-GetCorrectedParent(nsPresContext* aPresContext, nsIFrame* aFrame,
-                   nsIFrame** aSpecialParent)
+static nsIFrame*
+GetCorrectedParent(const nsIFrame* aFrame)
 {
   nsIFrame *parent = aFrame->GetParent();
   if (!parent) {
-    *aSpecialParent = nsnull;
-  } else {
-    nsIAtom* pseudo = aFrame->GetStyleContext()->GetPseudo();
-    // Outer tables are always anon boxes; if we're in here for an outer
-    // table, that actually means its the _inner_ table that wants to
-    // know its parent.  So get the pseudo of the inner in that case.
-    if (pseudo == nsCSSAnonBoxes::tableOuter) {
-      pseudo = aFrame->GetFirstPrincipalChild()
-                         ->GetStyleContext()->GetPseudo();
-    }
-    *aSpecialParent = nsFrame::CorrectStyleParentFrame(parent, pseudo);
-  }
-
-  return NS_OK;
+    return nsnull;
+  }
+
+  // Outer tables are always anon boxes; if we're in here for an outer
+  // table, that actually means its the _inner_ table that wants to
+  // know its parent.  So get the pseudo of the inner in that case.
+  nsIAtom* pseudo = aFrame->GetStyleContext()->GetPseudo();
+  if (pseudo == nsCSSAnonBoxes::tableOuter) {
+    pseudo = aFrame->GetFirstPrincipalChild()->GetStyleContext()->GetPseudo();
+  }
+  return nsFrame::CorrectStyleParentFrame(parent, pseudo);
 }
 
 /* static */
 nsIFrame*
 nsFrame::CorrectStyleParentFrame(nsIFrame* aProspectiveParent,
                                  nsIAtom* aChildPseudo)
 {
   NS_PRECONDITION(aProspectiveParent, "Must have a prospective parent");
@@ -6654,73 +6641,61 @@ nsFrame::CorrectStyleParentFrame(nsIFram
   // We can get here if the root element is absolutely positioned.
   // We can't test for this very accurately, but it can only happen
   // when the prospective parent is a canvas frame.
   NS_ASSERTION(aProspectiveParent->GetType() == nsGkAtoms::canvasFrame,
                "Should have found a parent before this");
   return nsnull;
 }
 
-nsresult
-nsFrame::DoGetParentStyleContextFrame(nsPresContext* aPresContext,
-                                      nsIFrame**      aProviderFrame,
-                                      PRBool*         aIsChild)
-{
-  *aIsChild = PR_FALSE;
-  *aProviderFrame = nsnull;
+nsIFrame*
+nsFrame::DoGetParentStyleContextFrame()
+{
   if (mContent && !mContent->GetParent() &&
       !GetStyleContext()->GetPseudo()) {
     // we're a frame for the root.  We have no style context parent.
-    return NS_OK;
+    return nsnull;
   }
   
   if (!(mState & NS_FRAME_OUT_OF_FLOW)) {
     /*
      * If this frame is an anonymous block created when an inline with a block
      * inside it got split, then the parent style context is on its preceding
      * inline. We can get to it using GetIBSpecialSiblingForAnonymousBlock.
      */
     if (mState & NS_FRAME_IS_SPECIAL) {
-      *aProviderFrame = GetIBSpecialSiblingForAnonymousBlock(this);
-
-      if (*aProviderFrame) {
-        return NS_OK;
+      nsIFrame* specialSibling = GetIBSpecialSiblingForAnonymousBlock(this);
+      if (specialSibling) {
+        return specialSibling;
       }
     }
 
     // If this frame is one of the blocks that split an inline, we must
     // return the "special" inline parent, i.e., the parent that this
     // frame would have if we didn't mangle the frame structure.
-    return GetCorrectedParent(aPresContext, this, aProviderFrame);
+    return GetCorrectedParent(this);
   }
 
   // For out-of-flow frames, we must resolve underneath the
   // placeholder's parent.
   nsIFrame* oofFrame = this;
   if ((oofFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
       GetPrevInFlow()) {
     // Out of flows that are continuations do not
     // have placeholders. Use their first-in-flow's placeholder.
     oofFrame = oofFrame->GetFirstInFlow();
   }
-  nsIFrame *placeholder =
-    aPresContext->FrameManager()->GetPlaceholderFrameFor(oofFrame);
+  nsIFrame* placeholder = oofFrame->PresContext()->FrameManager()->
+                            GetPlaceholderFrameFor(oofFrame);
   if (!placeholder) {
     NS_NOTREACHED("no placeholder frame for out-of-flow frame");
-    GetCorrectedParent(aPresContext, this, aProviderFrame);
-    return NS_ERROR_FAILURE;
-  }
-  return static_cast<nsFrame*>(placeholder)->
-    GetParentStyleContextFrame(aPresContext, aProviderFrame, aIsChild);
-}
-
-//-----------------------------------------------------------------------------------
-
-
-
+    return GetCorrectedParent(this);
+  }
+  return placeholder->GetParentStyleContextFrame();
+}
 
 void
 nsFrame::GetLastLeaf(nsPresContext* aPresContext, nsIFrame **aFrame)
 {
   if (!aFrame || !*aFrame)
     return;
   nsIFrame *child = *aFrame;
   //if we are a block frame then go for the last line of 'this'
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -263,19 +263,28 @@ public:
 
   NS_IMETHOD  GetOffsets(PRInt32 &aStart, PRInt32 &aEnd) const;
   virtual void ChildIsDirty(nsIFrame* aChild);
 
 #ifdef ACCESSIBILITY
   virtual already_AddRefed<nsAccessible> CreateAccessible();
 #endif
 
-  NS_IMETHOD GetParentStyleContextFrame(nsPresContext* aPresContext,
-                                        nsIFrame**      aProviderFrame,
-                                        PRBool*         aIsChild);
+  virtual nsIFrame* GetParentStyleContextFrame() {
+    return DoGetParentStyleContextFrame();
+  }
+
+  /**
+   * Do the work for getting the parent style context frame so that
+   * other frame's |GetParentStyleContextFrame| methods can call this
+   * method on *another* frame.  (This function handles out-of-flow
+   * frames by using the frame manager's placeholder map and it also
+   * handles block-within-inline and generated content wrappers.)
+   */
+  nsIFrame* DoGetParentStyleContextFrame();
 
   virtual PRBool IsEmpty();
   virtual PRBool IsSelfEmpty();
 
   virtual void MarkIntrinsicWidthsDirty();
   virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext);
   virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext);
   virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext,
@@ -394,25 +403,16 @@ public:
   // it marks the frame as "unflowable", zeroes out the metrics, sets
   // the reflow status, and returns PR_TRUE. Otherwise, the frame is
   // unmarked "unflowable" and the metrics and reflow status are not
   // touched and PR_FALSE is returned.
   PRBool IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
                             nsHTMLReflowMetrics& aMetrics,
                             nsReflowStatus& aStatus);
 
-  // Do the work for getting the parent style context frame so that
-  // other frame's |GetParentStyleContextFrame| methods can call this
-  // method on *another* frame.  (This function handles out-of-flow
-  // frames by using the frame manager's placeholder map and it also
-  // handles block-within-inline and generated content wrappers.)
-  nsresult DoGetParentStyleContextFrame(nsPresContext* aPresContext,
-                                        nsIFrame**      aProviderFrame,
-                                        PRBool*         aIsChild);
-
   // Incorporate the child overflow areas into aOverflowAreas.
   // If the child does not have a overflow, use the child area.
   void ConsiderChildOverflow(nsOverflowAreas& aOverflowAreas,
                              nsIFrame* aChildFrame);
 
   virtual const void* GetStyleDataExternal(nsStyleStructID aSID) const;
 
 
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -2391,29 +2391,21 @@ public:
 
   /**
    * Get the frame whose style context should be the parent of this
    * frame's style context (i.e., provide the parent style context).
    * This frame must either be an ancestor of this frame or a child.  If
    * this frame returns a child frame, then the child frame must be sure
    * to return a grandparent or higher!
    *
-   * @param aPresContext:   PresContext
-   * @param aProviderFrame: The frame whose style context should be the
-   *                        parent of this frame's style context.  Null
-   *                        is permitted, and means that this frame's
-   *                        style context should be the root of the
-   *                        style context tree.
-   * @param aIsChild:       True if |aProviderFrame| is set to a child
-   *                        of this frame; false if it is an ancestor or
-   *                        null.
+   * @return The frame whose style context should be the parent of this frame's
+   *         style context.  Null is permitted, and means that this frame's
+   *         style context should be the root of the style context tree.
    */
-  NS_IMETHOD GetParentStyleContextFrame(nsPresContext* aPresContext,
-                                        nsIFrame**      aProviderFrame,
-                                        PRBool*         aIsChild) = 0;
+  virtual nsIFrame* GetParentStyleContextFrame() = 0;
 
   /**
    * Determines whether a frame is visible for painting;
    * taking into account whether it is painting a selection or printing.
    */
   PRBool IsVisibleForPainting(nsDisplayListBuilder* aBuilder);
   /**
    * Determines whether a frame is visible for painting or collapsed;
--- a/layout/generic/nsPlaceholderFrame.cpp
+++ b/layout/generic/nsPlaceholderFrame.cpp
@@ -186,30 +186,25 @@ nsPlaceholderFrame::CanContinueTextRun()
   if (!mOutOfFlowFrame) {
     return PR_FALSE;
   }
   // first-letter frames can continue text runs, and placeholders for floated
   // first-letter frames can too
   return mOutOfFlowFrame->CanContinueTextRun();
 }
 
-NS_IMETHODIMP
-nsPlaceholderFrame::GetParentStyleContextFrame(nsPresContext* aPresContext,
-                                               nsIFrame**      aProviderFrame,
-                                               PRBool*         aIsChild)
+nsIFrame*
+nsPlaceholderFrame::GetParentStyleContextFrame()
 {
   NS_PRECONDITION(GetParent(), "How can we not have a parent here?");
-  *aIsChild = PR_FALSE;
 
   // Lie about our pseudo so we can step out of all anon boxes and
   // pseudo-elements.  The other option would be to reimplement the
   // {ib} split gunk here.
-  *aProviderFrame =
-    CorrectStyleParentFrame(GetParent(), nsGkAtoms::placeholderFrame);
-  return NS_OK;
+  return CorrectStyleParentFrame(GetParent(), nsGkAtoms::placeholderFrame);
 }
 
 
 #ifdef DEBUG
 static void
 PaintDebugPlaceholder(nsIFrame* aFrame, nsRenderingContext* aCtx,
                       const nsRect& aDirtyRect, nsPoint aPt)
 {
--- a/layout/generic/nsPlaceholderFrame.h
+++ b/layout/generic/nsPlaceholderFrame.h
@@ -169,19 +169,18 @@ public:
   virtual already_AddRefed<nsAccessible> CreateAccessible()
   {
     nsIFrame* realFrame = GetRealFrameForPlaceholder(this);
     return realFrame ? realFrame->CreateAccessible() :
                        nsFrame::CreateAccessible();
   }
 #endif
 
-  NS_IMETHOD GetParentStyleContextFrame(nsPresContext* aPresContext,
-                                        nsIFrame**      aProviderFrame,
-                                        PRBool*         aIsChild);
+  virtual nsIFrame* GetParentStyleContextFrame();
+
   /**
    * @return the out-of-flow for aFrame if aFrame is a placeholder; otherwise
    * aFrame
    */
   static nsIFrame* GetRealFrameFor(nsIFrame* aFrame) {
     NS_PRECONDITION(aFrame, "Must have a frame to work with");
     if (aFrame->GetType() == nsGkAtoms::placeholderFrame) {
       return GetRealFrameForPlaceholder(aFrame);
--- a/layout/generic/test/test_bug632379.xul
+++ b/layout/generic/test/test_bug632379.xul
@@ -193,14 +193,13 @@ function doTest() {
 
 function openSubmenu()
 {
     ok(true, "openSubMenu() called");
     // open a submenu in the middle
     synthesizeKey("5", {});
 }
 
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(doTest);
+SimpleTest.waitForFocus(doTest);
 
 ]]></script>
 </window>
 
--- a/layout/mathml/nsMathMLmtableFrame.cpp
+++ b/layout/mathml/nsMathMLmtableFrame.cpp
@@ -453,18 +453,18 @@ nsMathMLmtableOuterFrame::AttributeChang
   // rowlines      : here 
   // rowspacing    : not yet supported 
   // columnalign   : here 
   // columnlines   : here 
   // columnspacing : not yet supported 
 
   // mtable is simple and only has one (pseudo) row-group inside our inner-table
   nsIFrame* tableFrame = mFrames.FirstChild();
-  if (!tableFrame || tableFrame->GetType() != nsGkAtoms::tableFrame)
-    return NS_OK;
+  NS_ASSERTION(tableFrame && tableFrame->GetType() == nsGkAtoms::tableFrame,
+               "should always have an inner table frame");
   nsIFrame* rgFrame = tableFrame->GetFirstPrincipalChild();
   if (!rgFrame || rgFrame->GetType() != nsGkAtoms::tableRowGroupFrame)
     return NS_OK;
 
   // align - just need to issue a dirty (resize) reflow command
   if (aAttribute == nsGkAtoms::align) {
     PresContext()->PresShell()->
       FrameNeedsReflow(this, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
@@ -543,18 +543,18 @@ nsMathMLmtableOuterFrame::GetRowFrameAt(
   } else {
     // aRowIndex is 1-based, so convert it to a 0-based index
     --aRowIndex;
   }
 
   // if our inner table says that the index is valid, find the row now
   if (0 <= aRowIndex && aRowIndex <= rowCount) {
     nsIFrame* tableFrame = mFrames.FirstChild();
-    if (!tableFrame || tableFrame->GetType() != nsGkAtoms::tableFrame)
-      return nsnull;
+    NS_ASSERTION(tableFrame && tableFrame->GetType() == nsGkAtoms::tableFrame,
+                 "should always have an inner table frame");
     nsIFrame* rgFrame = tableFrame->GetFirstPrincipalChild();
     if (!rgFrame || rgFrame->GetType() != nsGkAtoms::tableRowGroupFrame)
       return nsnull;
     nsTableIterator rowIter(*rgFrame);
     nsIFrame* rowFrame = rowIter.First();
     for ( ; rowFrame; rowFrame = rowIter.Next()) {
       if (aRowIndex == 0) {
         DEBUG_VERIFY_THAT_FRAME_IS(rowFrame, TABLE_ROW);
--- a/layout/tables/nsTableColGroupFrame.cpp
+++ b/layout/tables/nsTableColGroupFrame.cpp
@@ -331,20 +331,17 @@ nsTableColGroupFrame::RemoveFrame(ChildL
     nsTableColFrame* colFrame = (nsTableColFrame*)aOldFrame;
     if (colFrame->GetColType() == eColContent) {
       contentRemoval = PR_TRUE;
       // Remove any anonymous column frames this <col> produced via a colspan
       nsTableColFrame* col = colFrame->GetNextCol();
       nsTableColFrame* nextCol;
       while (col && col->GetColType() == eColAnonymousCol) {
 #ifdef DEBUG
-        nsIFrame* providerFrame;
-        PRBool isChild;
-        colFrame->GetParentStyleContextFrame(PresContext(), &providerFrame,
-                                             &isChild);
+        nsIFrame* providerFrame = colFrame->GetParentStyleContextFrame();
         if (colFrame->GetStyleContext()->GetParent() ==
             providerFrame->GetStyleContext()) {
           NS_ASSERTION(col->GetStyleContext() == colFrame->GetStyleContext() &&
                        col->GetContent() == colFrame->GetContent(),
                        "How did that happen??");
         }
         // else colFrame is being removed because of a frame
         // reconstruct on it, and its style context is still the old
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -156,34 +156,29 @@ struct BCPropertyData
   BCPixelSize mTopBorderWidth;
   BCPixelSize mRightBorderWidth;
   BCPixelSize mBottomBorderWidth;
   BCPixelSize mLeftBorderWidth;
   BCPixelSize mLeftCellBorderWidth;
   BCPixelSize mRightCellBorderWidth;
 };
 
-NS_IMETHODIMP
-nsTableFrame::GetParentStyleContextFrame(nsPresContext*  aPresContext,
-                                         nsIFrame**      aProviderFrame,
-                                         PRBool*         aIsChild)
+nsIFrame*
+nsTableFrame::GetParentStyleContextFrame()
 {
   // Since our parent, the table outer frame, returned this frame, we
   // must return whatever our parent would normally have returned.
 
   NS_PRECONDITION(mParent, "table constructed without outer table");
   if (!mContent->GetParent() && !GetStyleContext()->GetPseudo()) {
     // We're the root.  We have no style context parent.
-    *aIsChild = PR_FALSE;
-    *aProviderFrame = nsnull;
-    return NS_OK;
-  }
-
-  return static_cast<nsFrame*>(mParent)->
-          DoGetParentStyleContextFrame(aPresContext, aProviderFrame, aIsChild);
+    return nsnull;
+  }
+
+  return static_cast<nsFrame*>(GetParent())->DoGetParentStyleContextFrame();
 }
 
 
 nsIAtom*
 nsTableFrame::GetType() const
 {
   return nsGkAtoms::tableFrame;
 }
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -344,19 +344,17 @@ public:
   nsresult ReflowTable(nsHTMLReflowMetrics&     aDesiredSize,
                        const nsHTMLReflowState& aReflowState,
                        nscoord                  aAvailHeight,
                        nsIFrame*&               aLastChildReflowed,
                        nsReflowStatus&          aStatus);
 
   nsFrameList& GetColGroups();
 
-  NS_IMETHOD GetParentStyleContextFrame(nsPresContext* aPresContext,
-                                        nsIFrame**      aProviderFrame,
-                                        PRBool*         aIsChild);
+  virtual nsIFrame* GetParentStyleContextFrame();
 
   /**
    * Get the "type" of the frame
    *
    * @see nsGkAtoms::tableFrame
    */
   virtual nsIAtom* GetType() const;
 
--- a/layout/tables/nsTableOuterFrame.cpp
+++ b/layout/tables/nsTableOuterFrame.cpp
@@ -112,41 +112,35 @@ nsTableCaptionFrame::ComputeAutoSize(nsR
     if (min > aCBSize.width)
       min = aCBSize.width;
     if (min > result.width)
       result.width = min;
   }
   return result;
 }
 
-NS_IMETHODIMP 
-nsTableCaptionFrame::GetParentStyleContextFrame(nsPresContext* aPresContext,
-                                                nsIFrame**      aProviderFrame,
-                                                PRBool*         aIsChild)
+nsIFrame*
+nsTableCaptionFrame::GetParentStyleContextFrame()
 {
   NS_PRECONDITION(mContent->GetParent(),
                   "How could we not have a parent here?");
     
   // The caption's style context parent is the inner frame, unless
   // it's anonymous.
   nsIFrame* outerFrame = GetParent();
   if (outerFrame && outerFrame->GetType() == nsGkAtoms::tableOuterFrame) {
     nsIFrame* innerFrame = outerFrame->GetFirstPrincipalChild();
     if (innerFrame) {
-      *aProviderFrame =
-        nsFrame::CorrectStyleParentFrame(innerFrame,
-                                         GetStyleContext()->GetPseudo());
-      *aIsChild = PR_FALSE;
-      return NS_OK;
+      return nsFrame::CorrectStyleParentFrame(innerFrame,
+                                              GetStyleContext()->GetPseudo());
     }
   }
 
   NS_NOTREACHED("Where is our inner table frame?");
-  return nsBlockFrame::GetParentStyleContextFrame(aPresContext, aProviderFrame,
-                                                  aIsChild);
+  return nsBlockFrame::GetParentStyleContextFrame();
 }
 
 #ifdef ACCESSIBILITY
 already_AddRefed<nsAccessible>
 nsTableCaptionFrame::CreateAccessible()
 {
   if (!GetRect().IsEmpty()) {
     nsAccessibilityService* accService = nsIPresShell::AccService();
@@ -240,32 +234,24 @@ nsTableOuterFrame::GetChildLists(nsTArra
 
 NS_IMETHODIMP 
 nsTableOuterFrame::SetInitialChildList(ChildListID     aListID,
                                        nsFrameList&    aChildList)
 {
   if (kCaptionList == aListID) {
     // the frame constructor already checked for table-caption display type
     mCaptionFrames.SetFrames(aChildList);
-    mCaptionFrame = mCaptionFrames.FirstChild();
   }
   else {
     NS_ASSERTION(aListID == kPrincipalList, "wrong childlist");
     NS_ASSERTION(mFrames.IsEmpty(), "Frame leak!");
-    mInnerTableFrame = nsnull;
-    if (aChildList.NotEmpty()) {
-      if (nsGkAtoms::tableFrame == aChildList.FirstChild()->GetType()) {
-        mInnerTableFrame = (nsTableFrame*)aChildList.FirstChild();
-        mFrames.SetFrames(aChildList);
-      }
-      else {
-        NS_ERROR("expected a table frame");
-        return NS_ERROR_INVALID_ARG;
-      }
-    }
+    NS_ASSERTION(aChildList.FirstChild() &&
+                 nsGkAtoms::tableFrame == aChildList.FirstChild()->GetType(),
+                 "expected a table frame");
+    mFrames.SetFrames(aChildList);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTableOuterFrame::AppendFrames(ChildListID     aListID,
                                 nsFrameList&    aFrameList)
@@ -274,17 +260,16 @@ nsTableOuterFrame::AppendFrames(ChildLis
 
   // We only have two child frames: the inner table and a caption frame.
   // The inner frame is provided when we're initialized, and it cannot change
   if (kCaptionList == aListID) {
     NS_ASSERTION(aFrameList.IsEmpty() ||
                  aFrameList.FirstChild()->GetType() == nsGkAtoms::tableCaptionFrame,
                  "appending non-caption frame to captionList");
     mCaptionFrames.AppendFrames(this, aFrameList);
-    mCaptionFrame = mCaptionFrames.FirstChild();
     rv = NS_OK;
 
     // Reflow the new caption frame. It's already marked dirty, so
     // just tell the pres shell.
     PresContext()->PresShell()->
       FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                        NS_FRAME_HAS_DIRTY_CHILDREN);
   }
@@ -303,17 +288,16 @@ nsTableOuterFrame::InsertFrames(ChildLis
 {
   if (kCaptionList == aListID) {
     NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                  "inserting after sibling frame with different parent");
     NS_ASSERTION(aFrameList.IsEmpty() ||
                  aFrameList.FirstChild()->GetType() == nsGkAtoms::tableCaptionFrame,
                  "inserting non-caption frame into captionList");
     mCaptionFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
-    mCaptionFrame = mCaptionFrames.FirstChild();
 
     // Reflow the new caption frame. It's already marked dirty, so
     // just tell the pres shell.
     PresContext()->PresShell()->
       FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                        NS_FRAME_HAS_DIRTY_CHILDREN);
     return NS_OK;
   }
@@ -329,22 +313,21 @@ nsTableOuterFrame::RemoveFrame(ChildList
 {
   // We only have two child frames: the inner table and one caption frame.
   // The inner frame can't be removed so this should be the caption
   NS_PRECONDITION(kCaptionList == aListID, "can't remove inner frame");
 
   if (HasSideCaption()) {
     // The old caption width had an effect on the inner table width so
     // we're going to need to reflow it. Mark it dirty
-    mInnerTableFrame->AddStateBits(NS_FRAME_IS_DIRTY);
+    InnerTableFrame()->AddStateBits(NS_FRAME_IS_DIRTY);
   }
 
   // Remove the frame and destroy it
   mCaptionFrames.DestroyFrame(aOldFrame);
-  mCaptionFrame = mCaptionFrames.FirstChild();
   
   PresContext()->PresShell()->
     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                      NS_FRAME_HAS_DIRTY_CHILDREN); // also means child removed
 
   return NS_OK;
 }
 
@@ -355,25 +338,26 @@ nsTableOuterFrame::BuildDisplayList(nsDi
 {
   // No border, background or outline are painted because they all belong
   // to the inner table.
   if (!IsVisibleInSelection(aBuilder))
     return NS_OK;
 
   // If there's no caption, take a short cut to avoid having to create
   // the special display list set and then sort it.
-  if (!mCaptionFrame)
+  if (mCaptionFrames.IsEmpty())
     return BuildDisplayListForInnerTable(aBuilder, aDirtyRect, aLists);
     
   nsDisplayListCollection set;
   nsresult rv = BuildDisplayListForInnerTable(aBuilder, aDirtyRect, set);
   NS_ENSURE_SUCCESS(rv, rv);
   
   nsDisplayListSet captionSet(set, set.BlockBorderBackgrounds());
-  rv = BuildDisplayListForChild(aBuilder, mCaptionFrame, aDirtyRect, captionSet);
+  rv = BuildDisplayListForChild(aBuilder, mCaptionFrames.FirstChild(),
+                                aDirtyRect, captionSet);
   NS_ENSURE_SUCCESS(rv, rv);
   
   // Now we have to sort everything by content order, since the caption
   // may be somewhere inside the table
   set.SortAllByContentOrder(aBuilder, GetContent());
   set.MoveTo(aLists);
   return NS_OK;
 }
@@ -395,59 +379,49 @@ nsTableOuterFrame::BuildDisplayListForIn
   return NS_OK;
 }
 
 void
 nsTableOuterFrame::SetSelected(PRBool        aSelected,
                                SelectionType aType)
 {
   nsFrame::SetSelected(aSelected, aType);
-  if (mInnerTableFrame) {
-    mInnerTableFrame->SetSelected(aSelected, aType);
-  }
+  InnerTableFrame()->SetSelected(aSelected, aType);
 }
 
-NS_IMETHODIMP 
-nsTableOuterFrame::GetParentStyleContextFrame(nsPresContext* aPresContext,
-                                              nsIFrame**      aProviderFrame,
-                                              PRBool*         aIsChild)
+nsIFrame*
+nsTableOuterFrame::GetParentStyleContextFrame()
 {
   // The table outer frame and the (inner) table frame split the style
   // data by giving the table frame the style context associated with
   // the table content node and creating a style context for the outer
   // frame that is a *child* of the table frame's style context,
   // matching the ::-moz-table-outer pseudo-element.  html.css has a
   // rule that causes that pseudo-element (and thus the outer table)
   // to inherit *some* style properties from the table frame.  The
   // children of the table inherit directly from the inner table, and
   // the outer table's style context is a leaf.
 
-  if (!mInnerTableFrame) {
-    *aProviderFrame = this;
-    *aIsChild = PR_FALSE;
-    return NS_ERROR_FAILURE;
-  }
-  *aProviderFrame = mInnerTableFrame;
-  *aIsChild = PR_TRUE;
-  return NS_OK;
+  return InnerTableFrame();
 }
 
 // INCREMENTAL REFLOW HELPER FUNCTIONS 
 
 void
 nsTableOuterFrame::InitChildReflowState(nsPresContext&    aPresContext,                     
                                         nsHTMLReflowState& aReflowState)
                                     
 {
   nsMargin collapseBorder;
   nsMargin collapsePadding(0,0,0,0);
   nsMargin* pCollapseBorder  = nsnull;
   nsMargin* pCollapsePadding = nsnull;
-  if ((aReflowState.frame == mInnerTableFrame) && (mInnerTableFrame->IsBorderCollapse())) {
-    collapseBorder  = mInnerTableFrame->GetIncludedOuterBCBorder();
+  if (aReflowState.frame == InnerTableFrame() &&
+      InnerTableFrame()->IsBorderCollapse()) {
+    collapseBorder  = InnerTableFrame()->GetIncludedOuterBCBorder();
     pCollapseBorder = &collapseBorder;
     pCollapsePadding = &collapsePadding;
   }
   aReflowState.Init(&aPresContext, -1, -1, pCollapseBorder, pCollapsePadding);
 }
 
 // get the margin and padding data. nsHTMLReflowState doesn't handle the
 // case of auto margins
@@ -490,21 +464,22 @@ GetContainingBlockSize(const nsHTMLReflo
   }
   return size;
 }
 
 /* virtual */ nscoord
 nsTableOuterFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
 {
   nscoord width = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
-                    mInnerTableFrame, nsLayoutUtils::MIN_WIDTH);
+                    InnerTableFrame(), nsLayoutUtils::MIN_WIDTH);
   DISPLAY_MIN_WIDTH(this, width);
-  if (mCaptionFrame) {
+  if (mCaptionFrames.NotEmpty()) {
     nscoord capWidth =
-      nsLayoutUtils::IntrinsicForContainer(aRenderingContext, mCaptionFrame,
+      nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
+                                           mCaptionFrames.FirstChild(),
                                            nsLayoutUtils::MIN_WIDTH);
     if (HasSideCaption()) {
       width += capWidth;
     } else {
       if (capWidth > width) {
         width = capWidth;
       }
     }
@@ -514,25 +489,26 @@ nsTableOuterFrame::GetMinWidth(nsRenderi
 
 /* virtual */ nscoord
 nsTableOuterFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
 {
   nscoord maxWidth;
   DISPLAY_PREF_WIDTH(this, maxWidth);
 
   maxWidth = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
-               mInnerTableFrame, nsLayoutUtils::PREF_WIDTH);
-  if (mCaptionFrame) {
+               InnerTableFrame(), nsLayoutUtils::PREF_WIDTH);
+  if (mCaptionFrames.NotEmpty()) {
     PRUint8 captionSide = GetCaptionSide();
     switch(captionSide) {
     case NS_STYLE_CAPTION_SIDE_LEFT:
     case NS_STYLE_CAPTION_SIDE_RIGHT:
       {
         nscoord capMin =
-          nsLayoutUtils::IntrinsicForContainer(aRenderingContext, mCaptionFrame,
+          nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
+                                               mCaptionFrames.FirstChild(),
                                                nsLayoutUtils::MIN_WIDTH);
         maxWidth += capMin;
       }
       break;
     default:
       {
         nsLayoutUtils::IntrinsicWidthType iwt;
         if (captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
@@ -542,17 +518,18 @@ nsTableOuterFrame::GetPrefWidth(nsRender
           iwt = nsLayoutUtils::MIN_WIDTH;
         } else {
           NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE ||
                        captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE,
                        "unexpected caption side");
           iwt = nsLayoutUtils::PREF_WIDTH;
         }
         nscoord capPref =
-          nsLayoutUtils::IntrinsicForContainer(aRenderingContext, mCaptionFrame,
+          nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
+                                               mCaptionFrames.FirstChild(),
                                                iwt);
         maxWidth = NS_MAX(maxWidth, capPref);
       }
       break;
     }
   }
   return maxWidth;
 }
@@ -599,87 +576,89 @@ nsTableOuterFrame::ComputeAutoSize(nsRen
   // actual size of the table, which (if it is specified as a percent)
   // could be something that is not reflected in our GetMinWidth and
   // GetPrefWidth.  See bug 349457 for an example.
 
   // Match the availableWidth logic in Reflow.
   PRUint8 captionSide = GetCaptionSide();
   nscoord width;
   if (captionSide == NO_SIDE) {
-    width = ChildShrinkWrapWidth(aRenderingContext, mInnerTableFrame,
+    width = ChildShrinkWrapWidth(aRenderingContext, InnerTableFrame(),
                                  aCBSize, aAvailableWidth);
   } else if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT ||
              captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) {
-    nscoord capWidth = ChildShrinkWrapWidth(aRenderingContext, mCaptionFrame,
+    nscoord capWidth = ChildShrinkWrapWidth(aRenderingContext,
+                                            mCaptionFrames.FirstChild(),
                                             aCBSize, aAvailableWidth);
     width = capWidth + ChildShrinkWrapWidth(aRenderingContext,
-                                            mInnerTableFrame, aCBSize,
+                                            InnerTableFrame(), aCBSize,
                                             aAvailableWidth - capWidth);
   } else if (captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
              captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) {
     nscoord margin;
-    width = ChildShrinkWrapWidth(aRenderingContext, mInnerTableFrame,
+    width = ChildShrinkWrapWidth(aRenderingContext, InnerTableFrame(),
                                  aCBSize, aAvailableWidth, &margin);
     nscoord capWidth = ChildShrinkWrapWidth(aRenderingContext,
-                                            mCaptionFrame, aCBSize,
+                                            mCaptionFrames.FirstChild(), aCBSize,
                                             width - margin);
     if (capWidth > width)
       width = capWidth;
   } else {
     NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE ||
                  captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE,
                  "unexpected caption-side");
-    width = ChildShrinkWrapWidth(aRenderingContext, mInnerTableFrame,
+    width = ChildShrinkWrapWidth(aRenderingContext, InnerTableFrame(),
                                  aCBSize, aAvailableWidth);
     nscoord capWidth = ChildShrinkWrapWidth(aRenderingContext,
-                                            mCaptionFrame, aCBSize,
-                                            aAvailableWidth);
+                                            mCaptionFrames.FirstChild(),
+                                            aCBSize, aAvailableWidth);
     if (capWidth > width)
       width = capWidth;
   }
 
   return nsSize(width, NS_UNCONSTRAINEDSIZE);
 }
 
 PRUint8
 nsTableOuterFrame::GetCaptionSide()
 {
-  if (mCaptionFrame) {
-    return mCaptionFrame->GetStyleTableBorder()->mCaptionSide;
+  if (mCaptionFrames.NotEmpty()) {
+    return mCaptionFrames.FirstChild()->GetStyleTableBorder()->mCaptionSide;
   }
   else {
     return NO_SIDE; // no caption
   }
 }
 
 PRUint8
 nsTableOuterFrame::GetCaptionVerticalAlign()
 {
-  const nsStyleCoord& va = mCaptionFrame->GetStyleTextReset()->mVerticalAlign;
+  const nsStyleCoord& va =
+    mCaptionFrames.FirstChild()->GetStyleTextReset()->mVerticalAlign;
   return (va.GetUnit() == eStyleUnit_Enumerated)
            ? va.GetIntValue()
            : NS_STYLE_VERTICAL_ALIGN_TOP;
 }
 
 void
 nsTableOuterFrame::SetDesiredSize(PRUint8         aCaptionSide,
                                   const nsMargin& aInnerMargin,
                                   const nsMargin& aCaptionMargin,
                                   nscoord&        aWidth,
                                   nscoord&        aHeight)
 {
   aWidth = aHeight = 0;
 
-  nsRect innerRect = mInnerTableFrame->GetRect();
+  nsRect innerRect = InnerTableFrame()->GetRect();
   nscoord innerWidth = innerRect.width;
 
   nsRect captionRect(0,0,0,0);
   nscoord captionWidth = 0;
-  if (mCaptionFrame) {
-    captionRect = mCaptionFrame->GetRect();
+  if (mCaptionFrames.NotEmpty()) {
+    captionRect = mCaptionFrames.FirstChild()->GetRect();
     captionWidth = captionRect.width;
   }
   switch(aCaptionSide) {
     case NS_STYLE_CAPTION_SIDE_LEFT:
       aWidth = NS_MAX(aInnerMargin.left, aCaptionMargin.left + captionWidth + aCaptionMargin.right) +
                innerWidth + aInnerMargin.right;
       break;
     case NS_STYLE_CAPTION_SIDE_RIGHT:
@@ -710,17 +689,17 @@ nsTableOuterFrame::GetCaptionOrigin(PRUi
                                     nsMargin&        aCaptionMargin,
                                     nsPoint&         aOrigin)
 {
   aOrigin.x = aOrigin.y = 0;
   if ((NS_UNCONSTRAINEDSIZE == aInnerSize.width) || (NS_UNCONSTRAINEDSIZE == aInnerSize.height) ||  
       (NS_UNCONSTRAINEDSIZE == aCaptionSize.width) || (NS_UNCONSTRAINEDSIZE == aCaptionSize.height)) {
     return NS_OK;
   }
-  if (!mCaptionFrame) return NS_OK;
+  if (mCaptionFrames.IsEmpty()) return NS_OK;
   
   NS_ASSERTION(NS_AUTOMARGIN != aCaptionMargin.left,   "The computed caption margin is auto?");
   NS_ASSERTION(NS_AUTOMARGIN != aCaptionMargin.top,    "The computed caption margin is auto?");
   NS_ASSERTION(NS_AUTOMARGIN != aCaptionMargin.bottom, "The computed caption margin is auto?");
 
   // horizontal computation
   switch(aCaptionSide) {
   case NS_STYLE_CAPTION_SIDE_BOTTOM:
@@ -889,17 +868,17 @@ nsTableOuterFrame::OuterBeginReflowChild
                                          nsIFrame*                aChildFrame,
                                          const nsHTMLReflowState& aOuterRS,
                                          void*                    aChildRSSpace,
                                          nscoord                  aAvailWidth)
 { 
   // work around pixel rounding errors, round down to ensure we don't exceed the avail height in
   nscoord availHeight = aOuterRS.availableHeight;
   if (NS_UNCONSTRAINEDSIZE != availHeight) {
-    if (mCaptionFrame == aChildFrame) {
+    if (mCaptionFrames.FirstChild() == aChildFrame) {
       availHeight = NS_UNCONSTRAINEDSIZE;
     } else {
       nsMargin margin;
       GetChildMargin(aPresContext, aOuterRS, aChildFrame,
                      aOuterRS.availableWidth, margin);
     
       NS_ASSERTION(NS_UNCONSTRAINEDSIZE != margin.top, "No unconstrainedsize arithmetic, please");
       availHeight -= margin.top;
@@ -913,24 +892,24 @@ nsTableOuterFrame::OuterBeginReflowChild
   // stack space allocated by the caller, so that the caller can destroy
   // it
   nsHTMLReflowState &childRS = * new (aChildRSSpace)
     nsHTMLReflowState(aPresContext, aOuterRS, aChildFrame, availSize,
                       -1, -1, PR_FALSE);
   InitChildReflowState(*aPresContext, childRS);
 
   // see if we need to reset top of page due to a caption
-  if (mCaptionFrame) {
+  if (mCaptionFrames.NotEmpty()) {
     PRUint8 captionSide = GetCaptionSide();
     if (((captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM ||
           captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE) &&
-         mCaptionFrame == aChildFrame) || 
+         mCaptionFrames.FirstChild() == aChildFrame) || 
         ((captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
           captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE) &&
-         mInnerTableFrame == aChildFrame)) {
+         InnerTableFrame() == aChildFrame)) {
       childRS.mFlags.mIsTopOfPage = PR_FALSE;
     }
   }
 }
 
 nsresult
 nsTableOuterFrame::OuterDoReflowChild(nsPresContext*             aPresContext,
                                       nsIFrame*                  aChildFrame,
@@ -950,37 +929,31 @@ nsTableOuterFrame::UpdateReflowMetrics(P
                                        nsHTMLReflowMetrics& aMet,
                                        const nsMargin&      aInnerMargin,
                                        const nsMargin&      aCaptionMargin)
 {
   SetDesiredSize(aCaptionSide, aInnerMargin, aCaptionMargin,
                  aMet.width, aMet.height);
 
   aMet.SetOverflowAreasToDesiredBounds();
-  ConsiderChildOverflow(aMet.mOverflowAreas, mInnerTableFrame);
-  if (mCaptionFrame) {
-    ConsiderChildOverflow(aMet.mOverflowAreas, mCaptionFrame);
+  ConsiderChildOverflow(aMet.mOverflowAreas, InnerTableFrame());
+  if (mCaptionFrames.NotEmpty()) {
+    ConsiderChildOverflow(aMet.mOverflowAreas, mCaptionFrames.FirstChild());
   }
   FinishAndStoreOverflow(&aMet);
 }
 
 NS_METHOD nsTableOuterFrame::Reflow(nsPresContext*           aPresContext,
                                     nsHTMLReflowMetrics&     aDesiredSize,
                                     const nsHTMLReflowState& aOuterRS,
                                     nsReflowStatus&          aStatus)
 {
   DO_GLOBAL_REFLOW_COUNT("nsTableOuterFrame");
   DISPLAY_REFLOW(aPresContext, this, aOuterRS, aDesiredSize, aStatus);
 
-  // We desperately need an inner table frame,
-  // if this fails fix the frame constructor
-  if (mFrames.IsEmpty() || !mInnerTableFrame) {
-    NS_ERROR("incomplete children");
-    return NS_ERROR_FAILURE;
-  }
   nsresult rv = NS_OK;
   PRUint8 captionSide = GetCaptionSide();
 
   // Initialize out parameters
   aDesiredSize.width = aDesiredSize.height = 0;
   aStatus = NS_FRAME_COMPLETE;
 
   if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
@@ -994,88 +967,89 @@ NS_METHOD nsTableOuterFrame::Reflow(nsPr
     ((sizeof(nsHTMLReflowState) + sizeof(long) - 1) / sizeof(long))
   long captionRSSpace[LONGS_IN_HTMLRS];
   nsHTMLReflowState *captionRS =
     static_cast<nsHTMLReflowState*>((void*)captionRSSpace);
   long innerRSSpace[LONGS_IN_HTMLRS];
   nsHTMLReflowState *innerRS =
     static_cast<nsHTMLReflowState*>((void*) innerRSSpace);
 
-  nsRect origInnerRect = mInnerTableFrame->GetRect();
-  nsRect origInnerVisualOverflow = mInnerTableFrame->GetVisualOverflowRect();
+  nsRect origInnerRect = InnerTableFrame()->GetRect();
+  nsRect origInnerVisualOverflow = InnerTableFrame()->GetVisualOverflowRect();
   PRBool innerFirstReflow =
-    (mInnerTableFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
+    (InnerTableFrame()->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
   nsRect origCaptionRect;
   nsRect origCaptionVisualOverflow;
   PRBool captionFirstReflow;
-  if (mCaptionFrame) {
-    origCaptionRect = mCaptionFrame->GetRect();
-    origCaptionVisualOverflow = mCaptionFrame->GetVisualOverflowRect();
+  if (mCaptionFrames.NotEmpty()) {
+    origCaptionRect = mCaptionFrames.FirstChild()->GetRect();
+    origCaptionVisualOverflow =
+      mCaptionFrames.FirstChild()->GetVisualOverflowRect();
     captionFirstReflow =
-      (mCaptionFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
+      (mCaptionFrames.FirstChild()->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
   }
   
   // ComputeAutoSize has to match this logic.
   if (captionSide == NO_SIDE) {
     // We don't have a caption.
-    OuterBeginReflowChild(aPresContext, mInnerTableFrame, aOuterRS,
+    OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRS,
                           innerRSSpace, aOuterRS.ComputedWidth());
   } else if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT ||
              captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) {
     // nsTableCaptionFrame::ComputeAutoSize takes care of making side
     // captions small.  Compute the caption's size first, and tell the
     // table to fit in what's left.
-    OuterBeginReflowChild(aPresContext, mCaptionFrame, aOuterRS,
+    OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRS,
                           captionRSSpace, aOuterRS.ComputedWidth());
     nscoord innerAvailWidth = aOuterRS.ComputedWidth() -
       (captionRS->ComputedWidth() + captionRS->mComputedMargin.LeftRight() +
        captionRS->mComputedBorderPadding.LeftRight());
-    OuterBeginReflowChild(aPresContext, mInnerTableFrame, aOuterRS,
+    OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRS,
                           innerRSSpace, innerAvailWidth);
 
   } else if (captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
              captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) {
     // Compute the table's size first, and then prevent the caption from
     // being wider unless it has to be.
     //
     // Note that CSS 2.1 (but not 2.0) says:
     //   The width of the anonymous box is the border-edge width of the
     //   table box inside it
     // We don't actually make our anonymous box that width (if we did,
     // it would break 'auto' margins), but this effectively does that.
-    OuterBeginReflowChild(aPresContext, mInnerTableFrame, aOuterRS,
+    OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRS,
                           innerRSSpace, aOuterRS.ComputedWidth());
     // It's good that CSS 2.1 says not to include margins, since we
     // can't, since they already been converted so they exactly
     // fill the available width (ignoring the margin on one side if
     // neither are auto).  (We take advantage of that later when we call
     // GetCaptionOrigin, though.)
     nscoord innerBorderWidth = innerRS->ComputedWidth() +
                                innerRS->mComputedBorderPadding.LeftRight();
-    OuterBeginReflowChild(aPresContext, mCaptionFrame, aOuterRS,
+    OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRS,
                           captionRSSpace, innerBorderWidth);
   } else {
     NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE ||
                  captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE,
                  "unexpected caption-side");
     // Size the table and the caption independently.
-    OuterBeginReflowChild(aPresContext, mCaptionFrame, aOuterRS,
+    OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRS,
                           captionRSSpace, aOuterRS.ComputedWidth());
-    OuterBeginReflowChild(aPresContext, mInnerTableFrame, aOuterRS,
+    OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRS,
                           innerRSSpace, aOuterRS.ComputedWidth());
   }
 
   // First reflow the caption.
   nsHTMLReflowMetrics captionMet;
   nsSize captionSize;
   nsMargin captionMargin;
-  if (mCaptionFrame) {
+  if (mCaptionFrames.NotEmpty()) {
     nsReflowStatus capStatus; // don't let the caption cause incomplete
-    rv = OuterDoReflowChild(aPresContext, mCaptionFrame, *captionRS,
-                            captionMet, capStatus);
+    rv = OuterDoReflowChild(aPresContext, mCaptionFrames.FirstChild(),
+                            *captionRS, captionMet, capStatus);
     if (NS_FAILED(rv)) return rv;
     captionSize.width = captionMet.width;
     captionSize.height = captionMet.height;
     captionMargin = captionRS->mComputedMargin;
     // Now that we know the height of the caption, reduce the available height
     // for the table frame if we are height constrained and the caption is above
     // or below the inner table.
     if (NS_UNCONSTRAINEDSIZE != aOuterRS.availableHeight) {
@@ -1109,54 +1083,54 @@ NS_METHOD nsTableOuterFrame::Reflow(nsPr
   } else {
     captionSize.SizeTo(0,0);
     captionMargin.SizeTo(0,0,0,0);
   }
 
   // Then, now that we know how much to reduce the width of the inner
   // table to account for side captions, reflow the inner table.
   nsHTMLReflowMetrics innerMet;
-  rv = OuterDoReflowChild(aPresContext, mInnerTableFrame, *innerRS,
+  rv = OuterDoReflowChild(aPresContext, InnerTableFrame(), *innerRS,
                           innerMet, aStatus);
   if (NS_FAILED(rv)) return rv;
   nsSize innerSize;
   innerSize.width = innerMet.width;
   innerSize.height = innerMet.height;
   nsMargin innerMargin = innerRS->mComputedMargin;
 
   nsSize   containSize = GetContainingBlockSize(aOuterRS);
 
   // Now that we've reflowed both we can place them.
   // XXXldb Most of the input variables here are now uninitialized!
 
   // XXX Need to recompute inner table's auto margins for the case of side
   // captions.  (Caption's are broken too, but that should be fixed earlier.)
 
-  if (mCaptionFrame) {
+  if (mCaptionFrames.NotEmpty()) {
     nsPoint captionOrigin;
     GetCaptionOrigin(captionSide, containSize, innerSize, 
                      innerMargin, captionSize, captionMargin, captionOrigin);
-    FinishReflowChild(mCaptionFrame, aPresContext, captionRS, captionMet,
-                      captionOrigin.x, captionOrigin.y, 0);
+    FinishReflowChild(mCaptionFrames.FirstChild(), aPresContext, captionRS,
+                      captionMet, captionOrigin.x, captionOrigin.y, 0);
     captionRS->~nsHTMLReflowState();
   }
   // XXX If the height is constrained then we need to check whether
   // everything still fits...
 
   nsPoint innerOrigin;
   GetInnerOrigin(captionSide, containSize, captionSize, 
                  captionMargin, innerSize, innerMargin, innerOrigin);
-  FinishReflowChild(mInnerTableFrame, aPresContext, innerRS, innerMet,
+  FinishReflowChild(InnerTableFrame(), aPresContext, innerRS, innerMet,
                     innerOrigin.x, innerOrigin.y, 0);
   innerRS->~nsHTMLReflowState();
 
-  nsTableFrame::InvalidateFrame(mInnerTableFrame, origInnerRect,
+  nsTableFrame::InvalidateFrame(InnerTableFrame(), origInnerRect,
                                 origInnerVisualOverflow, innerFirstReflow);
-  if (mCaptionFrame) {
-    nsTableFrame::InvalidateFrame(mCaptionFrame, origCaptionRect,
+  if (mCaptionFrames.NotEmpty()) {
+    nsTableFrame::InvalidateFrame(mCaptionFrames.FirstChild(), origCaptionRect,
                                   origCaptionVisualOverflow,
                                   captionFirstReflow);
   }
 
   UpdateReflowMetrics(captionSide, aDesiredSize, innerMargin, captionMargin);
   
   // Return our desired rect
 
@@ -1176,51 +1150,43 @@ nsTableOuterFrame::GetType() const
 NS_IMETHODIMP 
 nsTableOuterFrame::GetCellDataAt(PRInt32 aRowIndex, PRInt32 aColIndex, 
                                  nsIDOMElement* &aCell,   //out params
                                  PRInt32& aStartRowIndex, PRInt32& aStartColIndex, 
                                  PRInt32& aRowSpan, PRInt32& aColSpan,
                                  PRInt32& aActualRowSpan, PRInt32& aActualColSpan,
                                  PRBool& aIsSelected)
 {
-  NS_ASSERTION(mInnerTableFrame, "no inner table frame yet?");
-  
-  return mInnerTableFrame->GetCellDataAt(aRowIndex, aColIndex, aCell,
-                                        aStartRowIndex, aStartColIndex, 
-                                        aRowSpan, aColSpan, aActualRowSpan,
-                                        aActualColSpan, aIsSelected);
+  return InnerTableFrame()->GetCellDataAt(aRowIndex, aColIndex, aCell,
+                                          aStartRowIndex, aStartColIndex, 
+                                          aRowSpan, aColSpan, aActualRowSpan,
+                                          aActualColSpan, aIsSelected);
 }
 
 NS_IMETHODIMP
 nsTableOuterFrame::GetTableSize(PRInt32& aRowCount, PRInt32& aColCount)
 {
-  NS_ASSERTION(mInnerTableFrame, "no inner table frame yet?");
-
-  return mInnerTableFrame->GetTableSize(aRowCount, aColCount);
+  return InnerTableFrame()->GetTableSize(aRowCount, aColCount);
 }
 
 NS_IMETHODIMP
 nsTableOuterFrame::GetIndexByRowAndColumn(PRInt32 aRow, PRInt32 aColumn,
                                           PRInt32 *aIndex)
 {
   NS_ENSURE_ARG_POINTER(aIndex);
-
-  NS_ASSERTION(mInnerTableFrame, "no inner table frame yet?");
-  return mInnerTableFrame->GetIndexByRowAndColumn(aRow, aColumn, aIndex);
+  return InnerTableFrame()->GetIndexByRowAndColumn(aRow, aColumn, aIndex);
 }
 
 NS_IMETHODIMP
 nsTableOuterFrame::GetRowAndColumnByIndex(PRInt32 aIndex,
                                           PRInt32 *aRow, PRInt32 *aColumn)
 {
   NS_ENSURE_ARG_POINTER(aRow);
   NS_ENSURE_ARG_POINTER(aColumn);
-
-  NS_ASSERTION(mInnerTableFrame, "no inner table frame yet?");
-  return mInnerTableFrame->GetRowAndColumnByIndex(aIndex, aRow, aColumn);
+  return InnerTableFrame()->GetRowAndColumnByIndex(aIndex, aRow, aColumn);
 }
 
 /*---------------- end of nsITableLayout implementation ------------------*/
 
 
 nsIFrame*
 NS_NewTableOuterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
--- a/layout/tables/nsTableOuterFrame.h
+++ b/layout/tables/nsTableOuterFrame.h
@@ -36,37 +36,34 @@
  * ***** END LICENSE BLOCK ***** */
 #ifndef nsTableOuterFrame_h__
 #define nsTableOuterFrame_h__
 
 #include "nscore.h"
 #include "nsHTMLContainerFrame.h"
 #include "nsBlockFrame.h"
 #include "nsITableLayout.h"
-
-struct nsStyleTable;
-class nsTableFrame;
+#include "nsTableFrame.h"
 
 class nsTableCaptionFrame : public nsBlockFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsISupports
   virtual nsIAtom* GetType() const;
   friend nsIFrame* NS_NewTableCaptionFrame(nsIPresShell* aPresShell, nsStyleContext*  aContext);
 
   virtual nsSize ComputeAutoSize(nsRenderingContext *aRenderingContext,
                                  nsSize aCBSize, nscoord aAvailableWidth,
                                  nsSize aMargin, nsSize aBorder,
                                  nsSize aPadding, PRBool aShrinkWrap);
 
-  NS_IMETHOD GetParentStyleContextFrame(nsPresContext* aPresContext,
-                                        nsIFrame**      aProviderFrame,
-                                        PRBool*         aIsChild);
+  virtual nsIFrame* GetParentStyleContextFrame();
+
 #ifdef ACCESSIBILITY
   virtual already_AddRefed<nsAccessible> CreateAccessible();
 #endif
 
 #ifdef NS_DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
@@ -164,19 +161,17 @@ public:
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
   /** SetSelected needs to be overridden to talk to inner tableframe
    */
   void SetSelected(PRBool aSelected,
                    SelectionType aType);
 
-  NS_IMETHOD GetParentStyleContextFrame(nsPresContext* aPresContext,
-                                        nsIFrame**      aProviderFrame,
-                                        PRBool*         aIsChild);
+  virtual nsIFrame* GetParentStyleContextFrame();
 
   /*---------------- nsITableLayout methods ------------------------*/
 
   /** @see nsITableFrame::GetCellDataAt */
   NS_IMETHOD GetCellDataAt(PRInt32 aRowIndex, PRInt32 aColIndex, 
                            nsIDOMElement* &aCell,   //out params
                            PRInt32& aStartRowIndex, PRInt32& aStartColIndex, 
                            PRInt32& aRowSpan, PRInt32& aColSpan,
@@ -257,22 +252,20 @@ protected:
   // Get the margin.  aMarginNoAuto is aMargin, but with auto 
   // margins set to 0
   void GetChildMargin(nsPresContext*           aPresContext,
                       const nsHTMLReflowState& aOuterRS,
                       nsIFrame*                aChildFrame,
                       nscoord                  aAvailableWidth,
                       nsMargin&                aMargin);
 
+  nsTableFrame* InnerTableFrame() {
+    return static_cast<nsTableFrame*>(mFrames.FirstChild());
+  }
+  
 private:
-  // used to keep track of this frame's children. They are redundant with mFrames, but more convient
-  nsTableFrame* mInnerTableFrame; 
   nsFrameList   mCaptionFrames;
-  nsIFrame*     mCaptionFrame;
 };
 
 inline PRIntn nsTableOuterFrame::GetSkipSides() const
 { return 0; }
 
 #endif
-
-
-
--- a/layout/xul/base/src/nsMenuBarListener.cpp
+++ b/layout/xul/base/src/nsMenuBarListener.cpp
@@ -136,16 +136,21 @@ nsMenuBarListener::ToggleMenuActiveState
       pm->HidePopup(popupFrame->GetContent(), PR_FALSE, PR_FALSE, PR_TRUE);
   }
 }
 
 ////////////////////////////////////////////////////////////////////////
 nsresult
 nsMenuBarListener::KeyUp(nsIDOMEvent* aKeyEvent)
 {  
+  nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
+  if (!keyEvent) {
+    return NS_OK;
+  }
+
   InitAccessKey();
 
   //handlers shouldn't be triggered by non-trusted events.
   nsCOMPtr<nsIDOMNSEvent> domNSEvent = do_QueryInterface(aKeyEvent);
   PRBool trustedEvent = PR_FALSE;
 
   if (domNSEvent) {
     domNSEvent->GetIsTrusted(&trustedEvent);
@@ -154,17 +159,16 @@ nsMenuBarListener::KeyUp(nsIDOMEvent* aK
   if (!trustedEvent)
     return NS_OK;
 
   if (mAccessKey && mAccessKeyFocuses)
   {
     // On a press of the ALT key by itself, we toggle the menu's 
     // active/inactive state.
     // Get the ascii key code.
-    nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
     PRUint32 theChar;
     keyEvent->GetKeyCode(&theChar);
 
     if (mAccessKeyDown && !mAccessKeyDownCanceled &&
         (PRInt32)theChar == mAccessKey)
     {
       // The access key was down and is now up, and no other
       // keys were pressed in between.
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -1105,16 +1105,17 @@ pref("intl.locale.matchOS",             
 // for ISO-8859-1
 pref("intl.fallbackCharsetList.ISO-8859-1", "windows-1252");
 pref("font.language.group",                 "chrome://global/locale/intl.properties");
 
 // these locales have right-to-left UI
 pref("intl.uidirection.ar", "rtl");
 pref("intl.uidirection.he", "rtl");
 pref("intl.uidirection.fa", "rtl");
+pref("intl.uidirection.ur", "rtl");
 
 // use en-US hyphenation by default for content tagged with plain lang="en"
 pref("intl.hyphenation-alias.en", "en-us");
 // and for other subtags of en-*, if no specific patterns are available
 pref("intl.hyphenation-alias.en-*", "en-us");
 
 pref("intl.hyphenation-alias.af-*", "af");
 pref("intl.hyphenation-alias.bg-*", "bg");
--- a/netwerk/base/public/nsNetError.h
+++ b/netwerk/base/public/nsNetError.h
@@ -147,16 +147,27 @@
 /**
  * A transport level corruption was found in the source document. for example
  * a document with a calculated checksum that does not match the Content-MD5
  * http header.
  */
 #define NS_ERROR_CORRUPTED_CONTENT \
     NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 29)
 
+/**
+ * While parsing for the first component of a header field using
+ * syntax as in Content-Disposition or Content-Type, the first component
+ * was found to be empty, such as in:
+ *
+ * Content-Disposition: ; filename=foo
+ */
+#define NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY \
+    NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 34)
+
+
 /******************************************************************************
  * Connectivity error codes:
  */
 
 /**
  * The connection is already established.
  * XXX currently unused - consider removing.
  */
--- a/netwerk/base/public/nsNetUtil.h
+++ b/netwerk/base/public/nsNetUtil.h
@@ -1938,18 +1938,23 @@ NS_GetContentDispositionFromHeader(const
     aChan->GetURI(getter_AddRefs(uri));
     if (uri)
       uri->GetOriginCharset(fallbackCharset);
   }
 
   nsAutoString dispToken;
   rv = mimehdrpar->GetParameter(aHeader, "", fallbackCharset, PR_TRUE, nsnull,
                                 dispToken);
-  if (NS_FAILED(rv))
-    return nsIChannel::DISPOSITION_ATTACHMENT;
+
+  if (NS_FAILED(rv)) {
+    // special case (see bug 272541): empty disposition type handled as "inline"
+    return rv == NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY
+                 ? nsIChannel::DISPOSITION_INLINE
+                 : nsIChannel::DISPOSITION_ATTACHMENT;
+  }
 
   return NS_GetContentDispositionFromToken(dispToken);
 }
 
 /** Extracts the filename out of a content-disposition header
  * @param aFilename [out] The filename. Can be empty on error.
  * @param aDisposition Value of a Content-Disposition header
  * @param aURI Optional. Will be used to get a fallback charset for the
--- a/netwerk/mime/nsMIMEHeaderParamImpl.cpp
+++ b/netwerk/mime/nsMIMEHeaderParamImpl.cpp
@@ -52,16 +52,17 @@
 #include "nsCOMPtr.h"
 #include "nsEscape.h"
 #include "nsIUTF8ConverterService.h"
 #include "nsUConvCID.h"
 #include "nsIServiceManager.h"
 #include "nsMIMEHeaderParamImpl.h"
 #include "nsReadableUtils.h"
 #include "nsNativeCharsetUtils.h"
+#include "nsNetError.h"
 
 // static functions declared below are moved from mailnews/mime/src/comi18n.cpp
   
 static char *DecodeQ(const char *, PRUint32);
 static PRBool Is7bitNonAsciiString(const char *, PRUint32);
 static void CopyRawHeader(const char *, PRUint32, const char *, nsACString &);
 static nsresult DecodeRFC2047Str(const char *, const char *, PRBool, nsACString&);
 
@@ -176,17 +177,18 @@ nsMIMEHeaderParamImpl::GetParameterInter
   // aParamName is empty. return the first (possibly) _unnamed_ 'parameter'
   // For instance, return 'inline' in the following case:
   // Content-Disposition: inline; filename=.....
   if (!aParamName || !*aParamName) 
     {
       for (; *str && *str != ';' && !nsCRT::IsAsciiSpace(*str); ++str)
         ;
       if (str == start)
-        return NS_ERROR_UNEXPECTED;
+        return NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY;
+
       *aResult = (char *) nsMemory::Clone(start, (str - start) + 1);
       NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
       (*aResult)[str - start] = '\0';  // null-terminate
       return NS_OK;
     }
 
   /* Skip forward to first ';' */
   for (; *str && *str != ';' && *str != ','; ++str)
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -771,35 +771,46 @@ HttpBaseChannel::nsContentEncodings::Pre
 
 //-----------------------------------------------------------------------------
 // HttpBaseChannel::nsIHttpChannel
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 HttpBaseChannel::GetRequestMethod(nsACString& aMethod)
 {
-  aMethod = mRequestHead.Method();
+  mRequestHead.Method()->ToUTF8String(aMethod);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpBaseChannel::SetRequestMethod(const nsACString& aMethod)
 {
   ENSURE_CALLED_BEFORE_ASYNC_OPEN();
 
-  const nsCString& flatMethod = PromiseFlatCString(aMethod);
+  nsCAutoString upperCaseMethod;
+  ToUpperCase(aMethod, upperCaseMethod);
 
   // Method names are restricted to valid HTTP tokens.
-  if (!nsHttp::IsValidToken(flatMethod))
+  if (!nsHttp::IsValidToken(upperCaseMethod))
     return NS_ERROR_INVALID_ARG;
 
-  nsHttpAtom atom = nsHttp::ResolveAtom(flatMethod.get());
-  if (!atom)
-    return NS_ERROR_FAILURE;
+  nsCOMPtr<nsIAtom> atom = do_GetAtom(upperCaseMethod);
 
+  // We've changed method names to case sensitive in bug 477578. Some
+  // methods are kept case insensitive to keep backward compatibility and
+  // to satisfy XMLHttpRequest specification which demands it.
+#define HTTP_METHOD_ATOM(name_, value_)
+#define HTTP_CASE_INSENSITIVE_METHOD_ATOM(name_, value_) \
+  if (nsHttp::name_ == atom) {} else
+#include "nsHttpAtomList.h"
+#undef HTTP_CASE_INSENSITIVE_METHOD_ATOM
+#undef HTTP_METHOD_ATOM
+  { // upper case atom doesn't match any case insensitive atom
+    atom = do_GetAtom(aMethod);
+  }
   mRequestHead.SetMethod(atom);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpBaseChannel::GetReferrer(nsIURI **referrer)
 {
   NS_ENSURE_ARG_POINTER(referrer);
@@ -1538,17 +1549,17 @@ HttpBaseChannel::SetupReplacementChannel
       if (uploadChannel2) {
         const char *ctype = mRequestHead.PeekHeader(nsHttp::Content_Type);
         if (!ctype)
           ctype = "";
         const char *clen  = mRequestHead.PeekHeader(nsHttp::Content_Length);
         PRInt64 len = clen ? nsCRT::atoll(clen) : -1;
         uploadChannel2->ExplicitSetUploadStream(
                                   mUploadStream, nsDependentCString(ctype), len,
-                                  nsDependentCString(mRequestHead.Method()),
+                                  nsAtomCString(mRequestHead.Method()),
                                   mUploadStreamHasHeaders);
       } else {
         if (mUploadStreamHasHeaders) {
           uploadChannel->SetUploadStream(mUploadStream, EmptyCString(),
                            -1);
         } else {
           const char *ctype =
             mRequestHead.PeekHeader(nsHttp::Content_Type);
@@ -1565,17 +1576,17 @@ HttpBaseChannel::SetupReplacementChannel
         }
       }
     }
     // since preserveMethod is true, we need to ensure that the appropriate 
     // request method gets set on the channel, regardless of whether or not 
     // we set the upload stream above. This means SetRequestMethod() will
     // be called twice if ExplicitSetUploadStream() gets called above.
 
-    httpChannel->SetRequestMethod(nsDependentCString(mRequestHead.Method()));
+    httpChannel->SetRequestMethod(nsAtomCString(mRequestHead.Method()));
   }
   // convey the referrer if one was used for this channel to the next one
   if (mReferrer)
     httpChannel->SetReferrer(mReferrer);
   // convey the mAllowPipelining flag
   httpChannel->SetAllowPipelining(mAllowPipelining);
   // convey the new redirection limit
   httpChannel->SetRedirectionLimit(mRedirectionLimit - 1);
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -1067,17 +1067,17 @@ HttpChannelChild::AsyncOpen(nsIStreamLis
   // The socket transport in the chrome process now holds a logical ref to us
   // until OnStopRequest, or we do a redirect, or we hit an IPDL error.
   AddIPDLReference();
 
   gNeckoChild->SendPHttpChannelConstructor(this, tabChild);
 
   SendAsyncOpen(IPC::URI(mURI), IPC::URI(mOriginalURI),
                 IPC::URI(mDocumentURI), IPC::URI(mReferrer), mLoadFlags,
-                mRequestHeaders, mRequestHead.Method(),
+                mRequestHeaders, nsAtomCString(mRequestHead.Method()),
                 IPC::InputStream(mUploadStream), mUploadStreamHasHeaders,
                 mPriority, mRedirectionLimit, mAllowPipelining,
                 mForceAllowThirdPartyCookie, mSendResumeAt,
                 mStartPos, mEntityID, mChooseApplicationCache, 
                 appCacheClientId);
 
   return NS_OK;
 }
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -127,17 +127,17 @@ HttpChannelParent::GetInterface(const ns
 
 bool 
 HttpChannelParent::RecvAsyncOpen(const IPC::URI&            aURI,
                                  const IPC::URI&            aOriginalURI,
                                  const IPC::URI&            aDocURI,
                                  const IPC::URI&            aReferrerURI,
                                  const PRUint32&            loadFlags,
                                  const RequestHeaderTuples& requestHeaders,
-                                 const nsHttpAtom&          requestMethod,
+                                 const nsCString&           requestMethod,
                                  const IPC::InputStream&    uploadStream,
                                  const PRBool&              uploadStreamHasHeaders,
                                  const PRUint16&            priority,
                                  const PRUint8&             redirectionLimit,
                                  const PRBool&              allowPipelining,
                                  const PRBool&              forceAllowThirdPartyCookie,
                                  const bool&                doResumeAt,
                                  const PRUint64&            startPos,
@@ -185,17 +185,17 @@ HttpChannelParent::RecvAsyncOpen(const I
                                requestHeaders[i].mMerge);
   }
 
   nsRefPtr<HttpChannelParentListener> channelListener =
       new HttpChannelParentListener(this);
 
   httpChan->SetNotificationCallbacks(channelListener);
 
-  httpChan->SetRequestMethod(nsDependentCString(requestMethod.get()));
+  httpChan->SetRequestMethod(requestMethod);
 
   nsCOMPtr<nsIInputStream> stream(uploadStream);
   if (stream) {
     httpChan->InternalSetUploadStream(stream);
     httpChan->SetUploadStreamHasHeaders(uploadStreamHasHeaders);
   }
 
   if (priority != nsISupportsPriority::PRIORITY_NORMAL)
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -81,17 +81,17 @@ public:
 
 protected:
   virtual bool RecvAsyncOpen(const IPC::URI&            uri,
                              const IPC::URI&            originalUri,
                              const IPC::URI&            docUri,
                              const IPC::URI&            referrerUri,
                              const PRUint32&            loadFlags,
                              const RequestHeaderTuples& requestHeaders,
-                             const nsHttpAtom&          requestMethod,
+                             const nsCString&           requestMethod,
                              const IPC::InputStream&    uploadStream,
                              const PRBool&              uploadStreamHasHeaders,
                              const PRUint16&            priority,
                              const PRUint8&             redirectionLimit,
                              const PRBool&              allowPipelining,
                              const PRBool&              forceAllowThirdPartyCookie,
                              const bool&                doResumeAt,
                              const PRUint64&            startPos,
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -42,17 +42,16 @@
 include protocol PNecko;
 
 include "mozilla/net/PHttpChannelParams.h";
 include "mozilla/net/NeckoMessageUtils.h";
 include "prio.h";
 
 using RequestHeaderTuples;
 using nsHttpResponseHead;
-using nsHttpAtom;
 using IPC::URI;
 using IPC::InputStream;
 using PRNetAddr;
 
 namespace mozilla {
 namespace net {
 
 //-------------------------------------------------------------------
@@ -65,17 +64,17 @@ parent:
             // - TODO: bug 571161: unclear if any HTTP channel clients ever
             // set originalURI != uri (about:credits?); also not clear if
             // chrome channel would ever need to know.  Get rid of next arg?
             URI                 original,
             URI                 doc,
             URI                 referrer,
             PRUint32            loadFlags,
             RequestHeaderTuples requestHeaders,
-            nsHttpAtom          requestMethod,
+            nsCString           requestMethod,
             InputStream         uploadStream,
             PRBool              uploadStreamHasHeaders,
             PRUint16            priority,
             PRUint8             redirectionLimit,
             PRBool              allowPipelining,
             PRBool              forceAllowThirdPartyCookie,
             bool                resumeAt,
             PRUint64            startPos,
--- a/netwerk/protocol/http/nsHttp.cpp
+++ b/netwerk/protocol/http/nsHttp.cpp
@@ -37,16 +37,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsHttp.h"
 #include "pldhash.h"
 #include "mozilla/Mutex.h"
 #include "nsCRT.h"
 #include "prbit.h"
+#include "nsStaticAtom.h"
 
 #if defined(PR_LOGGING)
 PRLogModuleInfo *gHttpLog = nsnull;
 #endif
 
 // define storage for all atoms
 #define HTTP_ATOM(_name, _value) nsHttpAtom nsHttp::_name = { _value };
 #include "nsHttpAtomList.h"
@@ -55,16 +56,33 @@ PRLogModuleInfo *gHttpLog = nsnull;
 // find out how many atoms we have
 #define HTTP_ATOM(_name, _value) Unused_ ## _name,
 enum {
 #include "nsHttpAtomList.h"
     NUM_HTTP_ATOMS
 };
 #undef HTTP_ATOM
 
+// define all method atoms
+#define HTTP_METHOD_ATOM(name_, value_) nsIAtom* nsHttp::name_;
+#include "nsHttpAtomList.h"
+#undef HTTP_METHOD_ATOM
+
+#define HTTP_METHOD_ATOM(name_, value_) \
+    NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#include "nsHttpAtomList.h"
+#undef HTTP_METHOD_ATOM
+
+static const nsStaticAtom methodAtomsInfo[] = {
+#define HTTP_METHOD_ATOM(name_, value_) \
+    NS_STATIC_ATOM(name_##_buffer, &nsHttp::name_),
+#include "nsHttpAtomList.h"
+#undef HTTP_METHOD_ATOM
+};
+
 using namespace mozilla;
 
 // we keep a linked list of atoms allocated on the heap for easy clean up when
 // the atom table is destroyed.  The structure and value string are allocated
 // as one contiguous block.
 
 struct HttpHeapAtom {
     struct HttpHeapAtom *next;
@@ -179,16 +197,22 @@ nsHttp::DestroyAtomTable()
     }
 
     if (sLock) {
         delete sLock;
         sLock = nsnull;
     }
 }
 
+void
+nsHttp::CreateMethodAtoms()
+{
+    NS_RegisterStaticAtoms(methodAtomsInfo, NS_ARRAY_LENGTH(methodAtomsInfo));
+}
+
 // this function may be called from multiple threads
 nsHttpAtom
 nsHttp::ResolveAtom(const char *str)
 {
     nsHttpAtom atom = { nsnull };
 
     if (!str || !sAtomTable.ops)
         return atom;
--- a/netwerk/protocol/http/nsHttp.h
+++ b/netwerk/protocol/http/nsHttp.h
@@ -62,16 +62,17 @@
 
 #include "plstr.h"
 #include "prlog.h"
 #include "prtime.h"
 #include "nsISupportsUtils.h"
 #include "nsPromiseFlatString.h"
 #include "nsURLHelper.h"
 #include "netCore.h"
+#include "nsIAtom.h"
 
 #if defined(PR_LOGGING)
 //
 // Log module for HTTP Protocol logging...
 //
 // To enable logging (see prlog.h for full details):
 //
 //    set NSPR_LOG_MODULES=nsHttp:5
@@ -159,16 +160,18 @@ struct nsHttpAtom
     const char *_val;
 };
 
 struct nsHttp
 {
     static nsresult CreateAtomTable();
     static void DestroyAtomTable();
 
+    static void CreateMethodAtoms();
+
     // will dynamically add atoms to the table if they don't already exist
     static nsHttpAtom ResolveAtom(const char *);
     static nsHttpAtom ResolveAtom(const nsACString &s)
     {
         return ResolveAtom(PromiseFlatCString(s).get());
     }
 
     // returns true if the specified token [start,end) is valid per RFC 2616
@@ -210,16 +213,20 @@ struct nsHttp
     // 
     // The atom names and values are stored in nsHttpAtomList.h and are brought
     // to you by the magic of C preprocessing.  Add new atoms to nsHttpAtomList
     // and all support logic will be auto-generated.
     //
 #define HTTP_ATOM(_name, _value) static nsHttpAtom _name;
 #include "nsHttpAtomList.h"
 #undef HTTP_ATOM
+
+#define HTTP_METHOD_ATOM(_name, _value) static nsIAtom* _name;
+#include "nsHttpAtomList.h"
+#undef HTTP_METHOD_ATOM
 };
 
 //-----------------------------------------------------------------------------
 // utilities...
 //-----------------------------------------------------------------------------
 
 static inline PRUint32
 PRTimeToSeconds(PRTime t_usec)
--- a/netwerk/protocol/http/nsHttpAtomList.h
+++ b/netwerk/protocol/http/nsHttpAtomList.h
@@ -45,16 +45,17 @@
 
   All entries must be enclosed in the macro HTTP_ATOM which will have cruel
   and unusual things done to it.
 
   The first argument to HTTP_ATOM is the C++ name of the atom.
   The second argument to HTTP_ATOM is the string value of the atom.
  ******/
 
+#if defined(HTTP_ATOM)
 HTTP_ATOM(Accept,                    "Accept")
 HTTP_ATOM(Accept_Encoding,           "Accept-Encoding")
 HTTP_ATOM(Accept_Language,           "Accept-Language")
 HTTP_ATOM(Accept_Ranges,             "Accept-Ranges")
 HTTP_ATOM(Age,                       "Age")
 HTTP_ATOM(Allow,                     "Allow")
 HTTP_ATOM(Authentication,            "Authentication")
 HTTP_ATOM(Authorization,             "Authorization")
@@ -118,31 +119,45 @@ HTTP_ATOM(Trailer,                   "Tr
 HTTP_ATOM(Transfer_Encoding,         "Transfer-Encoding")
 HTTP_ATOM(URI,                       "URI")
 HTTP_ATOM(Upgrade,                   "Upgrade")
 HTTP_ATOM(User_Agent,                "User-Agent")
 HTTP_ATOM(Vary,                      "Vary")
 HTTP_ATOM(Version,                   "Version")
 HTTP_ATOM(WWW_Authenticate,          "WWW-Authenticate")
 HTTP_ATOM(Warning,                   "Warning")
+#endif
 
 // methods are atoms too.
 //
 // Note: winnt.h defines DELETE macro, so we'll just keep the methods mixedcase
 // even though they're normally written all uppercase. -- darin
 
-HTTP_ATOM(Connect,                   "CONNECT")
-HTTP_ATOM(Copy,                      "COPY")
-HTTP_ATOM(Delete,                    "DELETE")
-HTTP_ATOM(Get,                       "GET")
-HTTP_ATOM(Head,                      "HEAD")
-HTTP_ATOM(Index,                     "INDEX")
-HTTP_ATOM(Lock,                      "LOCK")
-HTTP_ATOM(M_Post,                    "M-POST")
-HTTP_ATOM(Mkcol,                     "MKCOL")
-HTTP_ATOM(Move,                      "MOVE")
-HTTP_ATOM(Options,                   "OPTIONS")
-HTTP_ATOM(Post,                      "POST")
-HTTP_ATOM(Propfind,                  "PROPFIND")
-HTTP_ATOM(Proppatch,                 "PROPPATCH")
-HTTP_ATOM(Put,                       "PUT")
-HTTP_ATOM(Trace,                     "TRACE")
-HTTP_ATOM(Unlock,                    "UNLOCK")
+#if defined(HTTP_METHOD_ATOM)
+
+#if !defined(HTTP_CASE_INSENSITIVE_METHOD_ATOM)
+#define HTTP_CASE_INSENSITIVE_METHOD_ATOM HTTP_METHOD_ATOM
+#define UNDEF_HTTP_CASE_INSENSITIVE_METHOD_ATOM
+#endif
+HTTP_CASE_INSENSITIVE_METHOD_ATOM(Connect,   "CONNECT")
+HTTP_METHOD_ATOM                 (Copy,      "COPY")
+HTTP_CASE_INSENSITIVE_METHOD_ATOM(Delete,    "DELETE")
+HTTP_CASE_INSENSITIVE_METHOD_ATOM(Get,       "GET")
+HTTP_CASE_INSENSITIVE_METHOD_ATOM(Head,      "HEAD")
+HTTP_METHOD_ATOM                 (Index,     "INDEX")
+HTTP_METHOD_ATOM                 (Lock,      "LOCK")
+HTTP_METHOD_ATOM                 (M_Post,    "M-POST")
+HTTP_METHOD_ATOM                 (Mkcol,     "MKCOL")
+HTTP_METHOD_ATOM                 (Move,      "MOVE")
+HTTP_CASE_INSENSITIVE_METHOD_ATOM(Options,   "OPTIONS")
+HTTP_CASE_INSENSITIVE_METHOD_ATOM(Post,      "POST")
+HTTP_METHOD_ATOM                 (Propfind,  "PROPFIND")
+HTTP_METHOD_ATOM                 (Proppatch, "PROPPATCH")
+HTTP_CASE_INSENSITIVE_METHOD_ATOM(Put,       "PUT")
+HTTP_CASE_INSENSITIVE_METHOD_ATOM(Trace,     "TRACE")
+HTTP_CASE_INSENSITIVE_METHOD_ATOM(Track,     "TRACK")
+HTTP_METHOD_ATOM                 (Unlock,    "UNLOCK")
+#if defined(UNDEF_HTTP_CASE_INSENSITIVE_METHOD_ATOM)
+#undef UNDEF_HTTP_CASE_INSENSITIVE_METHOD_ATOM
+#undef HTTP_CASE_INSENSITIVE_METHOD_ATOM
+#endif
+
+#endif
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -2407,17 +2407,19 @@ nsHttpChannel::CheckCache()
         return NS_OK;
 
     nsXPIDLCString buf;
 
     // Get the method that was used to generate the cached response
     rv = mCacheEntry->GetMetaDataElement("request-method", getter_Copies(buf));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsHttpAtom method = nsHttp::ResolveAtom(buf);
+    nsCOMPtr<nsIAtom> method = do_GetAtom(buf);
+    NS_ENSURE_TRUE(method, NS_ERROR_OUT_OF_MEMORY);
+
     if (method == nsHttp::Head) {
         // The cached response does not contain an entity.  We can only reuse
         // the response if the current request is also HEAD.
         if (mRequestHead.Method() != nsHttp::Head)
             return NS_OK;
     }
     buf.Adopt(0);
 
@@ -2976,17 +2978,17 @@ nsHttpChannel::AddCacheEntryHeaders(nsIC
     LOG(("nsHttpChannel::AddCacheEntryHeaders [this=%x] begin", this));
     // Store secure data in memory only
     if (mSecurityInfo)
         entry->SetSecurityInfo(mSecurityInfo);
 
     // Store the HTTP request method with the cache entry so we can distinguish
     // for example GET and HEAD responses.
     rv = entry->SetMetaDataElement("request-method",
-                                   mRequestHead.Method().get());
+                                   nsAtomCString(mRequestHead.Method()).get());
     if (NS_FAILED(rv)) return rv;
 
     // Store the HTTP authorization scheme used if any...
     rv = StoreAuthorizationMetaData(entry);
     if (NS_FAILED(rv)) return rv;
 
     // Iterate over the headers listed in the Vary response header, and
     // store the value of the corresponding request header so we can verify
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -233,16 +233,18 @@ nsHttpHandler::Init()
     nsresult rv;
 
     LOG(("nsHttpHandler::Init\n"));
 
     rv = nsHttp::CreateAtomTable();
     if (NS_FAILED(rv))
         return rv;
 
+    nsHttp::CreateMethodAtoms();
+
     mIOService = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
     if (NS_FAILED(rv)) {
         NS_WARNING("unable to continue without io service");
         return rv;
     }
 
     if (IsNeckoChild())
         NeckoChild::InitNeckoChild();
--- a/netwerk/protocol/http/nsHttpRequestHead.cpp
+++ b/netwerk/protocol/http/nsHttpRequestHead.cpp
@@ -42,17 +42,17 @@
 // nsHttpRequestHead
 //-----------------------------------------------------------------------------
 
 void
 nsHttpRequestHead::Flatten(nsACString &buf, PRBool pruneProxyHeaders)
 {
     // note: the first append is intentional.
  
-    buf.Append(mMethod.get());
+    buf.Append(nsAtomCString(mMethod));
     buf.Append(' ');
     buf.Append(mRequestURI);
     buf.AppendLiteral(" HTTP/");
 
     switch (mVersion) {
     case NS_HTTP_VERSION_1_1:
         buf.AppendLiteral("1.1");
         break;
--- a/netwerk/protocol/http/nsHttpRequestHead.h
+++ b/netwerk/protocol/http/nsHttpRequestHead.h
@@ -50,36 +50,36 @@
 //-----------------------------------------------------------------------------
 
 class nsHttpRequestHead
 {
 public:
     nsHttpRequestHead() : mMethod(nsHttp::Get), mVersion(NS_HTTP_VERSION_1_1) {}
     ~nsHttpRequestHead() {}
 
-    void SetMethod(nsHttpAtom method) { mMethod = method; }
+    void SetMethod(nsIAtom *method) { mMethod = method; }
     void SetVersion(nsHttpVersion version) { mVersion = version; }
     void SetRequestURI(const nsCSubstring &s) { mRequestURI = s; }
 
     nsHttpHeaderArray  &Headers()    { return mHeaders; }
-    nsHttpAtom          Method()     { return mMethod; }
+    nsIAtom            *Method()     { return mMethod; }
     nsHttpVersion       Version()    { return mVersion; }
     const nsCSubstring &RequestURI() { return mRequestURI; }
 
     const char *PeekHeader(nsHttpAtom h)                                     { return mHeaders.PeekHeader(h); }
     nsresult SetHeader(nsHttpAtom h, const nsACString &v, PRBool m=PR_FALSE) { return mHeaders.SetHeader(h, v, m); }
     nsresult GetHeader(nsHttpAtom h, nsACString &v)                          { return mHeaders.GetHeader(h, v); }
     void ClearHeader(nsHttpAtom h)                                           { mHeaders.ClearHeader(h); }
     void ClearHeaders()                                                      { mHeaders.Clear(); }
 
     const char *FindHeaderValue(nsHttpAtom h, const char *v) { return mHeaders.FindHeaderValue(h, v); }
     PRBool      HasHeaderValue(nsHttpAtom h, const char *v) { return mHeaders.HasHeaderValue(h, v); }
 
     void Flatten(nsACString &, PRBool pruneProxyHeaders = PR_FALSE);
 
 private:
     nsHttpHeaderArray mHeaders;
-    nsHttpAtom        mMethod;
+    nsCOMPtr<nsIAtom> mMethod;
     nsHttpVersion     mVersion;
     nsCString         mRequestURI;
 };
 
 #endif // nsHttpRequestHead_h__
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_bug272541.js
@@ -0,0 +1,37 @@
+/**
+ * Test for bug 272541: - Empty disposition type treated as "attachment" 
+ */
+
+const Cr = Components.results
+
+var tests = [
+                 [ /* the actual bug */
+                  "; filename=foo.html", 
+                  Cr.NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY],
+                 [ /* regression check, but see bug 671204 */
+                  "filename=foo.html", 
+                  "filename=foo.html"],
+                 [ /* sanity check */
+                  "attachment; filename=foo.html", 
+                  "attachment"],
+                ];
+
+function run_test() {
+
+  var mhp = Components.classes["@mozilla.org/network/mime-hdrparam;1"]
+                      .getService(Components.interfaces.nsIMIMEHeaderParam);
+
+  var unused = { value : null };
+
+  for (var i = 0; i < tests.length; ++i) {
+    dump("Testing " + tests[i] + "\n");
+    try {
+      do_check_eq(mhp.getParameter(tests[i][0], "", "UTF-8", true, unused),
+                  tests[i][1]);
+    }
+    catch (e) {
+      do_check_eq(e.result, tests[i][1]);
+    }
+  }
+}
+
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_bug477578.js
@@ -0,0 +1,42 @@
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+const testMethods = [
+  ["get", "GET"],
+  ["post", "POST"],
+  ["head", "HEAD"],
+  ["put", "PUT"],
+  ["delete", "DELETE"],
+  ["connect", "CONNECT"],
+  ["options", "OPTIONS"],
+  ["trace", "TRACE"],
+  ["track", "TRACK"],
+  ["copy", "copy"],
+  ["index", "index"],
+  ["lock", "lock"],
+  ["m-post", "m-post"],
+  ["mkcol", "mkcol"],
+  ["move", "move"],
+  ["propfind", "propfind"],
+  ["proppatch", "proppatch"],
+  ["unlock", "unlock"],
+  ["link", "link"],
+  ["foo", "foo"],
+  ["foO", "foO"],
+  ["fOo", "fOo"],
+  ["Foo", "Foo"]
+]
+
+function run_test() {
+  var ios =
+    Cc["@mozilla.org/network/io-service;1"].
+    getService(Ci.nsIIOService);
+
+  var chan = ios.newChannel("http://localhost/", null, null)
+                  .QueryInterface(Components.interfaces.nsIHttpChannel);
+
+  for (var i = 0; i < testMethods.length; i++) {
+    chan.requestMethod = testMethods[i][0];
+    do_check_eq(chan.requestMethod, testMethods[i][1]);
+  }
+}
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -11,16 +11,17 @@ tail =
 # Bug 675039: test hangs consistently on Android
 skip-if = os == "android"
 [test_authpromptwrapper.js]
 [test_bug203271.js]
 [test_bug248970_cache.js]
 [test_bug248970_cookie.js]
 [test_bug261425.js]
 [test_bug263127.js]
+[test_bug272541.js]
 [test_bug321706.js]
 [test_bug331825.js]
 [test_bug336501.js]
 [test_bug337744.js]
 [test_bug365133.js]
 [test_bug368702.js]
 [test_bug369787.js]
 [test_bug371473.js]
@@ -39,16 +40,17 @@ skip-if = os == "android"
 [test_bug429347.js]
 [test_bug455311.js]
 [test_bug455598.js]
 [test_bug468426.js]
 # Bug 675039: test hangs consistently on Android 
 skip-if = os == "android"
 [test_bug468594.js]
 [test_bug470716.js]
+[test_bug477578.js]
 [test_bug479413.js]
 [test_bug479485.js]
 [test_bug482601.js]
 [test_bug484684.js]
 [test_bug490095.js]
 [test_bug504014.js]
 [test_bug510359.js]
 # Bug 675039: test hangs consistently on Android 
--- a/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType.properties
+++ b/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType.properties
@@ -45,18 +45,18 @@ chooseAppFilePickerTitle=Choose Helper A
 badApp=The application you chose ("%S") could not be found.  Check the file name or choose another application.
 badApp.title=Application not found
 badPermissions=The file could not be saved because you do not have the proper permissions.  Choose another save directory.
 badPermissions.title=Invalid Save Permissions
 selectDownloadDir=Select Download Folder
 unknownAccept.label=Save File
 unknownCancel.label=Cancel
 fileType=%S file
-# LOCALIZATION NOTE (fileSizeWithType): first %S is type, second %S is size, and third %S is unit  
-fileSizeWithType=%1S (%2S %3S)
+# LOCALIZATION NOTE (orderedFileSizeWithType): first %S is type, second %S is size, and third %S is unit  
+orderedFileSizeWithType=%1$S (%2$S %3$S)
 
 # LOCALIZATION NOTE (wpsDefaultOS2): OS/2 only, WPS refers to the Workplace Shell and should probably not be translated
 wpsDefaultOS2=WPS Default
 # LOCALIZATION NOTE (classViewerOS2): OS/2 only
 classViewerOS2=Viewer for Class %S
 # LOCALIZATION NOTE (mmImageViewerOS2): OS/2 only, default operation of image files with OS/2 multimedia support installed
 mmImageViewerOS2=Image Viewer
 # LOCALIZATION NOTE (mmAudioPlayerOS2): OS/2 only, default operation of audio files with OS/2 multimedia support installed
--- a/toolkit/mozapps/downloads/nsHelperAppDlg.js
+++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js
@@ -611,17 +611,17 @@ nsUnknownContentTypeDialog.prototype = {
       else
         typeString = mimeInfo.MIMEType;
     }
     // When the length is unknown, contentLength would be -1
     if (this.mLauncher.contentLength >= 0) {
       let [size, unit] = DownloadUtils.
                          convertByteUnits(this.mLauncher.contentLength);
       type.value = this.dialogElement("strings")
-                       .getFormattedString("fileSizeWithType", 
+                       .getFormattedString("orderedFileSizeWithType", 
                                            [typeString, size, unit]);
     }
     else {
       type.value = typeString;
     }
   },
 
   _blurred: false,
--- a/widget/src/windows/nsNativeDragTarget.cpp
+++ b/widget/src/windows/nsNativeDragTarget.cpp
@@ -275,16 +275,18 @@ nsNativeDragTarget::DragEnter(LPDATAOBJE
   nsresult loadResult = nsClipboard::GetNativeDataOffClipboard(
       pIDataSource, 0, ::RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT), nsnull, &tempOutData, &tempDataLen);
   if (NS_SUCCEEDED(loadResult) && tempOutData) {
     NS_ASSERTION(tempDataLen == 2, "Expected word size");
     WORD preferredEffect = *((WORD*)tempOutData);
 
     // Mask effect coming from function call with effect preferred by the source.
     mMovePreferred = (preferredEffect & DROPEFFECT_MOVE) != 0;
+
+    nsMemory::Free(tempOutData);
   } else {
     mMovePreferred = PR_FALSE;
   }
 
   // Set the native data object into drag service
   //
   // This cast is ok because in the constructor we created a
   // the actual implementation we wanted, so we know this is