Merge last green changeset of mozilla-inbound to mozilla-central
authorEd Morley <bmo@edmorley.co.uk>
Fri, 09 Dec 2011 11:12:51 +0000
changeset 82352 63bff373cb94613e93c2795eb3b46e9a23ab3ee5
parent 82270 141fe205fb73cbbf0263bdd44bc61a46ca51f032 (current diff)
parent 82351 6bafbaa9ac33d146df75546a7a47dc1fd59b4c7a (diff)
child 82382 d8a345cf98ca25148889f930d2adc9681bc9223e
child 82439 9f98db90b6e1e4a344570b54776bbb4f345eed83
child 82990 4bc459c8af2438056540fa2794147ea473666155
push id21591
push userbmo@edmorley.co.uk
push dateFri, 09 Dec 2011 11:33:41 +0000
treeherdermozilla-central@63bff373cb94 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone11.0a1
first release with
nightly linux32
63bff373cb94 / 11.0a1 / 20111210031150 / files
nightly linux64
63bff373cb94 / 11.0a1 / 20111210031150 / files
nightly mac
63bff373cb94 / 11.0a1 / 20111210031150 / files
nightly win32
63bff373cb94 / 11.0a1 / 20111210031150 / files
nightly win64
63bff373cb94 / 11.0a1 / 20111210031150 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge last green changeset of mozilla-inbound to mozilla-central
browser/themes/gnomestripe/places/searching_16.png
browser/themes/pinstripe/places/searching_16.png
browser/themes/winstripe/places/searching_16.png
mobile/android/base/resources/values/arrays.xml
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -1061,52 +1061,37 @@ NS_IMETHODIMP nsAccessible::TakeSelectio
       selectable->ClearSelection();
     }
     return SetSelected(true);
   }
 
   return NS_ERROR_FAILURE;
 }
 
-/* void takeFocus (); */
 NS_IMETHODIMP
 nsAccessible::TakeFocus()
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   nsIFrame *frame = GetFrame();
   NS_ENSURE_STATE(frame);
 
   nsIContent* focusContent = mContent;
 
-  // If the current element can't take real DOM focus and if it has an ID and
-  // an ancestor with an aria-activedescendant attribute present, then set DOM
-  // focus to that ancestor and set aria-activedescendant on the ancestor to
-  // the ID of the desired element.
+  // If the accessible focus is managed by container widget then focus the
+  // widget and set the accessible as its current item.
   if (!frame->IsFocusable()) {
-    nsAutoString id;
-    if (nsCoreUtils::GetID(mContent, id)) {
-
-      nsIContent* ancestorContent = mContent;
-      while ((ancestorContent = ancestorContent->GetParent()) &&
-             !ancestorContent->HasAttr(kNameSpaceID_None,
-                                       nsGkAtoms::aria_activedescendant));
-
-      if (ancestorContent) {
-        nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
-        if (presShell) {
-          nsIFrame *frame = ancestorContent->GetPrimaryFrame();
-          if (frame && frame->IsFocusable()) {
-            focusContent = ancestorContent;
-            focusContent->SetAttr(kNameSpaceID_None,
-                                  nsGkAtoms::aria_activedescendant,
-                                  id, true);
-          }
-        }
+    nsAccessible* widget = ContainerWidget();
+    if (widget && widget->AreItemsOperable()) {
+      nsIContent* widgetElm = widget->GetContent();
+      nsIFrame* widgetFrame = widgetElm->GetPrimaryFrame();
+      if (widgetFrame && widgetFrame->IsFocusable()) {
+        focusContent = widgetElm;
+        widget->SetCurrentItem(this);
       }
     }
   }
 
   nsCOMPtr<nsIDOMElement> element(do_QueryInterface(focusContent));
   nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
   if (fm)
     fm->SetFocus(element, 0);
@@ -2932,16 +2917,28 @@ nsAccessible::CurrentItem()
       nsDocAccessible* document = GetDocAccessible();
       if (document)
         return document->GetAccessible(activeDescendantElm);
     }
   }
   return nsnull;
 }
 
+void
+nsAccessible::SetCurrentItem(nsAccessible* aItem)
+{
+  nsIAtom* id = aItem->GetContent()->GetID();
+  if (id) {
+    nsAutoString idStr;
+    id->ToString(idStr);
+    mContent->SetAttr(kNameSpaceID_None,
+                      nsGkAtoms::aria_activedescendant, idStr, true);
+  }
+}
+
 nsAccessible*
 nsAccessible::ContainerWidget() const
 {
   nsIAtom* idAttribute = mContent->GetIDAttributeName();
   if (idAttribute) {
     if (mContent->HasAttr(kNameSpaceID_None, idAttribute)) {
       for (nsAccessible* parent = Parent(); parent; parent = parent->Parent()) {
         nsIContent* parentContent = parent->GetContent();
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -584,16 +584,21 @@ public:
 
   /**
    * Return the current item of the widget, i.e. an item that has or will have
    * keyboard focus when widget gets active.
    */
   virtual nsAccessible* CurrentItem();
 
   /**
+   * Set the current item of the widget.
+   */
+  virtual void SetCurrentItem(nsAccessible* aItem);
+
+  /**
    * Return container widget this accessible belongs to.
    */
   virtual nsAccessible* ContainerWidget() const;
 
 protected:
 
   //////////////////////////////////////////////////////////////////////////////
   // Initializing, cache and tree traverse methods
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp
+++ b/accessible/src/html/nsHTMLSelectAccessible.cpp
@@ -146,16 +146,24 @@ nsHTMLSelectListAccessible::CurrentItem(
       nsDocAccessible* document = GetDocAccessible();
       if (document)
         return document->GetAccessible(activeOptionNode);
     }
   }
   return nsnull;
 }
 
+void
+nsHTMLSelectListAccessible::SetCurrentItem(nsAccessible* aItem)
+{
+  aItem->GetContent()->SetAttr(kNameSpaceID_None,
+                               nsGkAtoms::selected, NS_LITERAL_STRING("true"),
+                               true);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLSelectListAccessible: nsAccessible protected
 
 void
 nsHTMLSelectListAccessible::CacheChildren()
 {
   // Cache accessibles for <optgroup> and <option> DOM decendents as children,
   // as well as the accessibles for them. Avoid whitespace text nodes. We want
@@ -681,16 +689,23 @@ nsHTMLComboboxAccessible::AreItemsOperab
 }
 
 nsAccessible*
 nsHTMLComboboxAccessible::CurrentItem()
 {
   return AreItemsOperable() ? mListAccessible->CurrentItem() : nsnull;
 }
 
+void
+nsHTMLComboboxAccessible::SetCurrentItem(nsAccessible* aItem)
+{
+  if (AreItemsOperable())
+    mListAccessible->SetCurrentItem(aItem);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLComboboxAccessible: protected
 
 nsAccessible*
 nsHTMLComboboxAccessible::SelectedOption() const
 {
   nsIFrame* frame = GetFrame();
   nsIComboboxControlFrame* comboboxFrame = do_QueryFrame(frame);
--- a/accessible/src/html/nsHTMLSelectAccessible.h
+++ b/accessible/src/html/nsHTMLSelectAccessible.h
@@ -80,16 +80,17 @@ public:
   virtual bool SelectAll();
   virtual bool UnselectAll();
 
   // Widgets
   virtual bool IsWidget() const;
   virtual bool IsActiveWidget() const;
   virtual bool AreItemsOperable() const;
   virtual nsAccessible* CurrentItem();
+  virtual void SetCurrentItem(nsAccessible* aItem);
 
 protected:
 
   // nsAccessible
   virtual void CacheChildren();
 
   // nsHTMLSelectListAccessible
 
@@ -204,16 +205,17 @@ public:
   // ActionAccessible
   virtual PRUint8 ActionCount();
 
   // Widgets
   virtual bool IsWidget() const;
   virtual bool IsActiveWidget() const;
   virtual bool AreItemsOperable() const;
   virtual nsAccessible* CurrentItem();
+  virtual void SetCurrentItem(nsAccessible* aItem);
 
 protected:
   // nsAccessible
   virtual void CacheChildren();
 
   /**
    * Return selected option.
    */
--- a/accessible/src/mac/mozAccessible.h
+++ b/accessible/src/mac/mozAccessible.h
@@ -41,26 +41,42 @@
 #import <Cocoa/Cocoa.h>
 
 #import "mozAccessibleProtocol.h"
 
 @class mozRootAccessible;
 
 @interface mozAccessible : NSObject <mozAccessible>
 {
-  nsAccessibleWrap *mGeckoAccessible;  // weak reference; it owns us.
-  NSMutableArray   *mChildren;         // strong ref to array of children
+  /**
+   * Weak reference; it owns us.
+   */
+  nsAccessibleWrap* mGeckoAccessible;
+  
+  /**
+   * Strong ref to array of children
+   */
+  NSMutableArray* mChildren;
   
-  // we can be marked as 'expired' if Shutdown() is called on our geckoAccessible.
-  // since we might still be retained by some third-party, we need to do cleanup
-  // in |expire|, and prevent any potential harm that could come from someone using us
-  // after this point.
+  /** 
+   * Weak reference to the parent
+   */
+  mozAccessible* mParent;
+  
+  /**
+   * We can be marked as 'expired' if Shutdown() is called on our geckoAccessible.
+   * since we might still be retained by some third-party, we need to do cleanup
+   * in |expire|, and prevent any potential harm that could come from someone using us
+   * after this point.
+   */
   BOOL mIsExpired;
   
-  // the nsIAccessible role of our gecko accessible.
+  /**
+   * The nsIAccessible role of our gecko accessible.
+   */
   PRUint32        mRole;
 }
 
 // inits with the gecko owner.
 - (id)initWithAccessible:(nsAccessibleWrap*)geckoParent;
 
 // our accessible parent (AXParent)
 - (id <mozAccessible>)parent;
@@ -109,27 +125,30 @@
 - (void)didReceiveFocus;
 - (void)valueDidChange;
 
 #pragma mark -
 
 // invalidates and removes all our children from our cached array.
 - (void)invalidateChildren;
 
+// invalidates the cached parent, used by invalidateChildren.
+- (void)invalidateParent;
+
 // makes ourselves "expired". after this point, we might be around if someone
 // has retained us (e.g., a third-party), but we really contain no information.
 - (void)expire;
 - (BOOL)isExpired;
 
 #ifdef DEBUG
 - (void)printHierarchy;
 - (void)printHierarchyWithLevel:(unsigned)numSpaces;
 
 - (void)sanityCheckChildren;
-- (void)sanityCheckChildren:(NSArray *)theChildren;
+- (void)sanityCheckChildren:(NSArray*)theChildren;
 #endif
 
 // ---- NSAccessibility methods ---- //
 
 // whether to skip this element when traversing the accessibility
 // hierarchy.
 - (BOOL)accessibilityIsIgnored;
 
--- a/accessible/src/mac/mozAccessible.mm
+++ b/accessible/src/mac/mozAccessible.mm
@@ -42,18 +42,20 @@
 #import "mozView.h"
 #import "nsRoleMap.h"
 
 #include "nsRect.h"
 #include "nsCoord.h"
 #include "nsObjCExceptions.h"
 
 #include "nsIAccessible.h"
+#include "nsIAccessibleRelation.h"
 #include "nsIAccessibleText.h"
 #include "nsIAccessibleEditableText.h"
+#include "Relation.h"
 
 #include "nsRootAccessible.h"
 
 using namespace mozilla::a11y;
 
 // These constants are only defined in OS X SDK 10.4, so we define them in order
 // to be able to use for earlier OS versions.
 const NSString *kInstanceDescriptionAttribute = @"AXDescription";       // NSAccessibilityDescriptionAttribute
@@ -241,26 +243,30 @@ GetNativeFromGeckoAccessible(nsIAccessib
   if ([attribute isEqualToString:NSAccessibilityFocusedAttribute])
     return [NSNumber numberWithBool:[self isFocused]];
   if ([attribute isEqualToString:NSAccessibilitySizeAttribute])
     return [self size];
   if ([attribute isEqualToString:NSAccessibilityWindowAttribute])
     return [self window];
   if ([attribute isEqualToString: (NSString*) kTopLevelUIElementAttribute])
     return [self window];
-  if ([attribute isEqualToString:NSAccessibilityTitleAttribute] || 
-      [attribute isEqualToString:NSAccessibilityTitleUIElementAttribute])
+  if ([attribute isEqualToString:NSAccessibilityTitleAttribute])
     return [self title];
+  if ([attribute isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
+    Relation rel = mGeckoAccessible->RelationByType(nsIAccessibleRelation::RELATION_LABELLED_BY);
+    nsAccessible* tempAcc = rel.Next();
+    return tempAcc ? GetNativeFromGeckoAccessible(tempAcc) : nil;
+  }
   if ([attribute isEqualToString:NSAccessibilityHelpAttribute])
     return [self help];
     
 #ifdef DEBUG
  NSLog (@"!!! %@ can't respond to attribute %@", self, attribute);
 #endif
-  return nil; // be nice and return empty string instead?
+  return nil;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
@@ -344,33 +350,38 @@ GetNativeFromGeckoAccessible(nsIAccessib
 }
 
 #pragma mark -
 
 - (id <mozAccessible>)parent
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
+  if (mParent)
+    return mParent;
+
   nsCOMPtr<nsIAccessible> accessibleParent(mGeckoAccessible->GetUnignoredParent());
   if (accessibleParent) {
     id nativeParent = GetNativeFromGeckoAccessible(accessibleParent);
-    if (nativeParent)
-      return GetClosestInterestingAccessible(nativeParent);
+    if (nativeParent) {
+      return mParent = GetClosestInterestingAccessible(nativeParent);
+    }
   }
   
   // GetUnignoredParent() returns null when there is no unignored accessible all the way up to
   // the root accessible. so we'll have to return whatever native accessible is above our root accessible 
   // (which might be the owning NSWindow in the application, for example).
   //
   // get the native root accessible, and tell it to return its first parent unignored accessible.
   nsRootAccessible* root = mGeckoAccessible->RootAccessible();
   id nativeParent = GetNativeFromGeckoAccessible(static_cast<nsIAccessible*>(root));
   NSAssert1 (nativeParent, @"!!! we can't find a parent for %@", self);
   
-  return GetClosestInterestingAccessible(nativeParent);
+  mParent = GetClosestInterestingAccessible(nativeParent);
+  return mParent;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
 - (BOOL)hasRepresentedView
 {
   return NO;
 }
@@ -599,23 +610,30 @@ GetNativeFromGeckoAccessible(nsIAccessib
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
 - (void)invalidateChildren
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
+  [mChildren makeObjectsPerformSelector:@selector(invalidateParent)];
+
   // make room for new children
   [mChildren release];
   mChildren = nil;
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
+- (void)invalidateParent
+{
+  mParent = nil;
+}
+
 - (void)expire
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   [self invalidateChildren];
   mIsExpired = YES;
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
--- a/accessible/src/mac/mozDocAccessible.mm
+++ b/accessible/src/mac/mozDocAccessible.mm
@@ -50,16 +50,54 @@ static id <mozAccessible, mozView> getNa
   root->GetNativeWidget ((void**)&nativeView);
   return nativeView;
 }
 
 #pragma mark -
 
 @implementation mozRootAccessible
 
+- (NSArray*)accessibilityAttributeNames
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
+  
+  // if we're expired, we don't support any attributes.
+  if (mIsExpired)
+    return [NSArray array];
+  
+  // standard attributes that are shared and supported by root accessible (AXMain) elements.
+  static NSMutableArray* attributes = nil;
+  
+  if (!attributes) {
+    attributes = [[super accessibilityAttributeNames] mutableCopy];
+    [attributes addObject:NSAccessibilityMainAttribute];
+    [attributes addObject:NSAccessibilityMinimizedAttribute];
+  }
+
+  return attributes;
+
+  NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
+}
+
+- (id)accessibilityAttributeValue:(NSString *)attribute
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
+  
+  if ([attribute isEqualToString:NSAccessibilityMainAttribute]) {
+    return [NSNumber numberWithBool:[[self window] isMainWindow]];
+  }
+  if ([attribute isEqualToString:NSAccessibilityMinimizedAttribute]) {
+    return [NSNumber numberWithBool:[[self window] isMiniaturized]];
+  }
+  return [super accessibilityAttributeValue:attribute];
+  
+  NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
+}
+
+
 // return the AXParent that our parallell NSView tells us about.
 - (id)parent
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
   if (!mParallelView)
     mParallelView = (id<mozView, mozAccessible>)[self representedView];
   
--- a/accessible/src/xul/nsXULMenuAccessible.cpp
+++ b/accessible/src/xul/nsXULMenuAccessible.cpp
@@ -297,16 +297,32 @@ nsXULSelectableAccessible::CurrentItem()
     nsDocAccessible* document = GetDocAccessible();
     if (document)
       return document->GetAccessible(DOMNode);
   }
 
   return nsnull;
 }
 
+void
+nsXULSelectableAccessible::SetCurrentItem(nsAccessible* aItem)
+{
+  if (!mSelectControl)
+    return;
+
+  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
+    do_QueryInterface(aItem->GetContent());
+  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+    do_QueryInterface(mSelectControl);
+  if (multiSelectControl)
+    multiSelectControl->SetCurrentItem(itemElm);
+  else
+    mSelectControl->SetSelectedItem(itemElm);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULMenuitemAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULMenuitemAccessible::
   nsXULMenuitemAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
   nsAccessibleWrap(aContent, aShell)
 {
@@ -888,8 +904,14 @@ nsXULMenubarAccessible::CurrentItem()
     nsMenuFrame* menuFrame = menuBarFrame->GetCurrentMenuItem();
     if (menuFrame) {
       nsIContent* menuItemNode = menuFrame->GetContent();
       return GetAccService()->GetAccessible(menuItemNode);
     }
   }
   return nsnull;
 }
+
+void
+nsXULMenubarAccessible::SetCurrentItem(nsAccessible* aItem)
+{
+  NS_ERROR("nsXULMenubarAccessible::SetCurrentItem not implemented");
+}
--- a/accessible/src/xul/nsXULMenuAccessible.h
+++ b/accessible/src/xul/nsXULMenuAccessible.h
@@ -62,16 +62,17 @@ public:
   virtual bool IsItemSelected(PRUint32 aIndex);
   virtual bool AddItemToSelection(PRUint32 aIndex);
   virtual bool RemoveItemFromSelection(PRUint32 aIndex);
   virtual bool SelectAll();
   virtual bool UnselectAll();
 
   // Widgets
   virtual nsAccessible* CurrentItem();
+  virtual void SetCurrentItem(nsAccessible* aItem);
 
 protected:
   // nsIDOMXULMultiSelectControlElement inherits from this, so we'll always have
   // one of these if the widget is valid and not defunct
   nsCOMPtr<nsIDOMXULSelectControlElement> mSelectControl;
 };
 
 /**
@@ -165,11 +166,12 @@ public:
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual PRUint32 NativeRole();
   virtual PRUint64 NativeState();
 
   // Widget
   virtual bool IsActiveWidget() const;
   virtual bool AreItemsOperable() const;
   virtual nsAccessible* CurrentItem();
+  virtual void SetCurrentItem(nsAccessible* aItem);
 };
 
 #endif  
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -274,16 +274,22 @@ nsXULTreeAccessible::CurrentItem()
     selection->GetCurrentIndex(&currentIndex);
     if (currentIndex >= 0)
       return GetTreeItemAccessible(currentIndex);
   }
 
   return nsnull;
 }
 
+void
+nsXULTreeAccessible::SetCurrentItem(nsAccessible* aItem)
+{
+  NS_ERROR("nsXULTreeAccessible::SetCurrentItem not implemented");
+}
+
 already_AddRefed<nsIArray>
 nsXULTreeAccessible::SelectedItems()
 {
   nsCOMPtr<nsITreeSelection> selection;
   mTreeView->GetSelection(getter_AddRefs(selection));
   if (!selection)
     return nsnull;
 
--- a/accessible/src/xul/nsXULTreeAccessible.h
+++ b/accessible/src/xul/nsXULTreeAccessible.h
@@ -101,16 +101,17 @@ public:
   virtual bool SelectAll();
   virtual bool UnselectAll();
 
   // Widgets
   virtual bool IsWidget() const;
   virtual bool IsActiveWidget() const;
   virtual bool AreItemsOperable() const;
   virtual nsAccessible* CurrentItem();
+  virtual void SetCurrentItem(nsAccessible* aItem);
 
   virtual nsAccessible* ContainerWidget() const;
 
   // nsXULTreeAccessible
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEACCESSIBLE_IMPL_CID)
 
   /**
--- a/accessible/tests/mochitest/focus/Makefile.in
+++ b/accessible/tests/mochitest/focus/Makefile.in
@@ -43,12 +43,13 @@ VPATH		= @srcdir@
 relativesrcdir  = accessible/focus
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		test_focusedChild.html \
 		test_takeFocus.html \
+		test_takeFocus.xul \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
--- a/accessible/tests/mochitest/focus/test_takeFocus.html
+++ b/accessible/tests/mochitest/focus/test_takeFocus.html
@@ -13,19 +13,17 @@
           src="../common.js"></script>
   <script type="application/javascript"
           src="../states.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
 
   <script type="application/javascript">
     ////////////////////////////////////////////////////////////////////////////
-    // Test
-
-    var gQueue = null;
+    // Invokers
 
     function takeFocusInvoker(aID)
     {
       this.accessible = getAccessible(aID);
 
       this.eventSeq = [ new focusChecker(this.accessible) ];
 
       this.invoke = function takeFocusInvoker_invoke()
@@ -34,26 +32,33 @@
       }
 
       this.getID = function takeFocusInvoker_getID()
       {
         return "takeFocus for " + prettyName(aID);
       }
     }
 
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    //gA11yEventDumpToConsole = true; // debug stuff
+
+    var gQueue = null;
     function doTest()
     {
       gQueue = new eventQueue();
 
       gQueue.push(new takeFocusInvoker("aria-link"));
       gQueue.push(new takeFocusInvoker("aria-link2"));
       gQueue.push(new takeFocusInvoker("link"));
       gQueue.push(new takeFocusInvoker("item2"));
       gQueue.push(new takeFocusInvoker("plugin"));
       gQueue.push(new takeFocusInvoker(document));
+      gQueue.push(new takeFocusInvoker("lb_item2"));
 
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
@@ -70,16 +75,21 @@
      title="nsIAccessible::takeFocus testing">
     Mozilla Bug 452710
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=646361"
      title="No focus event fired on document when focus is set to the document while focused in a plugin">
     Mozilla Bug 646361
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=706067"
+     title="Make takeFocus work on widget items">
+    Mozilla Bug 706067
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <span id="aria-link" role="link" tabindex="0">link</span>
   <span id="aria-link2" role="link" tabindex="0">link</span>
 
@@ -87,10 +97,15 @@
 
   <div role="listbox" aria-activedescendant="item1" id="container" tabindex="1">
     <div role="listitem" id="item1">item1</div>
     <div role="listitem" id="item2">item2</div>
     <div role="listitem" id="item3">item3</div>
   </div>
 
   <embed id="plugin" type="application/x-test" width="200" height="200" wmode="window"></embed>
+
+  <select id="listbox" size="5">
+    <option id="lb_item1">item1</option>
+    <option id="lb_item2">item2</option>
+  </select>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/focus/test_takeFocus.xul
@@ -0,0 +1,125 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<?xml-stylesheet href="chrome://browser/content/browser.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Accessible focus testing">
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+  <script type="application/javascript"
+          src="../common.js" />
+  <script type="application/javascript"
+          src="../states.js" />
+  <script type="application/javascript"
+          src="../events.js" />
+
+  <script type="application/javascript"
+          src="../treeview.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+    ////////////////////////////////////////////////////////////////////////////
+    // Invokers
+
+    function setTreeView(aTreeID, aView)
+    {
+      this.DOMNode = getNode(aTreeID);
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, this.DOMNode)
+      ];
+
+      this.invoke = function setTreeView_invoke()
+      {
+        this.DOMNode.treeBoxObject.view = aView;
+      }
+
+      this.getID = function setTreeView_getID()
+        { return "set tree view for " + prettyName(aTreeID); }
+    };
+
+    function takeFocusInvoker(aID, aArgConverterFunc)
+    {
+      this.targetFunc = aArgConverterFunc ? aArgConverterFunc : getAccessible;
+
+      this.eventSeq = [ new focusChecker(this.targetFunc, aID) ];
+
+      this.invoke = function takeFocusInvoker_invoke()
+      {
+        this.targetFunc.call(null, aID).takeFocus();
+      }
+
+      this.getID = function takeFocusInvoker_getID()
+      {
+        return "takeFocus for " + prettyName(aID);
+      }
+    }
+
+    function getLastChild(aID)
+    {
+      return getAccessible(aID).lastChild;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Tests
+
+    //gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpToConsole = true; // debug stuff
+
+    var gQueue = null;
+    function doTests()
+    {
+      // Test focus events.
+      gQueue = new eventQueue();
+
+      gQueue.push(new setTreeView("tree", new nsTableTreeView(5)));
+      gQueue.push(new takeFocusInvoker("tree", getLastChild));
+      gQueue.push(new takeFocusInvoker("listitem2"));
+
+      gQueue.invoke(); // Will call SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTests);
+  ]]>
+  </script>
+
+  <hbox flex="1" style="overflow: auto;">
+    <body xmlns="http://www.w3.org/1999/xhtml">
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=706067"
+         title="Make takeFocus work on widget items">
+        Mozilla Bug 706067
+      </a>
+      <p id="display"></p>
+      <div id="content" style="display: none"></div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+      <tree id="tree" flex="1">
+        <treecols>
+          <treecol id="col1" flex="1" primary="true" label="column"/>
+          <treecol id="col2" flex="1" label="column 2"/>
+        </treecols>
+        <treechildren id="treechildren"/>
+      </tree>
+
+      <listbox id="listbox">
+        <listitem id="listitem1">item1</listitem>
+        <listitem id="listitem2">item2</listitem>
+      </listbox>
+
+      <vbox id="eventdump"/>
+    </vbox>
+  </hbox>
+</window>
--- a/accessible/tests/mochitest/states/test_aria.html
+++ b/accessible/tests/mochitest/states/test_aria.html
@@ -92,16 +92,32 @@
       // aria-checked
       testStates("aria_checked_checkbox", STATE_CHECKED);
       testStates("aria_mixed_checkbox", STATE_MIXED);
 
       // test disabled group and all its descendants to see if they are
       // disabled, too. See bug 429285.
       testAriaDisabledTree("group");
 
+      // aria-multiline
+      testStates("aria_multiline_textbox", 0, EXT_STATE_MULTI_LINE);
+
+      // aria-multiselectable
+      testStates("aria_multiselectable_listbox",
+                 STATE_MULTISELECTABLE | STATE_EXTSELECTABLE);
+
+      // aria-pressed
+      testStates("aria_pressed_button", STATE_PRESSED | STATE_CHECKABLE);
+
+      // aria-readonly
+      testStates("aria_readonly_textbox", STATE_READONLY);
+
+      // aria-selectable
+      testStates("aria_selectable_listitem", STATE_SELECTABLE | STATE_SELECTED);
+
       // active state caused by aria-activedescendant
       testStates("as_item1", 0, EXT_STATE_ACTIVE);
       testStates("as_item2", 0, 0, 0, EXT_STATE_ACTIVE);
 
       // universal ARIA properties inherited from file input control
       var fileTextField = getAccessible("fileinput").firstChild;
       testStates(fileTextField,
                  STATE_BUSY | STATE_UNAVAILABLE | STATE_REQUIRED | STATE_HASPOPUP | STATE_INVALID);
@@ -188,16 +204,21 @@
      title="File input control should be propogate states to descendants">
     Mozilla Bug 699017
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=689847"
      title="Expose active state on current item of selectable widgets">
     Mozilla Bug 689847
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=457226"
+     title="Mochitests for ARIA states">
+    Mozilla Bug 457226
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div id="textbox_autocomplete_inline" role="textbox" aria-autocomplete="inline"></div>
   <div id="textbox_autocomplete_list" role="textbox" aria-autocomplete="list"></div>
   <div id="textbox_autocomplete_both" role="textbox" aria-autocomplete="both"></div>
@@ -220,16 +241,23 @@
 
   <div id="aria_checked_checkbox" role="checkbox" aria-checked="true">
     I agree
   </div>
 
   <div id="aria_mixed_checkbox" role="checkbox" aria-checked="mixed">
     I might agree
   </div>
+  <div id="aria_multiline_textbox" role="textbox" aria-multiline="true"></div>
+  <div id="aria_multiselectable_listbox" role="listbox" aria-multiselectable="true"></div>
+  <div id="aria_pressed_button" role="button" aria-pressed="true">Button</div>
+  <div id="aria_readonly_textbox" role="textbox" aria-readonly="true">This text should be readonly</div>
+  <div role="listbox">
+    <div id="aria_selectable_listitem" role="option" aria-selected="true">Item1</div>
+  </div>
 
   <!-- Test that aria-disabled state gets propagated to all descendants -->
   <div id="group" role="group" aria-disabled="true">
     <button>hi</button>
     <div tabindex="0" role="listbox" aria-activedescendant="item1">
       <div role="option" id="item1">Item 1</div>
       <div role="option" id="item2">Item 2</div>
       <div role="option" id="item3">Item 3</div>
copy from netwerk/test/httpserver/httpd.js
copy to b2g/chrome/content/httpd.js
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -34,32 +34,65 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const CC = Components.Constructor;
 
-Cu.import('resource://gre/modules/Services.jsm');
-
 const LocalFile = CC('@mozilla.org/file/local;1',
                      'nsILocalFile',
                      'initWithPath');
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import('resource://gre/modules/Services.jsm');
+XPCOMUtils.defineLazyGetter(Services, 'env', function() {
+  return Cc['@mozilla.org/process/environment;1']
+           .getService(Ci.nsIEnvironment);
+});
+XPCOMUtils.defineLazyGetter(Services, 'ss', function() {
+  return Cc['@mozilla.org/content/style-sheet-service;1']
+           .getService(Ci.nsIStyleSheetService);
+});
+XPCOMUtils.defineLazyGetter(Services, 'fm', function() {
+  return Cc['@mozilla.org/focus-manager;1']
+           .getService(Ci.nsIFocusManager);
+});
+
+// In order to use http:// scheme instead of file:// scheme
+// (that is much more restricted) the following code kick-off
+// a local http server listening on http://127.0.0.1:8888 and
+// http://localhost:8888.
+function startupHttpd(baseDir, port) {
+  const httpdURL = 'chrome://browser/content/httpd.js';
+  let httpd = {};
+  Services.scriptloader.loadSubScript(httpdURL, httpd);
+  let server = new httpd.nsHttpServer();
+  server.registerDirectory('/', new LocalFile(baseDir));
+  server.start(port);
+}
+
+// XXX until we have a security model, just let the pre-installed
+// app used indexedDB.
+function allowIndexedDB(url) {
+  let uri = Services.io.newURI(url, null, null);
+  Services.perms.add(uri, 'indexedDB', Ci.nsIPermissionManager.ALLOW_ACTION);
+}
+
+
 var shell = {
   get home() {
     delete this.home;
     return this.home = document.getElementById('homescreen');
   },
 
-  get homeSrc() {
+  get homeURL() {
     try {
-      let homeSrc = Cc['@mozilla.org/process/environment;1']
-                      .getService(Ci.nsIEnvironment)
-                      .get('B2G_HOMESCREEN');
+      let homeSrc = Services.env.get('B2G_HOMESCREEN');
       if (homeSrc)
         return homeSrc;
     } catch (e) {}
 
     let urls = Services.prefs.getCharPref('browser.homescreenURL').split(',');
     for (let i = 0; i < urls.length; i++) {
       let url = urls[i];
       if (url.substring(0, 7) != 'file://')
@@ -68,26 +101,51 @@ var shell = {
       let file = new LocalFile(url.substring(7, url.length));
       if (file.exists())
         return url;
     }
     return null;
   },
 
   start: function shell_init() {
+    let homeURL = this.homeURL;
+    if (!homeURL) {
+      let msg = 'Fatal error during startup: [No homescreen found]';
+      return alert(msg);
+    }
+
     window.controllers.appendController(this);
     window.addEventListener('keypress', this);
     this.home.addEventListener('load', this, true);
 
-    let ioService = Cc['@mozilla.org/network/io-service;1']
-                      .getService(Ci.nsIIOService2);
-    ioService.offline = false;
+    try {
+      Services.io.offline = false;
+
+      let fileScheme = 'file://';
+      if (homeURL.substring(0, fileScheme.length) == fileScheme) {
+        homeURL = homeURL.replace(fileScheme, '');
+
+        let baseDir = homeURL.split('/');
+        baseDir.pop();
+        baseDir = baseDir.join('/');
+
+        const SERVER_PORT = 8888;
+        startupHttpd(baseDir, SERVER_PORT);
+
+        let baseHost = 'http://localhost';
+        homeURL = homeURL.replace(baseDir, baseHost + ':' + SERVER_PORT);
+      }
+      allowIndexedDB(homeURL);
+    } catch (e) {
+      let msg = 'Fatal error during startup: [' + e + '[' + homeURL + ']';
+      return alert(msg);
+    }
 
     let browser = this.home;
-    browser.homePage = this.homeSrc;
+    browser.homePage = homeURL;
     browser.goHome();
   },
 
   stop: function shell_stop() {
     window.controllers.removeController(this);
     window.removeEventListener('keypress', this);
   },
 
@@ -178,32 +236,30 @@ var shell = {
           break;
       }
     },
     observe: function vkm_observe(subject, topic, data) {
       let contentWindow = shell.home.contentWindow;
 
       let shouldOpen = parseInt(data);
       if (shouldOpen && !isKeyboardOpened) {
-        activeElement = Cc['@mozilla.org/focus-manager;1']
-                          .getService(Ci.nsIFocusManager)
-                          .focusedElement;
+        activeElement = Services.fm.focusedElement;
         if (!activeElement)
           return;
 
         let type = activeElement.type;
         shell.sendEvent(contentWindow, 'showime', { type: type });
       } else if (!shouldOpen && isKeyboardOpened) {
         shell.sendEvent(contentWindow, 'hideime');
       }
       isKeyboardOpened = shouldOpen;
     }
   };
 
-  Services.obs.addObserver(constructor, "ime-enabled-state-changed", false);
+  Services.obs.addObserver(constructor, 'ime-enabled-state-changed', false);
   ['ContentStart', 'keypress', 'mousedown'].forEach(function vkm_events(type) {
     window.addEventListener(type, constructor, true);
   });
 })();
 
 
 function MozKeyboard() {
 }
--- a/b2g/chrome/content/touch.js
+++ b/b2g/chrome/content/touch.js
@@ -146,28 +146,27 @@
             debug('click: cancel');
 
             evt.preventDefault();
             evt.stopPropagation();
           } else {
             // Mouse events has been cancelled so dispatch a sequence
             // of events to where touchend has been fired
             if (preventMouseEvents) {
+              evt.preventDefault();
+              evt.stopPropagation();
+
               let target = evt.target;
               ignoreEvents = true;
-              try {
-                this.fireMouseEvent('mousemove', evt);
-                this.fireMouseEvent('mousedown', evt);
-                this.fireMouseEvent('mouseup', evt);
-              } catch (e) {
-                alert(e);
-              }
-              evt.preventDefault();
-              evt.stopPropagation();
-              ignoreEvents = false;
+              window.setTimeout(function dispatchMouseEvents(self) {
+                self.fireMouseEvent('mousemove', evt);
+                self.fireMouseEvent('mousedown', evt);
+                self.fireMouseEvent('mouseup', evt);
+                ignoreEvents = false;
+              }, 0, this);
             }
 
             debug('click: fire');
           }
           return;
       }
 
       let target = eventTarget || this.target;
--- a/b2g/chrome/jar.mn
+++ b/b2g/chrome/jar.mn
@@ -3,11 +3,12 @@
 chrome.jar:
 % content branding %content/branding/
 % content browser %content/
 
 * content/shell.xul                     (content/shell.xul)
   content/shell.js                      (content/shell.js)
   content/touch.js                      (content/touch.js)
   content/commandUtil.js                (content/commandUtil.js)
+  content/httpd.js                      (content/httpd.js)
 
 % override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
   content/netError.xhtml                (content/netError.xhtml)
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -386,16 +386,22 @@
 @BINPATH@/components/contentSecurityPolicy.manifest
 @BINPATH@/components/contentSecurityPolicy.js
 @BINPATH@/components/contentAreaDropListener.manifest
 @BINPATH@/components/contentAreaDropListener.js
 @BINPATH@/components/messageWakeupService.js
 @BINPATH@/components/messageWakeupService.manifest
 @BINPATH@/components/nsFilePicker.js
 @BINPATH@/components/nsFilePicker.manifest
+#ifdef MOZ_B2G_RIL
+@BINPATH@/components/nsTelephonyWorker.manifest
+@BINPATH@/components/nsTelephonyWorker.js
+@BINPATH@/components/Telephony.manifest
+@BINPATH@/components/Telephony.js
+#endif
 #ifdef XP_MACOSX
 @BINPATH@/components/libalerts_s.dylib
 #endif
 #ifdef MOZ_ENABLE_DBUS
 @BINPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@
 #endif
 @BINPATH@/components/nsINIProcessor.manifest
 @BINPATH@/components/nsINIProcessor.js
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -238,21 +238,16 @@ panel[noactions] > richlistbox > richlis
 #PopupAutoComplete {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#browser-autocomplete-result-popup");
 }
 
 #PopupAutoCompleteRichResult {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#urlbar-rich-result-popup");
 }
 
-#urlbar-throbber:not([busy="true"]),
-#urlbar-throbber[busy="true"] + #page-proxy-favicon {
-  display: none;
-}
-
 #urlbar-container[combined] > #urlbar > #urlbar-icons > #go-button,
 #urlbar[pageproxystate="invalid"] > #urlbar-icons > .urlbar-icon:not(#go-button),
 #urlbar[pageproxystate="valid"] > #urlbar-icons > #go-button,
 #urlbar[pageproxystate="invalid"][focused="true"] > #urlbar-go-button ~ toolbarbutton,
 #urlbar[pageproxystate="valid"] > #urlbar-go-button,
 #urlbar:not([focused="true"]) > #urlbar-go-button {
   visibility: collapse;
 }
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2596,38 +2596,16 @@ function UpdateUrlbarSearchSplitterState
       splitter.setAttribute("resizeafter", "flex");
       splitter.className = "chromeclass-toolbar-additional";
     }
     urlbar.parentNode.insertBefore(splitter, ibefore);
   } else if (splitter)
     splitter.parentNode.removeChild(splitter);
 }
 
-var LocationBarHelpers = {
-  _timeoutID: null,
-
-  _searchBegin: function LocBar_searchBegin() {
-    function delayedBegin(self) {
-      self._timeoutID = null;
-      document.getElementById("urlbar-throbber").setAttribute("busy", "true");
-    }
-
-    this._timeoutID = setTimeout(delayedBegin, 500, this);
-  },
-
-  _searchComplete: function LocBar_searchComplete() {
-    // Did we finish the search before delayedBegin was invoked?
-    if (this._timeoutID) {
-      clearTimeout(this._timeoutID);
-      this._timeoutID = null;
-    }
-    document.getElementById("urlbar-throbber").removeAttribute("busy");
-  }
-};
-
 function UpdatePageProxyState()
 {
   if (gURLBar && gURLBar.value != gLastValidURLStr)
     SetPageProxyState("invalid");
 }
 
 function SetPageProxyState(aState)
 {
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -511,18 +511,16 @@
                  showimagecolumn="true"
                  enablehistory="true"
                  maxrows="6"
                  newlines="stripsurroundingwhitespace"
                  oninput="gBrowser.userTypedValue = this.value;"
                  ontextentered="this.handleCommand(param);"
                  ontextreverted="return this.handleRevert();"
                  pageproxystate="invalid"
-                 onsearchbegin="LocationBarHelpers._searchBegin();"
-                 onsearchcomplete="LocationBarHelpers._searchComplete();"
                  onfocus="document.getElementById('identity-box').style.MozUserFocus= 'normal'"
                  onblur="setTimeout(function() document.getElementById('identity-box').style.MozUserFocus = '', 0);">
           <box id="notification-popup-box" hidden="true" align="center">
             <image id="default-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="geo-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="password-notification-icon" class="notification-anchor-icon" role="button"/>
@@ -533,17 +531,16 @@
                has focus, otherwise pressing F6 focuses it instead of the location bar -->
           <box id="identity-box" role="button"
                onclick="gIdentityHandler.handleIdentityButtonEvent(event);"
                onkeypress="gIdentityHandler.handleIdentityButtonEvent(event);"
                ondragstart="gIdentityHandler.onDragStart(event);">
             <hbox id="identity-box-inner" align="center">
               <stack id="page-proxy-stack"
                      onclick="PageProxyClickHandler(event);">
-                <image id="urlbar-throbber" busy="false"/>
                 <image id="page-proxy-favicon" validate="never"
                        pageproxystate="invalid"
                        onerror="this.removeAttribute('src');"/>
               </stack>
               <hbox id="identity-icon-labels">
                 <label id="identity-icon-label" class="plain" flex="1"/>
                 <label id="identity-icon-country-label" class="plain"/>
               </hbox>
--- a/browser/config/mozconfigs/macosx64/debug
+++ b/browser/config/mozconfigs/macosx64/debug
@@ -1,8 +1,10 @@
+. $topsrcdir/build/macosx/common
+
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
 ac_add_options --enable-accessibility
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 # Needed to enable breakpad in application.ini
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -1019,18 +1019,17 @@ toolbar[iconsize="small"] #feed-button {
 
 #urlbar-display {
   margin-top: 0;
   margin-bottom: 0;
   color: GrayText;
 }
 
 /* Favicon */
-#page-proxy-favicon,
-#urlbar-throbber {
+#page-proxy-favicon {
   width: 16px;
   height: 16px;
 }
 
 #page-proxy-stack {
   width: 24px;
   height: 20px;
   padding: 2px 4px;
@@ -1039,20 +1038,16 @@ toolbar[iconsize="small"] #feed-button {
 #page-proxy-favicon:not([src]) {
   list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
 }
 
 #page-proxy-favicon[pageproxystate="invalid"] {
   opacity: 0.3;
 }
 
-#urlbar-throbber {
-  list-style-image: url("chrome://browser/skin/places/searching_16.png");
-}
-
 /* Identity indicator */
 #identity-box {
   background-image: -moz-linear-gradient(hsl(0,0%,98%), hsl(0,0%,92%));
   box-shadow: 0 1px 0 hsla(0,0%,0%,.05) inset;
   -moz-border-end: 1px solid rgba(0,0,0,.1);
   padding: 1px;
   margin: -1px;
   -moz-margin-end: 0;
--- a/browser/themes/gnomestripe/jar.mn
+++ b/browser/themes/gnomestripe/jar.mn
@@ -52,17 +52,16 @@ browser.jar:
   skin/classic/browser/places/livemark-item.png       (places/livemark-item.png)
   skin/classic/browser/places/pageStarred.png         (places/pageStarred.png)
   skin/classic/browser/places/starred48.png           (places/starred48.png)
   skin/classic/browser/places/unstarred48.png         (places/unstarred48.png)
   skin/classic/browser/places/places.css              (places/places.css)
   skin/classic/browser/places/organizer.css           (places/organizer.css)
 * skin/classic/browser/places/organizer.xml           (places/organizer.xml)
   skin/classic/browser/places/query.png               (places/query.png)
-  skin/classic/browser/places/searching_16.png        (places/searching_16.png)
   skin/classic/browser/places/starPage.png            (places/starPage.png)
   skin/classic/browser/places/tag.png                 (places/tag.png)
   skin/classic/browser/places/toolbarDropMarker.png   (places/toolbarDropMarker.png)
   skin/classic/browser/places/unsortedBookmarks.png   (places/unsortedBookmarks.png)
   skin/classic/browser/places/downloads.png           (places/downloads.png)
   skin/classic/browser/preferences/alwaysAsk.png      (preferences/alwaysAsk.png)
   skin/classic/browser/preferences/mail.png           (preferences/mail.png)
   skin/classic/browser/preferences/Options.png        (preferences/Options.png)
deleted file mode 100644
index 2f97e742a3f0855c97a356c9f699b3bda3ac7c7b..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -1101,18 +1101,17 @@ toolbar[mode="icons"] #zoom-in-button {
   min-width: 8px;
   width: 8px;
   background-image: none;
   margin: 0 -4px;
   position: relative;
   height: 22px;
 }
 
-#page-proxy-favicon,
-#urlbar-throbber {
+#page-proxy-favicon {
   width: 16px;
   height: 16px;
   margin: 0px;
   padding: 0px;
 }
 
 #page-proxy-stack {
   width: 16px;
@@ -1122,20 +1121,16 @@ toolbar[mode="icons"] #zoom-in-button {
 #page-proxy-favicon:not([src]) {
   list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
 }
 
 #page-proxy-favicon[pageproxystate="invalid"] {
   opacity: 0.5;
 }
 
-#urlbar-throbber {
-  list-style-image: url("chrome://browser/skin/places/searching_16.png");
-}
-
 #wrapper-urlbar-container[place="palette"] {
   max-width: 20em;
 }
 
 #urlbar-display-box {
   -moz-border-end: 1px solid #AAA;
   -moz-margin-end: 3px;
 }
--- a/browser/themes/pinstripe/jar.mn
+++ b/browser/themes/pinstripe/jar.mn
@@ -71,17 +71,16 @@ browser.jar:
   skin/classic/browser/places/toolbarDropMarker.png         (places/toolbarDropMarker.png)
   skin/classic/browser/places/folderDropArrow.png           (places/folderDropArrow.png)
   skin/classic/browser/places/editBookmarkOverlay.css       (places/editBookmarkOverlay.css)
   skin/classic/browser/places/minus.png                     (places/minus.png)
   skin/classic/browser/places/minus-active.png              (places/minus-active.png)
   skin/classic/browser/places/plus.png                      (places/plus.png)
   skin/classic/browser/places/plus-active.png               (places/plus-active.png)
   skin/classic/browser/places/starPage.png                  (places/starPage.png)
-  skin/classic/browser/places/searching_16.png              (places/searching_16.png)
   skin/classic/browser/places/starred48.png                 (places/starred48.png)
   skin/classic/browser/places/unstarred48.png               (places/unstarred48.png)
   skin/classic/browser/places/unfiledBookmarks.png          (places/unfiledBookmarks.png)
   skin/classic/browser/places/twisty-open.gif               (places/twisty-open.gif)
   skin/classic/browser/places/twisty-closed.gif             (places/twisty-closed.gif)
   skin/classic/browser/places/tag.png                       (places/tag.png)
   skin/classic/browser/places/downloads.png                 (places/downloads.png)
   skin/classic/browser/places/expander-closed-active.png    (places/expander-closed-active.png)
deleted file mode 100644
index 15ec5d0a76f7bc9cd478f44c17e1af60d92b8abf..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -1484,18 +1484,17 @@ html|*.urlbar-input:-moz-lwtheme:-moz-pl
 .urlbar-history-dropmarker:hover:active,
 .urlbar-history-dropmarker[open="true"] {
   background-image: -moz-radial-gradient(center, circle closest-side, hsla(205,100%,70%,.1), hsla(205,100%,70%,0));
   -moz-image-region: rect(0px, 33px, 14px, 22px);
 }
 
 /* page proxy icon */
 
-#page-proxy-favicon,
-#urlbar-throbber {
+#page-proxy-favicon {
   width: 16px;
   height: 16px;
 }
 
 #page-proxy-stack {
   width: 24px;
   height: 18px;
   padding: 1px 4px;
@@ -1504,20 +1503,16 @@ html|*.urlbar-input:-moz-lwtheme:-moz-pl
 #page-proxy-favicon:not([src]) {
   list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
 }
 
 #page-proxy-favicon[pageproxystate="invalid"] {
   opacity: 0.5;
 }
 
-#urlbar-throbber {
-  list-style-image: url("chrome://browser/skin/places/searching_16.png");
-}
-
 /* autocomplete */
 
 #treecolAutoCompleteImage {
   max-width: 36px;
 }
 
 .ac-result-type-bookmark,
 .autocomplete-treebody::-moz-tree-image(bookmark, treecolAutoCompleteImage) {
--- a/browser/themes/winstripe/jar.mn
+++ b/browser/themes/winstripe/jar.mn
@@ -70,17 +70,16 @@ browser.jar:
         skin/classic/browser/places/editBookmarkOverlay.css          (places/editBookmarkOverlay.css)
         skin/classic/browser/places/libraryToolbar.png               (places/libraryToolbar.png)
         skin/classic/browser/places/starred48.png                    (places/starred48.png)
         skin/classic/browser/places/unstarred48.png                  (places/unstarred48.png)
         skin/classic/browser/places/tag.png                          (places/tag.png)
         skin/classic/browser/places/history.png                      (places/history.png)
         skin/classic/browser/places/allBookmarks.png                 (places/allBookmarks.png)
         skin/classic/browser/places/unsortedBookmarks.png            (places/unsortedBookmarks.png)
-        skin/classic/browser/places/searching_16.png                 (places/searching_16.png)
         skin/classic/browser/places/downloads.png                    (places/downloads.png)
         skin/classic/browser/preferences/alwaysAsk.png               (preferences/alwaysAsk.png)
         skin/classic/browser/preferences/application.png             (preferences/application.png)
         skin/classic/browser/preferences/mail.png                    (preferences/mail.png)
         skin/classic/browser/preferences/Options.png                 (preferences/Options.png)
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/browser/preferences/Options-sync.png            (preferences/Options-sync.png)
 #endif
@@ -226,17 +225,16 @@ browser.jar:
         skin/classic/aero/browser/places/editBookmarkOverlay.css     (places/editBookmarkOverlay.css)
         skin/classic/aero/browser/places/libraryToolbar.png          (places/libraryToolbar-aero.png)
         skin/classic/aero/browser/places/starred48.png               (places/starred48-aero.png)
         skin/classic/aero/browser/places/unstarred48.png             (places/unstarred48.png)
         skin/classic/aero/browser/places/tag.png                     (places/tag-aero.png)
         skin/classic/aero/browser/places/history.png                 (places/history-aero.png)
         skin/classic/aero/browser/places/allBookmarks.png            (places/allBookmarks-aero.png)
         skin/classic/aero/browser/places/unsortedBookmarks.png       (places/unsortedBookmarks-aero.png)
-        skin/classic/aero/browser/places/searching_16.png            (places/searching_16.png)
         skin/classic/aero/browser/places/downloads.png               (places/downloads.png)
         skin/classic/aero/browser/preferences/alwaysAsk.png          (preferences/alwaysAsk-aero.png)
         skin/classic/aero/browser/preferences/application.png        (preferences/application-aero.png)
         skin/classic/aero/browser/preferences/mail.png               (preferences/mail-aero.png)
         skin/classic/aero/browser/preferences/Options.png            (preferences/Options-aero.png)
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/aero/browser/preferences/Options-sync.png       (preferences/Options-sync.png)
 #endif
deleted file mode 100644
index 2f97e742a3f0855c97a356c9f699b3bda3ac7c7b..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/build/macosx/common
@@ -0,0 +1,2 @@
+CC=/usr/bin/gcc-4.2
+CXX=/usr/bin/g++-4.2
--- a/build/macosx/mozconfig.leopard
+++ b/build/macosx/mozconfig.leopard
@@ -1,15 +1,9 @@
-if test -z "$CC" ; then
-   CC=gcc-4.2
-fi
-
-if test -z "$CXX" ; then
-   CXX=g++-4.2
-fi
+. $topsrcdir/build/macosx/common
 
 # Mac builds don't nomally have to be handled as cross
 # compilation, but some of the libraries on the bots
 # (IDL for example) are built only for one arch.
 
 HOST_CC=$CC
 HOST_CXX=$CXX
 
--- a/build/macosx/universal/mozconfig.common
+++ b/build/macosx/universal/mozconfig.common
@@ -40,31 +40,25 @@ mk_add_options MOZ_POSTFLIGHT_ALL+=build
 
 # Note, the version (10) is used by libffi's configure.
 ac_add_app_options i386 --target=i386-apple-darwin10
 ac_add_app_options x86_64 --target=x86_64-apple-darwin10
 
 ac_add_app_options i386 --with-macos-sdk=/Developer/SDKs/MacOSX10.5.sdk
 ac_add_app_options x86_64 --with-macos-sdk=/Developer/SDKs/MacOSX10.6.sdk
 
+. $topsrcdir/build/macosx/common
+
 # $MOZ_BUILD_APP is only defined when sourced by configure.  That's not a
 # problem, because the variables it affects only need to be set for
 # configure.
 if test -n "$MOZ_BUILD_APP" ; then
 if test "$MOZ_BUILD_APP" = "i386" -o "$MOZ_BUILD_APP" = "x86_64"; then
   TARGET_CPU=$MOZ_BUILD_APP
 
-  if test -z "$CC" ; then
-     CC=gcc-4.2
-  fi
-
-  if test -z "$CXX" ; then
-     CXX=g++-4.2
-  fi
-
   # $HOST_CXX is presently unused.  $HOST_CC will only be used during a cross
   # compile.
   HOST_CC=$CC
   HOST_CXX=$CXX
 
   NATIVE_CPU=`$topsrcdir/build/autoconf/config.guess | cut -f1 -d-`
 
   # It's not strictly necessary to specify -arch during native builds, but it
--- a/client.mk
+++ b/client.mk
@@ -110,17 +110,17 @@ CONFIG_GUESS_SCRIPT := $(wildcard $(TOPS
 ifdef CONFIG_GUESS_SCRIPT
   CONFIG_GUESS = $(shell $(CONFIG_GUESS_SCRIPT))
 endif
 
 
 ####################################
 # Sanity checks
 
-ifneq (,$(filter MINGW%,$(shell uname -s)))
+ifneq (,$(findstring mingw,$(CONFIG_GUESS)))
 # check for CRLF line endings
 ifneq (0,$(shell $(PERL) -e 'binmode(STDIN); while (<STDIN>) { if (/\r/) { print "1"; exit } } print "0"' < $(TOPSRCDIR)/client.mk))
 $(error This source tree appears to have Windows-style line endings. To \
 convert it to Unix-style line endings, run \
 "python mozilla/build/win32/mozilla-dos2unix.py")
 endif
 endif
 
@@ -128,25 +128,30 @@ endif
 # Load mozconfig Options
 
 # See build pages, http://www.mozilla.org/build/ for how to set up mozconfig.
 
 MOZCONFIG_LOADER := build/autoconf/mozconfig2client-mk
 MOZCONFIG_FINDER := build/autoconf/mozconfig-find 
 MOZCONFIG_MODULES := build/unix/uniq.pl
 
-
-
 run_for_side_effects := \
   $(shell $(TOPSRCDIR)/$(MOZCONFIG_LOADER) $(TOPSRCDIR) $(TOPSRCDIR)/.mozconfig.mk > $(TOPSRCDIR)/.mozconfig.out)
 
 include $(TOPSRCDIR)/.mozconfig.mk
 
 ifndef MOZ_OBJDIR
   MOZ_OBJDIR = obj-$(CONFIG_GUESS)
+else
+# On Windows Pymake builds check MOZ_OBJDIR doesn't start with "/"
+  ifneq (,$(findstring mingw,$(CONFIG_GUESS)))
+  ifeq (1_a,$(.PYMAKE)_$(firstword a$(subst /, ,$(MOZ_OBJDIR))))
+  $(error For Windows Pymake builds, MOZ_OBJDIR must be a Windows [and not MSYS] style path.)
+  endif
+  endif
 endif
 
 ifdef MOZ_BUILD_PROJECTS
 
 ifdef MOZ_CURRENT_PROJECT
   OBJDIR = $(MOZ_OBJDIR)/$(MOZ_CURRENT_PROJECT)
   MOZ_MAKE = $(MAKE) $(MOZ_MAKE_FLAGS) -C $(OBJDIR)
   BUILD_PROJECT_ARG = MOZ_BUILD_APP=$(MOZ_CURRENT_PROJECT)
@@ -289,16 +294,20 @@ CONFIG_STATUS_DEPS := \
 	$(TOPSRCDIR)/.mozconfig.mk \
 	$(wildcard $(TOPSRCDIR)/nsprpub/configure) \
 	$(wildcard $(TOPSRCDIR)/config/milestone.txt) \
 	$(wildcard $(TOPSRCDIR)/js/src/config/milestone.txt) \
 	$(wildcard $(TOPSRCDIR)/browser/config/version.txt) \
 	$(wildcard $(addsuffix confvars.sh,$(wildcard $(TOPSRCDIR)/*/))) \
 	$(NULL)
 
+CONFIGURE_ENV_ARGS += \
+  MAKE="$(MAKE)" \
+  $(NULL)
+
 # configure uses the program name to determine @srcdir@. Calling it without
 #   $(TOPSRCDIR) will set @srcdir@ to "."; otherwise, it is set to the full
 #   path of $(TOPSRCDIR).
 ifeq ($(TOPSRCDIR),$(OBJDIR))
   CONFIGURE = ./configure
 else
   CONFIGURE = $(TOPSRCDIR)/configure
 endif
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -59,16 +59,18 @@ endif
 
 ifdef SDK_XPIDLSRCS
 XPIDLSRCS += $(SDK_XPIDLSRCS)
 endif
 ifdef SDK_HEADERS
 EXPORTS += $(SDK_HEADERS)
 endif
 
+REPORT_BUILD = @echo $(notdir $<)
+
 ifeq ($(OS_ARCH),OS2)
 EXEC			=
 else
 EXEC			= exec
 endif
 
 # Don't copy xulrunner files at install time, when using system xulrunner
 ifdef SYSTEM_LIBXUL
@@ -1143,45 +1145,53 @@ MAKE_DEPS_AUTO_CC = $(MAKE_DEPS_AUTO)
 MAKE_DEPS_AUTO_CXX = $(MAKE_DEPS_AUTO)
 
 endif # COMPILER_DEPEND
 
 endif # MOZ_AUTO_DEPS
 
 # Rules for building native targets must come first because of the host_ prefix
 host_%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 %:: %.c $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS)
 
 %.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
 
 # DEFINES and ACDEFINES are needed here to enable conditional compilation of Q_OBJECTs:
 # 'moc' only knows about #defines it gets on the command line (-D...), not in
 # included headers like mozilla-config.h
 moc_%.cpp: %.h $(GLOBAL_DEPS)
 	$(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@
 
 moc_%.cc: %.cc $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@
 
 ifdef ASFILES
 # The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept
 # a '-c' flag.
 %.$(OBJ_SUFFIX): %.$(ASM_SUFFIX) $(GLOBAL_DEPS)
 	$(AS) $(ASOUTOPTION)$@ $(ASFLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS)
 endif
@@ -1192,34 +1202,38 @@ endif
 %:: %.cpp $(GLOBAL_DEPS)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(CCC) $(OUTOPTION)$@ $(CXXFLAGS) $(_VPATH_SRCS) $(LDFLAGS)
 
 #
 # Please keep the next two rules in sync.
 #
 %.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
 %.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 ifdef STRICT_CPLUSPLUS_SUFFIX
 	echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc
 	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) t_$*.cc
 	$(RM) t_$*.cc
 else
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 endif #STRICT_CPLUSPLUS_SUFFIX
 
 $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
 
 $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS)
 
 %.s: %.cpp
 	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
 %.s: %.cc
 	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
@@ -1459,27 +1473,29 @@ endif
 
 XPIDL_DEPS = \
   $(topsrcdir)/xpcom/idl-parser/header.py \
   $(topsrcdir)/xpcom/idl-parser/typelib.py \
   $(topsrcdir)/xpcom/idl-parser/xpidl.py \
   $(NULL)
 
 $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
+	$(REPORT_BUILD)
 	$(PYTHON_PATH) \
 	  -I$(topsrcdir)/other-licenses/ply \
 	  -I$(topsrcdir)/xpcom/idl-parser \
 	  $(topsrcdir)/xpcom/idl-parser/header.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 	@if test -n "$(findstring $*.h, $(EXPORTS))"; \
 	  then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi
 
 ifndef NO_GEN_XPT
 # generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
 # into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
 $(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
+	$(REPORT_BUILD)
 	$(PYTHON_PATH) \
 	  -I$(topsrcdir)/other-licenses/ply \
 	  -I$(topsrcdir)/xpcom/idl-parser \
 	  -I$(topsrcdir)/xpcom/typelib/xpt/tools \
 	  $(topsrcdir)/xpcom/idl-parser/typelib.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 
 # no need to link together if XPIDLSRCS contains only XPIDL_MODULE
 ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS)))
@@ -1758,22 +1774,25 @@ else # ! COMPILER_DEPEND
 
 ifndef MOZ_AUTO_DEPS
 
 define MAKE_DEPS_NOAUTO
 	$(MKDEPEND) -w1024 -o'.$(OBJ_SUFFIX)' -f- $(DEFINES) $(ACDEFINES) $(INCLUDES) $< 2>/dev/null | sed -e "s|^[^ ]*/||" > $@
 endef
 
 $(MDDEPDIR)/%.pp: %.c
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_NOAUTO)
 
 $(MDDEPDIR)/%.pp: %.cpp
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_NOAUTO)
 
 $(MDDEPDIR)/%.pp: %.s
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_NOAUTO)
 
 ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))
 depend:: $(SUBMAKEFILES) $(MAKE_DIRS) $(MDDEPFILES)
 else
 depend:: $(SUBMAKEFILES)
 endif
 	$(LOOP_OVER_PARALLEL_DIRS)
--- a/configure.in
+++ b/configure.in
@@ -2246,16 +2246,27 @@ changequote(,)
 $PYTHON -c "import sys; sys.exit(sys.version[:3] < sys.argv[1] or sys.version[:2] != '2.')" $PYTHON_VERSION
 _python_res=$?
 changequote([,])
 if test "$_python_res" != 0; then
     AC_MSG_ERROR([Python $PYTHON_VERSION or higher (but not Python 3.x) is required.])
 fi
 AC_MSG_RESULT([yes])
 
+dnl Check for using a custom <stdint.h> implementation
+dnl ========================================================
+AC_MSG_CHECKING(for custom <stdint.h> implementation)
+if test "$MOZ_CUSTOM_STDINT_H"; then
+  AC_DEFINE_UNQUOTED(MOZ_CUSTOM_STDINT_H, "$MOZ_CUSTOM_STDINT_H")
+  AC_SUBST(MOZ_CUSTOM_STDINT_H)
+  AC_MSG_RESULT(using $MOZ_CUSTOM_STDINT_H)
+else
+  AC_MSG_RESULT(none specified)
+fi
+
 dnl Get mozilla version from central milestone file
 MOZILLA_VERSION=`$PERL $srcdir/config/milestone.pl -topsrcdir $srcdir`
 
 dnl Get version of various core apps from the version files.
 FIREFOX_VERSION=`cat $_topsrcdir/browser/config/version.txt`
 
 if test -z "$FIREFOX_VERSION"; then
     AC_MSG_ERROR([FIREFOX_VERSION is unexpectedly blank.])
@@ -3012,57 +3023,18 @@ AC_CACHE_VAL(ac_cv_siginfo_t,
                  [ac_cv_siginfo_t=false])])
 if test "$ac_cv_siginfo_t" = true ; then
   AC_DEFINE(HAVE_SIGINFO_T)
   AC_MSG_RESULT(yes)
 else
   AC_MSG_RESULT(no)
 fi
 
-dnl Check for int16_t, int32_t, int64_t, int64, uint, uint_t, and uint16_t.
-dnl ========================================================
-AC_MSG_CHECKING(for int16_t)
-AC_CACHE_VAL(ac_cv_int16_t,
- [AC_TRY_COMPILE([#include <stdio.h>
-                  #include <sys/types.h>],
-                 [int16_t foo = 0;],
-                 [ac_cv_int16_t=true],
-                 [ac_cv_int16_t=false])])
-if test "$ac_cv_int16_t" = true ; then
-  AC_DEFINE(HAVE_INT16_T)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
-AC_MSG_CHECKING(for int32_t)
-AC_CACHE_VAL(ac_cv_int32_t,
- [AC_TRY_COMPILE([#include <stdio.h>
-                  #include <sys/types.h>],
-                 [int32_t foo = 0;],
-                 [ac_cv_int32_t=true],
-                 [ac_cv_int32_t=false])])
-if test "$ac_cv_int32_t" = true ; then
-  AC_DEFINE(HAVE_INT32_T)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
-AC_MSG_CHECKING(for int64_t)
-AC_CACHE_VAL(ac_cv_int64_t,
- [AC_TRY_COMPILE([#include <stdio.h>
-                  #include <sys/types.h>],
-                 [int64_t foo = 0;],
-                 [ac_cv_int64_t=true],
-                 [ac_cv_int64_t=false])])
-if test "$ac_cv_int64_t" = true ; then
-  AC_DEFINE(HAVE_INT64_T)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
+dnl Check for int64, uint, and uint_t.
+dnl ========================================================
 AC_MSG_CHECKING(for int64)
 AC_CACHE_VAL(ac_cv_int64,
  [AC_TRY_COMPILE([#include <stdio.h>
                   #include <sys/types.h>],
                  [int64 foo = 0;],
                  [ac_cv_int64=true],
                  [ac_cv_int64=false])])
 if test "$ac_cv_int64" = true ; then
@@ -3092,29 +3064,16 @@ AC_CACHE_VAL(ac_cv_uint_t,
                  [ac_cv_uint_t=true],
                  [ac_cv_uint_t=false])])
 if test "$ac_cv_uint_t" = true ; then
   AC_DEFINE(HAVE_UINT_T)
   AC_MSG_RESULT(yes)
 else
   AC_MSG_RESULT(no)
 fi
-AC_MSG_CHECKING(for uint16_t)
-AC_CACHE_VAL(ac_cv_uint16_t,
- [AC_TRY_COMPILE([#include <stdio.h>
-                  #include <sys/types.h>],
-                 [uint16_t foo = 0;],
-                 [ac_cv_uint16_t=true],
-                 [ac_cv_uint16_t=false])])
-if test "$ac_cv_uint16_t" = true ; then
-  AC_DEFINE(HAVE_UINT16_T)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
 
 dnl On the gcc trunk (as of 2001-02-09) _GNU_SOURCE, and thus __USE_GNU,
 dnl are defined when compiling C++ but not C.  Since the result of this
 dnl test is used only in C++, do it in C++.
 AC_LANG_CPLUSPLUS
 
 AC_MSG_CHECKING(for uname.domainname)
 AC_CACHE_VAL(ac_cv_have_uname_domainname_field,
@@ -7746,17 +7705,17 @@ dnl ====================================
 MOZ_ARG_HEADER(Compiler Options)
 
 dnl ========================================================
 dnl Check for gcc -pipe support
 dnl ========================================================
 AC_MSG_CHECKING([for gcc -pipe support])
 if test -n "$GNU_CC" -a -n "$GNU_CXX" -a -n "$GNU_AS"; then
     echo '#include <stdio.h>' > dummy-hello.c
-    echo 'int main() { printf("Hello World\n"); exit(0); }' >> dummy-hello.c
+    echo 'int main() { printf("Hello World"); exit(0); }' >> dummy-hello.c
     ${CC} -S dummy-hello.c -o dummy-hello.s 2>&5
     cat dummy-hello.s 2> /dev/null | ${AS_BIN} -o dummy-hello.S - 2>&5
     if test $? = 0; then
         _res_as_stdin="yes"
     else
         _res_as_stdin="no"
     fi
     if test "$_res_as_stdin" = "yes"; then
--- a/content/base/src/nsCSPService.cpp
+++ b/content/base/src/nsCSPService.cpp
@@ -292,17 +292,16 @@ CSPService::AsyncOnChannelRedirect(nsICh
                                         channelPolicy);
     if (NS_SUCCEEDED(rv)) {
       return NS_OK;
     }
   }
 
   // The redirecting channel isn't a writable property bag, we won't be able
   // to enforce the load policy if it redirects again, so we stop it now.
-  nsXPIDLString message;
   nsCAutoString newUriSpec;
   newUri->GetSpec(newUriSpec);
   const PRUnichar *formatParams[] = { NS_ConvertUTF8toUTF16(newUriSpec).get() };
   if (NS_SUCCEEDED(rv)) {
     nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
                                    "InvalidRedirectChannelWarning",
                                     formatParams, 1, nsnull, EmptyString(),
                                     0, 0, nsIScriptError::warningFlag,
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -345,16 +345,17 @@ GK_ATOM(elementAvailable, "element-avail
 GK_ATOM(elements, "elements")
 GK_ATOM(em, "em")
 GK_ATOM(embed, "embed")
 GK_ATOM(embossed, "embossed")
 GK_ATOM(empty, "empty")
 GK_ATOM(encoding, "encoding")
 GK_ATOM(enctype, "enctype")
 GK_ATOM(end, "end")
+GK_ATOM(endEvent, "endEvent")
 GK_ATOM(end_after, "end_after")
 GK_ATOM(end_before, "end_before")
 GK_ATOM(equalsize, "equalsize")
 GK_ATOM(error, "error")
 GK_ATOM(even, "even")
 GK_ATOM(event, "event")
 GK_ATOM(events, "events")
 GK_ATOM(excludeResultPrefixes, "exclude-result-prefixes")
@@ -1365,16 +1366,17 @@ GK_ATOM(z, "z")
 GK_ATOM(zoomAndPan, "zoomAndPan")
 
 GK_ATOM(accumulate, "accumulate")
 GK_ATOM(additive, "additive")
 GK_ATOM(attributeName, "attributeName")
 GK_ATOM(attributeType, "attributeType")
 GK_ATOM(auto_reverse, "auto-reverse")
 GK_ATOM(begin, "begin")
+GK_ATOM(beginEvent, "beginEvent")
 GK_ATOM(by, "by")
 GK_ATOM(calcMode, "calcMode")
 GK_ATOM(css, "CSS")
 GK_ATOM(dur, "dur")
 GK_ATOM(keyPoints, "keyPoints")
 GK_ATOM(keySplines, "keySplines")
 GK_ATOM(keyTimes, "keyTimes")
 GK_ATOM(mozAnimateMotionDummyAttr, "_mozAnimateMotionDummyAttr")
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -696,57 +696,56 @@ NS_IMETHODIMP
 nsXMLHttpRequest::GetChannel(nsIChannel **aChannel)
 {
   NS_ENSURE_ARG_POINTER(aChannel);
   NS_IF_ADDREF(*aChannel = mChannel);
 
   return NS_OK;
 }
 
+static void LogMessage(const char* aWarning, nsPIDOMWindow* aWindow)
+{
+  nsCOMPtr<nsIDocument> doc;
+  if (aWindow) {
+    doc = do_QueryInterface(aWindow->GetExtantDocument());
+  }
+  nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
+                                  aWarning,
+                                  nsnull,
+                                  0,
+                                  nsnull, // Response URL not kept around
+                                  EmptyString(),
+                                  0,
+                                  0,
+                                  nsIScriptError::warningFlag,
+                                  "DOM",
+                                  doc);
+}
+
 /* readonly attribute nsIDOMDocument responseXML; */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetResponseXML(nsIDOMDocument **aResponseXML)
 {
   NS_ENSURE_ARG_POINTER(aResponseXML);
   *aResponseXML = nsnull;
   if (mResponseType != XML_HTTP_RESPONSE_TYPE_DEFAULT &&
       mResponseType != XML_HTTP_RESPONSE_TYPE_DOCUMENT) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
   if ((XML_HTTP_REQUEST_DONE & mState) && mResponseXML) {
     *aResponseXML = mResponseXML;
     NS_ADDREF(*aResponseXML);
   }
   if (mWarnAboutMultipartHtml) {
     mWarnAboutMultipartHtml = false;
-    nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
-                                    "HTMLMultipartXHRWarning",
-                                    nsnull,
-                                    0,
-                                    nsnull, // Response URL not kept around
-                                    EmptyString(),
-                                    0,
-                                    0,
-                                    nsIScriptError::warningFlag,
-                                    "DOM",
-                                    mOwner->WindowID());
+    LogMessage("HTMLMultipartXHRWarning", mOwner);
   }
   if (mWarnAboutSyncHtml) {
     mWarnAboutSyncHtml = false;
-    nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
-                                    "HTMLSyncXHRWarning",
-                                    nsnull,
-                                    0,
-                                    nsnull, // Response URL not kept around
-                                    EmptyString(),
-                                    0,
-                                    0,
-                                    nsIScriptError::warningFlag,
-                                    "DOM",
-                                    mOwner->WindowID());
+    LogMessage("HTMLSyncXHRWarning", mOwner);
   }
   return NS_OK;
 }
 
 /*
  * This piece copied from nsXMLDocument, we try to get the charset
  * from HTTP headers.
  */
@@ -779,16 +778,23 @@ nsXMLHttpRequest::DetectCharset()
     }
   }
 
   if (NS_FAILED(rv) || mResponseCharset.IsEmpty()) {
     // MS documentation states UTF-8 is default for responseText
     mResponseCharset.AssignLiteral("UTF-8");
   }
 
+  if (mResponseType == XML_HTTP_RESPONSE_TYPE_JSON &&
+      !mResponseCharset.EqualsLiteral("UTF-8")) {
+    // The XHR spec says only UTF-8 is supported for responseType == "json"
+    LogMessage("JSONCharsetWarning", mOwner);
+    mResponseCharset.AssignLiteral("UTF-8");
+  }
+
   nsCOMPtr<nsICharsetConverterManager> ccm =
     do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return ccm->GetUnicodeDecoderRaw(mResponseCharset.get(),
                                    getter_AddRefs(mDecoder));
 }
 
@@ -916,17 +922,17 @@ NS_IMETHODIMP nsXMLHttpRequest::GetRespo
 }
 
 nsresult
 nsXMLHttpRequest::CreateResponseParsedJSON(JSContext* aCx)
 {
   if (!aCx) {
     return NS_ERROR_FAILURE;
   }
-
+  // The Unicode converter has already zapped the BOM if there was one
   if (!JS_ParseJSON(aCx,
                     (jschar*)mResponseText.get(),
                     mResponseText.Length(), &mResultJSON)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
@@ -969,17 +975,17 @@ NS_IMETHODIMP nsXMLHttpRequest::GetRespo
     break;
   case XML_HTTP_RESPONSE_TYPE_DOCUMENT:
     aResponseType.AssignLiteral("document");
     break;
   case XML_HTTP_RESPONSE_TYPE_TEXT:
     aResponseType.AssignLiteral("text");
     break;
   case XML_HTTP_RESPONSE_TYPE_JSON:
-    aResponseType.AssignLiteral("moz-json");
+    aResponseType.AssignLiteral("json");
     break;
   case XML_HTTP_RESPONSE_TYPE_CHUNKED_TEXT:
     aResponseType.AssignLiteral("moz-chunked-text");
     break;
   case XML_HTTP_RESPONSE_TYPE_CHUNKED_ARRAYBUFFER:
     aResponseType.AssignLiteral("moz-chunked-arraybuffer");
     break;
   default:
@@ -993,28 +999,35 @@ NS_IMETHODIMP nsXMLHttpRequest::GetRespo
 NS_IMETHODIMP nsXMLHttpRequest::SetResponseType(const nsAString& aResponseType)
 {
   // If the state is not OPENED or HEADERS_RECEIVED raise an
   // INVALID_STATE_ERR exception and terminate these steps.
   if (!(mState & (XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_SENT |
                   XML_HTTP_REQUEST_HEADERS_RECEIVED)))
     return NS_ERROR_DOM_INVALID_STATE_ERR;
 
+  // sync request is not allowed setting responseType in window context
+  if (mOwner &&
+      !(mState & (XML_HTTP_REQUEST_UNSENT | XML_HTTP_REQUEST_ASYNC))) {
+    LogMessage("ResponseTypeSyncXHRWarning", mOwner);
+    return NS_ERROR_DOM_INVALID_ACCESS_ERR;
+  }
+
   // Set the responseType attribute's value to the given value.
   if (aResponseType.IsEmpty()) {
     mResponseType = XML_HTTP_RESPONSE_TYPE_DEFAULT;
   } else if (aResponseType.EqualsLiteral("arraybuffer")) {
     mResponseType = XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER;
   } else if (aResponseType.EqualsLiteral("blob")) {
     mResponseType = XML_HTTP_RESPONSE_TYPE_BLOB;
   } else if (aResponseType.EqualsLiteral("document")) {
     mResponseType = XML_HTTP_RESPONSE_TYPE_DOCUMENT;
   } else if (aResponseType.EqualsLiteral("text")) {
     mResponseType = XML_HTTP_RESPONSE_TYPE_TEXT;
-  } else if (aResponseType.EqualsLiteral("moz-json")) {
+  } else if (aResponseType.EqualsLiteral("json")) {
     mResponseType = XML_HTTP_RESPONSE_TYPE_JSON;
   } else if (aResponseType.EqualsLiteral("moz-chunked-text")) {
     if (!(mState & XML_HTTP_REQUEST_ASYNC)) {
       return NS_ERROR_DOM_INVALID_STATE_ERR;
     }
     mResponseType = XML_HTTP_RESPONSE_TYPE_CHUNKED_TEXT;
   } else if (aResponseType.EqualsLiteral("moz-chunked-arraybuffer")) {
     if (!(mState & XML_HTTP_REQUEST_ASYNC)) {
@@ -1093,19 +1106,25 @@ NS_IMETHODIMP nsXMLHttpRequest::GetRespo
       *aResult = JSVAL_NULL;
     }
     break;
 
   case XML_HTTP_RESPONSE_TYPE_JSON:
     if (mState & XML_HTTP_REQUEST_DONE) {
       if (mResultJSON == JSVAL_VOID) {
         rv = CreateResponseParsedJSON(aCx);
-        NS_ENSURE_SUCCESS(rv, rv);
-
         mResponseText.Truncate();
+        if (NS_FAILED(rv)) {
+          // Per spec, errors aren't propagated. null is returned instead.
+          rv = NS_OK;
+          // It would be nice to log the error to the console. That's hard to
+          // do without calling window.onerror as a side effect, though.
+          JS_ClearPendingException(aCx);
+          mResultJSON = JSVAL_NULL;
+        }
       }
       *aResult = mResultJSON;
     } else {
       *aResult = JSVAL_NULL;
     }
     break;
 
   default:
@@ -1514,16 +1533,30 @@ nsXMLHttpRequest::Open(const nsACString&
 
   // Disallow HTTP/1.1 TRACE method (see bug 302489)
   // and MS IIS equivalent TRACK (see bug 381264)
   if (method.LowerCaseEqualsLiteral("trace") ||
       method.LowerCaseEqualsLiteral("track")) {
     return NS_ERROR_INVALID_ARG;
   }
 
+  // sync request is not allowed using withCredential or responseType
+  // in window context
+  if (!async && mOwner &&
+      (mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS ||
+       mResponseType != XML_HTTP_RESPONSE_TYPE_DEFAULT)) {
+    if (mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS) {
+      LogMessage("WithCredentialsSyncXHRWarning", mOwner);
+    }
+    if (mResponseType != XML_HTTP_RESPONSE_TYPE_DEFAULT) {
+      LogMessage("ResponseTypeSyncXHRWarning", mOwner);
+    }
+    return NS_ERROR_DOM_INVALID_ACCESS_ERR;
+  }
+
   nsresult rv;
   nsCOMPtr<nsIURI> uri;
   bool authp = false;
 
   if (mState & (XML_HTTP_REQUEST_OPENED |
                 XML_HTTP_REQUEST_HEADERS_RECEIVED |
                 XML_HTTP_REQUEST_LOADING |
                 XML_HTTP_REQUEST_SENT |
@@ -2915,17 +2948,24 @@ nsXMLHttpRequest::GetWithCredentials(boo
 /* attribute boolean withCredentials; */
 NS_IMETHODIMP
 nsXMLHttpRequest::SetWithCredentials(bool aWithCredentials)
 {
   // Return error if we're already processing a request
   if (XML_HTTP_REQUEST_SENT & mState) {
     return NS_ERROR_FAILURE;
   }
-  
+
+  // sync request is not allowed setting withCredentials in window context
+  if (mOwner &&
+      !(mState & (XML_HTTP_REQUEST_UNSENT | XML_HTTP_REQUEST_ASYNC))) {
+    LogMessage("WithCredentialsSyncXHRWarning", mOwner);
+    return NS_ERROR_DOM_INVALID_ACCESS_ERR;
+  }
+
   if (aWithCredentials) {
     mState |= XML_HTTP_REQUEST_AC_WITH_CREDENTIALS;
   }
   else {
     mState &= ~XML_HTTP_REQUEST_AC_WITH_CREDENTIALS;
   }
   return NS_OK;
 }
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -528,16 +528,20 @@ include $(topsrcdir)/config/rules.mk
 		test_bug692434.html \
 		file_bug692434.xml \
 		test_bug693875.html \
 		test_nodelist_holes.html \
 		test_xhr_abort_after_load.html \
 		test_bug702439.html \
 		test_bug702439.html^headers^ \
 		file_bug702439.html \
+		test_bug707142.html \
+		file_bug707142_baseline.json \
+		file_bug707142_bom.json \
+		file_bug707142_utf-16.json \
 		$(NULL)
 
 _CHROME_FILES =	\
 		test_bug357450.js \
 		$(NULL)
 
 # This test fails on the Mac for some reason
 ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_bug707142_baseline.json
@@ -0,0 +1,1 @@
+{"foo": "bar"}
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_bug707142_bom.json
@@ -0,0 +1,1 @@
+{"foo": "bar"}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..eb28f6bb7ee7ed29876bc03d7c09ade3fbf4cdd5
GIT binary patch
literal 32
jc%1wHubM%LA&ns)2$dMD7!-hH5<?<G5s<EB;9>v(h>!+b
--- a/content/base/test/test_XHR.html
+++ b/content/base/test/test_XHR.html
@@ -1,24 +1,29 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test for XMLHttpRequest</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
-<body>
+<body onload="gen.next();">
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
-<script class="testbody" type="text/javascript">
+<script class="testbody" type="application/javascript;version=1.7">
 SimpleTest.waitForExplicitFinish();
 
+var gen = runTests();
+function continueTest() { gen.next(); }
+
+function runTests() {
+
 var path = "/tests/content/base/test/";
 
 var passFiles = [['file_XHR_pass1.xml', 'GET'],
                  ['file_XHR_pass2.txt', 'GET'],
                  ['file_XHR_pass3.txt', 'GET'],
                  ];
 
 var failFiles = [['//example.com' + path + 'file_XHR_pass1.xml', 'GET'],
@@ -58,139 +63,168 @@ for (i = 0; i < failFiles.length; ++i) {
     is(xhr.status, 301, "wrong status");
     is(xhr.responseText, "redirect file\n", "wrong response");
   }
   else {
     ok(1, "should have thrown or given incorrect result");
   }
 }
 
-// test response (responseType='document')
 function checkResponseTextAccessThrows(xhr) {
   var didthrow = false;
   try { xhr.responseText } catch (e) { didthrow = true; }
   ok(didthrow, "should have thrown when accessing responseText");
 }
 function checkResponseXMLAccessThrows(xhr) {
   var didthrow = false;
   try { xhr.responseXML } catch (e) { didthrow = true; }
   ok(didthrow, "should have thrown when accessing responseXML");
 }
-function checkResponseAccessThrows(xhr) {
-  var didthrow = false;
-  try { xhr.response } catch (e) { didthrow = true; }
-  ok(didthrow, "should have thrown when accessing response");
-}
 function checkSetResponseTypeThrows(xhr, type) {
   var didthrow = false;
   try { xhr.responseType = type; } catch (e) { didthrow = true; }
   ok(didthrow, "should have thrown when setting responseType");
 }
+function checkOpenThrows(xhr, method, url, async) {
+  var didthrow = false;
+  try { xhr.open(method, url, async); } catch (e) { didthrow = true; }
+  ok(didthrow, "should have thrown when open is called");
+}
 
+// test response (sync, responseType is not changeable)
 xhr = new XMLHttpRequest();
+xhr.open("GET", 'file_XHR_pass2.txt', false); 
+checkSetResponseTypeThrows(xhr, "");
+checkSetResponseTypeThrows(xhr, "text");
 checkSetResponseTypeThrows(xhr, "document");
-xhr.open("GET", 'file_XHR_pass1.xml', false); 
+checkSetResponseTypeThrows(xhr, "arraybuffer");
+checkSetResponseTypeThrows(xhr, "blob");
+checkSetResponseTypeThrows(xhr, "json");
 checkSetResponseTypeThrows(xhr, "moz-chunked-text");
 checkSetResponseTypeThrows(xhr, "moz-chunked-arraybuffer");
+xhr.send(null);
+checkSetResponseTypeThrows(xhr, "document");
+is(xhr.status, 200, "wrong status");
+is(xhr.response, "hello pass\n", "wrong response");
+
+// test response (responseType='document')
+xhr = new XMLHttpRequest();
+xhr.open("GET", 'file_XHR_pass1.xml'); 
 xhr.responseType = 'document';
+xhr.onloadend = continueTest;
 xhr.send(null);
+yield;
 checkSetResponseTypeThrows(xhr, "document");
 is(xhr.status, 200, "wrong status");
 checkResponseTextAccessThrows(xhr);
 is((new XMLSerializer()).serializeToString(xhr.response.documentElement),
    "<res>hello</res>",
    "wrong response");
 
 // test response (responseType='text')
 xhr = new XMLHttpRequest();
-xhr.open("GET", 'file_XHR_pass2.txt', false); 
+xhr.open("GET", 'file_XHR_pass2.txt'); 
 xhr.responseType = 'text';
+xhr.onloadend = continueTest;
 xhr.send(null);
+yield;
 is(xhr.status, 200, "wrong status");
 checkResponseXMLAccessThrows(xhr);
 is(xhr.response, "hello pass\n", "wrong response");
 
 // test response (responseType='arraybuffer')
 function arraybuffer_equals_to(ab, s) {
   is(ab.byteLength, s.length, "wrong arraybuffer byteLength");
 
   u8v = new Uint8Array(ab);
   is(String.fromCharCode.apply(String, u8v), s, "wrong values");
 }
 
 // with a simple text file
 xhr = new XMLHttpRequest();
-xhr.open("GET", 'file_XHR_pass2.txt', false); 
+xhr.open("GET", 'file_XHR_pass2.txt'); 
 xhr.responseType = 'arraybuffer';
+xhr.onloadend = continueTest;
 xhr.send(null);
+yield;
 is(xhr.status, 200, "wrong status");
 checkResponseTextAccessThrows(xhr);
 checkResponseXMLAccessThrows(xhr);
 ab = xhr.response;
 ok(ab != null, "should have a non-null arraybuffer");
 arraybuffer_equals_to(ab, "hello pass\n");
 
 // test reusing the same XHR (Bug 680816)
-xhr.open("GET", 'file_XHR_binary1.bin', false);
+xhr.open("GET", 'file_XHR_binary1.bin');
 xhr.responseType = 'arraybuffer';
+xhr.onloadend = continueTest;
 xhr.send(null);
+yield;
 is(xhr.status, 200, "wrong status");
 ab2 = xhr.response;
 ok(ab2 != null, "should have a non-null arraybuffer");
 ok(ab2 != ab, "arraybuffer on XHR reuse should be distinct");
 arraybuffer_equals_to(ab, "hello pass\n");
 arraybuffer_equals_to(ab2, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb");
 
 // with a binary file
 xhr = new XMLHttpRequest();
-xhr.open("GET", 'file_XHR_binary1.bin', false); 
+xhr.open("GET", 'file_XHR_binary1.bin'); 
 xhr.responseType = 'arraybuffer';
-xhr.send(null)
+xhr.onloadend = continueTest;
+xhr.send(null);
+yield;
 is(xhr.status, 200, "wrong status");
 checkResponseTextAccessThrows(xhr);
 checkResponseXMLAccessThrows(xhr);
 ab = xhr.response;
 ok(ab != null, "should have a non-null arraybuffer");
 arraybuffer_equals_to(ab, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb");
 is(xhr.response, xhr.response, "returns the same ArrayBuffer");
 
-// test response (responseType='moz-json')
+// test response (responseType='json')
 var xhr = new XMLHttpRequest();
-xhr.open("POST", 'responseIdentical.sjs', false);
-xhr.responseType = 'moz-json';
+xhr.open("POST", 'responseIdentical.sjs');
+xhr.responseType = 'json';
 jsonObjStr = JSON.stringify({title: "aBook", author: "john"});
+xhr.onloadend = continueTest;
 xhr.send(jsonObjStr);
+yield;
 is(xhr.status, 200, "wrong status");
 checkResponseTextAccessThrows(xhr);
 checkResponseXMLAccessThrows(xhr);
 is(JSON.stringify(xhr.response), jsonObjStr, "correct result");
 is(xhr.response, xhr.response, "returning the same object on each access");
 
 // with invalid json
 var xhr = new XMLHttpRequest();
-xhr.open("POST", 'responseIdentical.sjs', false);
-xhr.responseType = 'moz-json';
+xhr.open("POST", 'responseIdentical.sjs');
+xhr.responseType = 'json';
+xhr.onloadend = continueTest;
 xhr.send("{");
+yield;
 is(xhr.status, 200, "wrong status");
 checkResponseTextAccessThrows(xhr);
 checkResponseXMLAccessThrows(xhr);
-checkResponseAccessThrows(xhr);
-checkResponseAccessThrows(xhr); // Check twice to ensure that we still throw
+is(xhr.response, null, "Bad JSON should result in null response.");
+is(xhr.response, null, "Bad JSON should result in null response even 2nd time.");
 
 // test response (responseType='blob')
 var onloadCount = 0;
 function checkOnloadCount() {
   if (++onloadCount >= 3) SimpleTest.finish();
 };
 
 // with a simple text file
 xhr = new XMLHttpRequest();
-xhr.open("GET", 'file_XHR_pass2.txt', false); 
+xhr.open("GET", 'file_XHR_pass2.txt'); 
 xhr.responseType = 'blob';
+xhr.onloadend = continueTest;
 xhr.send(null);
+yield;
 is(xhr.status, 200, "wrong status");
 checkResponseTextAccessThrows(xhr);
 checkResponseXMLAccessThrows(xhr);
 b = xhr.response;
 ok(b, "should have a non-null blob");
 ok(b instanceof Blob, "should be a Blob");
 ok(!(b instanceof File), "should not be a File");
 is(b.size, "hello pass\n".length, "wrong blob size");
@@ -276,12 +310,14 @@ client.onreadystatechange = function() {
         ok(false, "Shouldn't throw! [" + ex + "]");
       }
     }
   }
 client.open("GET", "file_XHR_pass1.xml", true);
 client.send();
 client.abort();
 
+yield;
+} /* runTests */
 </script>
 </pre>
 </body>
 </html>
--- a/content/base/test/test_XHRSendData.html
+++ b/content/base/test/test_XHRSendData.html
@@ -3,27 +3,33 @@
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=464848
 -->
 <head>
   <title>XMLHttpRequest send data and headers</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
-<body>
+<body onload="gen.next();">
 <a target="_blank"
    href="https://bugzilla.mozilla.org/show_bug.cgi?id=464848">Mozilla Bug 464848</a>
 <p id="display">
   <input id="fileList" type="file"></input>
 </p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="application/javascript;version=1.8">
+SimpleTest.waitForExplicitFinish();
+
+var gen = runTests();
+function continueTest() { gen.next(); }
+
+function runTests() {
 
 xhr = new XMLHttpRequest();
 xhr.open("GET", "file_XHRSendData_doc.xml", false);
 xhr.send();
 testDoc1 = xhr.responseXML;
 is(testDoc1.inputEncoding, "ISO-8859-1", "wrong encoding");
 
 testDoc2 = document.implementation.createDocument("", "", null);
@@ -171,22 +177,26 @@ for (var i = 0; i < testDOMFiles.length;
                resContentType: fileTypes[i],
                resContentLength: testData.length,
               });
 }
 
 try {
   for each(test in tests) {
     xhr = new XMLHttpRequest;
-    xhr.open("POST", "file_XHRSendData.sjs", false);
+    xhr.open("POST", "file_XHRSendData.sjs", !!test.resType);
     if (test.contentType)
       xhr.setRequestHeader("Content-Type", test.contentType);
-    if (test.resType)
+    if (test.resType) {
       xhr.responseType = test.resType;
+      xhr.onloadend = continueTest;
+    }
     xhr.send(test.body);
+    if (test.resType)
+      yield;
 
     if (test.resContentType) {
       is(xhr.getResponseHeader("Result-Content-Type"), test.resContentType,
          "Wrong Content-Type sent");
     }
     else {
       is(xhr.getResponseHeader("Result-Content-Type"), null);
     }
@@ -229,12 +239,16 @@ function cleanUpData() {
 function is_identical_arraybuffer(ab1, ab2) {
   is(ab1.byteLength, ab2.byteLength, "arraybuffer byteLengths not equal");
   u8v1 = new Uint8Array(ab1);
   u8v2 = new Uint8Array(ab2);
   is(String.fromCharCode.apply(String, u8v1),
      String.fromCharCode.apply(String, u8v2), "arraybuffer values not equal");
 }
 
+SimpleTest.finish();
+yield;
+} /* runTests */
+
 </script>
 </pre>
 </body>
 </html>
--- a/content/base/test/test_bug338583.html
+++ b/content/base/test/test_bug338583.html
@@ -419,114 +419,122 @@ https://bugzilla.mozilla.org/show_bug.cg
   }
 
   function doTest5_c(test_id)
   {
     // credentials using the auth cache and cookies
     var xhr = SpecialPowers.createSystemXHR();
     xhr.withCredentials = true;
     // also, test mixed mode UI
-    xhr.open("GET", "https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_xhr", false, "user 1", "password 1");
+    xhr.open("GET", "https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_xhr", true, "user 1", "password 1");
     xhr.send();
-    ok(xhr.status == 200, "Failed to set credentials in test 5.c");
+    xhr.onloadend = function() {
+      ok(xhr.status == 200, "Failed to set credentials in test 5.c");
 
-    gEventSourceObj5_c = new EventSource("https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_evtsrc",
-                                         { withCredentials: true } );
-    ok(gEventSourceObj5_c.withCredentials, "Wrong withCredentials in test 5.c");
+      gEventSourceObj5_c = new EventSource("https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_evtsrc",
+                                           { withCredentials: true } );
+      ok(gEventSourceObj5_c.withCredentials, "Wrong withCredentials in test 5.c");
 
-    gEventSourceObj5_c.onmessage = function(e) {
-      ok(e.origin == "https://example.com", "Wrong Origin in test 5.c");
-      fn_onmessage(e);
+      gEventSourceObj5_c.onmessage = function(e) {
+        ok(e.origin == "https://example.com", "Wrong Origin in test 5.c");
+        fn_onmessage(e);
+      };
+      gEventSourceObj5_c.hits = [];
+      gEventSourceObj5_c.hits['fn_onmessage'] = 0;
+
+      setTimeout(function() {
+        ok(gEventSourceObj5_c.hits['fn_onmessage'] > 0, "Test 5.c failed");
+        gEventSourceObj5_c.close();
+        doTest5_d(test_id);
+      }, parseInt(3000*stress_factor));
     };
-    gEventSourceObj5_c.hits = [];
-    gEventSourceObj5_c.hits['fn_onmessage'] = 0;
-
-    setTimeout(function() {
-      ok(gEventSourceObj5_c.hits['fn_onmessage'] > 0, "Test 5.c failed");
-      gEventSourceObj5_c.close();
-      doTest5_d(test_id);
-    }, parseInt(3000*stress_factor));
   }
 
   function doTest5_d(test_id)
   {
     var xhr = SpecialPowers.createSystemXHR();
     xhr.withCredentials = true;
-    xhr.open("GET", "https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_xhr", false, "user 2", "password 2");
+    xhr.open("GET", "https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_xhr", true, "user 2", "password 2");
     xhr.send();
-    ok(xhr.status == 200, "Failed to set credentials in test 5.d");
-
-    gEventSourceObj5_d = new EventSource("https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_evtsrc");
-    ok(!gEventSourceObj5_d.withCredentials, "Wrong withCredentials in test 5.d");
-
-    gEventSourceObj5_d.onmessage = function(e) {
-      ok(e.origin == "https://example.com", "Wrong Origin in test 5.d");
-      fn_onmessage(e);
+    xhr.onloadend = function() {
+      ok(xhr.status == 200, "Failed to set credentials in test 5.d");
+  
+      gEventSourceObj5_d = new EventSource("https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_evtsrc");
+      ok(!gEventSourceObj5_d.withCredentials, "Wrong withCredentials in test 5.d");
+  
+      gEventSourceObj5_d.onmessage = function(e) {
+        ok(e.origin == "https://example.com", "Wrong Origin in test 5.d");
+        fn_onmessage(e);
+      };
+      gEventSourceObj5_d.hits = [];
+      gEventSourceObj5_d.hits['fn_onmessage'] = 0;
+  
+      setTimeout(function() {
+        ok(gEventSourceObj5_d.hits['fn_onmessage'] == 0, "Test 5.d failed");
+        gEventSourceObj5_d.close();
+        setTestHasFinished(test_id);
+      }, parseInt(3000*stress_factor));
     };
-    gEventSourceObj5_d.hits = [];
-    gEventSourceObj5_d.hits['fn_onmessage'] = 0;
-
-    setTimeout(function() {
-      ok(gEventSourceObj5_d.hits['fn_onmessage'] == 0, "Test 5.d failed");
-      gEventSourceObj5_d.close();
-      setTestHasFinished(test_id);
-    }, parseInt(3000*stress_factor));
   }
 
   function doTest5_e(test_id)
   {
     // credentials using the auth cache and cookies
     var xhr = SpecialPowers.createSystemXHR();
     xhr.withCredentials = true;
-    xhr.open("GET", "http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_xhr", false, "user 1", "password 1");
+    xhr.open("GET", "http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_xhr", true, "user 1", "password 1");
     xhr.send();
-    ok(xhr.status == 200, "Failed to set credentials in test 5.e");
+    xhr.onloadend = function() {
+      ok(xhr.status == 200, "Failed to set credentials in test 5.e");
 
-    gEventSourceObj5_e = new EventSource("http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_evtsrc",
-                                         { get withCredentials() { return true; } } );
-    ok(gEventSourceObj5_e.withCredentials, "Wrong withCredentials in test 5.e");
+      gEventSourceObj5_e = new EventSource("http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_evtsrc",
+                                           { get withCredentials() { return true; } } );
+      ok(gEventSourceObj5_e.withCredentials, "Wrong withCredentials in test 5.e");
 
-    gEventSourceObj5_e.onmessage = function(e) {
-      ok(e.origin == "http://example.org", "Wrong Origin in test 5.e");
-      fn_onmessage(e);
+      gEventSourceObj5_e.onmessage = function(e) {
+        ok(e.origin == "http://example.org", "Wrong Origin in test 5.e");
+        fn_onmessage(e);
+      };
+      gEventSourceObj5_e.hits = [];
+      gEventSourceObj5_e.hits['fn_onmessage'] = 0;
+
+      setTimeout(function() {
+        ok(gEventSourceObj5_e.hits['fn_onmessage'] > 0, "Test 5.e failed");
+        gEventSourceObj5_e.close();
+        doTest5_f(test_id);
+      }, parseInt(5000*stress_factor));
     };
-    gEventSourceObj5_e.hits = [];
-    gEventSourceObj5_e.hits['fn_onmessage'] = 0;
-
-    setTimeout(function() {
-      ok(gEventSourceObj5_e.hits['fn_onmessage'] > 0, "Test 5.e failed");
-      gEventSourceObj5_e.close();
-      doTest5_f(test_id);
-    }, parseInt(5000*stress_factor));
   }
 
   function doTest5_f(test_id)
   {
     var xhr = SpecialPowers.createSystemXHR();
     xhr.withCredentials = true;
-    xhr.open("GET", "http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_xhr", false, "user 2", "password 2");
+    xhr.open("GET", "http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_xhr", true, "user 2", "password 2");
     xhr.send();
-    ok(xhr.status == 200, "Failed to set credentials in test 5.f");
+    xhr.onloadend = function() {
+      ok(xhr.status == 200, "Failed to set credentials in test 5.f");
 
-    gEventSourceObj5_f = new EventSource("http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_evtsrc",
-                                         { });
-    ok(!gEventSourceObj5_f.withCredentials, "Wrong withCredentials in test 5.f");
+      gEventSourceObj5_f = new EventSource("http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_evtsrc",
+                                           { });
+      ok(!gEventSourceObj5_f.withCredentials, "Wrong withCredentials in test 5.f");
 
-    gEventSourceObj5_f.onmessage = function(e) {
-      ok(e.origin == "http://example.org", "Wrong Origin in test 5.f");
-      fn_onmessage(e);
+      gEventSourceObj5_f.onmessage = function(e) {
+        ok(e.origin == "http://example.org", "Wrong Origin in test 5.f");
+        fn_onmessage(e);
+      };
+      gEventSourceObj5_f.hits = [];
+      gEventSourceObj5_f.hits['fn_onmessage'] = 0;
+
+      setTimeout(function() {
+        ok(gEventSourceObj5_f.hits['fn_onmessage'] == 0, "Test 5.f failed");
+        gEventSourceObj5_f.close();
+        setTestHasFinished(test_id);
+      }, parseInt(3000*stress_factor));
     };
-    gEventSourceObj5_f.hits = [];
-    gEventSourceObj5_f.hits['fn_onmessage'] = 0;
-
-    setTimeout(function() {
-      ok(gEventSourceObj5_f.hits['fn_onmessage'] == 0, "Test 5.f failed");
-      gEventSourceObj5_f.close();
-      setTestHasFinished(test_id);
-    }, parseInt(3000*stress_factor));
   }
 
   function doTest6(test_id)
   {
     gEventSourceObj6 = new EventSource("somedatas.resource");
     var fn_somedata = function(e) {
       if (fn_somedata.expected == 0) {
         ok(e.data == "123456789\n123456789123456789\n123456789123456789123456789123456789\n 123456789123456789123456789123456789123456789123456789123456789123456789\nçãá\"\'@`~Ý Ḿyyyy",
--- a/content/base/test/test_bug466080.html
+++ b/content/base/test/test_bug466080.html
@@ -81,38 +81,47 @@ var alltests = [
 ];
 
 function onWindowLoad() {
     // First, check that resource was loaded into the iframe
     // This check in fact depends on bug #444165... :)
     ok(document.iframeWasLoaded, "Loading resource via src-attribute");
 
 
-    for each (test in alltests) {
+    function runTest(test) {
 
         var xhr =  new XMLHttpRequest();
-        
+
         var method = "GET";
         if (test.method != null) { method = test.method; }
-        xhr.open(method, test.url, false);
-        
+        xhr.open(method, test.url);
+
         xhr.withCredentials = test.withCredentials;
 
         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
         xhr.setRequestHeader("Connection", "Keep-Alive", false);
         netscape.security.PrivilegeManager.disablePrivilege("UniversalXPConnect");
 
         try {
             xhr.send();
         } catch(e) {
         }
-        var success = eval(xhr.status + test.status_check);
-        ok(success, test.error);
+
+        xhr.onloadend = function() {
+            var success = eval(xhr.status + test.status_check);
+            ok(success, test.error);
+
+            if (alltests.length == 0) {
+                SimpleTest.finish();
+            } else {
+                runTest(alltests.shift());
+            }
+        };
     }
-    
-    SimpleTest.finish();
+
+    runTest(alltests.shift());
 }
 
 SimpleTest.waitForExplicitFinish();
 
 </script>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug707142.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=707142
+-->
+<head>
+  <title>Test for Bug 707142</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.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=707142">Mozilla Bug 707142</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 707142 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var xhr = new XMLHttpRequest();
+xhr.onload = function() {
+  is(xhr.response["foo"], "bar", "Should have gotten bar on baseline");
+  
+  xhr.onload = function() {
+    is(xhr.response["foo"], "bar", "Should have gotten bar with BOM");
+
+    xhr.onload = function() {
+      is(xhr.response, null, "Should have gotten null response with UTF-16 JSON");
+
+      SimpleTest.finish();
+    };
+    xhr.open("GET", "file_bug707142_utf-16.json");
+    xhr.responseType = "json";
+    xhr.send();
+  };
+  xhr.open("GET", "file_bug707142_bom.json");
+  xhr.responseType = "json";
+  xhr.send();
+};
+xhr.open("GET", "file_bug707142_baseline.json");
+xhr.responseType = "json";
+xhr.send();
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/base/test/test_xhr_progressevents.html
+++ b/content/base/test/test_xhr_progressevents.html
@@ -110,17 +110,17 @@ function bufferToString(buffer) {
 function runTests() {
   var xhr = new XMLHttpRequest();
   xhr.onprogress = xhr.onload = xhr.onerror = xhr.onreadystatechange = xhr.onloadend = getEvent;
 
   var responseTypes = [{ type: "text", text: true },
                        { type: "arraybuffer", text: false, nodata: true },
                        { type: "blob", text: false, nodata: true },
                        { type: "document", text: true, nodata: true },
-                       { type: "moz-json", text: true, nodata: true },
+                       { type: "json", text: true, nodata: true },
                        { type: "", text: true },
                        { type: "moz-chunked-text", text: true, chunked: true },
                        { type: "moz-chunked-arraybuffer", text: false, chunked: true },
                       ];
   var responseType;
   var fileExpectedResult = "";
   for (var i = 0; i < 65536; i++) {
     fileExpectedResult += String.fromCharCode(i & 255);
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/test_xhr_standalone.js
@@ -0,0 +1,21 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Test setting .responseType and .withCredentials is allowed
+// in non-window non-Worker context
+
+function run_test()
+{
+    var xhr = Components.classes['@mozilla.org/xmlextras/xmlhttprequest;1'].
+          createInstance(Components.interfaces.nsIXMLHttpRequest);
+    xhr.open('GET', 'data:,', false);
+    var exceptionThrown = false;
+    try {
+        xhr.responseType = '';
+        xhr.withCredentials = false;
+    } catch (e) {
+        exceptionThrown = true;
+    }
+    do_check_eq(false, exceptionThrown);
+}
--- a/content/base/test/unit/xpcshell.ini
+++ b/content/base/test/unit/xpcshell.ini
@@ -2,9 +2,10 @@
 head = head_utilities.js
 tail = 
 
 [test_bug553888.js]
 [test_bug558431.js]
 [test_csputils.js]
 [test_error_codes.js]
 [test_thirdpartyutil.js]
+[test_xhr_standalone.js]
 [test_xmlserializer.js]
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -2766,17 +2766,17 @@ struct NS_STACK_CLASS nsCanvasBidiProces
         }
 
         return NSToCoordRound(textRunMetrics.mAdvanceWidth);
     }
 
     virtual void DrawText(nscoord xOffset, nscoord width)
     {
         gfxPoint point = mPt;
-        point.x += xOffset * mAppUnitsPerDevPixel;
+        point.x += xOffset;
 
         // offset is given in terms of left side of string
         if (mTextRun->IsRightToLeft()) {
             // Bug 581092 - don't use rounded pixel width to advance to
             // right-hand end of run, because this will cause different
             // glyph positioning for LTR vs RTL drawing of the same
             // glyph string on OS X and DWrite where textrun widths may
             // involve fractional pixels.
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -2970,17 +2970,17 @@ struct NS_STACK_CLASS nsCanvasBidiProces
     }
 
     return NSToCoordRound(textRunMetrics.mAdvanceWidth);
   }
 
   virtual void DrawText(nscoord xOffset, nscoord width)
   {
     gfxPoint point = mPt;
-    point.x += xOffset * mAppUnitsPerDevPixel;
+    point.x += xOffset;
 
     // offset is given in terms of left side of string
     if (mTextRun->IsRightToLeft()) {
       // Bug 581092 - don't use rounded pixel width to advance to
       // right-hand end of run, because this will cause different
       // glyph positioning for LTR vs RTL drawing of the same
       // glyph string on OS X and DWrite where textrun widths may
       // involve fractional pixels.
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -130,16 +130,17 @@
 #include "nsIController.h"
 #include "nsICommandParams.h"
 #include "mozilla/Services.h"
 #include "mozAutoDocUpdate.h"
 #include "nsHTMLLabelElement.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/LookAndFeel.h"
+#include "sampler.h"
 
 #ifdef XP_MACOSX
 #import <ApplicationServices/ApplicationServices.h>
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
@@ -3803,16 +3804,17 @@ public:
   nsCOMPtr<nsIContent> mTarget;
 };
 
 nsIFrame*
 nsEventStateManager::DispatchMouseEvent(nsGUIEvent* aEvent, PRUint32 aMessage,
                                         nsIContent* aTargetContent,
                                         nsIContent* aRelatedContent)
 {
+  SAMPLE_LABEL("Input", "DispatchMouseEvent");
   nsEventStatus status = nsEventStatus_eIgnore;
   nsMouseEvent event(NS_IS_TRUSTED_EVENT(aEvent), aMessage, aEvent->widget,
                      nsMouseEvent::eReal);
   event.refPoint = aEvent->refPoint;
   event.isShift = ((nsMouseEvent*)aEvent)->isShift;
   event.isControl = ((nsMouseEvent*)aEvent)->isControl;
   event.isAlt = ((nsMouseEvent*)aEvent)->isAlt;
   event.isMeta = ((nsMouseEvent*)aEvent)->isMeta;
--- a/content/html/content/src/nsDOMStringMap.cpp
+++ b/content/html/content/src/nsDOMStringMap.cpp
@@ -45,19 +45,22 @@
 
 DOMCI_DATA(DOMStringMap, nsDOMStringMap)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMStringMap)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMStringMap)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMStringMap)
-  // Call back to element to null out weak reference to this object.
-  tmp->mElement->ClearDataset();
-  tmp->mElement = nsnull;
+  // Check that mElement exists in case the unlink code is run more than once.
+  if (tmp->mElement) {
+    // Call back to element to null out weak reference to this object.
+    tmp->mElement->ClearDataset();
+    tmp->mElement = nsnull;
+  }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMStringMap)
   NS_INTERFACE_MAP_ENTRY(nsIDOMDOMStringMap)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DOMStringMap)
 NS_INTERFACE_MAP_END
 
--- a/content/media/webm/nsWebMReader.h
+++ b/content/media/webm/nsWebMReader.h
@@ -34,23 +34,28 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #if !defined(nsWebMReader_h_)
 #define nsWebMReader_h_
 
+#include "mozilla/StdInt.h"
+
 #include "nsDeque.h"
 #include "nsBuiltinDecoderReader.h"
 #include "nsWebMBufferedParser.h"
 #include "nsAutoRef.h"
 #include "nestegg/nestegg.h"
+
+#define VPX_DONT_DEFINE_STDINT_TYPES
 #include "vpx/vpx_decoder.h"
 #include "vpx/vp8dx.h"
+
 #ifdef MOZ_TREMOR
 #include "tremor/ivorbiscodec.h"
 #else
 #include "vorbis/codec.h"
 #endif
 
 class nsMediaDecoder;
 
--- a/content/smil/nsSMILTimeValueSpec.cpp
+++ b/content/smil/nsSMILTimeValueSpec.cpp
@@ -317,32 +317,55 @@ nsSMILTimeValueSpec::GetTimedElement(Ele
 
   nsCOMPtr<nsISMILAnimationElement> animElement = do_QueryInterface(aElement);
   if (!animElement)
     return nsnull;
 
   return &animElement->TimedElement();
 }
 
+// Indicates whether we're allowed to register an event-listener
+// when scripting is disabled.
+bool
+nsSMILTimeValueSpec::IsWhitelistedEvent()
+{
+  // The category of (SMIL-specific) "repeat(n)" events are allowed.
+  if (mParams.mType == nsSMILTimeValueSpecParams::REPEAT) {
+    return true;
+  }
+
+  // A specific list of other SMIL-related events are allowed, too.
+  if (mParams.mType == nsSMILTimeValueSpecParams::EVENT &&
+      (mParams.mEventSymbol == nsGkAtoms::repeat ||
+       mParams.mEventSymbol == nsGkAtoms::repeatEvent ||
+       mParams.mEventSymbol == nsGkAtoms::beginEvent ||
+       mParams.mEventSymbol == nsGkAtoms::endEvent)) {
+    return true;
+  }
+
+  return false;
+}
+
 void
 nsSMILTimeValueSpec::RegisterEventListener(Element* aTarget)
 {
   NS_ABORT_IF_FALSE(IsEventBased(),
     "Attempting to register event-listener for unexpected nsSMILTimeValueSpec"
     " type");
   NS_ABORT_IF_FALSE(mParams.mEventSymbol,
     "Attempting to register event-listener but there is no event name");
 
   if (!aTarget)
     return;
 
-  // Don't listen for accessKey events if script is disabled. (see bug 704482)
-  if (mParams.mType == nsSMILTimeValueSpecParams::ACCESSKEY &&
-      !aTarget->GetOwnerDocument()->IsScriptEnabled())
+  // When script is disabled, only allow registration for whitelisted events.
+  if (!aTarget->GetOwnerDocument()->IsScriptEnabled() &&
+      !IsWhitelistedEvent()) {
     return;
+  }
 
   if (!mEventListener) {
     mEventListener = new EventListener(this);
   }
 
   nsEventListenerManager* elm = GetEventListenerManager(aTarget);
   if (!elm)
     return;
--- a/content/smil/nsSMILTimeValueSpec.h
+++ b/content/smil/nsSMILTimeValueSpec.h
@@ -88,16 +88,17 @@ public:
   // Cycle-collection support
   void Traverse(nsCycleCollectionTraversalCallback* aCallback);
   void Unlink();
 
 protected:
   void UpdateReferencedElement(Element* aFrom, Element* aTo);
   void UnregisterFromReferencedElement(Element* aElement);
   nsSMILTimedElement* GetTimedElement(Element* aElement);
+  bool IsWhitelistedEvent();
   void RegisterEventListener(Element* aElement);
   void UnregisterEventListener(Element* aElement);
   nsEventListenerManager* GetEventListenerManager(Element* aElement);
   void HandleEvent(nsIDOMEvent* aEvent);
   bool CheckEventDetail(nsIDOMEvent* aEvent);
   bool CheckRepeatEventDetail(nsIDOMEvent* aEvent);
   bool CheckAccessKeyEventDetail(nsIDOMEvent* aEvent);
   nsSMILTimeValue ConvertBetweenTimeContainers(const nsSMILTimeValue& aSrcTime,
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -78,16 +78,17 @@
 #include <gdk/gdk.h>
 #include <gdk/gdkx.h>
 #endif
 
 #include "Layers.h"
 #include "nsIIOService.h"
 
 #include "mozilla/dom/Element.h"
+#include "sampler.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 using namespace mozilla::widget;
 
 static bool IsUniversalXPConnectCapable()
 {
   bool hasCap = false;
@@ -724,16 +725,17 @@ nsDOMWindowUtils::Focus(nsIDOMElement* a
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GarbageCollect(nsICycleCollectorListener *aListener)
 {
+  SAMPLE_LABEL("GC", "GarbageCollect");
   // Always permit this in debug builds.
 #ifndef DEBUG
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 #endif
 
   nsJSContext::GarbageCollectNow();
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -103,16 +103,18 @@
 #define FORCE_PR_LOG 1
 #endif
 #include "prlog.h"
 #include "prthread.h"
 
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/Preferences.h"
 
+#include "sampler.h"
+
 using namespace mozilla;
 
 const size_t gStackSize = 8192;
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gJSDiagnostics;
 #endif
 
@@ -1180,16 +1182,17 @@ nsJSContext::EvaluateStringWithValue(con
                                      PRUint32 aLineNo,
                                      PRUint32 aVersion,
                                      JS::Value* aRetValue,
                                      bool* aIsUndefined)
 {
   NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (url: %s, line: %d)", MOZ_FUNCTION_NAME,
                            __LINE__, aURL, aLineNo);
 
+  SAMPLE_LABEL("JS", "EvaluateStringWithValue");
   NS_ABORT_IF_FALSE(aScopeObject,
     "Shouldn't call EvaluateStringWithValue with null scope object.");
 
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
 
   if (!mScriptsEnabled) {
     if (aIsUndefined) {
       *aIsUndefined = true;
@@ -1382,16 +1385,17 @@ nsJSContext::EvaluateString(const nsAStr
                             PRUint32 aLineNo,
                             PRUint32 aVersion,
                             nsAString *aRetValue,
                             bool* aIsUndefined)
 {
   NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (url: %s, line: %d)", MOZ_FUNCTION_NAME,
                            __LINE__, aURL, aLineNo);
 
+  SAMPLE_LABEL("JS", "EvaluateString");
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
 
   if (!mScriptsEnabled) {
     if (aIsUndefined) {
       *aIsUndefined = true;
     }
 
     if (aRetValue) {
@@ -1852,16 +1856,17 @@ nsJSContext::CallEventHandler(nsISupport
     if (js::IsFunctionProxy(obj))
       obj = js::UnwrapObject(obj);
     JSString *id = JS_GetFunctionId(static_cast<JSFunction *>(JS_GetPrivate(mContext, obj)));
     JSAutoByteString bytes;
     const char *name = !id ? "anonymous" : bytes.encode(mContext, id) ? bytes.ptr() : "<error>";
     NS_TIME_FUNCTION_FMT(1.0, "%s (line %d) (function: %s)", MOZ_FUNCTION_NAME, __LINE__, name);
   }
 #endif
+  SAMPLE_LABEL("JS", "CallEventHandler");
 
   JSAutoRequest ar(mContext);
   JSObject* target = nsnull;
   nsresult rv = JSObjectFromInterface(aTarget, aScope, &target);
   NS_ENSURE_SUCCESS(rv, rv);
 
   js::AutoObjectRooter targetVal(mContext, target);
   jsval rval = JSVAL_VOID;
@@ -3161,16 +3166,17 @@ nsJSContext::ScriptExecuted()
   return NS_OK;
 }
 
 //static
 void
 nsJSContext::GarbageCollectNow(bool shrinkingGC)
 {
   NS_TIME_FUNCTION_MIN(1.0);
+  SAMPLE_LABEL("GC", "GarbageCollectNow");
 
   KillGCTimer();
 
   // Reset sPendingLoadCount in case the timer that fired was a
   // timer we scheduled due to a normal GC timer firing while
   // documents were loading. If this happens we're waiting for a
   // document that is taking a long time to load, and we effectively
   // ignore the fact that the currently loading documents are still
@@ -3186,16 +3192,17 @@ nsJSContext::GarbageCollectNow(bool shri
 //Static
 void
 nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener)
 {
   if (!NS_IsMainThread()) {
     return;
   }
 
+  SAMPLE_LABEL("GC", "CycleCollectNow");
   NS_TIME_FUNCTION_MIN(1.0);
 
   KillCCTimer();
 
   PRTime start = PR_Now();
 
   PRUint32 suspected = nsCycleCollector_suspectedCount();
   PRUint32 collected = nsCycleCollector_collect(aListener);
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -125,8 +125,11 @@ FullScreenDeniedMovedDocument=Request fo
 FullScreenDeniedLostWindow=Request for full-screen was denied because we no longer have a window.
 FullScreenDeniedSubDocFullScreen=Request for full-screen was denied because a subdocument of the document requesting full-screen is already full-screen.
 FullScreenDeniedNotDescendant=Request for full-screen was denied because requesting element is not a descendant of the current full-screen element.
 RemovedFullScreenElement=Exited full-screen because full-screen element was removed from document.
 AddedWindowedPluginWhileFullScreen=Exited full-screen because windowed plugin was added to document.
 HTMLMultipartXHRWarning=HTML parsing in XMLHttpRequest is not supported for multipart responses.
 HTMLSyncXHRWarning=HTML parsing in XMLHttpRequest is not supported in the synchronous mode.
 InvalidRedirectChannelWarning=Unable to redirect to %S because the channel doesn't implement nsIWritablePropertyBag2.
+ResponseTypeSyncXHRWarning=Use of XMLHttpRequest's responseType attribute is no longer supported in the synchronous mode in window context.
+WithCredentialsSyncXHRWarning=Use of XMLHttpRequest's withCredentials attribute is no longer supported in the synchronous mode in window context.
+JSONCharsetWarning=An attempt was made to declare a non-UTF-8 encoding for JSON retrieved using XMLHttpRequest. Only UTF-8 is supported for decoding JSON.
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -228,17 +228,19 @@ PRLogModuleInfo* nsPluginLogging::gNPPLo
 PRLogModuleInfo* nsPluginLogging::gPluginLog = nsnull;
 #endif
 
 #define BRAND_PROPERTIES_URL "chrome://branding/locale/brand.properties"
 #define PLUGIN_PROPERTIES_URL "chrome://global/locale/downloadProgress.properties"
 
 // #defines for plugin cache and prefs
 #define NS_PREF_MAX_NUM_CACHED_INSTANCES "browser.plugins.max_num_cached_plugins"
-#define DEFAULT_NUMBER_OF_STOPPED_INSTANCES 10
+// Raise this from '10' to '50' to work around a bug in Apple's current Java
+// plugins on OS X Lion and SnowLeopard.  See bug 705931.
+#define DEFAULT_NUMBER_OF_STOPPED_INSTANCES 50
 
 #ifdef CALL_SAFETY_ON
 // By default we run OOPP, so we don't want to cover up crashes.
 bool gSkipPluginSafeCalls = true;
 #endif
 
 nsIFile *nsPluginHost::sPluginTempDir;
 nsPluginHost *nsPluginHost::sInst;
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -33,32 +33,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef MOZILLA_GFX_TYPES_H_
 #define MOZILLA_GFX_TYPES_H_
 
-#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || defined (_sgi) || defined (__sun) || defined (sun) || defined (__digital__)
-#  include <inttypes.h>
-#elif defined (_MSC_VER)
-typedef unsigned __int8 uint8_t;
-typedef __int16 int16_t;
-typedef unsigned __int16 uint16_t;
-typedef __int32 int32_t;
-typedef unsigned __int32 uint32_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-
-#elif defined (_AIX)
-#  include <sys/inttypes.h>
-#else
-#  include <stdint.h>
-#endif
+#include "mozilla/StdInt.h"
 
 #include <stddef.h>
 
 namespace mozilla {
 namespace gfx {
 
 typedef float Float;
 
--- a/gfx/cairo/libpixman/src/Makefile.in
+++ b/gfx/cairo/libpixman/src/Makefile.in
@@ -180,18 +180,21 @@ CFLAGS += -DPACKAGE="mozpixman" -D_USE_M
 
 # Disable spammy "missing initializer" GCC warning
 ifdef GNU_CC
 CFLAGS += -Wno-missing-field-initializers
 endif # GNU_CC
 
 # special rule for pixman-mmx to get the right cflags
 pixman-mmx.$(OBJ_SUFFIX): pixman-mmx.c $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(MMX_CFLAGS) $(_VPATH_SRCS)
 
 pixman-sse2.$(OBJ_SUFFIX): pixman-sse2.c $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(SSE2_CFLAGS) $(_VPATH_SRCS)
 
 pixman-arm-neon.$(OBJ_SUFFIX): pixman-arm-neon.c $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(ARM_NEON_CFLAGS) $(_VPATH_SRCS)
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -60,16 +60,18 @@
 #include "ThebesLayerBuffer.h"
 #include "nsIWidget.h"
 #include "ReadbackProcessor.h"
 #ifdef MOZ_X11
 #include "gfxXlibSurface.h"
 #endif
 
 #include "GLContext.h"
+
+#define PIXMAN_DONT_DEFINE_STDINT
 #include "pixman.h"
 
 namespace mozilla {
 namespace layers {
 
 class BasicContainerLayer;
 class ShadowableLayer;
 
--- a/gfx/qcms/Makefile.in
+++ b/gfx/qcms/Makefile.in
@@ -98,14 +98,16 @@ CFLAGS          += -DMOZ_QCMS
 
 # Disable spammy "missing initializer" GCC warning
 ifdef GNU_CC
 CFLAGS += -Wno-missing-field-initializers
 endif # GNU_CC
 
 # special rules for transform-sse*.c to get the right cflags. (taken from pixman/src/Makefile.in)
 transform-sse1.$(OBJ_SUFFIX): transform-sse1.c $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(SSE1_FLAGS) $(_VPATH_SRCS)
 
 transform-sse2.$(OBJ_SUFFIX): transform-sse2.c $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(SSE2_FLAGS) $(_VPATH_SRCS)
--- a/gfx/thebes/woff.h
+++ b/gfx/thebes/woff.h
@@ -35,28 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef WOFF_H_
 #define WOFF_H_
 
 /* API for the WOFF encoder and decoder */
 
-#ifdef _MSC_VER /* MS VC lacks inttypes.h
-                   but we can make do with a few definitons here */
-typedef signed char    int8_t;
-typedef short          int16_t;
-typedef int            int32_t;
-typedef unsigned char  uint8_t;
-typedef unsigned short uint16_t;
-typedef unsigned int   uint32_t;
-typedef unsigned __int64  uint64_t;
-#else
-#include <inttypes.h>
-#endif
+#include "mozilla/StdInt.h"
 
 #include <stdio.h> /* only for FILE, needed for woffPrintStatus */
 
 /* error codes returned in the status parameter of WOFF functions */
 enum {
   /* Success */
   eWOFF_ok = 0,
 
--- a/image/test/mochitest/animationPolling.js
+++ b/image/test/mochitest/animationPolling.js
@@ -1,12 +1,14 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 var currentTest;
 var gIsRefImageLoaded = false;
+const gShouldOutputDebugInfo = false;
 
-function pollForSuccess ()
+function pollForSuccess()
 {
   if (!currentTest.isTestFinished) {
     if (!currentTest.reusingReferenceImage || (currentTest.reusingReferenceImage
         && gRefImageLoaded)) {
       currentTest.checkImage();
     }
 
     setTimeout(pollForSuccess, currentTest.pollFreq);
@@ -18,19 +20,18 @@ function referencePoller()
   currentTest.takeReferenceSnapshot();
 }
 
 function reuseImageCallback()
 {
   gIsRefImageLoaded = true;
 }
 
-function failTest ()
-{    imageLoadCallback();
-
+function failTest()
+{
   if (currentTest.isTestFinished || currentTest.closeFunc) {
     return;
   }
 
   ok(false, "timing out after " + currentTest.timeout + "ms.  "
      + "Animated image still doesn't look correct, after poll #"
      + currentTest.pollCounter);
   currentTest.wereFailures = true;
@@ -115,16 +116,19 @@ AnimationTest.prototype.preloadImage = f
     this.myImage.src = this.srcAttr;
   } else {
     this.continueTest();
   }
 };
 
 AnimationTest.prototype.outputDebugInfo = function(message, id, dataUri)
 {
+  if (!gShouldOutputDebugInfo) {
+    return;
+  }
   var debugElement = document.getElementById(this.debugElementId);
   var newDataUriElement = document.createElement("a");
   newDataUriElement.setAttribute("id", id);
   newDataUriElement.setAttribute("href", dataUri);
   newDataUriElement.appendChild(document.createTextNode(message));
   debugElement.appendChild(newDataUriElement);
   var brElement = document.createElement("br");
   debugElement.appendChild(brElement);
@@ -198,26 +202,27 @@ AnimationTest.prototype.continueTest = f
   setTimeout(failTest, this.timeout);
 
   if (!this.reusingImageAsReference) {
     this.disableDisplay(document.getElementById(this.imageElementId));
   }
 
   this.takeReferenceSnapshot();
   this.setupPolledImage();
-  setTimeout(pollForSuccess, 10);
+  SimpleTest.executeSoon(pollForSuccess);
 };
 
 AnimationTest.prototype.setupPolledImage = function ()
 {
   // Make sure the image is visible
   if (!this.reusingImageAsReference) {
     this.enableDisplay(document.getElementById(this.imageElementId));
     var currentSnapshot = snapshotWindow(window, false);
-    var result = compareSnapshots(currentSnapshot, this.referenceSnapshot, true);
+    var result = compareSnapshots(currentSnapshot,
+                                  this.referenceSnapshot, true);
 
     this.currentSnapshotDataURI = currentSnapshot.toDataURL();
 
     if (result[0]) {
       // SUCCESS!
       ok(true, "Animated image looks correct, at poll #"
          + this.pollCounter);
 
@@ -271,35 +276,35 @@ AnimationTest.prototype.takeReferenceSna
   }
 
   // Used later to verify that the reference div disappeared
   if (!this.blankSnapshot) {
     this.takeBlankSnapshot();
   }
 
   if (this.reusingImageAsReference) {
-    // Show reference div, & take a snapshot
-    var referenceDiv = document.getElementById(this.imageElementId);
-    this.enableDisplay(referenceDiv);
+    // Show reference elem (which is actually our image), & take a snapshot
+    var referenceElem = document.getElementById(this.imageElementId);
+    this.enableDisplay(referenceElem);
 
     this.referenceSnapshot = snapshotWindow(window, false);
 
-    var snapResult = compareSnapshots(this.cleanSnapshot, this.referenceSnapshot,
-                                      false);
+    var snapResult = compareSnapshots(this.cleanSnapshot,
+                                      this.referenceSnapshot, false);
     if (!snapResult[0]) {
       if (this.blankWaitTime > 2000) {
         // if it took longer than two seconds to load the image, we probably
         // have a problem.
         this.wereFailures = true;
         ok(snapResult[0],
            "Reference snapshot shouldn't match clean (non-image) snapshot");
       } else {
-        this.blankWaitTime += 20;
+        this.blankWaitTime += currentTest.pollFreq;
         // let's wait a bit and see if it clears up
-        setTimeout(referencePoller, 20);
+        setTimeout(referencePoller, currentTest.pollFreq);
         return;
       }
     }
 
     ok(snapResult[0],
        "Reference snapshot shouldn't match clean (non-image) snapshot");
 
     var dataString = "Reference Snapshot #" + this.numRefsTaken;
@@ -309,17 +314,18 @@ AnimationTest.prototype.takeReferenceSna
     // Make sure the animation section is hidden
     this.disableDisplay(document.getElementById(this.imageElementId));
 
     // Show reference div, & take a snapshot
     var referenceDiv = document.getElementById(this.referenceElementId);
     this.enableDisplay(referenceDiv);
 
     this.referenceSnapshot = snapshotWindow(window, false);
-    var snapResult = compareSnapshots(this.cleanSnapshot, this.referenceSnapshot, false);
+    var snapResult = compareSnapshots(this.cleanSnapshot,
+                                      this.referenceSnapshot, false);
     if (!snapResult[0]) {
       if (this.blankWaitTime > 2000) {
         // if it took longer than two seconds to load the image, we probably
         // have a problem.
         this.wereFailures = true;
         ok(snapResult[0],
            "Reference snapshot shouldn't match clean (non-image) snapshot");
       } else {
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -279,18 +279,20 @@ VPATH		+= \
 		$(srcdir)/../../mfbt \
 		$(NULL)
 
 EXPORTS_NAMESPACES += mozilla
 
 EXPORTS_mozilla = \
 		Attributes.h	\
 		GuardObjects.h \
+		MSStdInt.h \
 		RangedPtr.h \
 		RefPtr.h \
+		StdInt.h \
 		Types.h	\
 		Util.h \
 		$(NULL)
 
 ifdef ENABLE_METHODJIT
 
 ###############################################
 # BEGIN include sources for the method JIT
@@ -796,32 +798,35 @@ else
 EXTRA_LIBS	+= -lposix4 -ldl -lnsl -lsocket
 endif
 endif
 
 ifdef SOLARIS_SUNPRO_CXX
 ifeq ($(TARGET_CPU),sparc)
 # Sun Studio SPARC doesn't work well with gcc inline asm, use lock_SunOS_sparc*.il
 jslock.o: jslock.cpp Makefile.in lock_sparcv8plus.il lock_sparcv9.il
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 ifeq (sparcv9,$(findstring sparcv9,$(OS_TEST)))
 	$(CXX) -o $@ -c $(COMPILE_CFLAGS) $(srcdir)/lock_sparcv9.il $<
 else
 	$(CXX) -o $@ -c $(COMPILE_CFLAGS) $(srcdir)/lock_sparcv8plus.il $<
 endif # sparcv9
 endif # sparc
 endif # SOLARIS_SUNPRO_CXX
 
 # An AIX Optimization bug causes PR_dtoa() & JS_dtoa to produce wrong result.
 # This suppresses optimization for this single compilation unit.
 ifeq ($(OS_ARCH),AIX)
 jsatom.o: jsatom.cpp Makefile.in
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(CXX) -o $@ -c $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(COMPILE_CFLAGS)) $<
 jsdtoa.o: jsdtoa.cpp Makefile.in
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(CXX) -o $@ -c $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(COMPILE_CFLAGS)) $<
 endif
 
 # Compute the linker flags that programs linking against SpiderMonkey should
 # pass to get SpiderMonkey and its dependencies, beyond just the -L and -l
 # for the SpiderMonkey library itself.
 # - EXTRA_DSO_LDOPTS includes the NSPR -L and -l flags.
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -59,16 +59,18 @@ endif
 
 ifdef SDK_XPIDLSRCS
 XPIDLSRCS += $(SDK_XPIDLSRCS)
 endif
 ifdef SDK_HEADERS
 EXPORTS += $(SDK_HEADERS)
 endif
 
+REPORT_BUILD = @echo $(notdir $<)
+
 ifeq ($(OS_ARCH),OS2)
 EXEC			=
 else
 EXEC			= exec
 endif
 
 # Don't copy xulrunner files at install time, when using system xulrunner
 ifdef SYSTEM_LIBXUL
@@ -1143,45 +1145,53 @@ MAKE_DEPS_AUTO_CC = $(MAKE_DEPS_AUTO)
 MAKE_DEPS_AUTO_CXX = $(MAKE_DEPS_AUTO)
 
 endif # COMPILER_DEPEND
 
 endif # MOZ_AUTO_DEPS
 
 # Rules for building native targets must come first because of the host_ prefix
 host_%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 %:: %.c $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS)
 
 %.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
 
 # DEFINES and ACDEFINES are needed here to enable conditional compilation of Q_OBJECTs:
 # 'moc' only knows about #defines it gets on the command line (-D...), not in
 # included headers like mozilla-config.h
 moc_%.cpp: %.h $(GLOBAL_DEPS)
 	$(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@
 
 moc_%.cc: %.cc $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@
 
 ifdef ASFILES
 # The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept
 # a '-c' flag.
 %.$(OBJ_SUFFIX): %.$(ASM_SUFFIX) $(GLOBAL_DEPS)
 	$(AS) $(ASOUTOPTION)$@ $(ASFLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS)
 endif
@@ -1192,34 +1202,38 @@ endif
 %:: %.cpp $(GLOBAL_DEPS)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(CCC) $(OUTOPTION)$@ $(CXXFLAGS) $(_VPATH_SRCS) $(LDFLAGS)
 
 #
 # Please keep the next two rules in sync.
 #
 %.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
 %.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 ifdef STRICT_CPLUSPLUS_SUFFIX
 	echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc
 	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) t_$*.cc
 	$(RM) t_$*.cc
 else
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 endif #STRICT_CPLUSPLUS_SUFFIX
 
 $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
 
 $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS)
 
 %.s: %.cpp
 	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
 %.s: %.cc
 	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
@@ -1459,27 +1473,29 @@ endif
 
 XPIDL_DEPS = \
   $(topsrcdir)/xpcom/idl-parser/header.py \
   $(topsrcdir)/xpcom/idl-parser/typelib.py \
   $(topsrcdir)/xpcom/idl-parser/xpidl.py \
   $(NULL)
 
 $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
+	$(REPORT_BUILD)
 	$(PYTHON_PATH) \
 	  -I$(topsrcdir)/other-licenses/ply \
 	  -I$(topsrcdir)/xpcom/idl-parser \
 	  $(topsrcdir)/xpcom/idl-parser/header.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 	@if test -n "$(findstring $*.h, $(EXPORTS))"; \
 	  then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi
 
 ifndef NO_GEN_XPT
 # generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
 # into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
 $(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
+	$(REPORT_BUILD)
 	$(PYTHON_PATH) \
 	  -I$(topsrcdir)/other-licenses/ply \
 	  -I$(topsrcdir)/xpcom/idl-parser \
 	  -I$(topsrcdir)/xpcom/typelib/xpt/tools \
 	  $(topsrcdir)/xpcom/idl-parser/typelib.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 
 # no need to link together if XPIDLSRCS contains only XPIDL_MODULE
 ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS)))
@@ -1758,22 +1774,25 @@ else # ! COMPILER_DEPEND
 
 ifndef MOZ_AUTO_DEPS
 
 define MAKE_DEPS_NOAUTO
 	$(MKDEPEND) -w1024 -o'.$(OBJ_SUFFIX)' -f- $(DEFINES) $(ACDEFINES) $(INCLUDES) $< 2>/dev/null | sed -e "s|^[^ ]*/||" > $@
 endef
 
 $(MDDEPDIR)/%.pp: %.c
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_NOAUTO)
 
 $(MDDEPDIR)/%.pp: %.cpp
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_NOAUTO)
 
 $(MDDEPDIR)/%.pp: %.s
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_NOAUTO)
 
 ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))
 depend:: $(SUBMAKEFILES) $(MAKE_DIRS) $(MDDEPFILES)
 else
 depend:: $(SUBMAKEFILES)
 endif
 	$(LOOP_OVER_PARALLEL_DIRS)
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -1235,16 +1235,21 @@ mingw*)
     MOZ_PATH_PROGS(GMAKE, $GMAKE $NOT_PYMAKE gmake make, :)
     ;;
 esac
 if test "$GMAKE" = ":"; then
    AC_MSG_ERROR([GNU make not found])
 fi
 AC_SUBST(GMAKE)
 
+# MAKE will be set by client.mk, but still need this for standalone js builds
+if test -z "$MAKE"; then
+  MAKE=$GMAKE
+fi
+
 if test "$COMPILE_ENVIRONMENT"; then
 
 AC_PATH_XTRA
 
 XCFLAGS="$X_CFLAGS"
 
 fi # COMPILE_ENVIRONMENT
 
@@ -2102,16 +2107,27 @@ changequote(,)
 $PYTHON -c "import sys; sys.exit(sys.version[:3] < sys.argv[1] or sys.version[:2] != '2.')" $PYTHON_VERSION
 _python_res=$?
 changequote([,])
 if test "$_python_res" != 0; then
     AC_MSG_ERROR([Python $PYTHON_VERSION or higher (but not Python 3.x) is required.])
 fi
 AC_MSG_RESULT([yes])
 
+dnl Check for using a custom <stdint.h> implementation
+dnl ========================================================
+AC_MSG_CHECKING(for custom <stdint.h> implementation)
+if test "$MOZ_CUSTOM_STDINT_H"; then
+  AC_DEFINE_UNQUOTED(MOZ_CUSTOM_STDINT_H, "$MOZ_CUSTOM_STDINT_H")
+  AC_SUBST(MOZ_CUSTOM_STDINT_H)
+  AC_MSG_RESULT(using $MOZ_CUSTOM_STDINT_H)
+else
+  AC_MSG_RESULT(none specified)
+fi
+
 MOZ_DOING_LTO(lto_is_enabled)
 
 dnl ========================================================
 dnl System overrides of the defaults for target
 dnl ========================================================
 
 case "$target" in
 *-aix*)
@@ -2915,38 +2931,16 @@ AC_CACHE_VAL(ac_cv_siginfo_t,
                  [ac_cv_siginfo_t=false])])
 if test "$ac_cv_siginfo_t" = true ; then
   AC_DEFINE(HAVE_SIGINFO_T)
   AC_MSG_RESULT(yes)
 else
   AC_MSG_RESULT(no)
 fi
 
-dnl Find exact-width integer types, or figure them out
-dnl ourselves.
-dnl ========================================================
-dnl Once this is working, we can delete the code for int16_t,
-dnl etc. below.
-
-MOZ_CHECK_HEADER(stdint.h)
-if test "$ac_cv_header_stdint_h" = yes; then
-    AC_DEFINE(JS_HAVE_STDINT_H)
-else
-    dnl We'll figure them out for ourselves.  List more likely types
-    dnl earlier.  If we ever really encounter a size for which none of
-    dnl the listed types are appropriate, we'll get a configure-time
-    dnl error; just add the right answer.
-    MOZ_N_BYTE_TYPE(JS_INT8_TYPE,  1, [char])
-    MOZ_N_BYTE_TYPE(JS_INT16_TYPE, 2, [short int long])
-    MOZ_N_BYTE_TYPE(JS_INT32_TYPE, 4, [int long 'long long' short])
-    MOZ_N_BYTE_TYPE(JS_INT64_TYPE, 8, [int long 'long long'])
-    MOZ_N_BYTE_TYPE(JS_INTPTR_TYPE, sizeof (void *),
-                                      [int long 'long long' short])
-fi
-
 MOZ_SIZE_OF_TYPE(JS_BYTES_PER_WORD, void*, 4 8)
 if test "$moz_cv_size_of_JS_BYTES_PER_WORD" -eq "4"; then
   AC_DEFINE(JS_BITS_PER_WORD_LOG2, 5)
 elif test "$moz_cv_size_of_JS_BYTES_PER_WORD" -eq "8"; then
   AC_DEFINE(JS_BITS_PER_WORD_LOG2, 6)
 else
   AC_MSG_ERROR([Unexpected JS_BYTES_PER_WORD])
 fi
@@ -2959,70 +2953,18 @@ if test "$ac_cv_header_endian_h" = yes; 
     AC_DEFINE(JS_HAVE_ENDIAN_H)
 fi
 
 MOZ_CHECK_HEADERS(sys/isa_defs.h)
 if test "$ac_cv_header_sys_isa_defs_h" = yes; then
     AC_DEFINE(JS_HAVE_SYS_ISA_DEFS_H)
 fi
 
-dnl Check for int16_t, int32_t, int64_t, int64, uint, uint_t, and uint16_t.
+dnl Check for uint and uint_t.
 dnl ========================================================
-AC_MSG_CHECKING(for int16_t)
-AC_CACHE_VAL(ac_cv_int16_t,
- [AC_TRY_COMPILE([#include <stdio.h>
-                  #include <sys/types.h>],
-                 [int16_t foo = 0;],
-                 [ac_cv_int16_t=true],
-                 [ac_cv_int16_t=false])])
-if test "$ac_cv_int16_t" = true ; then
-  AC_DEFINE(HAVE_INT16_T)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
-AC_MSG_CHECKING(for int32_t)
-AC_CACHE_VAL(ac_cv_int32_t,
- [AC_TRY_COMPILE([#include <stdio.h>
-                  #include <sys/types.h>],
-                 [int32_t foo = 0;],
-                 [ac_cv_int32_t=true],
-                 [ac_cv_int32_t=false])])
-if test "$ac_cv_int32_t" = true ; then
-  AC_DEFINE(HAVE_INT32_T)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
-AC_MSG_CHECKING(for int64_t)
-AC_CACHE_VAL(ac_cv_int64_t,
- [AC_TRY_COMPILE([#include <stdio.h>
-                  #include <sys/types.h>],
-                 [int64_t foo = 0;],
-                 [ac_cv_int64_t=true],
-                 [ac_cv_int64_t=false])])
-if test "$ac_cv_int64_t" = true ; then
-  AC_DEFINE(HAVE_INT64_T)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
-AC_MSG_CHECKING(for int64)
-AC_CACHE_VAL(ac_cv_int64,
- [AC_TRY_COMPILE([#include <stdio.h>
-                  #include <sys/types.h>],
-                 [int64 foo = 0;],
-                 [ac_cv_int64=true],
-                 [ac_cv_int64=false])])
-if test "$ac_cv_int64" = true ; then
-  AC_DEFINE(HAVE_INT64)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
 AC_MSG_CHECKING(for uint)
 AC_CACHE_VAL(ac_cv_uint,
  [AC_TRY_COMPILE([#include <stdio.h>
                   #include <sys/types.h>],
                  [uint foo = 0;],
                  [ac_cv_uint=true],
                  [ac_cv_uint=false])])
 if test "$ac_cv_uint" = true ; then
@@ -3039,29 +2981,16 @@ AC_CACHE_VAL(ac_cv_uint_t,
                  [ac_cv_uint_t=true],
                  [ac_cv_uint_t=false])])
 if test "$ac_cv_uint_t" = true ; then
   AC_DEFINE(HAVE_UINT_T)
   AC_MSG_RESULT(yes)
 else
   AC_MSG_RESULT(no)
 fi
-AC_MSG_CHECKING(for uint16_t)
-AC_CACHE_VAL(ac_cv_uint16_t,
- [AC_TRY_COMPILE([#include <stdio.h>
-                  #include <sys/types.h>],
-                 [uint16_t foo = 0;],
-                 [ac_cv_uint16_t=true],
-                 [ac_cv_uint16_t=false])])
-if test "$ac_cv_uint16_t" = true ; then
-  AC_DEFINE(HAVE_UINT16_T)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
 
 dnl On the gcc trunk (as of 2001-02-09) _GNU_SOURCE, and thus __USE_GNU,
 dnl are defined when compiling C++ but not C.  Since the result of this
 dnl test is used only in C++, do it in C++.
 AC_LANG_CPLUSPLUS
 
 AC_MSG_CHECKING(for uname.domainname)
 AC_CACHE_VAL(ac_cv_have_uname_domainname_field,
@@ -4718,17 +4647,17 @@ dnl ====================================
 MOZ_ARG_HEADER(Compiler Options)
 
 dnl ========================================================
 dnl Check for gcc -pipe support
 dnl ========================================================
 AC_MSG_CHECKING([for gcc -pipe support])
 if test -n "$GNU_CC" -a -n "$GNU_CXX" -a -n "$GNU_AS"; then
     echo '#include <stdio.h>' > dummy-hello.c
-    echo 'int main() { printf("Hello World\n"); exit(0); }' >> dummy-hello.c
+    echo 'int main() { printf("Hello World"); exit(0); }' >> dummy-hello.c
     ${CC} -S dummy-hello.c -o dummy-hello.s 2>&5
     cat dummy-hello.s 2> /dev/null | ${AS_BIN} -o dummy-hello.S - 2>&5
     if test $? = 0; then
         _res_as_stdin="yes"
     else
         _res_as_stdin="no"
     fi
     if test "$_res_as_stdin" = "yes"; then
@@ -5400,28 +5329,44 @@ AC_OUTPUT_MAKE_DEFS()
 MOZ_DEFINES=$DEFS
 AC_SUBST(MOZ_DEFINES)
 rm -f confdefs.h
 mv confdefs.h.save confdefs.h
 
 MAKEFILES="
   Makefile
   shell/Makefile
-  jsapi-tests/Makefile
-  tests/Makefile
   config/Makefile
   config/autoconf.mk
   config/expandlibs_config.py
-  config/mkdepend/Makefile
 "
 
-if test -n "$JS_NATIVE_EDITLINE"; then
-   MAKEFILES="$MAKEFILES
-editline/Makefile
-"
+if test "$JS_NATIVE_EDITLINE"; then
+  MAKEFILES="$MAKEFILES
+    editline/Makefile
+  "
+fi
+
+if test ! "$COMPILER_DEPEND" -a ! "$MOZ_NATIVE_MAKEDEPEND"; then
+  MAKEFILES="$MAKEFILES
+    config/mkdepend/Makefile
+  "
+fi
+
+if test "$ENABLE_TESTS"; then
+  MAKEFILES="$MAKEFILES
+    jsapi-tests/Makefile
+    tests/Makefile
+  "
+fi
+
+if test "$DEHYDRA_PATH"; then
+  MAKEFILES="$MAKEFILES
+    analysis-tests/Makefile
+  "
 fi
 
 dnl
 dnl Run a perl script to quickly create the makefiles.
 dnl If it succeeds, it outputs a shell command to set CONFIG_FILES
 dnl   for the files it cannot handle correctly. This way, config.status
 dnl   will handle these files.
 dnl If it fails, nothing is set and config.status will run as usual.
@@ -5443,18 +5388,18 @@ if cmp -s config/autoconf.mk config/auto
   echo "config/autoconf.mk is unchanged"
   mv -f config/autoconf.mk.orig config/autoconf.mk 2> /dev/null
 else
   rm -f config/autoconf.mk.orig 2> /dev/null
 fi
 
 # Produce the js-config script at configure time; see the comments for
 # 'js-config' in Makefile.in.
-AC_MSG_RESULT(invoking make to create js-config script)
-$GMAKE js-config
+AC_MSG_RESULT(invoking $MAKE to create js-config script)
+$MAKE js-config
 
 # Build jsctypes if it's enabled.
 if test "$JS_HAS_CTYPES" -a -z "$MOZ_NATIVE_FFI"; then
   # Run the libffi 'configure' script.
   ac_configure_args="--disable-shared --enable-static --disable-raw-api"
   if test "$MOZ_DEBUG"; then
     ac_configure_args="$ac_configure_args --enable-debug"
   fi
--- a/js/src/jit-test/tests/basic/bug674776.js
+++ b/js/src/jit-test/tests/basic/bug674776.js
@@ -1,9 +1,9 @@
-// |jit-test| debug
+// |jit-test| slow; debug
 
 /* Make a lot of functions of the form:
 function x1(){x1();}
 function x2(){x2();}
 function x3(){x3();}
 ...
 */
 
--- a/js/src/jit-test/tests/basic/testCompileScript.js
+++ b/js/src/jit-test/tests/basic/testCompileScript.js
@@ -1,9 +1,9 @@
-// |jit-test| mjitalways
+// |jit-test| slow; mjitalways
 
 var nlocals = 50;
 var localstr = "";
 for (var i = 0; i < nlocals; ++i)
     localstr += "var x" + i + "; ";
 
 /*
  * Attempt to test, in a stack-parameter-independent manner, ComileFunction
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-01.js
@@ -0,0 +1,23 @@
+// A live Environment can observe the new variables introduced by ES5 non-strict direct eval.
+
+var g = newGlobal('new-compartment');
+g.eval("var x = 'global'; function f(s) { h(); eval(s); h(); }");
+g.eval("function h() { debugger; }");
+var dbg = Debugger(g);
+var env = undefined;
+var hits = 0;
+dbg.onDebuggerStatement = function (hframe) {
+    if (env === undefined) {
+        // First debugger statement.
+        env = hframe.older.environment;
+        assertEq(env.find("x") !== env, true);
+        assertEq(env.names().indexOf("x"), -1);
+    } else {
+        // Second debugger statement, post-eval.
+        assertEq(env.find("x"), env);
+        assertEq(env.names().indexOf("x") >= 0, true);
+    }
+    hits++;
+};
+g.f("var x = 'local';");
+assertEq(hits, 2);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-02.js
@@ -0,0 +1,20 @@
+// The last Environment on the environment chain always has .type == "object" and .object === the global object.
+
+var g = newGlobal('new-compartment');
+var dbg = new Debugger;
+var gw = dbg.addDebuggee(g);
+g.eval("function h() { debugger; }");
+var hits = 0;
+dbg.onDebuggerStatement = function (hframe) {
+    var env = hframe.older.environment;
+    while (env.parent)
+        env = env.parent;
+    assertEq(env.type, "object");
+    assertEq(env.object, gw);
+    hits++;
+};
+
+g.eval("h();");
+g.eval("(function () { h(); return []; })();");
+g.eval("with (Math) { h(-2 * PI); }");
+assertEq(hits, 3);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-find-01.js
@@ -0,0 +1,19 @@
+// find sees that vars are hoisted out of with statements.
+
+var g = newGlobal('new-compartment');
+var dbg = Debugger(g);
+var hits = 0;
+dbg.onDebuggerStatement = function (frame) {
+    assertEq(frame.environment.find("x").type, "object");
+    hits++;
+};
+
+assertEq(g.eval("(function () {\n" +
+                "    function g() { x = 1; }\n" +
+                "    with ({x: 2}) {\n" +
+                "        var x;\n" +
+                "        debugger;\n" +
+                "        return x;\n" +
+                "    }\n" +
+                "})();"), 2);
+assertEq(hits, 1);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-find-02.js
@@ -0,0 +1,18 @@
+// env.find() finds nonenumerable names in the global environment.
+
+var g = newGlobal('new-compartment');
+var dbg = Debugger(g);
+var hits = 0;
+g.h = function () {
+    var env = dbg.getNewestFrame().environment;
+    var last = env;
+    while (last.parent)
+        last = last.parent;
+
+    assertEq(env.find("Array"), last);
+    hits++;
+};
+
+g.eval("h();");
+g.eval("(function () { let (x = 1, y = 2) h(); })();");
+assertEq(hits, 2);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-find-03.js
@@ -0,0 +1,20 @@
+// env.find() finds noneumerable properties in with statements.
+
+var g = newGlobal('new-compartment');
+var dbg = Debugger(g);
+var hits = 0;
+g.h = function () {
+    var frame = dbg.getNewestFrame();
+    var target = frame.eval("obj").return;
+    var env = frame.environment.find("PI");
+    assertEq(env.object, target);
+    hits++;
+};
+
+g.obj = g.Math;
+g.eval("with (obj) h();");
+g.eval("with (Math) { let x = 12; h(); }");
+g.eval("obj = {};\n" +
+       "Object.defineProperty(obj, 'PI', {enumerable: false, value: 'Marlowe'});\n" +
+       "with (obj) h();\n");
+assertEq(hits, 3);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-find-04.js
@@ -0,0 +1,21 @@
+// env.find throws a TypeError if the argument is not an identifier.
+
+load(libdir + "asserts.js");
+
+var g = newGlobal('new-compartment');
+var dbg = Debugger(g);
+var hits = 0;
+g.h = function () {
+    var env = dbg.getNewestFrame().environment;
+    assertThrowsInstanceOf(function () { env.find(); }, TypeError);
+    assertThrowsInstanceOf(function () { env.find(""); }, TypeError);
+    assertThrowsInstanceOf(function () { env.find(" "); }, TypeError);
+    assertThrowsInstanceOf(function () { env.find(0); }, TypeError);
+    assertThrowsInstanceOf(function () { env.find("0"); }, TypeError);
+    assertThrowsInstanceOf(function () { env.find("0xc"); }, TypeError);
+    assertThrowsInstanceOf(function () { env.find("Anna Karenina"); }, TypeError);
+    hits++;
+};
+g.eval("h();");
+g.eval("with ([1]) h();");
+assertEq(hits, 2);
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-find-06.js
@@ -0,0 +1,49 @@
+// Environment.prototype.find finds bindings that are function arguments, 'let'
+// bindings, or FunctionExpression names.
+
+var g = newGlobal('new-compartment');
+g.eval("function h() { debugger; }");
+
+var dbg = new Debugger(g);
+
+function test1(code) {
+    var hits = 0;
+    dbg.onDebuggerStatement = function (frame) {
+        var env = frame.older.environment.find('X');
+        assertEq(env.names().indexOf('X') !== -1, true);
+        assertEq(env.type, 'declarative');
+        assertEq(env.parent !== null, true);
+        hits++;
+    };
+    g.eval(code);
+    assertEq(hits, 1);
+}
+
+var manyNames = '';
+for (var i = 0; i < 4096; i++)
+    manyNames += 'x' + i + ', ';
+manyNames += 'X';
+
+function test2(code) {
+    print(code + " : one");
+    test1(code.replace('@@', 'X'));
+    print(code + " : many");
+    test1(code.replace('@@', manyNames));
+}
+
+test2('function f(@@) { h(); }  f(1);');
+test2('function f(@@) { h(); }  f();');
+test2('function f(@@) { return function g() { h(X); }; }  f(1)();');
+test2('function f(@@) { return function g() { h(X); }; }  f()();');
+
+test2('                    { let @@ = 0; h(); }');
+test2('function f(a, b, c) { let @@ = 0; h(); }  f(1, 2, 3);');
+test2('             { let @@ = 0; { let y = 0; h(); } }');
+test2('function f() { let @@ = 0; { let y = 0; h(); } }  f();');
+test2('             { for (let @@ = 0; X < 1; X++) h(); }');
+test2('function f() { for (let @@ = 0; X < 1; X++) h(); }  f();');
+test2('             {        (let (@@ = 0) let (y = 2, z = 3) h()); }');
+test2('function f() { return (let (@@ = 0) let (y = 2, z = 3) h()); }  f();');
+
+test1('(function X() { h(); })();');
+test1('(function X(a, b, c) { h(); })(1, 2, 3);');
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-gc-01.js
@@ -0,0 +1,19 @@
+// An Environment keeps its referent alive.
+
+var g = newGlobal('new-compartment');
+g.eval("function f(x) { return 2 * x; }");
+var dbg = Debugger(g);
+var env;
+dbg.onEnterFrame = function (frame) { env = frame.environment; };
+assertEq(g.f(22), 44);
+dbg.onEnterFrame = undefined;
+
+assertEq(env.find("x"), env);
+assertEq(env.names().join(","), "x");
+
+gc();
+g.gc(g);
+gc(env);
+
+assertEq(env.find("x"), env);
+assertEq(env.names().join(","), "x");
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-gc-02.js
@@ -0,0 +1,28 @@
+// A closure's .environment keeps the lexical environment alive even if the closure is destroyed.
+
+var N = 4;
+var g = newGlobal('new-compartment');
+g.eval("function add(a) { return function (b) { return eval('a + b'); }; }");
+var dbg = new Debugger;
+var gw = dbg.addDebuggee(g);
+var aw = gw.getOwnPropertyDescriptor("add").value;
+
+// Create N closures and collect environments.
+var arr = [];
+for (var i = 0; i < N; i++)
+    arr[i] = aw.call(null, i).return.environment;
+
+// Test that they work now.
+function check() {
+    for (var i = 0; i < N; i++) {
+        assertEq(arr[i].find("b"), null);
+        assertEq(arr[i].find("a"), arr[i]);
+    }
+}
+check();
+
+// Test that they work after gc.
+gc();
+gc({});
+g.gc(g);
+check();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-identity-01.js
@@ -0,0 +1,40 @@
+// The value of frame.environment is the same Environment object at different
+// times within a single visit to a scope.
+
+var g = newGlobal('new-compartment');
+var dbg = Debugger(g);
+g.eval("function h() { debugger; }");
+var hits, env;
+dbg.onDebuggerStatement = function (hframe) {
+    var frame = hframe.older;
+    var e = frame.environment;
+
+    // frame.environment is at least cached from one moment to the next.
+    assertEq(e, frame.environment);
+
+    // frame.environment is cached from statement to statement within a call frame.
+    if (env === undefined)
+        env = e;
+    else
+        assertEq(e, env);
+
+    hits++;
+};
+
+hits = 0;
+env = undefined;
+g.eval("function f() { (function () { var i = 0; h(); var j = 2; h(); })(); }");
+g.f();
+assertEq(hits, 2);
+
+hits = 0;
+env = undefined;
+g.eval("function f2() { { let i = 0; h(); let j = 2; h(); } }");
+g.f2();
+assertEq(hits, 2);
+
+hits = 0;
+env = undefined;
+g.eval("function f3() { { let i; for (i = 0; i < 2; i++) h(); } }");
+g.f3();
+assertEq(hits, 2);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-identity-02.js
@@ -0,0 +1,29 @@
+// frame.environment is different for different activations of a scope.
+
+var g = newGlobal('new-compartment');
+var dbg = Debugger(g);
+g.eval("function h() { debugger; }");
+var arr;
+dbg.onDebuggerStatement = function (hframe) {
+    var e = hframe.older.environment;
+    assertEq(arr.indexOf(e), -1);
+    arr.push(e);
+};
+
+function test(code, expectedHits) {
+    arr = [];
+    g.eval(code);
+    assertEq(arr.length, expectedHits);
+}
+
+// two separate calls to a function
+test("(function () { var f = function (a) { h(); return a; }; f(1); f(2); })();", 2);
+
+// recursive calls to a function
+test("(function f(n) { h(); return n < 2 ? 1 : n * f(n - 1); })(3);", 3);
+
+// separate visits to a block in the same call frame
+test("(function () { for (var i = 0; i < 3; i++) { let j = i * 4; h(); }})();", 3);
+
+// two strict direct eval calls in the same function scope
+test("(function () { 'use strict'; for (var i = 0; i < 3; i++) eval('h();'); })();", 3);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-identity-03.js
@@ -0,0 +1,109 @@
+// Two Environments nested in the same runtime scope share the correct tail of their parent chains.
+
+// The compiler must be allowed to elide empty scopes and so forth, so this
+// test does not check the number of unshared Environments. Instead, each test
+// case identifies the expected innermost shared scope by the name of a
+// variable in it.
+
+var g = newGlobal('new-compartment');
+g.eval("function h() { debugger; }");
+var dbg = Debugger(g);
+var hits, name, shared, unshared;
+dbg.onDebuggerStatement = function (hframe) {
+    var frame = hframe.older;
+
+    // Find name in frame.environment.
+    var env, child = null;
+    for (env = frame.environment; env !== null; env = env.parent) {
+        if (env.names().indexOf(name) != -1)
+            break;
+        child = env;
+    }
+    assertEq(env !== null, true, "expected '" + name + "' to be in scope");
+    assertEq(env, frame.environment.find(name),
+             "env.find should find the same frame as the written out search");
+
+    if (hits === 0) {
+        // First hit.
+        shared = env;
+        unshared = child;
+    } else {
+        // Subsequent hit.
+        assertEq(env, shared, "the environment containing '" + name + "' should be shared");
+        assertEq(child === null || unshared === null || unshared !== child, true,
+                "environments nested within the one containing '" + name + "' should not be shared");
+    }
+    hits++;
+};
+
+function test(sharedName, expectedHits, code) {
+    hits = 0;
+    name = sharedName;
+    shared = unshared = undefined;
+    g.eval(code);
+    assertEq(hits, expectedHits);
+}
+
+// Basic test cases.
+//
+// (The stray "a = b" assignments in these tests are to inhibit the flat closure
+// optimization, which Environments expose. There's nothing really wrong with
+// the optimization or with the debugger exposing it, but that's not what we
+// want to test here.)
+
+test("q", 2, "var q = function (a) { h(); }; q(1); q(2);");
+test("a", 2, "q = function (a) { (function (b) { h(); a = b; })(2); h(); }; q(1);");
+test("a", 2, "q = function (a) { h(); return function (b) { h(); a = b; }; }; q(1)(2);");
+test("n", 3, "q = function (n) { for (var i = 0; i < n; i++) { let (j = i) { h(); } } }; q(3);");
+
+// Don't crash in E4X filter scopes.
+test("x", 2, "q = function () { var x = <><y/><z/></>.(function (e) { h(); }(this)); }; q();");
+
+// A function with long dynamic and static chains.
+var N = 80;
+
+var code = "function f" + N + "(a" + N + ") {\neval('a0 + a1'); h();\n}\n";
+for (var i = N; --i >= 0;) {
+    var call = "f" + (i + 1) + "(a" + i + " - 1);\n";
+    code = ("function f" + i + "(a" + i + ") {\n" +
+            code +
+            call +
+            "if (a" + i + " === 0) " + call +
+            "}\n");
+}
+
+g.eval(code);
+test("a0", 2, "f0(0);");
+test("a17", 2, "f0(17);");
+test("a" + (N-2), 2, "f0(" + (N-2) + ");");
+test("a" + (N-1), 2, "f0(" + (N-1) + ");");
+
+// A function with a short dynamic chain and a long static chain.
+N = 60;
+
+function DeepStaticShallowDynamic(i, n) {
+    var code = "function f" + i + "(a" + i + ") {\n";
+    if (i >= n)
+        code += "eval('a1 + a2'); h();\n";
+    else
+        code += "return " + DeepStaticShallowDynamic(i+1, n) + ";\n";
+    code += "}";
+    return code;
+}
+g.eval(DeepStaticShallowDynamic(1, N));
+
+function range(start, stop) {
+    for (var i = start; i < stop; i++)
+        yield i;
+}
+
+function DSSDsplit(s) {
+    return ("var mid = f1" + ["(" + i + ")" for (i in range(0, s))].join("") + ";\n" +
+            "mid" +          ["(" + i + ")" for (i in range(s, N))].join("") + ";\n" +
+            "mid" +          ["(" + i + ")" for (i in range(s, N))].join("") + ";\n");
+}
+
+test("a1", 2, DSSDsplit(1));
+test("a17", 2, DSSDsplit(17));
+test("a" + (N-2), 2, DSSDsplit(N-2));
+test("a" + (N-1), 2, DSSDsplit(N-1));
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-identity-04.js
@@ -0,0 +1,19 @@
+// Observably different visits to the same with-statement produce distinct Environments.
+
+var g = newGlobal('new-compartment');
+g.eval("function f(a, obj) { with (obj) return function () { return a; }; }");
+var dbg = Debugger(g);
+var hits = 0;
+dbg.onDebuggerStatement = function (frame) {
+    // Even though the two visits to the with-statement have the same target
+    // object, Math, the environments are observably different.
+    var f1 = frame.eval("f(1, Math);").return;
+    var f2 = frame.eval("f(2, Math);").return;
+    assertEq(f1.environment !== f2.environment, true);
+    assertEq(f1.object, f2.object);
+    assertEq(f1.call().return, 1);
+    assertEq(f2.call().return, 2);
+    hits++;
+};
+g.eval("debugger;");
+assertEq(hits, 1);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-names-01.js
@@ -0,0 +1,17 @@
+// env.names() lists nonenumerable names in with-statement environments.
+
+var g = newGlobal('new-compartment');
+var dbg = Debugger(g);
+var hits = 0;
+g.h = function () {
+    var env = dbg.getNewestFrame().environment;
+    var names = env.names();
+    assertEq(names.indexOf("a") !== -1, true);
+    assertEq(names.indexOf("b") !== -1, true);
+    assertEq(names.indexOf("isPrototypeOf") !== -1, true);
+    hits++;
+};
+g.eval("var obj = {a: 1};\n" +
+       "Object.defineProperty(obj, 'b', {value: 2});\n" +
+       "with (obj) h();");
+assertEq(hits, 1);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-names-02.js
@@ -0,0 +1,15 @@
+// env.names() on object environments ignores property names that are not identifiers.
+
+var g = newGlobal('new-compartment');
+var dbg = Debugger(g);
+var names;
+g.h = function () {
+    names = dbg.getNewestFrame().environment.names();
+};
+g.eval("var obj = {a: 1};\n" +
+       "with ({a: 1, '0xcafe': 2, ' ': 3, '': 4, '0': 5}) h();");
+assertEq(names.indexOf("a") !== -1, true);
+assertEq(names.indexOf("0xcafe"), -1);
+assertEq(names.indexOf(" "), -1);
+assertEq(names.indexOf(""), -1);
+assertEq(names.indexOf("0"), -1);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-parent-01.js
@@ -0,0 +1,18 @@
+// The objects on the environment chain are all Debugger.Environment objects.
+// The environment chain ends in null.
+
+var g = newGlobal('new-compartment')
+g.eval("function f(a) { return function (b) { return function (c) { h(); return a + b + c; }; }; }");
+var dbg = Debugger(g);
+var hits = 0;
+g.h = function () {
+    var n = 0;
+    for (var env = dbg.getNewestFrame().environment; env !== null; env = env.parent) {
+        n++;
+        assertEq(env instanceof Debugger.Environment, true);
+    }
+    assertEq(n >= 4, true);
+    hits++;
+};
+assertEq(g.f(5)(7)(9), 21);
+assertEq(hits, 1);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-type-01.js
@@ -0,0 +1,38 @@
+// env.type is 'object' in global environments and with-blocks, and 'declarative' otherwise.
+
+var g = newGlobal('new-compartment');
+var dbg = Debugger(g);
+function test(code, expected) {
+    var actual = '';
+    g.h = function () { actual += dbg.getNewestFrame().environment.type; }
+    g.eval(code);
+    assertEq(actual, expected);
+}
+
+test("h();", 'object');
+test("(function (s) { eval(s); })('var v = h();')", 'declarative');
+test("(function (s) { h(); })();", 'declarative');
+test("{let x = 1, y = 2; h();}", 'declarative');
+test("with({x: 1, y: 2}) h();", 'object');
+test("(function (s) { with ({x: 1, y: 2}) h(); })();", 'object');
+test("let (x = 1) { h(); }", 'declarative');
+test("(let (x = 1) h());", 'declarative');
+test("for (let x = 0; x < 1; x++) h();", 'declarative');
+test("for (let x in h()) ;", 'object');
+test("for (let x in {a:1}) h();", 'declarative');
+test("try { throw new Error; } catch (x) { h(x) }", 'declarative');
+test("'use strict'; eval('var z = 1; h();');", 'declarative');
+test("for (var x in [h(m) for (m in [1])]) ;", 'declarative');
+test("for (var x in (h(m) for (m in [1]))) ;", 'declarative');
+
+// Since a generator-expression is effectively a function, the innermost scope
+// is a function scope, and thus declarative. Thanks to an odd design decision,
+// m is already in scope at the point of the call to h(). The answer here is
+// not all that important, but we shouldn't crash.
+test("for (var x in (0 for (m in h()))) ;", 'declarative');
+
+dbg.onDebuggerStatement = function (frame) {
+    assertEq(frame.eval("h(), 2 + 2;").return, 4);
+}
+test("debugger;", 'object');
+test("(function f() { debugger; })();", 'declarative');
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Frame-environment-01.js
@@ -0,0 +1,13 @@
+// frame.environment is a Debugger.Environment object
+
+var g = newGlobal('new-compartment')
+var dbg = Debugger(g);
+g.h = function () {
+    assertEq(dbg.getNewestFrame().environment instanceof Debugger.Environment, true);
+};
+
+g.eval("h()");
+g.evaluate("h()");
+g.eval("eval('h()')");
+g.eval("function f() { h(); }");
+g.f();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Frame-environment-02.js
@@ -0,0 +1,12 @@
+// dbg.getNewestFrame().environment works.
+
+var g = newGlobal('new-compartment');
+var dbg = new Debugger;
+var gw = dbg.addDebuggee(g);
+g.h = function () {
+    var env = dbg.getNewestFrame().environment;
+    assertEq(env instanceof Debugger.Environment, true);
+    assertEq(env.object, gw);
+    assertEq(env.parent, null);
+};
+g.eval("h()");
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Frame-environment-03.js
@@ -0,0 +1,11 @@
+// If !frame.live, frame.environment throws.
+
+load(libdir + "asserts.js");
+
+var g = newGlobal('new-compartment');
+var dbg = Debugger(g);
+var frame;
+g.h = function () { frame = dbg.getNewestFrame(); };
+g.eval("h();");
+assertEq(frame.live, false);
+assertThrowsInstanceOf(function () { frame.environment; }, Error);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Frame-environment-04.js
@@ -0,0 +1,12 @@
+// frame.environment can be called from the onEnterFrame hook.
+
+var g = newGlobal('new-compartment');
+g.eval("function f(x) { return 2 * x; }");
+var dbg = Debugger(g);
+var hits = 0;
+dbg.onEnterFrame = function (frame) {
+    assertEq(frame.environment.names().join(","), "x");
+    hits++;
+};
+assertEq(g.f(22), 44);
+assertEq(hits, 1);
--- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-10.js
+++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-10.js
@@ -1,9 +1,10 @@
-// Direct eval code under evalWithbindings sees both the bindings and the enclosing scope.
+// Direct eval code under evalWithBindings sees both the bindings and the enclosing scope.
+
 var g = newGlobal('new-compartment');
 var dbg = new Debugger(g);
 var hits = 0;
 dbg.onDebuggerStatement = function (frame) {
     var code =
         "assertEq(a, 1234);\n" +
         "assertEq(b, null);\n" +
         "assertEq(c, 'ok');\n";
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Object-environment-01.js
@@ -0,0 +1,17 @@
+// obj.environment is undefined when the referent is not a JS function.
+
+var g = newGlobal('new-compartment')
+var dbg = new Debugger;
+var gw = dbg.addDebuggee(g);
+assertEq(gw.environment, undefined);
+
+g.eval("var r = /x/;");
+var rw = gw.getOwnPropertyDescriptor("r").value;
+assertEq(rw.class, "RegExp");
+assertEq(rw.environment, undefined);
+
+// Native function.
+var fw = gw.getOwnPropertyDescriptor("parseInt").value;
+assertEq(fw.class, "Function");
+assertEq(fw.environment, undefined);
+
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Object-environment-02.js
@@ -0,0 +1,20 @@
+// The .environment of a function Debugger.Object is an Environment object.
+
+var g = newGlobal('new-compartment')
+var dbg = Debugger(g);
+var hits = 0;
+g.h = function () {
+    var frame = dbg.getNewestFrame();
+    var fn = frame.eval("j").return;
+    assertEq(fn.environment instanceof Debugger.Environment, true);
+    var closure = frame.eval("f").return;
+    assertEq(closure.environment instanceof Debugger.Environment, true);
+    hits++;
+};
+g.eval("function j(a) {\n" +
+       "    var f = function () { return a; };\n" +
+       "    h();\n" +
+       "    return f;\n" +
+       "}\n" +
+       "j(0);\n");
+assertEq(hits, 1);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug707384.js
@@ -0,0 +1,8 @@
+// |jit-test| debug
+function f() {
+    do {
+        return
+    } while (e)
+}
+trap(f, 1, '')
+f()
--- a/js/src/js-config.h.in
+++ b/js/src/js-config.h.in
@@ -50,20 +50,16 @@
 
 /* Define to 1 if SpiderMonkey should include ctypes support.  */
 #undef JS_HAS_CTYPES
 
 /* Define to 1 if SpiderMonkey should support the ability to perform
    entirely too much GC.  */
 #undef JS_GC_ZEAL
 
-/* Define to 1 if the standard <stdint.h> header is present and
-   useable.  See jstypes.h and jsstdint.h.  */
-#undef JS_HAVE_STDINT_H
-
 /* Define to 1 if the <endian.h> header is present and
    useable.  See jscpucfg.h.  */
 #undef JS_HAVE_ENDIAN_H
 
 /* Define to 1 if the <sys/isa_defs.h> header is present and
    useable.  See jscpucfg.h.  */
 #undef JS_HAVE_SYS_ISA_DEFS_H
 
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -367,8 +367,9 @@ MSG_DEF(JSMSG_DEBUG_LOOP,             28
 MSG_DEF(JSMSG_DEBUG_NOT_IDLE,         281, 0, JSEXN_ERR, "can't start debugging: a debuggee script is on the stack")
 MSG_DEF(JSMSG_DEBUG_BAD_OFFSET,       282, 0, JSEXN_TYPEERR, "invalid script offset")
 MSG_DEF(JSMSG_DEBUG_BAD_LINE,         283, 0, JSEXN_TYPEERR, "invalid line number")
 MSG_DEF(JSMSG_DEBUG_NOT_DEBUGGING,    284, 0, JSEXN_ERR, "can't set breakpoint: script global is not a debuggee")
 MSG_DEF(JSMSG_DEBUG_COMPARTMENT_MISMATCH, 285, 2, JSEXN_TYPEERR, "{0}: descriptor .{1} property is an object in a different compartment than the target object")
 MSG_DEF(JSMSG_DEBUG_NOT_SCRIPT_FRAME, 286, 0, JSEXN_ERR, "stack frame is not running JavaScript code")
 MSG_DEF(JSMSG_CANT_WATCH_PROP,        287, 0, JSEXN_TYPEERR, "properties whose names are objects can't be watched")
 MSG_DEF(JSMSG_CSP_BLOCKED_EVAL,       288, 0, JSEXN_ERR, "call to eval() blocked by CSP")
+MSG_DEF(JSMSG_DEBUG_NO_SCOPE_OBJECT,  289, 0, JSEXN_TYPEERR, "declarative Environments don't have binding objects")
--- a/js/src/jsanalyze.h
+++ b/js/src/jsanalyze.h
@@ -1047,17 +1047,16 @@ class ScriptAnalysis
         return getCode(offset).allocation;
     }
     mjit::RegisterAllocation *&getAllocation(const jsbytecode *pc) {
         return getAllocation(pc - script->code);
     }
 
     LoopAnalysis *getLoop(uint32 offset) {
         JS_ASSERT(offset < script->length);
-        JS_ASSERT(getCode(offset).loop);
         return getCode(offset).loop;
     }
     LoopAnalysis *getLoop(const jsbytecode *pc) { return getLoop(pc - script->code); }
 
     /* For a JSOP_CALL* op, get the pc of the corresponding JSOP_CALL/NEW/etc. */
     jsbytecode *getCallPC(jsbytecode *pc)
     {
         JS_ASSERT(js_CodeSpec[*pc].format & JOF_CALLOP);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5263,23 +5263,16 @@ JS_TriggerAllOperationCallbacks(JSRuntim
     AutoLockGC lock(rt);
 #endif
     TriggerAllOperationCallbacks(rt);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_IsRunning(JSContext *cx)
 {
-    /*
-     * The use of cx->fp below is safe. Rationale: Here we don't care if the
-     * interpreter state is stale. We just want to know if there *is* any
-     * interpreter state.
-     */
-    VOUCH_DOES_NOT_REQUIRE_STACK();
-
 #ifdef JS_THREADSAFE
     if (!cx->thread())
         return false;
 #endif
 
     StackFrame *fp = cx->maybefp();
     while (fp && fp->isDummyFrame())
         fp = fp->prev();
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -428,17 +428,16 @@ js_NewContext(JSRuntime *rt, size_t stac
      * runtime list. After that it can be accessed from another thread via
      * js_ContextIterator.
      */
     JSContext *cx = OffTheBooks::new_<JSContext>(rt);
     if (!cx)
         return NULL;
 
     JS_ASSERT(cx->findVersion() == JSVERSION_DEFAULT);
-    VOUCH_DOES_NOT_REQUIRE_STACK();
 
     if (!cx->busyArrays.init()) {
         Foreground::delete_(cx);
         return NULL;
     }
 
 #ifdef JS_THREADSAFE
     if (!js_InitContextThreadAndLockGC(cx)) {
@@ -751,17 +750,17 @@ PopulateReportBlame(JSContext *cx, JSErr
 {
     /*
      * Walk stack until we find a frame that is associated with some script
      * rather than a native frame.
      */
     for (FrameRegsIter iter(cx); !iter.done(); ++iter) {
         if (iter.fp()->isScriptFrame()) {
             report->filename = iter.fp()->script()->filename;
-            report->lineno = js_FramePCToLineNumber(cx, iter.fp(), iter.pc());
+            report->lineno = js_PCToLineNumber(cx, iter.fp()->script(), iter.pc());
             break;
         }
     }
 }
 
 /*
  * We don't post an exception in this case, since doing so runs into
  * complications of pre-allocating an exception object which required
@@ -1469,17 +1468,16 @@ JSContext::JSContext(JSRuntime *rt)
 
 JSContext::~JSContext()
 {
 #ifdef JS_THREADSAFE
     JS_ASSERT(!thread_);
 #endif
 
     /* Free the stuff hanging off of cx. */
-    VOUCH_DOES_NOT_REQUIRE_STACK();
     if (parseMapPool_)
         Foreground::delete_<ParseMapPool>(parseMapPool_);
 
     if (lastMessage)
         Foreground::free_(lastMessage);
 
     /* Remove any argument formatters. */
     JSArgumentFormatMap *map = argumentFormatMap;
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -70,26 +70,16 @@ struct PreserveRegsGuard
   private:
     JSContext *cx;
     FrameRegs &regs_;
 };
 
 static inline GlobalObject *
 GetGlobalForScopeChain(JSContext *cx)
 {
-    /*
-     * This is essentially GetScopeChain(cx)->getGlobal(), but without
-     * falling off trace.
-     *
-     * This use of cx->fp, possibly on trace, is deliberate:
-     * cx->fp->scopeChain->getGlobal() returns the same object whether we're on
-     * trace or not, since we do not trace calls across global objects.
-     */
-    VOUCH_DOES_NOT_REQUIRE_STACK();
-
     if (cx->hasfp())
         return cx->fp()->scopeChain().getGlobal();
 
     JSObject *scope = JS_ObjectToInnerObject(cx, cx->globalObject);
     if (!scope)
         return NULL;
     return scope->asGlobal();
 }
@@ -147,17 +137,16 @@ class AutoPtr
 class CompartmentChecker
 {
     JSContext *context;
     JSCompartment *compartment;
 
   public:
     explicit CompartmentChecker(JSContext *cx) : context(cx), compartment(cx->compartment) {
         check(cx->hasfp() ? JS_GetGlobalForScopeChain(cx) : cx->globalObject);
-        VOUCH_DOES_NOT_REQUIRE_STACK();
     }
 
     /*
      * Set a breakpoint here (break js::CompartmentChecker::fail) to debug
      * compartment mismatches.
      */
     static void fail(JSCompartment *c1, JSCompartment *c2) {
         printf("*** Compartment mismatch %p vs. %p\n", (void *) c1, (void *) c2);
@@ -233,17 +222,18 @@ class CompartmentChecker
         if (script) {
             check(script->compartment());
             if (!script->isCachedEval && script->globalObject)
                 check(script->globalObject);
         }
     }
 
     void check(StackFrame *fp) {
-        check(&fp->scopeChain());
+        if (fp)
+            check(&fp->scopeChain());
     }
 };
 
 #endif
 
 /*
  * Don't perform these checks when called from a finalizer. The checking
  * depends on other objects not having been swept yet.
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -752,26 +752,26 @@ JS_PUBLIC_API(JSBool)
 JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fpArg,
                           const jschar *chars, uintN length,
                           const char *filename, uintN lineno,
                           jsval *rval)
 {
     if (!CheckDebugMode(cx))
         return false;
 
-    JSObject *scobj = JS_GetFrameScopeChain(cx, fpArg);
-    if (!scobj)
+    Env *env = JS_GetFrameScopeChain(cx, fpArg);
+    if (!env)
         return false;
 
-    js::AutoCompartment ac(cx, scobj);
+    js::AutoCompartment ac(cx, env);
     if (!ac.enter())
         return false;
 
     StackFrame *fp = Valueify(fpArg);
-    return EvaluateInScope(cx, scobj, fp, chars, length, filename, lineno, rval);
+    return EvaluateInEnv(cx, env, fp, chars, length, filename, lineno, rval);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
                         const char *bytes, uintN length,
                         const char *filename, uintN lineno,
                         jsval *rval)
 {
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -335,17 +335,17 @@ InitExnPrivate(JSContext *cx, JSObject *
                 if (!fp->forEachCanonicalActualArg(AppendArg(values)))
                     return false;
             } else {
                 frame.funName.init(NULL);
                 frame.argc = 0;
             }
             if (fp->isScriptFrame()) {
                 frame.filename = fp->script()->filename;
-                frame.ulineno = js_FramePCToLineNumber(cx, fp, i.pc());
+                frame.ulineno = js_PCToLineNumber(cx, fp->script(), i.pc());
             } else {
                 frame.ulineno = 0;
                 frame.filename = NULL;
             }
         }
     }
 
     /* Do not need overflow check: the vm stack is already bigger. */
@@ -760,17 +760,17 @@ Exception(JSContext *cx, uintN argc, Val
     }
 
     /* Set the 'lineNumber' property. */
     uint32_t lineno;
     if (args.length() > 2) {
         if (!ToUint32(cx, args[2], &lineno))
             return false;
     } else {
-        lineno = iter.done() ? 0 : js_FramePCToLineNumber(cx, iter.fp(), iter.pc());
+        lineno = iter.done() ? 0 : js_PCToLineNumber(cx, iter.fp()->script(), iter.pc());
     }
 
     intN exnType = args.callee().toFunction()->getExtendedSlot(0).toInt32();
     if (!InitExnPrivate(cx, obj, message, filename, lineno, NULL, exnType))
         return false;
 
     args.rval().setObject(*obj);
     return true;
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -2284,22 +2284,17 @@ js_AllocFlatClosure(JSContext *cx, JSFun
 
 JSFunction *
 js_NewFlatClosure(JSContext *cx, JSFunction *fun, JSOp op, size_t oplen)
 {
     /*
      * Flat closures cannot yet be partial, that is, all upvars must be copied,
      * or the closure won't be flattened. Therefore they do not need to search
      * enclosing scope objects via JSOP_NAME, etc.
-     *
-     * FIXME: bug 545759 proposes to enable partial flat closures. Fixing this
-     * bug requires a GetScopeChainFast call here, along with JS_REQUIRES_STACK
-     * annotations on this function's prototype and definition.
      */
-    VOUCH_DOES_NOT_REQUIRE_STACK();
     JSObject *scopeChain = &cx->fp()->scopeChain();
 
     JSFunction *closure = js_AllocFlatClosure(cx, fun, scopeChain);
     if (!closure || !fun->script()->bindings.hasUpvars())
         return closure;
 
     uintN level = fun->script()->staticLevel;
     JSUpvarArray *uva = fun->script()->upvars();
--- a/js/src/jsgcmark.cpp
+++ b/js/src/jsgcmark.cpp
@@ -180,26 +180,16 @@ MarkObjectUnbarriered(JSTracer *trc, JSO
 {
     JS_ASSERT(trc);
     JS_ASSERT(obj);
     JS_SET_TRACING_NAME(trc, name);
     Mark(trc, obj);
 }
 
 void
-MarkObjectWithPrinterUnbarriered(JSTracer *trc, JSObject *obj, JSTraceNamePrinter printer,
-                                 const void *arg, size_t index)
-{
-    JS_ASSERT(trc);
-    JS_ASSERT(obj);
-    JS_SET_TRACING_DETAILS(trc, printer, arg, index);
-    Mark(trc, obj);
-}
-
-void
 MarkObject(JSTracer *trc, const MarkablePtr<JSObject> &obj, const char *name)
 {
     MarkObjectUnbarriered(trc, obj.value, name);
 }
 
 void
 MarkScriptUnbarriered(JSTracer *trc, JSScript *script, const char *name)
 {
@@ -670,40 +660,16 @@ MarkRootRange(JSTracer *trc, jsid *beg, 
 }
 
 void
 MarkRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name)
 {
     MarkIdRangeUnbarriered(trc, len, vec, name);
 }
 
-static void
-PrintPropertyId(char *buf, size_t bufsize, jsid propid, const char *label)
-{
-    JS_ASSERT(!JSID_IS_VOID(propid));
-    if (JSID_IS_ATOM(propid)) {
-        size_t n = PutEscapedString(buf, bufsize, JSID_TO_ATOM(propid), 0);
-        if (n < bufsize)
-            JS_snprintf(buf + n, bufsize - n, " %s", label);
-    } else if (JSID_IS_INT(propid)) {
-        JS_snprintf(buf, bufsize, "%d %s", JSID_TO_INT(propid), label);
-    } else {
-        JS_snprintf(buf, bufsize, "<object> %s", label);
-    }
-}
-
-static void
-PrintPropertyGetterOrSetter(JSTracer *trc, char *buf, size_t bufsize)
-{
-    JS_ASSERT(trc->debugPrinter == PrintPropertyGetterOrSetter);
-    Shape *shape = (Shape *)trc->debugPrintArg;
-    PrintPropertyId(buf, bufsize, shape->propid(),
-                    trc->debugPrintIndex ? js_setter_str : js_getter_str); 
-}
-
 static inline void
 ScanValue(GCMarker *gcmarker, const Value &v)
 {
     if (v.isMarkable()) {
         JSGCTraceKind kind = v.gcKind();
         if (kind == JSTRACE_STRING) {
             PushMarkStack(gcmarker, v.toString());
         } else {
@@ -994,25 +960,20 @@ MarkChildren(JSTracer *trc, const Shape 
     MarkShapeChildrenAcyclic(trc, shape);
     if (shape->previous())
         MarkShape(trc, shape->previous(), "parent");
 }
 
 void
 MarkChildren(JSTracer *trc, BaseShape *base)
 {
-    if (base->hasGetterObject()) {
-        MarkObjectWithPrinterUnbarriered(trc, base->getterObject(),
-                                         PrintPropertyGetterOrSetter, base, 0);
-    }
-
-    if (base->hasSetterObject()) {
-        MarkObjectWithPrinterUnbarriered(trc, base->setterObject(),
-                                         PrintPropertyGetterOrSetter, base, 0);
-    }
+    if (base->hasGetterObject())
+        MarkObjectUnbarriered(trc, base->getterObject(), "getter");
+    if (base->hasSetterObject())
+        MarkObjectUnbarriered(trc, base->setterObject(), "setter");
 
     if (base->isOwned())
         MarkBaseShapeUnbarriered(trc, base->baseUnowned(), "base");
 
     if (JSObject *parent = base->getObjectParent())
         MarkObjectUnbarriered(trc, parent, "parent");
 }
 
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -146,17 +146,16 @@ js::GetScopeChain(JSContext *cx)
  * require bytecode scanning appears below.
  */
 JSObject *
 js::GetBlockChain(JSContext *cx, StackFrame *fp)
 {
     if (!fp->isScriptFrame())
         return NULL;
 
-    /* Assume that imacros don't affect blockChain */
     jsbytecode *target = fp->pcQuadratic(cx->stack);
 
     JSScript *script = fp->script();
     jsbytecode *start = script->code;
 
     /*
      * If the debugger asks for the scope chain at a pc where we are about to
      * fix it up, advance target past the fixup. See bug 672804.
@@ -3079,21 +3078,16 @@ BEGIN_CASE(JSOP_LENGTH)
                 if (js_IsTypedArray(obj)) {
                     JSObject *tarray = TypedArray::getTypedArray(obj);
                     rval = Int32Value(TypedArray::getLength(tarray));
                     break;
                 }
             }
         }
 
-        /*
-         * We do not impose the method read barrier if in an imacro,
-         * assuming any property gets it does (e.g., for 'toString'
-         * from JSOP_NEW) will not be leaked to the calling script.
-         */
         JSObject *obj;
         VALUE_TO_OBJECT(cx, vp, obj);
         JSObject *aobj = js_GetProtoIfDenseArray(obj);
 
         PropertyCacheEntry *entry;
         JSObject *obj2;
         JSAtom *atom;
         JS_PROPERTY_CACHE(cx).test(cx, regs.pc, aobj, obj2, entry, atom);
--- a/js/src/jsinttypes.h
+++ b/js/src/jsinttypes.h
@@ -34,105 +34,41 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jsinttypes_h___
 #define jsinttypes_h___
 
 #include "js-config.h"
 
+#include "mozilla/StdInt.h"
+
 /*
  * Types:
  *   JSInt<N>, JSUint<N> (for <N> = 8, 16, 32, and 64)
  *   JSIntPtr, JSUIntPtr
  *
  * JSInt<N> and JSUint<N> are signed and unsigned types known to be
  * <N> bits long.  Note that neither JSInt8 nor JSUInt8 is necessarily
  * equivalent to a plain "char".
  *
  * JSIntPtr and JSUintPtr are signed and unsigned types capable of
  * holding an object pointer.
  *
- * Use these types in public SpiderMonkey header files, not the
- * corresponding types from the C standard <stdint.h> header.  Windows
- * doesn't support <stdint.h>, and Microsoft says it has no plans to
- * do so in the future; this means that projects that embed
- * SpiderMonkey often take matters into their own hands and define the
- * standard types themselves.  If we define them in our public
- * headers, our definitions may conflict with embedders' (see bug
- * 479258).  The JS* types are in our namespace, and can be used
- * without troubling anyone.
- *
- * Internal SpiderMonkey code wishing to use the type names ISO C
- * defines in the standard header <stdint.h> can #include
- * "jsstdint.h", which provides those types regardless of whether
- * <stdint.h> itself is available.
+ * These typedefs were once necessary to support platforms without a working
+ * <stdint.h> (i.e. MSVC++ prior to 2010).  Now that we ship a custom <stdint.h>
+ * for such compilers, they are no longer necessary and will likely be shortly
+ * removed.
  */
 
-#if defined(JS_HAVE_STDINT_H) || \
-    defined(JS_SYS_TYPES_H_DEFINES_EXACT_SIZE_TYPES)
-
-#if defined(JS_HAVE_STDINT_H)
-#include <stdint.h>
-#else
-#include <sys/types.h>
-#endif
-
 typedef int8_t   JSInt8;
 typedef int16_t  JSInt16;
 typedef int32_t  JSInt32;
 typedef int64_t  JSInt64;
 typedef intptr_t JSIntPtr;
 
 typedef uint8_t   JSUint8;
 typedef uint16_t  JSUint16;
 typedef uint32_t  JSUint32;
 typedef uint64_t  JSUint64;
 typedef uintptr_t JSUintPtr;
 
-#else
-
-#if defined(JS_HAVE___INTN)
-
-typedef __int8  JSInt8;
-typedef __int16 JSInt16;
-typedef __int32 JSInt32;
-typedef __int64 JSInt64;
-
-typedef unsigned __int8 JSUint8;
-typedef unsigned __int16 JSUint16;
-typedef unsigned __int32 JSUint32;
-typedef unsigned __int64 JSUint64;
-
-#elif defined(JS_INT8_TYPE)
-
-typedef signed JS_INT8_TYPE   JSInt8;
-typedef signed JS_INT16_TYPE  JSInt16;
-typedef signed JS_INT32_TYPE  JSInt32;
-typedef signed JS_INT64_TYPE  JSInt64;
-
-typedef unsigned JS_INT8_TYPE   JSUint8;
-typedef unsigned JS_INT16_TYPE  JSUint16;
-typedef unsigned JS_INT32_TYPE  JSUint32;
-typedef unsigned JS_INT64_TYPE  JSUint64;
-
-#else
-#error "couldn't find exact-width integer types"
-#endif
-
-/* Microsoft Visual C/C++ defines intptr_t and uintptr_t in <stddef.h>.  */
-#if defined(JS_STDDEF_H_HAS_INTPTR_T)
-#include <stddef.h>
-typedef intptr_t JSIntPtr;
-typedef uintptr_t JSUintPtr;
-
-/* Failing that, the configure script will have found something.  */
-#elif defined(JS_INTPTR_TYPE)
-typedef signed   JS_INTPTR_TYPE JSIntPtr;
-typedef unsigned JS_INTPTR_TYPE JSUintPtr;
-
-#else
-#error "couldn't find pointer-sized integer types"
-#endif
-
-#endif /* JS_HAVE_STDINT_H */
-
 #endif /* jsinttypes_h___ */
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -81,43 +81,16 @@
 #include "jsstrinlines.h"
 
 #include "vm/NumberObject-inl.h"
 #include "vm/String-inl.h"
 
 using namespace js;
 using namespace js::types;
 
-#ifndef JS_HAVE_STDINT_H /* Native support is innocent until proven guilty. */
-
-JS_STATIC_ASSERT(uint8_t(-1) == UINT8_MAX);
-JS_STATIC_ASSERT(uint16_t(-1) == UINT16_MAX);
-JS_STATIC_ASSERT(uint32_t(-1) == UINT32_MAX);
-JS_STATIC_ASSERT(uint64_t(-1) == UINT64_MAX);
-
-JS_STATIC_ASSERT(INT8_MAX > INT8_MIN);
-JS_STATIC_ASSERT(uint8_t(INT8_MAX) + uint8_t(1) == uint8_t(INT8_MIN));
-JS_STATIC_ASSERT(INT16_MAX > INT16_MIN);
-JS_STATIC_ASSERT(uint16_t(INT16_MAX) + uint16_t(1) == uint16_t(INT16_MIN));
-JS_STATIC_ASSERT(INT32_MAX > INT32_MIN);
-JS_STATIC_ASSERT(uint32_t(INT32_MAX) + uint32_t(1) == uint32_t(INT32_MIN));
-JS_STATIC_ASSERT(INT64_MAX > INT64_MIN);
-JS_STATIC_ASSERT(uint64_t(INT64_MAX) + uint64_t(1) == uint64_t(INT64_MIN));
-
-JS_STATIC_ASSERT(INTPTR_MAX > INTPTR_MIN);
-JS_STATIC_ASSERT(uintptr_t(INTPTR_MAX) + uintptr_t(1) == uintptr_t(INTPTR_MIN));
-JS_STATIC_ASSERT(uintptr_t(-1) == UINTPTR_MAX);
-JS_STATIC_ASSERT(size_t(-1) == SIZE_MAX);
-JS_STATIC_ASSERT(PTRDIFF_MAX > PTRDIFF_MIN);
-JS_STATIC_ASSERT(ptrdiff_t(PTRDIFF_MAX) == PTRDIFF_MAX);
-JS_STATIC_ASSERT(ptrdiff_t(PTRDIFF_MIN) == PTRDIFF_MIN);
-JS_STATIC_ASSERT(uintptr_t(PTRDIFF_MAX) + uintptr_t(1) == uintptr_t(PTRDIFF_MIN));
-
-#endif /* JS_HAVE_STDINT_H */
-
 /*
  * If we're accumulating a decimal number and the number is >= 2^53, then the
  * fast result from the loop in GetPrefixInteger may be inaccurate. Call
  * js_strtod_harder to get the correct answer.
  */
 static bool
 ComputeAccurateDecimalInteger(JSContext *cx, const jschar *start, const jschar *end, jsdouble *dp)
 {
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -112,16 +112,18 @@
 
 #include "jsautooplen.h"
 
 using namespace mozilla;
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
 
+JS_STATIC_ASSERT(int32((JSObject::NELEMENTS_LIMIT - 1) * sizeof(Value)) == int64((JSObject::NELEMENTS_LIMIT - 1) * sizeof(Value)));
+
 Class js::ObjectClass = {
     js_Object_str,
     JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
@@ -4964,42 +4966,27 @@ js_GetClassObject(JSContext *cx, JSObjec
     *objp = cobj;
     return true;
 }
 
 JSBool
 js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey protoKey,
                    Value *vp, Class *clasp)
 {
-    StackFrame *fp;
     JSObject *obj, *cobj, *pobj;
     jsid id;
     JSProperty *prop;
     const Shape *shape;
 
-    /*
-     * Find the global object. Use cx->fp() directly to avoid falling off
-     * trace; all JIT-elided stack frames have the same global object as
-     * cx->fp().
-     */
-    VOUCH_DOES_NOT_REQUIRE_STACK();
-    if (!start && (fp = cx->maybefp()) != NULL)
-        start = &fp->scopeChain();
-
     if (start) {
         obj = start->getGlobal();
+        OBJ_TO_INNER_OBJECT(cx, obj);
     } else {
-        obj = cx->globalObject;
-        if (!obj) {
-            vp->setUndefined();
-            return true;
-        }
-    }
-
-    OBJ_TO_INNER_OBJECT(cx, obj);
+        obj = GetGlobalForScopeChain(cx);
+    }
     if (!obj)
         return false;
 
     if (protoKey != JSProto_Null) {
         JS_ASSERT(JSProto_Null < protoKey);
         JS_ASSERT(protoKey < JSProto_LIMIT);
         if (!js_GetClassObject(cx, obj, protoKey, &cobj))
             return false;
@@ -6750,17 +6737,16 @@ js::FindClassPrototype(JSContext *cx, JS
 /*
  * The first part of this function has been hand-expanded and optimized into
  * NewBuiltinClassInstance in jsobjinlines.h.
  */
 JSBool
 js_GetClassPrototype(JSContext *cx, JSObject *scopeobj, JSProtoKey protoKey,
                      JSObject **protop, Class *clasp)
 {
-    VOUCH_DOES_NOT_REQUIRE_STACK();
     JS_ASSERT(JSProto_Null <= protoKey);
     JS_ASSERT(protoKey < JSProto_LIMIT);
 
     if (protoKey != JSProto_Null) {
         GlobalObject *global;
         if (scopeobj) {
             global = scopeobj->getGlobal();
         } else {
@@ -7005,17 +6991,17 @@ js_ClearNative(JSContext *cx, JSObject *
     }
 
     /* Set all remaining writable plain data properties to undefined. */
     for (Shape::Range r(obj->lastProperty()->all()); !r.empty(); r.popFront()) {
         const Shape *shape = &r.front();
         if (shape->isDataDescriptor() &&
             shape->writable() &&
             shape->hasDefaultSetter() &&
-            obj->containsSlot(shape->slot())) {
+            obj->containsSlot(shape->maybeSlot())) {
             obj->setSlot(shape->slot(), UndefinedValue());
         }
     }
     return true;
 }
 
 bool
 js_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 slot, Value *vp)
@@ -7378,18 +7364,16 @@ MaybeDumpValue(const char *name, const V
         fputc('\n', stderr);
     }
 }
 
 JS_FRIEND_API(void)
 js_DumpStackFrame(JSContext *cx, StackFrame *start)
 {
     /* This should only called during live debugging. */
-    VOUCH_DOES_NOT_REQUIRE_STACK();
-
     FrameRegsIter i(cx, StackIter::GO_THROUGH_SAVED);
     if (!start) {
         if (i.done()) {
             fprintf(stderr, "no stack for cx = %p\n", (void*) cx);
             return;
         }
         start = i.fp();
     } else {
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -526,17 +526,17 @@ struct JSObject : js::gc::Cell
 
     inline js::Shape **nativeSearch(JSContext *cx, jsid id, bool adding = false);
     const js::Shape *nativeLookup(JSContext *cx, jsid id);
 
     inline bool nativeContains(JSContext *cx, jsid id);
     inline bool nativeContains(JSContext *cx, const js::Shape &shape);
 
     /* Upper bound on the number of elements in an object. */
-    static const uint32 NELEMENTS_LIMIT = JS_BIT(29);
+    static const uint32 NELEMENTS_LIMIT = JS_BIT(28);
 
   private:
     js::HeapValue   *slots;     /* Slots for object properties. */
     js::HeapValue   *elements;  /* Slots for object elements. */
 
   public:
 
     inline bool isNative() const;
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -575,18 +575,17 @@ js_Disassemble1(JSContext *cx, JSScript 
       case JOF_OBJECT:
       case JOF_REGEXP: {
         uintN index = js_GetIndexFromBytecode(cx, script, pc, 0);
         jsval v;
         if (type == JOF_ATOM) {
             if (op == JSOP_DOUBLE) {
                 v = script->getConst(index);
             } else {
-                JSAtom *atom;
-                JS_GET_SCRIPT_ATOM(script, pc, index, atom);
+                JSAtom *atom = script->getAtom(index);
                 v = STRING_TO_JSVAL(atom);
             }
         } else {
             JSObject *obj;
             if (type == JOF_OBJECT) {
                 /* Don't call obj.toSource if analysis/inference is active. */
                 if (cx->compartment->activeAnalysis) {
                     Sprint(sp, " object");
@@ -669,18 +668,17 @@ js_Disassemble1(JSContext *cx, JSScript 
         break;
 
       case JOF_SLOTATOM:
       case JOF_SLOTOBJECT: {
         Sprint(sp, " %u", GET_SLOTNO(pc));
         uintN index = js_GetIndexFromBytecode(cx, script, pc, SLOTNO_LEN);
         jsval v;
         if (type == JOF_SLOTATOM) {
-            JSAtom *atom;
-            JS_GET_SCRIPT_ATOM(script, pc, index, atom);
+            JSAtom *atom = script->getAtom(index);
             v = STRING_TO_JSVAL(atom);
         } else {
             v = OBJECT_TO_JSVAL(script->getObject(index));
         }
 
         JSAutoByteString bytes;
         if (!ToDisassemblySource(cx, v, &bytes))
             return 0;
@@ -4344,17 +4342,16 @@ Decompile(SprintStack *ss, jsbytecode *p
                             table[j].order = j;
                             j++;
                         }
                         pc2 += jmplen;
                     }
                     tmp = (TableEntry *)
                           cx->malloc_((size_t)j * sizeof *table);
                     if (tmp) {
-                        VOUCH_DOES_NOT_REQUIRE_STACK();
                         MergeSort(table, size_t(j), tmp, CompareTableEntries);
                         Foreground::free_(tmp);
                         ok = true;
                     } else {
                         ok = false;
                     }
                 }
 
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -337,17 +337,17 @@ js_GetIndexFromBytecode(JSContext *cx, J
 /*
  * A slower version of GET_ATOM when the caller does not want to maintain
  * the index segment register itself.
  */
 #define GET_ATOM_FROM_BYTECODE(script, pc, pcoff, atom)                       \
     JS_BEGIN_MACRO                                                            \
         JS_ASSERT(*(pc) != JSOP_DOUBLE);                                      \
         uintN index_ = js_GetIndexFromBytecode(cx, (script), (pc), (pcoff));  \
-        JS_GET_SCRIPT_ATOM(script, pc, index_, atom);                         \
+        (atom) = (script)->getAtom(index_);                                   \
     JS_END_MACRO
 
 #define GET_DOUBLE_FROM_BYTECODE(script, pc, pcoff, dbl)                      \
     JS_BEGIN_MACRO                                                            \
         uintN index_ = js_GetIndexFromBytecode(cx, (script), (pc), (pcoff));  \
         JS_ASSERT(index_ < (script)->consts()->length);                       \
         (dbl) = (script)->getConst(index_).toDouble();                        \
     JS_END_MACRO
--- a/js/src/jspropertycache.cpp
+++ b/js/src/jspropertycache.cpp
@@ -114,17 +114,17 @@ PropertyCache::fill(JSContext *cx, JSObj
         return JS_NO_PROP_CACHE_FILL;
     }
 
     /*
      * Optimize the cached vword based on our parameters and the current pc's
      * opcode format flags.
      */
     jsbytecode *pc;
-    JSScript *script = cx->stack.currentScript(&pc);
+    (void) cx->stack.currentScript(&pc);
     op = JSOp(*pc);
     cs = &js_CodeSpec[op];
 
     if ((cs->format & JOF_SET) && obj->watched())
         return JS_NO_PROP_CACHE_FILL;
 
     if (obj == pobj) {
         JS_ASSERT(scopeIndex == 0 && protoIndex == 0);
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -238,16 +238,24 @@ class Debugger;
 class WatchpointMap;
 
 typedef HashMap<JSAtom *,
                 detail::RegExpPrivateCacheValue,
                 DefaultHasher<JSAtom *>,
                 RuntimeAllocPolicy>
     RegExpPrivateCache;
 
+/*
+ * Env is the type of what ES5 calls "lexical environments" (runtime
+ * activations of lexical scopes). This is currently just JSObject, and is
+ * implemented by Call, Block, With, and DeclEnv objects, among others--but
+ * environments and objects are really two different concepts.
+ */
+typedef JSObject Env;
+
 typedef JSNative             Native;
 typedef JSPropertyOp         PropertyOp;
 typedef JSStrictPropertyOp   StrictPropertyOp;
 typedef JSPropertyDescriptor PropertyDescriptor;
 
 namespace analyze {
 
 struct LifetimeVariable;
--- a/js/src/jsscope.h
+++ b/js/src/jsscope.h
@@ -503,17 +503,17 @@ struct Shape : public js::gc::Cell
     HeapPtrBaseShape    base_;
     HeapId              propid_;
 
     JS_ENUM_HEADER(SlotInfo, uint32)
     {
         /* Number of fixed slots in objects with this shape. */
         FIXED_SLOTS_MAX        = 0x1f,
         FIXED_SLOTS_SHIFT      = 27,
-        FIXED_SLOTS_MASK       = FIXED_SLOTS_MAX << FIXED_SLOTS_SHIFT,
+        FIXED_SLOTS_MASK       = uint32(FIXED_SLOTS_MAX << FIXED_SLOTS_SHIFT),
 
         /* 
          * numLinearSearches starts at zero and is incremented initially on
          * search() calls. Once numLinearSearches reaches LINEAR_SEARCHES_MAX,
          * the table is created on the next search() call. The table can also
          * be created when hashifying for dictionary mode.
          */
         LINEAR_SEARCHES_MAX    = 0x7,
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1438,22 +1438,16 @@ js_GetSrcNoteCached(JSContext *cx, JSScr
             cache->code = script->code;
         }
     }
 
     return result;
 }
 
 uintN
-js_FramePCToLineNumber(JSContext *cx, StackFrame *fp, jsbytecode *pc)
-{
-    return js_PCToLineNumber(cx, fp->script(), pc);
-}
-
-uintN
 js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
 {
     /* Cope with StackFrame.pc value prior to entering js_Interpret. */
     if (!pc)
         return 0;
 
     /*
      * Special case: function definition needs no line number note because
@@ -1559,32 +1553,32 @@ js_GetScriptLineExtent(JSScript *script)
     return 1 + lineno - script->lineno;
 }
 
 namespace js {
 
 uintN
 CurrentLine(JSContext *cx)
 {
-    return js_FramePCToLineNumber(cx, cx->fp(), cx->regs().pc);
+    return js_PCToLineNumber(cx, cx->fp()->script(), cx->regs().pc);
 }
 
 const char *
 CurrentScriptFileAndLineSlow(JSContext *cx, uintN *linenop)
 {
     FrameRegsIter iter(cx);
     while (!iter.done() && !iter.fp()->isScriptFrame())
         ++iter;
 
     if (iter.done()) {
         *linenop = 0;
         return NULL;
     }
 
-    *linenop = js_FramePCToLineNumber(cx, iter.fp(), iter.pc());
+    *linenop = js_PCToLineNumber(cx, iter.fp()->script(), iter.pc());
     return iter.fp()->script()->filename;
 }
 
 }  /* namespace js */
 
 class DisablePrincipalsTranscoding {
     JSSecurityCallbacks *callbacks;
     JSPrincipalsTranscoder temp;
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -816,33 +816,16 @@ JS_STATIC_ASSERT(sizeof(JSScript) % js::
 #define SHARP_NSLOTS            2       /* [#array, #depth] slots if the script
                                            uses sharp variables */
 static JS_INLINE uintN
 StackDepth(JSScript *script)
 {
     return script->nslots - script->nfixed;
 }
 
-/*
- * If pc_ does not point within script_'s bytecode, then it must point into an
- * imacro body, so we use cx->runtime common atoms instead of script_'s atoms.
- * This macro uses cx from its callers' environments in the pc-in-imacro case.
- */
-#define JS_GET_SCRIPT_ATOM(script_, pc_, index, atom)                         \
-    JS_BEGIN_MACRO                                                            \
-        if ((pc_) < (script_)->code ||                                        \
-            (script_)->code + (script_)->length <= (pc_)) {                   \
-            JS_ASSERT((size_t)(index) < js_common_atom_count);                \
-            (atom) = cx->runtime->atomState.commonAtomsStart()[index];        \
-        } else {                                                              \
-            (atom) = script_->getAtom(index);                                 \
-        }                                                                     \
-    JS_END_MACRO
-
-
 extern void
 js_MarkScriptFilename(const char *filename);
 
 extern void
 js_SweepScriptFilenames(JSCompartment *comp);
 
 /*
  * New-script-hook calling is factored from NewScriptFromEmitter so that it
@@ -879,24 +862,16 @@ CheckScript(JSScript *script, JSScript *
  * cache without adding an explicit cx parameter.  Thus js_GetSrcNote becomes
  * a macro that uses cx from its calls' lexical environments.
  */
 #define js_GetSrcNote(script,pc) js_GetSrcNoteCached(cx, script, pc)
 
 extern jssrcnote *
 js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc);
 
-/*
- * NOTE: use js_FramePCToLineNumber(cx, fp) when you have an active fp, in
- * preference to js_PCToLineNumber (cx, fp->script  fp->regs->pc), because
- * fp->imacpc may be non-null, indicating an active imacro.
- */
-extern uintN
-js_FramePCToLineNumber(JSContext *cx, js::StackFrame *fp, jsbytecode *pc);
-
 extern uintN
 js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
 
 extern jsbytecode *
 js_LineNumberToPC(JSScript *script, uintN lineno);
 
 extern JS_FRIEND_API(uintN)
 js_GetScriptLineExtent(JSScript *script);
--- a/js/src/jsstdint.h
+++ b/js/src/jsstdint.h
@@ -33,90 +33,17 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /*
- * This header provides definitions for the <stdint.h> types we use,
- * even on systems that lack <stdint.h>.
- *
- * NOTE: This header should only be included in private SpiderMonkey
- * code; public headers should use only the JS{Int,Uint}N types; see
- * the comment for them in "jsinttypes.h".
- *
- * At the moment, these types are not widely used within SpiderMonkey;
- * this file is meant to make existing uses portable, and to allow us
- * to transition portably to using them more, if desired.
+ * This header implements the functionality of <stdint.h>, even on systems that
+ * lack it.  It does so by completely delegating to a separate header, which
+ * could just as easily be used.  However, as this header is part of the
+ * SpiderMonkey interface, we retain it for compatibility.
  */
-
 #ifndef jsstdint_h___
 #define jsstdint_h___
-
-#include "jsinttypes.h"
-
-/* If we have a working stdint.h, then jsinttypes.h has already
-   defined the standard integer types.  Otherwise, define the standard
-   names in terms of the 'JS' types.  */
-#if ! defined(JS_HAVE_STDINT_H) && \
-    ! defined(JS_SYS_TYPES_H_DEFINES_EXACT_SIZE_TYPES)
-
-typedef JSInt8  int8_t;
-typedef JSInt16 int16_t;
-typedef JSInt32 int32_t;
-typedef JSInt64 int64_t;
-
-typedef JSUint8  uint8_t;
-typedef JSUint16 uint16_t;
-typedef JSUint32 uint32_t;
-typedef JSUint64 uint64_t;
-
-/* Suppress other, conflicting attempts to define stdint-bits. */
-#define _STDINT_H
-
-/* If JS_STDDEF_H_HAS_INTPTR_T or JS_CRTDEFS_H_HAS_INTPTR_T are
-   defined, then jsinttypes.h included the given header, which
-   introduced definitions for intptr_t and uintptr_t.  Otherwise,
-   define the standard names in terms of the 'JS' types.  */
-#if !defined(JS_STDDEF_H_HAS_INTPTR_T) && !defined(JS_CRTDEFS_H_HAS_INTPTR_T)
-typedef JSIntPtr  intptr_t;
-typedef JSUintPtr uintptr_t;
-#endif
-
-#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS)
-
-#define INT8_MAX  127
-#define INT8_MIN  (-INT8_MAX - 1)
-#define INT16_MAX 32767
-#define INT16_MIN (-INT16_MAX - 1)
-#define INT32_MAX 2147483647
-#define INT32_MIN (-INT32_MAX - 1)
-#define INT64_MAX 9223372036854775807LL
-#define INT64_MIN (-INT64_MAX - 1)
-
-#define UINT8_MAX  255
-#define UINT16_MAX 65535
-#define UINT32_MAX 4294967295U
-#define UINT64_MAX 18446744073709551615ULL
-
-/*
- * These are technically wrong as they can't be used in the preprocessor, but
- * we would require compiler assistance, and at the moment we don't need
- * preprocessor-correctness.
- */
-#ifdef _MSC_VER
-#undef SIZE_MAX
-#endif
-
-#define INTPTR_MAX  ((intptr_t) (UINTPTR_MAX >> 1))
-#define INTPTR_MIN  (intptr_t(uintptr_t(INTPTR_MAX) + uintptr_t(1)))
-#define UINTPTR_MAX ((uintptr_t) -1)
-#define SIZE_MAX UINTPTR_MAX
-#define PTRDIFF_MAX INTPTR_MAX
-#define PTRDIFF_MIN INTPTR_MIN
-
-#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */
-
-#endif /* JS_HAVE_STDINT_H */
-
+#include "mozilla/StdInt.h"
 #endif /* jsstdint_h___ */
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -85,44 +85,51 @@
 #include "vm/String-inl.h"
 
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
 using namespace js::unicode;
 
 static JSLinearString *
-ArgToRootedString(JSContext *cx, uintN argc, Value *vp, uintN arg)
+ArgToRootedString(JSContext *cx, CallArgs &args, uintN argno)
 {
-    if (arg >= argc)
+    if (argno >= args.length())
         return cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
-    vp += 2 + arg;
-
-    if (!ToPrimitive(cx, JSTYPE_STRING, vp))
+
+    Value *arg = &args[argno];
+    if (!ToPrimitive(cx, JSTYPE_STRING, arg))
         return NULL;
 
     JSLinearString *str;
-    if (vp->isString()) {
-        str = vp->toString()->ensureLinear(cx);
-    } else if (vp->isBoolean()) {
-        str = cx->runtime->atomState.booleanAtoms[(int)vp->toBoolean()];
-    } else if (vp->isNull()) {
+    if (arg->isString()) {
+        str = arg->toString()->ensureLinear(cx);
+    } else if (arg->isBoolean()) {
+        str = cx->runtime->atomState.booleanAtoms[(int)arg->toBoolean()];
+    } else if (arg->isNull()) {
         str = cx->runtime->atomState.nullAtom;
-    } else if (vp->isUndefined()) {
+    } else if (arg->isUndefined()) {
         str = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
-    }
-    else {
-        str = NumberToString(cx, vp->toNumber());
+    } else {
+        str = NumberToString(cx, arg->toNumber());
         if (!str)
             return NULL;
-        vp->setString(str);
+        arg->setString(str);
     }
+
     return str;
 }
 
+static JSLinearString *
+ArgToRootedString(JSContext *cx, uintN argc, Value *vp, uintN argno)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return ArgToRootedString(cx, args, argno);
+}
+
 /*
  * Forward declarations for URI encode/decode and helper routines
  */
 static JSBool
 str_decodeURI(JSContext *cx, uintN argc, Value *vp);
 
 static JSBool
 str_decodeURI_Component(JSContext *cx, uintN argc, Value *vp);
@@ -233,78 +240,138 @@ str_escape(JSContext *cx, uintN argc, Va
     if (!retstr) {
         cx->free_(newchars);
         return JS_FALSE;
     }
     vp->setString(retstr);
     return JS_TRUE;
 }
 
+static inline bool
+Unhex4(const jschar *chars, jschar *result)
+{
+    jschar a = chars[0],
+           b = chars[1],
+           c = chars[2],
+           d = chars[3];
+
+    if (!(JS7_ISHEX(a) && JS7_ISHEX(b) && JS7_ISHEX(c) && JS7_ISHEX(d)))
+        return false;
+
+    *result = (((((JS7_UNHEX(a) << 4) + JS7_UNHEX(b)) << 4) + JS7_UNHEX(c)) << 4) + JS7_UNHEX(d);
+    return true;
+}
+
+static inline bool
+Unhex2(const jschar *chars, jschar *result)
+{
+    jschar a = chars[0],
+           b = chars[1];
+
+    if (!(JS7_ISHEX(a) && JS7_ISHEX(b)))
+        return false;
+
+    *result = (JS7_UNHEX(a) << 4) + JS7_UNHEX(b);
+    return true;
+}
+
 /* ES5 B.2.2 */
 static JSBool
 str_unescape(JSContext *cx, uintN argc, Value *vp)
 {
-    JSLinearString *str = ArgToRootedString(cx, argc, vp, 0);
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    /* Step 1. */
+    JSLinearString *str = ArgToRootedString(cx, args, 0);
     if (!str)
         return false;
 
+    /* Step 2. */
     size_t length = str->length();
     const jschar *chars = str->chars();
 
-    /* Start by allocating the maximum required space for the new string. */
-    jschar *newchars = (jschar *) cx->malloc_((length + 1) * sizeof(jschar));
-    if (!newchars)
-        return false;
-
-    size_t ni = 0, i = 0;
-    bool escapeFound = false;
-    while (i < length) {
-        jschar ch = chars[i++];
-        if (ch == '%') {
-            /* Incomplete escapes are interpreted as literal characters. */
-            if (i + 1 < length &&
-                JS7_ISHEX(chars[i]) && JS7_ISHEX(chars[i + 1]))
-            {
-                ch = JS7_UNHEX(chars[i]) * 16 + JS7_UNHEX(chars[i + 1]);
-                i += 2;
-                escapeFound = true;
-            } else if (i + 4 < length && chars[i] == 'u' &&
-                       JS7_ISHEX(chars[i + 1]) && JS7_ISHEX(chars[i + 2]) &&
-                       JS7_ISHEX(chars[i + 3]) && JS7_ISHEX(chars[i + 4]))
-            {
-                ch = (((((JS7_UNHEX(chars[i + 1]) << 4)
-                        + JS7_UNHEX(chars[i + 2])) << 4)
-                      + JS7_UNHEX(chars[i + 3])) << 4)
-                    + JS7_UNHEX(chars[i + 4]);
-                i += 5;
-                escapeFound = true;
+    /* Step 3. */
+    StringBuffer sb(cx);
+
+    /*
+     * Note that the spec algorithm has been optimized to avoid building
+     * a string in the case where no escapes are present.
+     */
+
+    /* Step 4. */
+    size_t k = 0;
+    bool building = false;
+
+    while (true) {
+        /* Step 5. */
+        if (k == length) {
+            JSLinearString *result;
+            if (building) {
+                result = sb.finishString();
+                if (!result)
+                    return false;
+            } else {
+                result = str;
             }
+
+            args.rval().setString(result);
+            return true;
         }
-        newchars[ni++] = ch;
+
+        /* Step 6. */
+        jschar c = chars[k];
+
+        /* Step 7. */
+        if (c != '%')
+            goto step_18;
+
+        /* Step 8. */
+        if (k > length - 6)
+            goto step_14;
+
+        /* Step 9. */
+        if (chars[k + 1] != 'u')
+            goto step_14;
+
+#define ENSURE_BUILDING                             \
+    JS_BEGIN_MACRO                                  \
+        if (!building) {                            \
+            building = true;                        \
+            if (!sb.reserve(length))                \
+                return false;                       \
+            sb.infallibleAppend(chars, chars + k);  \
+        }                                           \
+    JS_END_MACRO
+
+        /* Step 10-13. */
+        if (Unhex4(&chars[k + 2], &c)) {
+            ENSURE_BUILDING;
+            k += 5;
+            goto step_18;
+        }
+
+      step_14:
+        /* Step 14. */
+        if (k > length - 3)
+            goto step_18;
+
+        /* Step 15-17. */
+        if (Unhex2(&chars[k + 1], &c)) {
+            ENSURE_BUILDING;
+            k += 2;
+        }
+
+      step_18:
+        if (building)
+            sb.infallibleAppend(c);
+
+        /* Step 19. */
+        k += 1;
     }
-    newchars[ni] = 0;
-
-    /* If escapes were found, shrink the string. */
-    if (escapeFound) {
-        JS_ASSERT(ni < length);
-        jschar *tmpchars = (jschar *) cx->realloc_(newchars, (ni + 1) * sizeof(jschar));
-        if (!tmpchars) {
-            cx->free_(newchars);
-            return false;
-        }
-        newchars = tmpchars;
-    }
-
-    JSString *retstr = js_NewString(cx, newchars, ni);
-    if (!retstr) {
-        cx->free_(newchars);
-        return false;
-    }
-    vp->setString(retstr);
-    return true;
+#undef ENSURE_BUILDING
 }
 
 #if JS_HAS_UNEVAL
 static JSBool
 str_uneval(JSContext *cx, uintN argc, Value *vp)
 {
     JSString *str;
 
@@ -3072,18 +3139,17 @@ StringBuffer::extractWellSized()
     size_t length = cb.length();
 
     jschar *buf = cb.extractRawBuffer();
     if (!buf)
         return NULL;
 
     /* For medium/big buffers, avoid wasting more than 1/4 of the memory. */
     JS_ASSERT(capacity >= length);
-    if (length > CharBuffer::sMaxInlineStorage &&
-        capacity - length > (length >> 2)) {
+    if (length > CharBuffer::sMaxInlineStorage && capacity - length > length / 4) {
         size_t bytes = sizeof(jschar) * (length + 1);
         JSContext *cx = context();
         jschar *tmp = (jschar *)cx->realloc_(buf, bytes);
         if (!tmp) {
             cx->free_(buf);
             return NULL;
         }
         buf = tmp;
--- a/js/src/jsstrinlines.h
+++ b/js/src/jsstrinlines.h
@@ -48,16 +48,23 @@
 #include "vm/String-inl.h"
 
 namespace js {
 
 /*
  * String builder that eagerly checks for over-allocation past the maximum
  * string length.
  *
+ * Any operation which would exceed the maximum string length causes an
+ * exception report on the context and results in a failed return value.
+ *
+ * Well-sized extractions (which waste no more than 1/4 of their char
+ * buffer space) are guaranteed for strings built by this interface.
+ * See |extractWellSized|.
+ *
  * Note: over-allocation is not checked for when using the infallible
  * |replaceRawBuffer|, so the implementation of |finishString| also must check
  * for over-allocation.
  */
 class StringBuffer
 {
     /* cb's buffer is taken by the new string so use ContextAllocPolicy. */
     typedef Vector<jschar, 32, ContextAllocPolicy> CharBuffer;
--- a/js/src/jsutil.h
+++ b/js/src/jsutil.h
@@ -373,22 +373,19 @@ enum MaybeReportError { REPORT_ERROR = t
 /* Static control-flow checks. */
 #ifdef NS_STATIC_CHECKING
 /* Trigger a control flow check to make sure that code flows through label */
 inline __attribute__ ((unused)) void MUST_FLOW_THROUGH(const char *label) {}
 
 /* Avoid unused goto-label warnings. */
 # define MUST_FLOW_LABEL(label) goto label; label:
 
-inline JS_FORCES_STACK void VOUCH_DOES_NOT_REQUIRE_STACK() {}
-
 #else
 # define MUST_FLOW_THROUGH(label)            ((void) 0)
 # define MUST_FLOW_LABEL(label)
-# define VOUCH_DOES_NOT_REQUIRE_STACK()      ((void) 0)
 #endif
 
 /* Crash diagnostics */
 #ifdef DEBUG
 # define JS_CRASH_DIAGNOSTICS 1
 #endif
 #ifdef JS_CRASH_DIAGNOSTICS
 # define JS_POISON(p, val, size) memset((p), (val), (size))
@@ -438,11 +435,9 @@ JS_DumpHistogram(JSBasicStats *bs, FILE 
 typedef size_t jsbitmap;
 #define JS_TEST_BIT(_map,_bit)  ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] &      \
                                  ((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
 #define JS_SET_BIT(_map,_bit)   ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] |=     \
                                  ((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
 #define JS_CLEAR_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] &=     \
                                  ~((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
 
-#define VOUCH_HAVE_STACK                    VOUCH_DOES_NOT_REQUIRE_STACK
-
 #endif /* jsutil_h___ */
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -1792,17 +1792,17 @@ ParseXMLSource(JSContext *cx, JSString *
     xml = NULL;
     filename = NULL;
     lineno = 1;
     FrameRegsIter i(cx);
     if (!i.done()) {
         op = (JSOp) *i.pc();
         if (op == JSOP_TOXML || op == JSOP_TOXMLLIST) {
             filename = i.fp()->script()->filename;
-            lineno = js_FramePCToLineNumber(cx, i.fp(), i.pc());
+            lineno = js_PCToLineNumber(cx, i.fp()->script(), i.pc());
             for (endp = srcp + srclen; srcp < endp; srcp++) {
                 if (*srcp == '\n')
                     --lineno;
             }
         }
     }
 
     {
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -1568,17 +1568,17 @@ mjit::Compiler::generateMethod()
                 fixedDoubleToAnyEntries.clear();
 
                 /*
                  * Watch for fallthrough to the head of a 'do while' loop.
                  * We don't know what register state we will be using at the head
                  * of the loop so sync, branch, and fix it up after the loop
                  * has been processed.
                  */
-                if (cx->typeInferenceEnabled() && op == JSOP_LOOPHEAD) {
+                if (cx->typeInferenceEnabled() && op == JSOP_LOOPHEAD && analysis->getLoop(PC)) {
                     frame.syncAndForgetEverything();
                     Jump j = masm.jump();
                     if (!startLoop(PC, j, PC))
                         return Compile_Error;
                 } else {
                     Label start = masm.label();
                     if (!frame.syncForBranch(PC, Uses(0)))
                         return Compile_Error;
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -1473,21 +1473,16 @@ InlineGetProp(VMFrame &f)
     }
 
     JSObject *obj = ValueToObject(f.cx, vp);
     if (!obj)
         return false;
 
     Value rval;
     do {
-        /*
-         * We do not impose the method read barrier if in an imacro,
-         * assuming any property gets it does (e.g., for 'toString'
-         * from JSOP_NEW) will not be leaked to the calling script.
-         */
         JSObject *aobj = js_GetProtoIfDenseArray(obj);
 
         PropertyCacheEntry *entry;
         JSObject *obj2;
         JSAtom *atom;
         JS_PROPERTY_CACHE(cx).test(cx, f.pc(), aobj, obj2, entry, atom);
         if (!atom) {
             NATIVE_GET(cx, obj, obj2, entry->prop, JSGET_METHOD_BARRIER, &rval, return false);
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -4116,17 +4116,38 @@ static const char *const shell_help_mess
 "    \"-l\" (show line numbers)",
 "dissrc([fun])            Disassemble functions with source lines",
 "dumpHeap([fileName[, start[, toFind[, maxDepth[, toIgnore]]]]])\n"
 "  Interface to JS_DumpHeap with output sent to file",
 "dumpObject()             Dump an internal representation of an object",
 "notes([fun])             Show source notes for functions",
 "stats([string ...])      Dump 'arena', 'atom', 'global' stats",
 "findReferences(target)\n"
-"  Walk the heap and return an object describing all references to target",
+"  Walk the entire heap, looking for references to |target|, and return a\n"
+"  \"references object\" describing what we found.\n"
+"\n"
+"  Each property of the references object describes one kind of reference. The\n"
+"  property's name is the label supplied to MarkObject, JS_CALL_TRACER, or what\n"
+"  have you, prefixed with \"edge: \" to avoid collisions with system properties\n"
+"  (like \"toString\" and \"__proto__\"). The property's value is an array of things\n"
+"  that refer to |thing| via that kind of reference. Ordinary references from\n"
+"  one object to another are named after the property name (with the \"edge: \"\n"
+"  prefix).\n"
+"\n"
+"  Garbage collection roots appear as references from 'null'. We use the name\n"
+"  given to the root (with the \"edge: \" prefix) as the name of the reference.\n"
+"\n"
+"  Note that the references object does record references from objects that are\n"
+"  only reachable via |thing| itself, not just the references reachable\n"
+"  themselves from roots that keep |thing| from being collected. (We could make\n"
+"  this distinction if it is useful.)\n"
+"\n"
+"  If any references are found by the conservative scanner, the references\n"
+"  object will have a property named \"edge: machine stack\"; the referrers will\n"
+"  be 'null', because they are roots.",
 #endif
 "dumpStack()              Dump the stack as an array of callees (youngest first)",
 #ifdef TEST_CVTARGS
 "cvtargs(arg1..., arg12)  Test argument formatter",
 #endif
 "build()                  Show build date and time",
 "clear([obj])             Clear properties of object",
 "intern(str)              Internalize str in the atom table",
--- a/js/src/shell/jsheaptools.cpp
+++ b/js/src/shell/jsheaptools.cpp
@@ -9,25 +9,25 @@
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
  * Software distributed under the License is distributed on an "AS IS" basis,
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  * for the specific language governing rights and limitations under the
  * License.
  *
- * The Original Code is JavaScript shell workers.
+ * The Original Code is JavaScript heap tools.
  *
  * The Initial Developer of the Original Code is
  * Mozilla Corporation.
  * Portions created by the Initial Developer are Copyright (C) 2010
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
- *   Jason Orendorff <jorendorff@mozilla.com>
+ *   Jim Blandy <jimb@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -546,42 +546,17 @@ ReferenceFinder::findReferences(JSObject
     if (!result)
         return NULL;
     if (!visit(target, NULL))
         return NULL;
 
     return result;
 }
 
-/*
- * findReferences(thing)
- *
- * Walk the entire heap, looking for references to |thing|, and return a
- * "references object" describing what we found.
- *
- * Each property of the references object describes one kind of reference. The
- * property's name is the label supplied to MarkObject, JS_CALL_TRACER, or what
- * have you, prefixed with "edge: " to avoid collisions with system properties
- * (like "toString" and "__proto__"). The property's value is an array of things
- * that refer to |thing| via that kind of reference. Ordinary references from
- * one object to another are named after the property name (with the "edge: "
- * prefix).
- *
- * Garbage collection roots appear as references from 'null'. We use the name
- * given to the root (with the "edge: " prefix) as the name of the reference.
- *
- * Note that the references object does record references from objects that are
- * only reachable via |thing| itself, not just the references reachable
- * themselves from roots that keep |thing| from being collected. (We could make
- * this distinction if it is useful.)
- *
- * If any references are found by the conservative scanner, the references
- * object will have a property named "edge: machine stack"; the referrers will
- * be 'null', because they are roots.
- */
+/* See help(findReferences). */
 JSBool
 FindReferences(JSContext *cx, uintN argc, jsval *vp)
 {
     if (argc < 1) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
                              "findReferences", "0", "s");
         return false;
     }
--- a/js/src/tests/js1_8/extensions/regress-422269.js
+++ b/js/src/tests/js1_8/extensions/regress-422269.js
@@ -33,56 +33,64 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 //-----------------------------------------------------------------------------
 var BUGNUMBER = 422269;
 var summary = 'Compile-time let block should not capture runtime references';
-var actual = 'No leak';
-var expect = 'No leak';
+var actual = 'referenced only by stack and closure';
+var expect = 'referenced only by stack and closure';
 
 
 //-----------------------------------------------------------------------------
 test();
 
 //-----------------------------------------------------------------------------
 
 function test()
 {
   enterFunc ('test');
   printBugNumber(BUGNUMBER);
   printStatus (summary);
 
   function f()
   {
     let m = {sin: Math.sin};
-    (function() { m.sin(1); })();
+    (function holder() { m.sin(1); })();
     return m;
   }
 
-  if (typeof countHeap == 'undefined')
+  if (typeof findReferences == 'undefined')
   {
     expect = actual = 'Test skipped';
-    print('Test skipped. Requires countHeap function.');
+    print('Test skipped. Requires findReferences function.');
   }
   else
   {
     var x = f();
-    f(); // overwrite the machine stack with new objects
-    gc();
-    var n = countHeap();
-    x = null;
-    // When running with the method JIT, null may not get stored to memory right away.
-    // Calling eval ensures that all values are stored out so that the old x is no
-    // longer rooted from the stack.
-    eval("");
-    gc();
+    var refs = findReferences(x);
 
-    var n2 = countHeap();
-    if (n2 >= n)
-      actual = "leak is detected, something roots the result of f";
+    // At this point, x should only be referenced from the stack --- the
+    // variable 'x' itself, and any random things the conservative scanner
+    // finds --- and possibly from the 'holder' closure, which could itself
+    // be held alive for random reasons. Remove those from the refs list, and 
+    // then complain if anything is left.
+    for (var edge in refs) {
+      // Remove references from roots, like the stack.
+      if (refs[edge].every(function (r) r === null))
+        delete refs[edge];
+      // Remove references from the closure, which could be held alive for
+      // random reasons.
+      else if (refs[edge].length === 1 &&
+               typeof refs[edge][0] === "function" &&
+               refs[edge][0].name === "holder")
+        delete refs[edge];
+    }
+
+    if (Object.keys(refs).length != 0)
+        actual = "unexpected references to the result of f: " + Object.keys(refs).join(", ");
   }
   reportCompare(expect, actual, summary);
 
   exitFunc ('test');
 }
--- a/js/src/tests/js1_8_5/extensions/findReferences-01.js
+++ b/js/src/tests/js1_8_5/extensions/findReferences-01.js
@@ -6,41 +6,41 @@ if (typeof findReferences == "function")
     function C() {}
     var o = new C;
     o.x = {};               // via ordinary property
     o[42] = {};             // via numeric property
     o.myself = o;           // self-references should be reported
     o.alsoMyself = o;       // multiple self-references should all be reported
 
     assertEq(referencesVia(o, 'type; type_proto', C.prototype), true);
-    assertEq(referencesVia(o, 'parent', this), true);
+    assertEq(referencesVia(o, 'shape; base; parent', this), true);
     assertEq(referencesVia(o, 'x', o.x), true);
     assertEq(referencesVia(o, '42', o[42]), true);
     assertEq(referencesVia(o, 'myself', o), true);
     assertEq(referencesVia(o, 'alsoMyself', o), true);
 
     function g() { return 42; }
     function s(v) { }
     var p = Object.defineProperty({}, 'a', { get:g, set:s });
-    assertEq(referencesVia(p, 'shape; a getter', g), true);
-    assertEq(referencesVia(p, 'shape; a setter', s), true);
+    assertEq(referencesVia(p, 'shape; base; getter', g), true);
+    assertEq(referencesVia(p, 'shape; base; setter', s), true);
 
     // If there are multiple objects with the same shape referring to a getter
     // or setter, findReferences should get all of them, even though the shape
     // gets 'marked' the first time we visit it.
     var q = Object.defineProperty({}, 'a', { get:g, set:s });
-    assertEq(referencesVia(p, 'shape; a getter', g), true);
-    assertEq(referencesVia(q, 'shape; a getter', g), true);
+    assertEq(referencesVia(p, 'shape; base; getter', g), true);
+    assertEq(referencesVia(q, 'shape; base; getter', g), true);
 
     // If we extend each object's shape chain, both should still be able to
     // reach the getter, even though the two shapes are each traversed twice.
     p.b = 9;
     q.b = 9;
-    assertEq(referencesVia(p, 'shape; a getter', g), true);
-    assertEq(referencesVia(q, 'shape; a getter', g), true);
+    assertEq(referencesVia(p, 'shape; parent; base; getter', g), true);
+    assertEq(referencesVia(q, 'shape; parent; base; getter', g), true);
 
     // These are really just ordinary own property references.
     assertEq(referencesVia(C, 'prototype', Object.getPrototypeOf(o)), true);
     assertEq(referencesVia(Object.getPrototypeOf(o), 'constructor', C), true);
 
     // Dense arrays should work, too.
     a = [];
     a[1] = o;
--- a/js/src/tests/js1_8_5/extensions/findReferences-02.js
+++ b/js/src/tests/js1_8_5/extensions/findReferences-02.js
@@ -8,21 +8,21 @@ if (typeof findReferences == "function")
      })();
 
     var o = ({});
 
     function returnFlat(x) { return function flat() { return x; }; }
     assertEq(referencesVia(returnFlat(o), 'upvars[0]', o), true);
 
     function returnHeavy(y) { eval(''); return function heavy() { return y; }; }
-    assertEq(referencesVia(returnHeavy(o), 'parent; y', o), true);
-    assertEq(referencesVia(returnHeavy(o), 'parent; parent', this), true);
+    assertEq(referencesVia(returnHeavy(o), 'fun_callscope; y', o), true);
+    assertEq(referencesVia(returnHeavy(o), 'fun_callscope; shape; base; parent', this), true);
 
     function returnBlock(z) { eval(''); let(w = z) { return function block() { return w; }; }; }
-    assertEq(referencesVia(returnBlock(o), 'parent; w', o), true);
+    assertEq(referencesVia(returnBlock(o), 'fun_callscope; w', o), true);
 
     function returnWithObj(v) { with(v) return function withObj() { return u; }; }
-    assertEq(referencesVia(returnWithObj(o), 'parent; type; type_proto', o), true);
+    assertEq(referencesVia(returnWithObj(o), 'fun_callscope; type; type_proto', o), true);
 
     reportCompare(true, true);
 } else {
     reportCompare(true, true, "test skipped: findReferences is not a function");
 }
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -73,16 +73,23 @@ enum {
 
 extern Class DebuggerArguments_class;
 
 enum {
     JSSLOT_DEBUGARGUMENTS_FRAME,
     JSSLOT_DEBUGARGUMENTS_COUNT
 };
 
+extern Class DebuggerEnv_class;
+
+enum {
+    JSSLOT_DEBUGENV_OWNER,
+    JSSLOT_DEBUGENV_COUNT
+};
+
 extern Class DebuggerObject_class;
 
 enum {
     JSSLOT_DEBUGOBJECT_OWNER,
     JSSLOT_DEBUGOBJECT_COUNT
 };
 
 extern Class DebuggerScript_class;
@@ -116,16 +123,31 @@ ReportMoreArgsNeeded(JSContext *cx, cons
 
 bool
 ReportObjectRequired(JSContext *cx)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_NONNULL_OBJECT);
     return false;
 }
 
+bool
+ValueToIdentifier(JSContext *cx, const Value &v, jsid *idp)
+{
+    jsid id;
+    if (!ValueToId(cx, v, &id))
+        return false;
+    if (!JSID_IS_ATOM(id) || !IsIdentifier(JSID_TO_ATOM(id))) {
+        js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE,
+                                 JSDVG_SEARCH_STACK, v, NULL, "not an identifier", NULL);
+        return false;
+    }
+    *idp = id;
+    return true;
+}
+
 
 /*** Breakpoints *********************************************************************************/
 
 BreakpointSite::BreakpointSite(JSScript *script, jsbytecode *pc)
   : script(script), pc(pc), scriptGlobal(NULL), enabledCount(0),
     trapHandler(NULL), trapClosure(UndefinedValue())
 {
     JS_ASSERT(!script->hasBreakpointsAt(pc));
@@ -292,17 +314,17 @@ Breakpoint::nextInSite()
     return (link == &site->breakpoints) ? NULL : fromSiteLinks(link);
 }
 
 
 /*** Debugger hook dispatch **********************************************************************/
 
 Debugger::Debugger(JSContext *cx, JSObject *dbg)
   : object(dbg), uncaughtExceptionHook(NULL), enabled(true),
-    frames(cx), objects(cx), scripts(cx)
+    frames(cx), scripts(cx), objects(cx), environments(cx)
 {
     assertSameCompartment(cx, dbg);
 
     JSRuntime *rt = cx->runtime;
     AutoLockGC lock(rt);
     JS_APPEND_LINK(&link, &rt->debuggerList);
     JS_INIT_CLIST(&breakpoints);
 }
@@ -314,34 +336,37 @@ Debugger::~Debugger()
     /* This always happens in the GC thread, so no locking is required. */
     JS_ASSERT(object->compartment()->rt->gcRunning);
     JS_REMOVE_LINK(&link);
 }
 
 bool
 Debugger::init(JSContext *cx)
 {
-    bool ok = frames.init() &&
+    bool ok = debuggees.init() &&
+              frames.init() &&
+              scripts.init() &&
               objects.init() &&
-              debuggees.init() &&
-              scripts.init();
+              environments.init();
     if (!ok)
         js_ReportOutOfMemory(cx);
     return ok;
 }
 
+JS_STATIC_ASSERT(uintN(JSSLOT_DEBUGFRAME_OWNER) == uintN(JSSLOT_DEBUGSCRIPT_OWNER));
 JS_STATIC_ASSERT(uintN(JSSLOT_DEBUGFRAME_OWNER) == uintN(JSSLOT_DEBUGOBJECT_OWNER));
-JS_STATIC_ASSERT(uintN(JSSLOT_DEBUGFRAME_OWNER) == uintN(JSSLOT_DEBUGSCRIPT_OWNER));
+JS_STATIC_ASSERT(uintN(JSSLOT_DEBUGFRAME_OWNER) == uintN(JSSLOT_DEBUGENV_OWNER));
 
 Debugger *
 Debugger::fromChildJSObject(JSObject *obj)
 {
     JS_ASSERT(obj->getClass() == &DebuggerFrame_class ||
+              obj->getClass() == &DebuggerScript_class ||
               obj->getClass() == &DebuggerObject_class ||
-              obj->getClass() == &DebuggerScript_class);
+              obj->getClass() == &DebuggerEnv_class);
     JSObject *dbgobj = &obj->getReservedSlot(JSSLOT_DEBUGOBJECT_OWNER).toObject();
     return fromJSObject(dbgobj);
 }
 
 bool
 Debugger::getScriptFrame(JSContext *cx, StackFrame *fp, Value *vp)
 {
     JS_ASSERT(fp->isScriptFrame());
@@ -465,16 +490,45 @@ Debugger::slowPathOnLeaveFrame(JSContext
      */
     if (fp->isEvalFrame()) {
         JSScript *script = fp->script();
         script->clearBreakpointsIn(cx, NULL, NULL);
     }
 }
 
 bool
+Debugger::wrapEnvironment(JSContext *cx, Env *env, Value *rval)
+{
+    if (!env) {
+        rval->setNull();
+        return true;
+    }
+
+    JSObject *envobj;
+    ObjectWeakMap::AddPtr p = environments.lookupForAdd(env);
+    if (p) {
+        envobj = p->value;
+    } else {
+        /* Create a new Debugger.Environment for env. */
+        JSObject *proto = &object->getReservedSlot(JSSLOT_DEBUG_ENV_PROTO).toObject();
+        envobj = NewObjectWithGivenProto(cx, &DebuggerEnv_class, proto, NULL);
+        if (!envobj)
+            return false;
+        envobj->setPrivate(env);
+        envobj->setReservedSlot(JSSLOT_DEBUGENV_OWNER, ObjectValue(*object));
+        if (!environments.relookupOrAdd(p, env, envobj)) {
+            js_ReportOutOfMemory(cx);
+            return false;
+        }
+    }
+    rval->setObject(*envobj);
+    return true;
+}
+
+bool
 Debugger::wrapDebuggeeValue(JSContext *cx, Value *vp)
 {
     assertSameCompartment(cx, object.get());
 
     if (vp->isObject()) {
         JSObject *obj = &vp->toObject();
 
         ObjectWeakMap::AddPtr p = objects.lookupForAdd(obj);
@@ -1008,16 +1062,23 @@ Debugger::markKeysInCompartment(JSTracer
         ObjectMap;
     const ObjectMap &objStorage = objects;
     for (ObjectMap::Range r = objStorage.all(); !r.empty(); r.popFront()) {
         const HeapPtrObject &key = r.front().key;
         if (key->compartment() == comp && IsAboutToBeFinalized(tracer->context, key))
             gc::MarkObject(tracer, key, "cross-compartment WeakMap key");
     }
 
+    const ObjectMap &envStorage = environments;
+    for (ObjectMap::Range r = envStorage.all(); !r.empty(); r.popFront()) {
+        const HeapPtrObject &key = r.front().key;
+        if (key->compartment() == comp && IsAboutToBeFinalized(tracer->context, key))
+            js::gc::MarkObject(tracer, key, "cross-compartment WeakMap key");
+    }
+
     typedef HashMap<HeapPtrScript, HeapPtrObject, DefaultHasher<HeapPtrScript>, RuntimeAllocPolicy>
         ScriptMap;
     const ScriptMap &scriptStorage = scripts;
     for (ScriptMap::Range r = scriptStorage.all(); !r.empty(); r.popFront()) {
         const HeapPtrScript &key = r.front().key;
         if (key->compartment() == comp && IsAboutToBeFinalized(tracer->context, key))
             gc::MarkScript(tracer, key, "cross-compartment WeakMap key");
     }
@@ -1173,21 +1234,24 @@ Debugger::trace(JSTracer *trc)
      * frames.)
      */
     for (FrameMap::Range r = frames.all(); !r.empty(); r.popFront()) {
         const HeapPtrObject &frameobj = r.front().value;
         JS_ASSERT(frameobj->getPrivate());
         MarkObject(trc, frameobj, "live Debugger.Frame");
     }
 
+    /* Trace the weak map from JSScript instances to Debugger.Script objects. */
+    scripts.trace(trc);
+
     /* Trace the referent -> Debugger.Object weak map. */
     objects.trace(trc);
 
-    /* Trace the weak map from JSScript instances to Debugger.Script objects. */
-    scripts.trace(trc);
+    /* Trace the referent -> Debugger.Environment weak map. */
+    environments.trace(trc);
 }
 
 void
 Debugger::sweepAll(JSContext *cx)
 {
     JSRuntime *rt = cx->runtime;
     JS_ASSERT(!rt->gcCurrentCompartment);
 
@@ -2397,16 +2461,20 @@ StackContains(JSContext *cx, StackFrame 
 #define THIS_FRAME(cx, argc, vp, fnname, args, thisobj, fp)                  \
     CallArgs args = CallArgsFromVp(argc, vp);                                \
     JSObject *thisobj = CheckThisFrame(cx, args, fnname, true);              \
     if (!thisobj)                                                            \
         return false;                                                        \
     StackFrame *fp = (StackFrame *) thisobj->getPrivate();                   \
     JS_ASSERT(StackContains(cx, fp))
 
+#define THIS_FRAME_OWNER(cx, argc, vp, fnname, args, thisobj, fp, dbg)       \
+    THIS_FRAME(cx, argc, vp, fnname, args, thisobj, fp);                     \
+    Debugger *dbg = Debugger::fromChildJSObject(thisobj)
+
 static JSBool
 DebuggerFrame_getType(JSContext *cx, uintN argc, Value *vp)
 {
     THIS_FRAME(cx, argc, vp, "get type", args, thisobj, fp);
 
     /*
      * Indirect eval frames are both isGlobalFrame() and isEvalFrame(), so the
      * order of checks here is significant.
@@ -2414,16 +2482,43 @@ DebuggerFrame_getType(JSContext *cx, uin
     args.rval().setString(fp->isEvalFrame()
                           ? cx->runtime->atomState.evalAtom
                           : fp->isGlobalFrame()
                           ? cx->runtime->atomState.globalAtom
                           : cx->runtime->atomState.callAtom);
     return true;
 }
 
+static Env *
+Frame_GetEnv(JSContext *cx, StackFrame *fp)
+{
+    assertSameCompartment(cx, fp);
+    if (fp->isNonEvalFunctionFrame() && !fp->hasCallObj() && !CreateFunCallObject(cx, fp))
+        return NULL;
+    return GetScopeChain(cx, fp);
+}
+
+static JSBool
+DebuggerFrame_getEnvironment(JSContext *cx, uintN argc, Value *vp)
+{
+    THIS_FRAME_OWNER(cx, argc, vp, "get environment", args, thisobj, fp, dbg);
+
+    Env *env;
+    {
+        AutoCompartment ac(cx, &fp->scopeChain());
+        if (!ac.enter())
+            return false;
+        env = Frame_GetEnv(cx, fp);
+        if (!env)
+            return false;
+    }
+
+    return dbg->wrapEnvironment(cx, env, &args.rval());
+}
+
 static JSBool
 DebuggerFrame_getCallee(JSContext *cx, uintN argc, Value *vp)
 {
     THIS_FRAME(cx, argc, vp, "get callee", args, thisobj, fp);
     Value calleev = (fp->isFunctionFrame() && !fp->isEvalFrame()) ? fp->calleev() : NullValue();
     if (!Debugger::fromChildJSObject(thisobj)->wrapDebuggeeValue(cx, &calleev))
         return false;
     args.rval() = calleev;
@@ -2685,42 +2780,44 @@ DebuggerFrame_setOnStep(JSContext *cx, u
     thisobj->setReservedSlot(JSSLOT_DEBUGFRAME_ONSTEP_HANDLER, args[0]);
     args.rval().setUndefined();
     return true;
 }
 
 namespace js {
 
 JSBool
-EvaluateInScope(JSContext *cx, JSObject *scobj, StackFrame *fp, const jschar *chars,
-                uintN length, const char *filename, uintN lineno, Value *rval)
+EvaluateInEnv(JSContext *cx, Env *env, StackFrame *fp, const jschar *chars,
+              uintN length, const char *filename, uintN lineno, Value *rval)
 {
-    assertSameCompartment(cx, scobj, fp);
-
-    /* Execute assumes an already-computed 'this" value. */
-    if (!ComputeThis(cx, fp))
-        return false;
+    assertSameCompartment(cx, env, fp);
+
+    if (fp) {
+        /* Execute assumes an already-computed 'this" value. */
+        if (!ComputeThis(cx, fp))
+            return false;
+    }
 
     /*
      * NB: This function breaks the assumption that the compiler can see all
      * calls and properly compute a static level. In order to get around this,
      * we use a static level that will cause us not to attempt to optimize
      * variable references made by this frame.
      */
-    JSScript *script = frontend::CompileScript(cx, scobj, fp,
+    JSScript *script = frontend::CompileScript(cx, env, fp,
                                                fp->scopeChain().principals(cx),
                                                TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_GLOBAL,
                                                chars, length, filename, lineno,
                                                cx->findVersion(), NULL,
                                                UpvarCookie::UPVAR_LEVEL_LIMIT);
 
     if (!script)
         return false;
 
-    return ExecuteKernel(cx, script, *scobj, fp->thisValue(), EXECUTE_DEBUG, fp, rval);
+    return ExecuteKernel(cx, script, *env, fp->thisValue(), EXECUTE_DEBUG, fp, rval);
 }
 
 }
 
 enum EvalBindingsMode { WithoutBindings, WithBindings };
 
 static JSBool
 DebuggerFrameEval(JSContext *cx, uintN argc, Value *vp, EvalBindingsMode mode)
@@ -2767,40 +2864,40 @@ DebuggerFrameEval(JSContext *cx, uintN a
             }
         }
     }
 
     AutoCompartment ac(cx, &fp->scopeChain());
     if (!ac.enter())
         return false;
 
-    JSObject *scobj = JS_GetFrameScopeChain(cx, Jsvalify(fp));
-    if (!scobj)
+    Env *env = JS_GetFrameScopeChain(cx, Jsvalify(fp));
+    if (!env)
         return false;
 
-    /* If evalWithBindings, create the inner scope object. */
+    /* If evalWithBindings, create the inner environment. */
     if (mode == WithBindings) {
-        /* TODO - Should probably create a With object here. */
-        scobj = NewObjectWithGivenProto(cx, &ObjectClass, NULL, scobj);
-        if (!scobj)
+        /* TODO - This should probably be a Call object, like ES5 strict eval. */
+        env = NewObjectWithGivenProto(cx, &ObjectClass, NULL, env);
+        if (!env)
             return false;
         for (size_t i = 0; i < keys.length(); i++) {
             if (!cx->compartment->wrap(cx, &values[i]) ||
-                !DefineNativeProperty(cx, scobj, keys[i], values[i], NULL, NULL, 0, 0, 0))
+                !DefineNativeProperty(cx, env, keys[i], values[i], NULL, NULL, 0, 0, 0))
             {
                 return false;
             }
         }
     }
 
     /* Run the code and produce the completion value. */
     Value rval;
     JS::Anchor<JSString *> anchor(linearStr);
-    bool ok = EvaluateInScope(cx, scobj, fp, linearStr->chars(), linearStr->length(),
-                              "debugger eval code", 1, &rval);
+    bool ok = EvaluateInEnv(cx, env, fp, linearStr->chars(), linearStr->length(),
+                            "debugger eval code", 1, &rval);
     return dbg->newCompletionValue(ac, ok, rval, vp);
 }
 
 static JSBool
 DebuggerFrame_eval(JSContext *cx, uintN argc, Value *vp)
 {
     return DebuggerFrameEval(cx, argc, vp, WithoutBindings);
 }
@@ -2817,16 +2914,17 @@ DebuggerFrame_construct(JSContext *cx, u
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR, "Debugger.Frame");
     return false;
 }
 
 static JSPropertySpec DebuggerFrame_properties[] = {
     JS_PSG("arguments", DebuggerFrame_getArguments, 0),
     JS_PSG("callee", DebuggerFrame_getCallee, 0),
     JS_PSG("constructing", DebuggerFrame_getConstructing, 0),
+    JS_PSG("environment", DebuggerFrame_getEnvironment, 0),
     JS_PSG("generator", DebuggerFrame_getGenerator, 0),
     JS_PSG("live", DebuggerFrame_getLive, 0),
     JS_PSG("offset", DebuggerFrame_getOffset, 0),
     JS_PSG("older", DebuggerFrame_getOlder, 0),
     JS_PSG("script", DebuggerFrame_getScript, 0),
     JS_PSG("this", DebuggerFrame_getThis, 0),
     JS_PSG("type", DebuggerFrame_getType, 0),
     JS_PSGS("onStep", DebuggerFrame_getOnStep, DebuggerFrame_setOnStep, 0),
@@ -3009,34 +3107,51 @@ DebuggerObject_getParameterNames(JSConte
     return true;
 }
 
 static JSBool
 DebuggerObject_getScript(JSContext *cx, uintN argc, Value *vp)
 {
     THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "get script", args, dbg, obj);
 
-    args.rval().setUndefined();
-
-    if (!obj->isFunction())
+    if (!obj->isFunction()) {
+        args.rval().setUndefined();
         return true;
+    }
 
     JSFunction *fun = obj->toFunction();
-    if (!fun->isInterpreted())
+    if (!fun->isInterpreted()) {
+        args.rval().setUndefined();
         return true;
+    }
 
     JSObject *scriptObject = dbg->wrapScript(cx, fun->script());
     if (!scriptObject)
         return false;
 
     args.rval().setObject(*scriptObject);
     return true;
 }
 
 static JSBool
+DebuggerObject_getEnvironment(JSContext *cx, uintN argc, Value *vp)
+{
+    THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "get environment", args, dbg, obj);
+
+    /* Don't bother switching compartments just to check obj's type and get its env. */
+    if (!obj->isFunction() || !obj->toFunction()->isInterpreted()) {
+        args.rval().setUndefined();
+        return true;
+    }
+
+    Env *env = obj->toFunction()->environment();
+    return dbg->wrapEnvironment(cx, env, &args.rval());
+}
+
+static JSBool
 DebuggerObject_getOwnPropertyDescriptor(JSContext *cx, uintN argc, Value *vp)
 {
     THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "getOwnPropertyDescriptor", args, dbg, obj);
 
     jsid id;
     if (!ValueToId(cx, argc >= 1 ? args[0] : UndefinedValue(), &id))
         return false;
 
@@ -3441,16 +3556,17 @@ DebuggerObject_call(JSContext *cx, uintN
 
 static JSPropertySpec DebuggerObject_properties[] = {
     JS_PSG("proto", DebuggerObject_getProto, 0),
     JS_PSG("class", DebuggerObject_getClass, 0),
     JS_PSG("callable", DebuggerObject_getCallable, 0),
     JS_PSG("name", DebuggerObject_getName, 0),
     JS_PSG("parameterNames", DebuggerObject_getParameterNames, 0),
     JS_PSG("script", DebuggerObject_getScript, 0),
+    JS_PSG("environment", DebuggerObject_getEnvironment, 0),
     JS_PS_END
 };
 
 static JSFunctionSpec DebuggerObject_methods[] = {
     JS_FN("getOwnPropertyDescriptor", DebuggerObject_getOwnPropertyDescriptor, 1, 0),
     JS_FN("getOwnPropertyNames", DebuggerObject_getOwnPropertyNames, 0, 0),
     JS_FN("defineProperty", DebuggerObject_defineProperty, 2, 0),
     JS_FN("defineProperties", DebuggerObject_defineProperties, 1, 0),
@@ -3462,16 +3578,218 @@ static JSFunctionSpec DebuggerObject_met
     JS_FN("isFrozen", DebuggerObject_isFrozen, 0, 0),
     JS_FN("isExtensible", DebuggerObject_isExtensible, 0, 0),
     JS_FN("apply", DebuggerObject_apply, 0, 0),
     JS_FN("call", DebuggerObject_call, 0, 0),
     JS_FS_END
 };
 
 
+/*** Debugger.Environment ************************************************************************/
+
+static void
+DebuggerEnv_trace(JSTracer *trc, JSObject *obj)
+{
+    if (!trc->runtime->gcCurrentCompartment) {
+        /*
+         * There is a barrier on private pointers, so the Unbarriered marking
+         * is okay.
+         */
+        if (Env *referent = (JSObject *) obj->getPrivate())
+            MarkObjectUnbarriered(trc, referent, "Debugger.Environment referent");
+    }
+}
+
+Class DebuggerEnv_class = {
+    "Environment", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGENV_COUNT),
+    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
+    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
+    NULL,                 /* reserved0   */
+    NULL,                 /* checkAccess */
+    NULL,                 /* call        */
+    NULL,                 /* construct   */
+    NULL,                 /* xdrObject   */
+    NULL,                 /* hasInstance */
+    DebuggerEnv_trace
+};
+
+static JSObject *
+DebuggerEnv_checkThis(JSContext *cx, const CallArgs &args, const char *fnname)
+{
+    if (!args.thisv().isObject()) {
+        ReportObjectRequired(cx);
+        return NULL;
+    }
+    JSObject *thisobj = &args.thisv().toObject();
+    if (thisobj->getClass() != &DebuggerEnv_class) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
+                             "Debugger.Environment", fnname, thisobj->getClass()->name);
+        return NULL;
+    }
+
+    /*
+     * Forbid Debugger.Environment.prototype, which is of class DebuggerEnv_class
+     * but isn't a real working Debugger.Environment. The prototype object is
+     * distinguished by having no referent.
+     */
+    if (!thisobj->getPrivate()) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
+                             "Debugger.Environment", fnname, "prototype object");
+        return NULL;
+    }
+    return thisobj;
+}
+
+#define THIS_DEBUGENV(cx, argc, vp, fnname, args, envobj, env)                \
+    CallArgs args = CallArgsFromVp(argc, vp);                                 \
+    JSObject *envobj = DebuggerEnv_checkThis(cx, args, fnname);               \
+    if (!envobj)                                                              \
+        return false;                                                         \
+    Env *env = static_cast<Env *>(envobj->getPrivate());                      \
+    JS_ASSERT(env)
+
+#define THIS_DEBUGENV_OWNER(cx, argc, vp, fnname, args, envobj, env, dbg)     \
+    THIS_DEBUGENV(cx, argc, vp, fnname, args, envobj, env);                   \
+    Debugger *dbg = Debugger::fromChildJSObject(envobj)
+
+static JSBool
+DebuggerEnv_construct(JSContext *cx, uintN argc, Value *vp)
+{
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR, "Debugger.Environment");
+    return false;
+}
+
+static JSBool
+DebuggerEnv_getType(JSContext *cx, uintN argc, Value *vp)
+{
+    THIS_DEBUGENV(cx, argc, vp, "get type", args, envobj, env);
+
+    /* Don't bother switching compartments just to check env's class. */
+    const char *s;
+    if (env->isCall() || env->isBlock() || env->isDeclEnv())
+        s = "declarative";
+    else
+        s = "object";
+
+    JSAtom *str = js_Atomize(cx, s, strlen(s), InternAtom, NormalEncoding);
+    if (!str)
+        return false;
+    args.rval().setString(str);
+    return true;
+}
+
+static JSBool
+DebuggerEnv_getParent(JSContext *cx, uintN argc, Value *vp)
+{
+    THIS_DEBUGENV_OWNER(cx, argc, vp, "get parent", args, envobj, env, dbg);
+
+    /* Don't bother switching compartments just to get env's parent. */
+    Env *parent = env->scopeChain();
+    return dbg->wrapEnvironment(cx, parent, &args.rval());
+}
+
+static JSBool
+DebuggerEnv_getObject(JSContext *cx, uintN argc, Value *vp)
+{
+    THIS_DEBUGENV_OWNER(cx, argc, vp, "get type", args, envobj, env, dbg);
+
+    /*
+     * Don't bother switching compartments just to check env's class and
+     * possibly get its proto.
+     */
+    if (env->isCall() || env->isBlock() || env->isDeclEnv()) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NO_SCOPE_OBJECT);
+        return false;
+    }
+    JSObject *obj = env->isWith() ? env->getProto() : env;
+
+    Value rval = ObjectValue(*obj);
+    if (!dbg->wrapDebuggeeValue(cx, &rval))
+        return false;
+    args.rval() = rval;
+    return true;
+}
+
+static JSBool
+DebuggerEnv_names(JSContext *cx, uintN argc, Value *vp)
+{
+    THIS_DEBUGENV_OWNER(cx, argc, vp, "get type", args, envobj, env, dbg);
+
+    AutoIdVector keys(cx);
+    {
+        AutoCompartment ac(cx, env);
+        if (!ac.enter())
+            return false;
+
+        ErrorCopier ec(ac, dbg->toJSObject());
+        if (!GetPropertyNames(cx, env, JSITER_HIDDEN, &keys))
+            return false;
+    }
+
+    JSObject *arr = NewDenseEmptyArray(cx);
+    if (!arr)
+        return false;
+    for (size_t i = 0, len = keys.length(); i < len; i++) {
+         jsid id = keys[i];
+         if (JSID_IS_ATOM(id) && IsIdentifier(JSID_TO_ATOM(id))) {
+             if (!cx->compartment->wrapId(cx, &id))
+                 return false;
+             if (!js_NewbornArrayPush(cx, arr, StringValue(JSID_TO_STRING(id))))
+                 return false;
+         }
+    }
+    args.rval().setObject(*arr);
+    return true;
+}
+
+static JSBool
+DebuggerEnv_find(JSContext *cx, uintN argc, Value *vp)
+{
+    REQUIRE_ARGC("Debugger.Environment.find", 1);
+    THIS_DEBUGENV_OWNER(cx, argc, vp, "get type", args, envobj, env, dbg);
+
+    jsid id;
+    if (!ValueToIdentifier(cx, args[0], &id))
+        return false;
+
+    {
+        AutoCompartment ac(cx, env);
+        if (!ac.enter() || !cx->compartment->wrapId(cx, &id))
+            return false;
+
+        /* This can trigger resolve hooks. */
+        ErrorCopier ec(ac, dbg->toJSObject());
+        JSProperty *prop = NULL;
+        JSObject *pobj;
+        for (; env && !prop; env = env->scopeChain()) {
+            if (!env->lookupGeneric(cx, id, &pobj, &prop))
+                return false;
+            if (prop)
+                break;
+        }
+    }
+
+    return dbg->wrapEnvironment(cx, env, &args.rval());
+}
+
+static JSPropertySpec DebuggerEnv_properties[] = {
+    JS_PSG("type", DebuggerEnv_getType, 0),
+    JS_PSG("object", DebuggerEnv_getObject, 0),
+    JS_PSG("parent", DebuggerEnv_getParent, 0),
+    JS_PS_END
+};
+
+static JSFunctionSpec DebuggerEnv_methods[] = {
+    JS_FN("names", DebuggerEnv_names, 0, 0),
+    JS_FN("find", DebuggerEnv_find, 1, 0),
+    JS_FS_END
+};
+
+
+
 /*** Glue ****************************************************************************************/
 
 extern JS_PUBLIC_API(JSBool)
 JS_DefineDebuggerObject(JSContext *cx, JSObject *obj)
 {
     JSObject *objProto;
     if (!js_GetClassPrototype(cx, obj, JSProto_Object, &objProto))
         return false;
@@ -3499,13 +3817,21 @@ JS_DefineDebuggerObject(JSContext *cx, J
 
     JSObject *objectProto = js_InitClass(cx, debugCtor, objProto, &DebuggerObject_class,
                                          DebuggerObject_construct, 0,
                                          DebuggerObject_properties, DebuggerObject_methods,
                                          NULL, NULL);
     if (!objectProto)
         return false;
 
+    JSObject *envProto = js_InitClass(cx, debugCtor, objProto, &DebuggerEnv_class,
+                                      DebuggerEnv_construct, 0,
+                                      DebuggerEnv_properties, DebuggerEnv_methods,
+                                      NULL, NULL);
+    if (!envProto)
+        return false;
+
     debugProto->setReservedSlot(Debugger::JSSLOT_DEBUG_FRAME_PROTO, ObjectValue(*frameProto));
     debugProto->setReservedSlot(Debugger::JSSLOT_DEBUG_OBJECT_PROTO, ObjectValue(*objectProto));
     debugProto->setReservedSlot(Debugger::JSSLOT_DEBUG_SCRIPT_PROTO, ObjectValue(*scriptProto));
+    debugProto->setReservedSlot(Debugger::JSSLOT_DEBUG_ENV_PROTO, ObjectValue(*envProto));
     return true;
 }
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -67,16 +67,17 @@ class Debugger {
         OnNewScript,
         OnEnterFrame,
         HookCount
     };
 
     enum {
         JSSLOT_DEBUG_PROTO_START,
         JSSLOT_DEBUG_FRAME_PROTO = JSSLOT_DEBUG_PROTO_START,
+        JSSLOT_DEBUG_ENV_PROTO,
         JSSLOT_DEBUG_OBJECT_PROTO,
         JSSLOT_DEBUG_SCRIPT_PROTO,
         JSSLOT_DEBUG_PROTO_STOP,
         JSSLOT_DEBUG_HOOK_START = JSSLOT_DEBUG_PROTO_STOP,
         JSSLOT_DEBUG_HOOK_STOP = JSSLOT_DEBUG_HOOK_START + HookCount,
         JSSLOT_DEBUG_COUNT = JSSLOT_DEBUG_HOOK_STOP
     };
 
@@ -100,23 +101,26 @@ class Debugger {
      * thus necessarily live), but we do trace the values. It's like a WeakMap
      * that way, but since stack frames are not gc-things, the implementation
      * has to be different.
      */
     typedef HashMap<StackFrame *, HeapPtrObject, DefaultHasher<StackFrame *>, RuntimeAllocPolicy>
         FrameMap;
     FrameMap frames;
 
+    /* An ephemeral map from JSScript* to Debugger.Script instances. */
+    typedef WeakMap<HeapPtrScript, HeapPtrObject> ScriptWeakMap;
+    ScriptWeakMap scripts;
+
     /* The map from debuggee objects to their Debugger.Object instances. */
     typedef WeakMap<HeapPtrObject, HeapPtrObject> ObjectWeakMap;
     ObjectWeakMap objects;
 
-    /* An ephemeral map from JSScript* to Debugger.Script instances. */
-    typedef WeakMap<HeapPtrScript, HeapPtrObject> ScriptWeakMap;
-    ScriptWeakMap scripts;
+    /* The map from debuggee Envs to Debugger.Environment instances. */
+    ObjectWeakMap environments;
 
     bool addDebuggeeGlobal(JSContext *cx, GlobalObject *obj);
     void removeDebuggeeGlobal(JSContext *cx, GlobalObject *global,
                               GlobalObjectSet::Enum *compartmentEnum,
                               GlobalObjectSet::Enum *debugEnum);
 
     /*
      * Cope with an error or exception in a debugger hook.
@@ -268,16 +272,23 @@ class Debugger {
     /************************************* Functions for use by Debugger.cpp. */
 
     inline bool observesEnterFrame() const;
     inline bool observesNewScript() const;
     inline bool observesGlobal(GlobalObject *global) const;
     inline bool observesFrame(StackFrame *fp) const;
 
     /*
+     * If env is NULL, call vp->setNull() and return true. Otherwise, find or
+     * create a Debugger.Environment object for the given Env. On success,
+     * store the Environment object in *vp and return true.
+     */
+    bool wrapEnvironment(JSContext *cx, Env *env, Value *vp);
+
+    /*
      * Like cx->compartment->wrap(cx, vp), but for the debugger compartment.
      *
      * Preconditions: *vp is a value from a debuggee compartment; cx is in the
      * debugger's compartment.
      *
      * If *vp is an object, this produces a (new or existing) Debugger.Object
      * wrapper for it. Otherwise this is the same as JSCompartment::wrap.
      */
@@ -513,14 +524,14 @@ Debugger::onNewScript(JSContext *cx, JSS
 {
     JS_ASSERT_IF(script->compileAndGo, compileAndGoGlobal);
     JS_ASSERT_IF(!script->compileAndGo, !compileAndGoGlobal);
     if (!script->compartment()->getDebuggees().empty())
         slowPathOnNewScript(cx, script, compileAndGoGlobal);
 }
 
 extern JSBool
-EvaluateInScope(JSContext *cx, JSObject *scobj, StackFrame *fp, const jschar *chars,
-                uintN length, const char *filename, uintN lineno, Value *rval);
+EvaluateInEnv(JSContext *cx, Env *env, StackFrame *fp, const jschar *chars,
+              uintN length, const char *filename, uintN lineno, Value *rval);
 
 }
 
 #endif /* Debugger_h__ */
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -45,16 +45,17 @@
 #include "nsSubDocumentFrame.h"
 #include "nsCSSRendering.h"
 #include "nsCSSFrameConstructor.h"
 #include "gfxUtils.h"
 #include "nsImageFrame.h"
 #include "nsRenderingContext.h"
 
 #include "mozilla/Preferences.h"
+#include "sampler.h"
 
 #ifdef DEBUG
 #include <stdio.h>
 #endif
 
 using namespace mozilla::layers;
 
 namespace mozilla {
@@ -2009,16 +2010,18 @@ FrameLayerBuilder::GetDedicatedLayer(nsI
 
 /* static */ void
 FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
                                    gfxContext* aContext,
                                    const nsIntRegion& aRegionToDraw,
                                    const nsIntRegion& aRegionToInvalidate,
                                    void* aCallbackData)
 {
+  SAMPLE_LABEL("gfx", "DrawThebesLayer");
+
   nsDisplayListBuilder* builder = static_cast<nsDisplayListBuilder*>
     (aCallbackData);
 
   if (builder->LayerBuilder()->CheckDOMModified())
     return;
 
   nsTArray<ClippedDisplayItem> items;
   nsIFrame* containerLayerFrame;
--- a/layout/base/RestyleTracker.cpp
+++ b/layout/base/RestyleTracker.cpp
@@ -39,16 +39,17 @@
 /**
  * A class which manages pending restyles.  This handles keeping track
  * of what nodes restyles need to happen on and so forth.
  */
 
 #include "RestyleTracker.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsStyleChangeList.h"
+#include "sampler.h"
 
 namespace mozilla {
 namespace css {
 
 inline nsIDocument*
 RestyleTracker::Document() const {
   return mFrameConstructor->mDocument;
 }
@@ -162,16 +163,17 @@ RestyleTracker::ProcessOneRestyle(Elemen
     changeList.AppendChange(primaryFrame, aElement, aChangeHint);
     mFrameConstructor->ProcessRestyledFrames(changeList);
   }
 }
 
 void
 RestyleTracker::ProcessRestyles()
 {
+  SAMPLE_LABEL("CSS", "ProcessRestyles");
   // Make sure to not rebuild quote or counter lists while we're
   // processing restyles
   mFrameConstructor->BeginUpdate();
 
   mFrameConstructor->mInStyleRefresh = true;
 
   // loop so that we process any restyle events generated by processing
   while (mPendingRestyles.Count()) {
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -198,16 +198,17 @@
 // Content viewer interfaces
 #include "nsIContentViewer.h"
 #include "imgIEncoder.h"
 #include "gfxPlatform.h"
 
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
+#include "sampler.h"
 
 #include "Layers.h"
 #include "nsPLDOMEvent.h"
 
 #ifdef NS_FUNCTION_TIMER
 #define NS_TIME_FUNCTION_DECLARE_DOCURL                \
   nsCAutoString docURL__("N/A");                       \
   nsIURI *uri__ = mDocument->GetDocumentURI();         \
@@ -3969,16 +3970,17 @@ PresShell::FlushPendingNotifications(moz
     "Flush_Styles",
     "Flush_InterruptibleLayout",
     "Flush_Layout",
     "Flush_Display"
   };
   NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (document: %s, type: %s)", MOZ_FUNCTION_NAME,
                            __LINE__, docURL__.get(), flushTypeNames[aType - 1]);
 #endif
+  SAMPLE_LABEL("layout", "FlushPendingNotifications");
 
 #ifdef ACCESSIBILITY
 #ifdef DEBUG
   nsAccessibilityService* accService = GetAccService();
   if (accService) {
     NS_ASSERTION(!accService->IsProcessingRefreshDriverNotification(),
                  "Flush during accessible tree update!");
   }
@@ -5416,16 +5418,17 @@ PresShell::Paint(nsIView*           aVie
   NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (document: %s, dirty rect: (<%f, %f>, <%f, %f>)",
                            MOZ_FUNCTION_NAME, __LINE__, docURL__.get(),
                            NSCoordToFloat(bounds__.x),
                            NSCoordToFloat(bounds__.y),
                            NSCoordToFloat(bounds__.XMost()),
                            NSCoordToFloat(bounds__.YMost()));
 #endif
 
+  SAMPLE_LABEL("Paint", "PresShell::Paint");
   NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell");
   NS_ASSERTION(aViewToPaint, "null view");
   NS_ASSERTION(aWidgetToPaint, "Can't paint without a widget");
 
   nsPresContext* presContext = GetPresContext();
   AUTO_LAYOUT_PHASE_ENTRY_POINT(presContext, Paint);
 
   nsIFrame* frame = aPaintDefaultBackground ? nsnull : aViewToPaint->GetFrame();
@@ -7198,16 +7201,17 @@ PresShell::ScheduleReflowOffTimer()
   }
   return true;
 }
 
 bool
 PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
 {
   NS_TIME_FUNCTION_WITH_DOCURL;
+  SAMPLE_LABEL("layout", "DoReflow");
 
   if (mReflowContinueTimer) {
     mReflowContinueTimer->Cancel();
     mReflowContinueTimer = nsnull;
   }
 
   nsIFrame* rootFrame = FrameManager()->GetRootFrame();
 
--- a/layout/reftests/canvas/reftest.list
+++ b/layout/reftests/canvas/reftest.list
@@ -33,16 +33,17 @@ asserts-if(cocoaWidget,0-2) == size-chan
 == text-font-inherit.html text-big-fill.html
 == text-space-replace-test.html text-space-replace-ref.html
 
 == text-no-frame-test.html text-no-frame-ref.html
 == text-no-frame-2-test.html text-not-in-doc-ref.html
 == text-not-in-doc-test.html text-not-in-doc-ref.html
 
 == text-bidi-ltr-test.html text-bidi-ltr-ref.html
+!= text-bidi-ltr-test.html text-bidi-ltr-notref.html # for bug 698185
 == text-bidi-rtl-test.html text-bidi-rtl-ref.html
 
 fails-if(Android) != text-font-lang.html text-font-lang-notref.html
 
 == text-measure.html text-measure-ref.html
 
 == strokeText-path.html strokeText-path-ref.html
 
copy from layout/reftests/canvas/text-bidi-ltr-test.html
copy to layout/reftests/canvas/text-bidi-ltr-notref.html
--- a/layout/reftests/canvas/text-bidi-ltr-test.html
+++ b/layout/reftests/canvas/text-bidi-ltr-notref.html
@@ -4,17 +4,19 @@
 <title>Test to ensure bidi is resolved correctly</title>
 </head>
 <body>
 <canvas id="c" width="256" height="64" style="direction:ltr"></canvas>
 <script type="text/javascript">
   var canvas = document.getElementById('c');
   var ctx = canvas.getContext('2d');
 
-  var str = "hello\u05E9\u05DC\u05D5\u05DDgoodbye";
+  // Bug 698185 caused the RTL and trailing LTR runs to be lost
+  // var str = "hello\u05E9\u05DC\u05D5\u05DDgoodbye";
+  var str = "hello";
 
   ctx.fillStyle = 'black';
   ctx.font = '10px sans-serif';
   ctx.fillText(str, 128, 32);
 
 </script>
 </body>
 </html>
--- a/layout/reftests/forms/reftest.list
+++ b/layout/reftests/forms/reftest.list
@@ -5,16 +5,26 @@ fails-if(Android) == checkbox-radio-stre
 == input-file-width-clip-1.html input-file-width-clip-ref.html # test for bug 409587
 == input-hidden-border.html about:blank
 == input-text-size-1.html input-text-size-1-ref.html
 fails-if(Android) == input-text-size-2.html input-text-size-2-ref.html
 HTTP(..) == input-text-baseline-1.html input-text-baseline-1-ref.html
 HTTP(..) == input-text-centering-1.xul input-text-centering-1-ref.xul
 fails-if(Android) HTTP(..) == text-control-baseline-1.html text-control-baseline-1-ref.html
 == input-text-dynamic-height-1.xul input-text-dynamic-height-1-ref.xul
+
+# access-key tests are no use on OS X because access keys are not indicated visually
+skip-if(cocoaWidget) != textbox-accesskey-1.xul textbox-accesskey-1-notref.xul
+skip-if(cocoaWidget) == textbox-accesskey-2.xul textbox-accesskey-2-ref.xul
+# textbox-accesskey-3 fails because of defects in XUL bidi support
+skip-if(cocoaWidget) fails-if(!cocoaWidget) == textbox-accesskey-3.xul textbox-accesskey-3-ref.xul
+skip-if(cocoaWidget) != textbox-accesskey-3.xul textbox-accesskey-3-notref.xul
+skip-if(cocoaWidget) == textbox-accesskey-4.xul textbox-accesskey-4-ref.xul
+skip-if(cocoaWidget) != textbox-accesskey-4.xul textbox-accesskey-4-notref.xul
+
 == textbox-align-baseline-1.xul textbox-align-baseline-1-ref.xul # test for bug 494901
 fails-if(Android) == textbox-setsize.xul textbox-setsize-ref.xul
 fails-if(Android) == textarea-resize.html textarea-resize-ref.html
 # an offset seems to apply to the native resizer on windows so skip this test for now
 fails-if(Android) skip-if(winWidget) == textarea-resize-background.html textarea-resize-background-ref.html
 fails-if(Android) != textarea-ltr.html textarea-rtl.html
 fails-if(Android) != textarea-ltr-scrollbar.html textarea-rtl-scrollbar.html
 fails-if(Android) != textarea-in-ltr-doc-scrollbar.html textarea-in-rtl-doc-scrollbar.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/textbox-accesskey-1-notref.xul
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/"?>
+<window title="textbox access key tests (see bug 698185)"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+	xmlns:html="http://www.w3.org/1999/xhtml">
+  <html:style type="text/css">
+    hbox {
+      margin-top: 0px;
+      padding-top: 0px;
+      font-size: 36px;
+    }
+    label, textbox {
+      -moz-appearance: none;
+      background: inherit;
+      border: none 0px;
+    }
+    label {
+      margin-top: 0px;
+      padding-top: 0px;
+      margin-bottom: 0px;
+      padding-bottom: 0px;
+    }
+    textbox {
+      margin-top: 12px;
+      padding-top: 8px;
+      margin-bottom: 5px;
+      padding-bottom: 9px;
+    }
+  </html:style>
+
+  <hbox align="baseline">
+    <label value="test"/>
+    <textbox value="text"/>
+  </hbox>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/textbox-accesskey-1.xul
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/"?>
+<window title="textbox access key tests (see bug 698185)"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+	xmlns:html="http://www.w3.org/1999/xhtml">
+  <html:style type="text/css">
+    hbox {
+      margin-top: 0px;
+      padding-top: 0px;
+      font-size: 36px;
+    }
+    label, textbox {
+      -moz-appearance: none;
+      background: inherit;
+      border: none 0px;
+    }
+    label {
+      margin-top: 0px;
+      padding-top: 0px;
+      margin-bottom: 0px;
+      padding-bottom: 0px;
+    }
+    textbox {
+      margin-top: 12px;
+      padding-top: 8px;
+      margin-bottom: 5px;
+      padding-bottom: 9px;
+    }
+  </html:style>
+
+  <hbox align="baseline">
+    <label value="test" accesskey="s"/>
+    <textbox value="text"/>
+  </hbox>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/textbox-accesskey-2-ref.xul
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/"?>
+<window title="textbox access key tests (see bug 698185)"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+	xmlns:html="http://www.w3.org/1999/xhtml">
+  <html:style type="text/css">
+    hbox {
+      margin-top: 0px;
+      padding-top: 0px;
+      font-size: 36px;
+    }
+    label, textbox {
+      -moz-appearance: none;
+      background: inherit;
+      border: none 0px;
+    }
+    label {
+      margin-top: 0px;
+      padding-top: 0px;
+      margin-bottom: 0px;
+      padding-bottom: 0px;
+    }
+    textbox {
+      margin-top: 12px;
+      padding-top: 8px;
+      margin-bottom: 5px;
+      padding-bottom: 9px;
+    }
+  </html:style>
+
+  <hbox align="baseline">
+    <!-- access key in LTR-overridden Arabic text -->
+    <label value="&#x202d;&#x64a;&#x628;&#x631;&#x639;&#x644;&#x627;&#x202c; test" accesskey="&#x639;"/>
+    <textbox value=""/>
+  </hbox>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/textbox-accesskey-2.xul
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/"?>
+<window title="textbox access key tests (see bug 698185)"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+	xmlns:html="http://www.w3.org/1999/xhtml">
+  <html:style type="text/css">
+    hbox {
+      margin-top: 0px;
+      padding-top: 0px;
+      font-size: 36px;
+    }
+    label, textbox {
+      -moz-appearance: none;
+      background: inherit;
+      border: none 0px;
+    }
+    label {
+      margin-top: 0px;
+      padding-top: 0px;
+      margin-bottom: 0px;
+      padding-bottom: 0px;
+    }
+    textbox {
+      margin-top: 12px;
+      padding-top: 8px;
+      margin-bottom: 5px;
+      padding-bottom: 9px;
+    }
+  </html:style>
+
+  <hbox align="baseline">
+    <!-- access key in RTL Arabic text -->
+    <label value="&#x627;&#x644;&#x639;&#x631;&#x628;&#x64a; test" accesskey="&#x639;"/>
+    <textbox value=""/>
+  </hbox>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/textbox-accesskey-3-notref.xul
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/"?>
+<window title="textbox access key tests (see bug 698185)"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+	xmlns:html="http://www.w3.org/1999/xhtml">
+  <html:style type="text/css">
+    hbox {
+      margin-top: 0px;
+      padding-top: 0px;
+      font-size: 36px;
+    }
+    label, textbox {
+      -moz-appearance: none;
+      background: inherit;
+      border: none 0px;
+    }
+    label {
+      margin-top: 0px;
+      padding-top: 0px;
+      margin-bottom: 0px;
+      padding-bottom: 0px;
+    }
+    textbox {
+      margin-top: 12px;
+      padding-top: 8px;
+      margin-bottom: 5px;
+      padding-bottom: 9px;
+    }
+  </html:style>
+
+  <hbox align="baseline">
+    <!-- no access key, for != test -->
+    <label value="&#x627;&#x644;&#x639;&#x631;&#x628;&#x64a; hello world"/>
+    <textbox value=""/>
+  </hbox>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/textbox-accesskey-3-ref.xul
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/"?>
+<window title="textbox access key tests (see bug 698185)"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+	xmlns:html="http://www.w3.org/1999/xhtml">
+  <html:style type="text/css">
+    hbox {
+      margin-top: 0px;
+      padding-top: 0px;
+      font-size: 36px;
+    }
+    label, textbox {
+      -moz-appearance: none;
+      background: inherit;
+      border: none 0px;
+    }
+    label {
+      margin-top: 0px;
+      padding-top: 0px;
+      margin-bottom: 0px;
+      padding-bottom: 0px;
+    }
+    textbox {
+      margin-top: 12px;
+      padding-top: 8px;
+      margin-bottom: 5px;
+      padding-bottom: 9px;
+    }
+  </html:style>
+
+  <hbox align="baseline">
+    <!-- access key in LTR text that follows RTL text (mixed direction) -->
+    <label value="&#x627;&#x644;&#x639;&#x631;&#x628;&#x64a; hello world" accesskey="d"/>
+    <textbox value=""/>
+  </hbox>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/textbox-accesskey-3.xul
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/"?>
+<window title="textbox access key tests (see bug 698185)"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+	xmlns:html="http://www.w3.org/1999/xhtml">
+  <html:style type="text/css">
+    hbox {
+      margin-top: 0px;
+      padding-top: 0px;
+      font-size: 36px;
+    }
+    label, textbox {
+      -moz-appearance: none;
+      background: inherit;
+      border: none 0px;
+    }
+    label {
+      margin-top: 0px;
+      padding-top: 0px;
+      margin-bottom: 0px;
+      padding-bottom: 0px;
+    }
+    textbox {
+      margin-top: 12px;
+      padding-top: 8px;
+      margin-bottom: 5px;
+      padding-bottom: 9px;
+    }
+  </html:style>
+
+  <hbox align="baseline">
+    <!-- access key in RTL-overridden English text -->
+    <label value="&#x627;&#x644;&#x639;&#x631;&#x628;&#x64a; hello &#x202e;dlrow&#x202c;" accesskey="d"/>
+    <textbox value=""/>
+  </hbox>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/textbox-accesskey-4-notref.xul
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/"?>
+<window title="textbox access key tests (see bug 698185)"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+	xmlns:html="http://www.w3.org/1999/xhtml">
+  <html:style type="text/css">
+    hbox {
+      margin-top: 0px;
+      padding-top: 0px;
+      font-size: 36px;
+    }
+    label, textbox {
+      -moz-appearance: none;
+      background: inherit;
+      border: none 0px;
+    }
+    label {
+      margin-top: 0px;
+      padding-top: 0px;
+      margin-bottom: 0px;
+      padding-bottom: 0px;
+    }
+    textbox {
+      margin-top: 12px;
+      padding-top: 8px;
+      margin-bottom: 5px;
+      padding-bottom: 9px;
+    }
+  </html:style>
+
+  <hbox align="baseline">
+    <!-- no access key, for != test -->
+    <label value="&#x627;&#x644;&#x639;&#x631;&#x628;&#x64a; hello world"/>
+    <textbox value=""/>
+  </hbox>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/textbox-accesskey-4-ref.xul
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/"?>
+<window title="textbox access key tests (see bug 698185)"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+	xmlns:html="http://www.w3.org/1999/xhtml">
+  <html:style type="text/css">
+    hbox {
+      margin-top: 0px;
+      padding-top: 0px;
+      font-size: 36px;
+    }
+    label, textbox {
+      -moz-appearance: none;
+      background: inherit;
+      border: none 0px;
+    }
+    label {
+      margin-top: 0px;
+      padding-top: 0px;
+      margin-bottom: 0px;
+      padding-bottom: 0px;
+    }
+    textbox {
+      margin-top: 12px;
+      padding-top: 8px;
+      margin-bottom: 5px;
+      padding-bottom: 9px;
+    }
+  </html:style>
+
+  <hbox align="baseline">
+    <!-- access key in English text following LTR-overridden Arabic -->
+    <label value="&#x202d;&#x64a;&#x628;&#x631;&#x639;&#x644;&#x627;&#x202c; hello world" accesskey="w"/>
+    <textbox value=""/>
+  </hbox>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/textbox-accesskey-4.xul
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/"?>
+<window title="textbox access key tests (see bug 698185)"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+	xmlns:html="http://www.w3.org/1999/xhtml">
+  <html:style type="text/css">
+    hbox {
+      margin-top: 0px;
+      padding-top: 0px;
+      font-size: 36px;
+    }
+    label, textbox {
+      -moz-appearance: none;
+      background: inherit;
+      border: none 0px;
+    }
+    label {
+      margin-top: 0px;
+      padding-top: 0px;
+      margin-bottom: 0px;
+      padding-bottom: 0px;
+    }
+    textbox {
+      margin-top: 12px;
+      padding-top: 8px;
+      margin-bottom: 5px;
+      padding-bottom: 9px;
+    }
+  </html:style>
+
+  <hbox align="baseline">
+    <!-- access key in English text following RTL Arabic -->
+    <label value="&#x627;&#x644;&#x639;&#x631;&#x628;&#x64a; hello world" accesskey="w"/>
+    <textbox value=""/>
+  </hbox>
+</window>
--- a/media/libvpx/Makefile.in
+++ b/media/libvpx/Makefile.in
@@ -523,12 +523,13 @@ else
 endif
 
 endif
 
 # Workaround a bug of Sun Studio (CR 6963410)
 ifdef SOLARIS_SUNPRO_CC
 ifeq (86,$(findstring 86,$(OS_TEST)))
 filter.o: filter.c Makefile.in
+	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(CC) -o $@ -c $(patsubst -xO[45],-xO3,$(COMPILE_CFLAGS)) $<
 endif
 endif
new file mode 100644
--- /dev/null
+++ b/media/libvpx/stdint.patch
@@ -0,0 +1,43 @@
+diff --git a/media/libvpx/stdint.patch b/media/libvpx/stdint.patch
+new file mode 100644
+diff --git a/media/libvpx/vpx/vpx_integer.h b/media/libvpx/vpx/vpx_integer.h
+--- a/media/libvpx/vpx/vpx_integer.h
++++ b/media/libvpx/vpx/vpx_integer.h
+@@ -10,16 +10,18 @@
+ 
+ 
+ #ifndef VPX_INTEGER_H
+ #define VPX_INTEGER_H
+ 
+ /* get ptrdiff_t, size_t, wchar_t, NULL */
+ #include <stddef.h>
+ 
++#if !defined(VPX_DONT_DEFINE_STDINT_TYPES)
++
+ #if (defined(_MSC_VER) && (_MSC_VER < 1600)) || defined(VPX_EMULATE_INTTYPES)
+ typedef signed char  int8_t;
+ typedef signed short int16_t;
+ typedef signed int   int32_t;
+ 
+ typedef unsigned char  uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int   uint32_t;
+@@ -47,16 +49,18 @@ typedef unsigned int   uintptr_t;
+ 
+ #if defined(__cplusplus) && !defined(__STDC_FORMAT_MACROS)
+ #define __STDC_FORMAT_MACROS
+ #endif
+ #include <stdint.h>
+ 
+ #endif
+ 
++#endif
++
+ /* VS2010 defines stdint.h, but not inttypes.h */
+ #if defined(_MSC_VER)
+ #define PRId64 "I64d"
+ #else
+ #include <inttypes.h>
+ #endif
+ 
+ #endif
--- a/media/libvpx/update.sh
+++ b/media/libvpx/update.sh
@@ -436,8 +436,11 @@ done
 # Patch to compile with Sun Studio on Solaris
 patch -p3 < solaris.patch
 
 # Patch to fix errors including C headers in C++
 patch -p3 < compile_errors.patch
 
 # Patch to fix MV clamping in the v0.9.7-p1 release.
 patch -p3 < bug696390.patch
+
+# Patch to permit vpx users to specify their own <stdint.h> types.
+patch -p3 < stdint.patch
--- a/media/libvpx/vpx/vpx_integer.h
+++ b/media/libvpx/vpx/vpx_integer.h
@@ -10,16 +10,18 @@
 
 
 #ifndef VPX_INTEGER_H
 #define VPX_INTEGER_H
 
 /* get ptrdiff_t, size_t, wchar_t, NULL */
 #include <stddef.h>
 
+#if !defined(VPX_DONT_DEFINE_STDINT_TYPES)
+
 #if (defined(_MSC_VER) && (_MSC_VER < 1600)) || defined(VPX_EMULATE_INTTYPES)
 typedef signed char  int8_t;
 typedef signed short int16_t;
 typedef signed int   int32_t;
 
 typedef unsigned char  uint8_t;
 typedef unsigned short uint16_t;
 typedef unsigned int   uint32_t;
@@ -47,16 +49,18 @@ typedef unsigned int   uintptr_t;
 
 #if defined(__cplusplus) && !defined(__STDC_FORMAT_MACROS)
 #define __STDC_FORMAT_MACROS
 #endif
 #include <stdint.h>
 
 #endif
 
+#endif
+
 /* VS2010 defines stdint.h, but not inttypes.h */
 #if defined(_MSC_VER)
 #define PRId64 "I64d"
 #else
 #include <inttypes.h>
 #endif
 
 #endif
new file mode 100644
--- /dev/null
+++ b/mfbt/MSStdInt.h
@@ -0,0 +1,247 @@
+// ISO C9x  compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
+// 
+//  Copyright (c) 2006-2008 Alexander Chemeris
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//   1. Redistributions of source code must retain the above copyright notice,
+//      this list of conditions and the following disclaimer.
+// 
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+// 
+//   3. The name of the author may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
+// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler give many errors like this:
+//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#ifdef __cplusplus
+extern "C" {
+#endif
+#  include <wchar.h>
+#ifdef __cplusplus
+}
+#endif
+
+// Define _W64 macros to mark types changing their size, like intptr_t.
+#ifndef _W64
+#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+#     define _W64 __w64
+#  else
+#     define _W64
+#  endif
+#endif
+
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+
+// Visual Studio 6 and Embedded Visual C++ 4 doesn't
+// realize that, e.g. char has the same size as __int8
+// so we give up on __intX for them.
+#if (_MSC_VER < 1300)
+   typedef signed char       int8_t;
+   typedef signed short      int16_t;
+   typedef signed int        int32_t;
+   typedef unsigned char     uint8_t;
+   typedef unsigned short    uint16_t;
+   typedef unsigned int      uint32_t;
+#else
+   typedef signed __int8     int8_t;
+   typedef signed __int16    int16_t;
+   typedef signed __int32    int32_t;
+   typedef unsigned __int8   uint8_t;
+   typedef unsigned __int16  uint16_t;
+   typedef unsigned __int32  uint32_t;
+#endif
+typedef signed __int64       int64_t;
+typedef unsigned __int64     uint64_t;
+
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t    int_least8_t;
+typedef int16_t   int_least16_t;
+typedef int32_t   int_least32_t;
+typedef int64_t   int_least64_t;
+typedef uint8_t   uint_least8_t;
+typedef uint16_t  uint_least16_t;
+typedef uint32_t  uint_least32_t;
+typedef uint64_t  uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t    int_fast8_t;
+typedef int32_t   int_fast16_t;
+typedef int32_t   int_fast32_t;
+typedef int64_t   int_fast64_t;
+typedef uint8_t   uint_fast8_t;
+typedef uint32_t  uint_fast16_t;
+typedef uint32_t  uint_fast32_t;
+typedef uint64_t  uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+   typedef signed __int64    intptr_t;
+   typedef unsigned __int64  uintptr_t;
+#else // _WIN64 ][
+   typedef _W64 signed int   intptr_t;
+   typedef _W64 unsigned int uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t   intmax_t;
+typedef uint64_t  uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN     ((int8_t)_I8_MIN)
+#define INT8_MAX     _I8_MAX
+#define INT16_MIN    ((int16_t)_I16_MIN)
+#define INT16_MAX    _I16_MAX
+#define INT32_MIN    ((int32_t)_I32_MIN)
+#define INT32_MAX    _I32_MAX
+#define INT64_MIN    ((int64_t)_I64_MIN)
+#define INT64_MAX    _I64_MAX
+#define UINT8_MAX    _UI8_MAX
+#define UINT16_MAX   _UI16_MAX
+#define UINT32_MAX   _UI32_MAX
+#define UINT64_MAX   _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN    INT8_MIN
+#define INT_LEAST8_MAX    INT8_MAX
+#define INT_LEAST16_MIN   INT16_MIN
+#define INT_LEAST16_MAX   INT16_MAX
+#define INT_LEAST32_MIN   INT32_MIN
+#define INT_LEAST32_MAX   INT32_MAX
+#define INT_LEAST64_MIN   INT64_MIN
+#define INT_LEAST64_MAX   INT64_MAX
+#define UINT_LEAST8_MAX   UINT8_MAX
+#define UINT_LEAST16_MAX  UINT16_MAX
+#define UINT_LEAST32_MAX  UINT32_MAX
+#define UINT_LEAST64_MAX  UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN    INT8_MIN
+#define INT_FAST8_MAX    INT8_MAX
+#define INT_FAST16_MIN   INT16_MIN
+#define INT_FAST16_MAX   INT16_MAX
+#define INT_FAST32_MIN   INT32_MIN
+#define INT_FAST32_MAX   INT32_MAX
+#define INT_FAST64_MIN   INT64_MIN
+#define INT_FAST64_MAX   INT64_MAX
+#define UINT_FAST8_MAX   UINT8_MAX
+#define UINT_FAST16_MAX  UINT16_MAX
+#define UINT_FAST32_MAX  UINT32_MAX
+#define UINT_FAST64_MAX  UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+#  define INTPTR_MIN   INT64_MIN
+#  define INTPTR_MAX   INT64_MAX
+#  define UINTPTR_MAX  UINT64_MAX
+#else // _WIN64 ][
+#  define INTPTR_MIN   INT32_MIN
+#  define INTPTR_MAX   INT32_MAX
+#  define UINTPTR_MAX  UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN   INT64_MIN
+#define INTMAX_MAX   INT64_MAX
+#define UINTMAX_MAX  UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+#  define PTRDIFF_MIN  _I64_MIN
+#  define PTRDIFF_MAX  _I64_MAX
+#else  // _WIN64 ][
+#  define PTRDIFF_MIN  _I32_MIN
+#  define PTRDIFF_MAX  _I32_MAX
+#endif  // _WIN64 ]
+
+#define SIG_ATOMIC_MIN  INT_MIN
+#define SIG_ATOMIC_MAX  INT_MAX
+
+#ifndef SIZE_MAX // [
+#  ifdef _WIN64 // [
+#     define SIZE_MAX  _UI64_MAX
+#  else // _WIN64 ][
+#     define SIZE_MAX  _UI32_MAX
+#  endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+#  define WCHAR_MIN  0
+#endif  // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+#  define WCHAR_MAX  _UI16_MAX
+#endif  // WCHAR_MAX ]
+
+#define WINT_MIN  0
+#define WINT_MAX  _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val)  val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val)  val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+#define INTMAX_C   INT64_C
+#define UINTMAX_C  UINT64_C
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+
+#endif // _MSC_STDINT_H_ ]
new file mode 100644
--- /dev/null
+++ b/mfbt/StdInt.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99 ft=cpp:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jeff Walden <jwalden+code@mit.edu> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implements the C99 <stdint.h> interface for C and C++ code. */
+
+#ifndef mozilla_StdInt_h_
+#define mozilla_StdInt_h_
+
+/*
+ * The C99 standard header <stdint.h> exposes typedefs for common fixed-width
+ * integer types.  It would be feasible to simply #include <stdint.h>, but
+ * MSVC++ versions prior to 2010 don't provide <stdint.h>.  We could solve this
+ * by reimplementing <stdint.h> for MSVC++ 2008 and earlier.  But then we reach
+ * a second problem: our custom <stdint.h> might conflict with a <stdint.h>
+ * defined by an embedder already looking to work around the MSVC++ <stdint.h>
+ * absence.
+ *
+ * We address these issues in this manner:
+ *
+ *   1. If the preprocessor macro MOZ_CUSTOM_STDINT_H is defined to a path to a
+ *      custom <stdint.h> implementation, we will #include it.  Embedders using
+ *      a custom <stdint.h> must define this macro to an implementation that
+ *      will work with their embedding.
+ *   2. Otherwise, if we are compiling with a an MSVC++ version without
+ *      <stdint.h>, #include our custom <stdint.h> reimplementation.
+ *   3. Otherwise, #include the standard <stdint.h> provided by the compiler.
+ */
+#if defined(MOZ_CUSTOM_STDINT_H)
+#  include MOZ_CUSTOM_STDINT_H
+#elif defined(_MSC_VER) && _MSC_VER < 1600
+#  include "mozilla/MSStdInt.h"
+#else
+#  include <stdint.h>
+#endif
+
+#endif  /* mozilla_StdInt_h_ */
--- a/mfbt/Types.h
+++ b/mfbt/Types.h
@@ -40,42 +40,38 @@
 /*
  * NB: This header must be both valid C and C++.  It must be
  * include-able by code embedding SpiderMonkey *and* Gecko.
  */
 
 #ifndef mozilla_Types_h_
 #define mozilla_Types_h_
 
+/*
+ * Expose the standard integer types from <stdint.h> (and the integer type
+ * limit and constant macros, if the right __STDC_*_MACRO has been defined for
+ * each).  These are all usable throughout mfbt code, and throughout Mozilla
+ * code more generally.
+ */
+#include "mozilla/StdInt.h"
+
 /* 
  * mfbt is logically "lower level" than js/src, but needs basic
  * definitions of numerical types and macros for compiler/linker
  * directives.  js/src already goes through some pain to provide them
  * on numerous platforms, so instead of moving all that goop here,
  * this header makes use of the fact that for the foreseeable future
  * mfbt code will be part and parcel with libmozjs, static or not.
  *
  * For now, the policy is to use jstypes definitions but add a layer
  * of indirection on top of them in case a Great Refactoring ever
  * happens.
  */
 #include "jstypes.h"
 
-/*
- * The numerical types provided by jstypes.h that are allowed within
- * mfbt code are
- *
- *   stddef types:  size_t, ptrdiff_t, etc.
- *   stdin [sic] types:  int8, uint32, etc.
- *
- * stdint types (int8_t etc.), are available for use here, but doing
- * so would change SpiderMonkey's and Gecko's contracts with
- * embedders: stdint types have not yet appeared in public APIs.
- */
-
 #define MOZ_EXPORT_API(type_)  JS_EXPORT_API(type_)
 #define MOZ_IMPORT_API(type_)  JS_IMPORT_API(type_)
 
 /*
  * mfbt definitions need to see export declarations when built, but
  * other code needs to see import declarations when using mfbt.
  */
 #if defined(IMPL_MFBT)
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -409,22 +409,16 @@ pref("devtools.errorconsole.enabled", fa
 pref("browser.ui.layout.tablet", -1); // on: 1, off: 0, auto: -1
 
 // kinetic tweakables
 pref("browser.ui.kinetic.updateInterval", 16);
 pref("browser.ui.kinetic.exponentialC", 1400);
 pref("browser.ui.kinetic.polynomialC", 100);
 pref("browser.ui.kinetic.swipeLength", 160);
 
-// zooming
-pref("browser.ui.zoom.pageFitGranularity", 9); // don't zoom to fit by less than 1/9 (11%)
-pref("browser.ui.zoom.animationDuration", 200); // ms duration of double-tap zoom animation
-pref("browser.ui.zoom.reflow", false); // Change text wrapping on double-tap
-pref("browser.ui.zoom.reflow.fontSize", 720);
-
 pref("font.size.inflation.minTwips", 120);
 
 // pinch gesture
 pref("browser.ui.pinch.maxGrowth", 150);     // max pinch distance growth
 pref("browser.ui.pinch.maxShrink", 200);     // max pinch distance shrinkage
 pref("browser.ui.pinch.scalingFactor", 500); // scaling factor for above pinch limits
 
 // Touch radius (area around the touch location to look for target elements),
@@ -560,17 +554,16 @@ pref("font.default.x-western", "SwissA")
 pref("services.sync.client.type", "mobile");
 pref("services.sync.registerEngines", "Tab,Bookmarks,Form,History,Password,Prefs");
 pref("services.sync.autoconnectDelay", 5);
 
 // prefs to sync by default
 pref("services.sync.prefs.sync.browser.startup.homepage.title", true);
 pref("services.sync.prefs.sync.browser.startup.homepage", true);
 pref("services.sync.prefs.sync.browser.tabs.warnOnClose", true);
-pref("services.sync.prefs.sync.browser.ui.zoom.reflow", true);
 pref("services.sync.prefs.sync.devtools.errorconsole.enabled", true);
 pref("services.sync.prefs.sync.javascript.enabled", true);
 pref("services.sync.prefs.sync.lightweightThemes.isThemeSelected", true);
 pref("services.sync.prefs.sync.lightweightThemes.usedThemes", true);
 pref("services.sync.prefs.sync.network.cookie.cookieBehavior", true);
 pref("services.sync.prefs.sync.permissions.default.image", true);
 pref("services.sync.prefs.sync.privacy.donottrackheader.enabled", true);
 pref("services.sync.prefs.sync.signon.rememberSignons", true);
--- a/mobile/android/base/AboutHomeContent.java
+++ b/mobile/android/base/AboutHomeContent.java
@@ -58,37 +58,37 @@ import android.widget.ListAdapter;
 import android.widget.GridView;
 import android.widget.SimpleCursorAdapter;
 import java.io.*;
 import java.util.zip.*;
 import android.os.Handler;
 import org.json.*;
 import android.util.AttributeSet;
 
+import org.mozilla.gecko.db.BrowserDB;
+import org.mozilla.gecko.db.BrowserDB.URLColumns;
+
 public class AboutHomeContent extends LinearLayout {
     public interface UriLoadCallback {
         public void callback(String uriSpec);
     }
 
     UriLoadCallback mUriLoadCallback = null;
 
     void setUriLoadCallback(UriLoadCallback uriLoadCallback) {
         mUriLoadCallback = uriLoadCallback;
     }
 
     public AboutHomeContent(Context context, AttributeSet attrs) {
         super(context, attrs);
-
-        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        inflater.inflate(R.layout.abouthome_content, this);
     }
 
     private static final String LOGTAG = "GeckoAboutHome";
     private static final String TITLE_KEY = "title";
-    private static final String kAbouthomeWhereClause = Browser.BookmarkColumns.BOOKMARK + " = 1";
+    private static final int NUMBER_OF_TOP_SITES = 3;
     private static final int kTileWidth = 122;
 
     private Cursor mCursor;
     private Uri mUri;
     private String mTitle;
 
     protected ListAdapter mGridAdapter;
     protected ArrayAdapter<String> mAddonAdapter;
@@ -121,30 +121,30 @@ public class AboutHomeContent extends Li
         {
             onGridItemClick((GridView)parent, v, position, id);
         }
     };
 
     void init(final Activity activity) {
         GeckoAppShell.getHandler().post(new Runnable() {
             public void run() {
-                mCursor = activity.managedQuery(Browser.BOOKMARKS_URI,
-                                                null, kAbouthomeWhereClause, null, null);
+                ContentResolver resolver = GeckoApp.mAppContext.getContentResolver();
+                mCursor = BrowserDB.filter(resolver, "", NUMBER_OF_TOP_SITES);
                 activity.startManagingCursor(mCursor);
 
                 onActivityContentChanged(activity);
                 mAddonAdapter = new ArrayAdapter<String>(activity, R.layout.abouthome_addon_list_item);
                 GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
                     public void run() {
                         final SimpleCursorAdapter gridAdapter =
                             new SimpleCursorAdapter(activity, R.layout.abouthome_grid_box, mCursor,
-                                                    new String[] {Browser.BookmarkColumns.TITLE,
-                                                                  Browser.BookmarkColumns.FAVICON,
-                                                                  Browser.BookmarkColumns.URL,
-                                                                  "thumbnail"},
+                                                    new String[] { URLColumns.TITLE,
+                                                                   URLColumns.FAVICON,
+                                                                   URLColumns.URL,
+                                                                   URLColumns.THUMBNAIL },
                                                     new int[] {R.id.bookmark_title, R.id.bookmark_icon, R.id.bookmark_url, R.id.screenshot});
                         mGrid.setAdapter(gridAdapter);
                         gridAdapter.setViewBinder(new AwesomeCursorViewBinder());
                         mAddonList.setAdapter(mAddonAdapter);
                     }
                 });
                 readRecommendedAddons(activity);
             }
@@ -205,45 +205,52 @@ public class AboutHomeContent extends Li
                     Log.i("GeckoAddons", "error reading json file", e);
                 }
             }
         });
     }
 
     protected void onGridItemClick(GridView l, View v, int position, long id) {
         mCursor.moveToPosition(position);
-        String spec = mCursor.getString(mCursor.getColumnIndex(Browser.BookmarkColumns.URL));
+        String spec = mCursor.getString(mCursor.getColumnIndex(URLColumns.URL));
         Log.i(LOGTAG, "clicked: " + spec);
         if (mUriLoadCallback != null)
             mUriLoadCallback.callback(spec);
     }
 
 }
 class AwesomeCursorViewBinder implements SimpleCursorAdapter.ViewBinder {
+    private static final String LOGTAG = "GeckoAwesomeCursorViewBinder";
+
     private boolean updateImage(View view, Cursor cursor, int faviconIndex) {
         byte[] b = cursor.getBlob(faviconIndex);
         ImageView favicon = (ImageView) view;
 
         if (b == null) {
             favicon.setImageResource(R.drawable.favicon);
         } else {
-            Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
-            favicon.setImageBitmap(bitmap);
+            try {
+                Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
+                favicon.setImageBitmap(bitmap);
+            } catch (OutOfMemoryError oom) {
+                Log.e(LOGTAG, "Unable to load thumbnail bitmap", oom);
+                favicon.setImageResource(R.drawable.favicon);
+            }
         }
 
         return true;
     }
 
     private boolean updateTitle(View view, Cursor cursor, int titleIndex) {
         String title = cursor.getString(titleIndex);
         TextView titleView = (TextView)view;
         // Use the URL instead of an empty title for consistency with the normal URL
         // bar view - this is the equivalent of getDisplayTitle() in Tab.java
         if (title == null || title.length() == 0) {
-            int urlIndex = cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.URL);
+            int urlIndex = cursor.getColumnIndexOrThrow(URLColumns.URL);
             title = cursor.getString(urlIndex);
         }
 
         titleView.setText(title);
         return true;
     }
 
     private boolean updateUrl(View view, Cursor cursor, int urlIndex) {
@@ -259,33 +266,32 @@ class AwesomeCursorViewBinder implements
                 title = title.substring(0, title.length() -1);
         }
         urlView.setText(title);
         return true;
     }
 
     @Override
     public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
-        int faviconIndex = cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.FAVICON);
+        int faviconIndex = cursor.getColumnIndexOrThrow(URLColumns.FAVICON);
         if (columnIndex == faviconIndex) {
             return updateImage(view, cursor, faviconIndex);
         }
 
-        int titleIndex = cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.TITLE);
+        int titleIndex = cursor.getColumnIndexOrThrow(URLColumns.TITLE);
         if (columnIndex == titleIndex) {
             return updateTitle(view, cursor, titleIndex);
         }
 
-        int urlIndex = cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.URL);
+        int urlIndex = cursor.getColumnIndexOrThrow(URLColumns.URL);
         if (columnIndex == urlIndex) {
             return updateUrl(view, cursor, urlIndex);
         }
 
-        int thumbIndex = cursor.getColumnIndexOrThrow("thumbnail");
-
+        int thumbIndex = cursor.getColumnIndexOrThrow(URLColumns.THUMBNAIL);
         if (columnIndex == thumbIndex) {
             return updateImage(view, cursor, thumbIndex);
         }
 
         // Other columns are handled automatically
         return false;
     }
 
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -134,10 +134,14 @@
         <activity android:name="org.mozilla.gecko.TabsTray"
                   android:theme="@style/Gecko.Translucent"/>
 
         <activity android:name="org.mozilla.gecko.GeckoPreferences"
                   android:theme="@style/Gecko.TitleBar"
                   android:label="@string/preferences_title"
                   android:excludeFromRecents="true"/>
 
+        <provider android:name="org.mozilla.gecko.db.BrowserProvider"
+                  android:authorities="org.mozilla.gecko.providers.browser"
+                  android:exported="false"/>
+
     </application>
 </manifest> 
--- a/mobile/android/base/AwesomeBar.java
+++ b/mobile/android/base/AwesomeBar.java
@@ -58,17 +58,16 @@ import android.widget.ImageButton;
 
 import org.json.JSONArray;
 import org.json.JSONObject;
 
 public class AwesomeBar extends Activity implements GeckoEventListener {
     private static final String LOGTAG = "GeckoAwesomeBar";
 
     static final String URL_KEY = "url";
-    static final String TITLE_KEY = "title";
     static final String CURRENT_URL_KEY = "currenturl";
     static final String TYPE_KEY = "type";
     static final String SEARCH_KEY = "search";
     static enum Type { ADD, EDIT };
 
     private String mType;
     private AwesomeBarTabs mAwesomeTabs;
     private AwesomeBarEditText mText;
--- a/mobile/android/base/AwesomeBarTabs.java
+++ b/mobile/android/base/AwesomeBarTabs.java
@@ -74,26 +74,30 @@ import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
+import org.mozilla.gecko.db.BrowserDB;
+import org.mozilla.gecko.db.BrowserDB.URLColumns;
+
 public class AwesomeBarTabs extends TabHost {
     private static final String LOGTAG = "GeckoAwesomeBarTabs";
 
     private static final String ALL_PAGES_TAB = "all";
     private static final String BOOKMARKS_TAB = "bookmarks";
     private static final String HISTORY_TAB = "history";
 
     private static enum HistorySection { TODAY, YESTERDAY, WEEK, OLDER };
 
     private Context mContext;
+    private boolean mInflated;
     private OnUrlOpenListener mUrlOpenListener;
     private View.OnTouchListener mListTouchListener;
     private JSONArray mSearchEngines;
 
     private AwesomeBarCursorAdapter mAllPagesCursorAdapter;
     private SimpleCursorAdapter mBookmarksAdapter;
     private SimpleExpandableListAdapter mHistoryAdapter;
 
@@ -122,17 +126,17 @@ public class AwesomeBarTabs extends TabH
 
             View childView =
                     super.getChildView(groupPosition, childPosition, isLastChild, convertView, parent); 
 
             @SuppressWarnings("unchecked")
             Map<String,Object> historyItem =
                     (Map<String,Object>) mHistoryAdapter.getChild(groupPosition, childPosition);
 
-            byte[] b = (byte[]) historyItem.get(Browser.BookmarkColumns.FAVICON);
+            byte[] b = (byte[]) historyItem.get(URLColumns.FAVICON);
             ImageView favicon = (ImageView) childView.findViewById(R.id.favicon);
 
             if (b == null) {
                 favicon.setImageResource(R.drawable.favicon);
             } else {
                 Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
                 favicon.setImageBitmap(bitmap);
             }
@@ -157,64 +161,55 @@ public class AwesomeBarTabs extends TabH
         }
 
         private boolean updateTitle(View view, Cursor cursor, int titleIndex) {
             String title = cursor.getString(titleIndex);
             TextView titleView = (TextView)view;
             // Use the URL instead of an empty title for consistency with the normal URL
             // bar view - this is the equivalent of getDisplayTitle() in Tab.java
             if (title == null || title.length() == 0) {
-                int urlIndex = cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.URL);
+                int urlIndex = cursor.getColumnIndexOrThrow(URLColumns.URL);
                 title = cursor.getString(urlIndex);
             }
 
             titleView.setText(title);
             return true;
         }
 
         public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
-            int faviconIndex = cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.FAVICON);
+            int faviconIndex = cursor.getColumnIndexOrThrow(URLColumns.FAVICON);
             if (columnIndex == faviconIndex) {
                 return updateFavicon(view, cursor, faviconIndex);
             }
 
-            int titleIndex = cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.TITLE);
+            int titleIndex = cursor.getColumnIndexOrThrow(URLColumns.TITLE);
             if (columnIndex == titleIndex) {
                 return updateTitle(view, cursor, titleIndex);
             }
 
             // Other columns are handled automatically
             return false;
         }
     }
 
     private class BookmarksQueryTask extends AsyncTask<Void, Void, Cursor> {
         protected Cursor doInBackground(Void... arg0) {
             ContentResolver resolver = mContext.getContentResolver();
-
-            return resolver.query(Browser.BOOKMARKS_URI,
-                                  null,
-                                  // Select all bookmarks with a non-empty URL. When the history
-                                  // is empty there appears to be a dummy entry in the database
-                                  // which has a title of "Bookmarks" and no URL; the length restriction
-                                  // is to avoid picking that up specifically.
-                                  Browser.BookmarkColumns.BOOKMARK + " = 1 AND LENGTH(" + Browser.BookmarkColumns.URL + ") > 0",
-                                  null,
-                                  Browser.BookmarkColumns.TITLE);
+            return BrowserDB.getAllBookmarks(resolver);
         }
 
         protected void onPostExecute(Cursor cursor) {
             // Load the list using a custom adapter so we can create the bitmaps
             mBookmarksAdapter = new SimpleCursorAdapter(
                 mContext,
                 R.layout.awesomebar_row,
                 cursor,
-                new String[] { AwesomeBar.TITLE_KEY,
-                               AwesomeBar.URL_KEY,
-                               Browser.BookmarkColumns.FAVICON },
+                new String[] { URLColumns.TITLE,
+                               URLColumns.URL,
+                               URLColumns.FAVICON },
                 new int[] { R.id.title, R.id.url, R.id.favicon }
             );
 
             mBookmarksAdapter.setViewBinder(new AwesomeCursorViewBinder());
 
             final ListView bookmarksList = (ListView) findViewById(R.id.bookmarks_list);
 
             bookmarksList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@@ -229,25 +224,17 @@ public class AwesomeBarTabs extends TabH
 
     private class HistoryQueryTask extends AsyncTask<Void, Void, Pair<List,List>> {
         private static final long MS_PER_DAY = 86400000;
         private static final long MS_PER_WEEK = MS_PER_DAY * 7;
 
         protected Pair<List,List> doInBackground(Void... arg0) {
             Pair<List,List> result = null;
             ContentResolver resolver = mContext.getContentResolver();
-
-            Cursor cursor =
-                    resolver.query(Browser.BOOKMARKS_URI,
-                                   null,
-                                   // Bookmarks that have not been visited have a date value
-                                   // of 0, so don't pick them up in the history view.
-                                   Browser.BookmarkColumns.DATE + " > 0",
-                                   null,
-                                   Browser.BookmarkColumns.DATE + " DESC LIMIT " + MAX_RESULTS);
+            Cursor cursor = BrowserDB.getRecentHistory(resolver, MAX_RESULTS);
 
             Date now = new Date();
             now.setHours(0);
             now.setMinutes(0);
             now.setSeconds(0);
 
             long today = now.getTime();
 
@@ -262,17 +249,17 @@ public class AwesomeBarTabs extends TabH
             // for the iteration.
             cursor.moveToPosition(-1);
 
             // Split the history query results into adapters per time
             // section (today, yesterday, week, older). Queries on content
             // Browser content provider don't support limitting the number
             // of returned rows so we limit it here.
             while (cursor.moveToNext()) {
-                long time = cursor.getLong(cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.DATE));
+                long time = cursor.getLong(cursor.getColumnIndexOrThrow(URLColumns.DATE_LAST_VISITED));
                 HistorySection itemSection = getSectionForTime(time, today);
 
                 if (groups == null)
                     groups = new LinkedList<Map<String,?>>();
 
                 if (childrenLists == null)
                     childrenLists = new LinkedList<List<Map<String,?>>>();
 
@@ -304,38 +291,38 @@ public class AwesomeBarTabs extends TabH
             }
 
             return result;
         }
 
         public Map<String,?> createHistoryItem(Cursor cursor) {
             Map<String,Object> historyItem = new HashMap<String,Object>();
 
-            String url = cursor.getString(cursor.getColumnIndexOrThrow(AwesomeBar.URL_KEY));
-            String title = cursor.getString(cursor.getColumnIndexOrThrow(AwesomeBar.TITLE_KEY));
-            byte[] favicon = cursor.getBlob(cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.FAVICON));
+            String url = cursor.getString(cursor.getColumnIndexOrThrow(URLColumns.URL));
+            String title = cursor.getString(cursor.getColumnIndexOrThrow(URLColumns.TITLE));
+            byte[] favicon = cursor.getBlob(cursor.getColumnIndexOrThrow(URLColumns.FAVICON));
 
             // Use the URL instead of an empty title for consistency with the normal URL
             // bar view - this is the equivalent of getDisplayTitle() in Tab.java
             if (title == null || title.length() == 0)
                 title = url;
 
-            historyItem.put(AwesomeBar.URL_KEY, url);
-            historyItem.put(AwesomeBar.TITLE_KEY, title);
+            historyItem.put(URLColumns.URL, url);
+            historyItem.put(URLColumns.TITLE, title);
 
             if (favicon != null)
-                historyItem.put(Browser.BookmarkColumns.FAVICON, favicon);
+                historyItem.put(URLColumns.FAVICON, favicon);
 
             return historyItem;
         }
 
         public Map<String,?> createGroupItem(HistorySection section) {
             Map<String,String> groupItem = new HashMap<String,String>();
 
-            groupItem.put(AwesomeBar.TITLE_KEY, getSectionName(section));
+            groupItem.put(URLColumns.TITLE, getSectionName(section));
 
             return groupItem;
         }
 
         private String getSectionName(HistorySection section) {
             Resources resources = mContext.getResources();
 
             switch (section) {
@@ -379,21 +366,21 @@ public class AwesomeBarTabs extends TabH
             // FIXME: display some sort of message when there's no history
             if (result == null)
                 return;
 
             mHistoryAdapter = new HistoryListAdapter(
                 mContext,
                 result.first,
                 R.layout.awesomebar_header_row,
-                new String[] { AwesomeBar.TITLE_KEY },
+                new String[] { URLColumns.TITLE },
                 new int[] { R.id.title },
                 result.second,
                 R.layout.awesomebar_row,
-                new String[] { AwesomeBar.TITLE_KEY, AwesomeBar.URL_KEY },
+                new String[] { URLColumns.TITLE, URLColumns.URL },
                 new int[] { R.id.title, R.id.url }
             );
 
             final ExpandableListView historyList =
                     (ExpandableListView) findViewById(R.id.history_list);
 
             historyList.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
                 public boolean onChildClick(ExpandableListView parent, View view,
@@ -521,23 +508,31 @@ public class AwesomeBarTabs extends TabH
     };
 
     public AwesomeBarTabs(Context context, AttributeSet attrs) {
         super(context, attrs);
 
         Log.d(LOGTAG, "Creating AwesomeBarTabs");
 
         mContext = context;
+        mInflated = false;
         mSearchEngines = new JSONArray();
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
 
-        // Load layout into the custom view
-        LayoutInflater inflater =
-                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        // HACK: Without this, the onFinishInflate is called twice
+        // This issue is due to a bug when Android inflates a layout with a
+        // parent. Fixed in Honeycomb
+        if (mInflated)
+            return;
 
-        inflater.inflate(R.layout.awesomebar_tabs, this);
+        mInflated = true;
 
         // This should be called before adding any tabs
         // to the TabHost.
         setup();
 
         mListTouchListener = new View.OnTouchListener() {
             public boolean onTouch(View view, MotionEvent event) {
                 hideSoftInput(view);
@@ -606,40 +601,28 @@ public class AwesomeBarTabs extends TabH
                       R.string.awesomebar_all_pages_title,
                       R.id.all_pages_list);
 
         // Load the list using a custom adapter so we can create the bitmaps
         mAllPagesCursorAdapter = new AwesomeBarCursorAdapter(
             mContext,
             R.layout.awesomebar_row,
             null,
-            new String[] { AwesomeBar.TITLE_KEY,
-                           AwesomeBar.URL_KEY,
-                           Browser.BookmarkColumns.FAVICON },
+            new String[] { URLColumns.TITLE,
+                           URLColumns.URL,
+                           URLColumns.FAVICON },
             new int[] { R.id.title, R.id.url, R.id.favicon }
         );
 
         mAllPagesCursorAdapter.setViewBinder(new AwesomeCursorViewBinder());
 
         mAllPagesCursorAdapter.setFilterQueryProvider(new FilterQueryProvider() {
             public Cursor runQuery(CharSequence constraint) {
                 ContentResolver resolver = mContext.getContentResolver();
-
-                return resolver.query(Browser.BOOKMARKS_URI,
-                                      null,
-                                      // The length restriction on URL is for the same reason as in the general bookmark query
-                                      // (see comment earlier in this file).
-                                      "(" + Browser.BookmarkColumns.URL + " LIKE ? OR " + Browser.BookmarkColumns.TITLE + " LIKE ?)"
-                                        + " AND LENGTH(" + Browser.BookmarkColumns.URL + ") > 0", 
-                                      new String[] {"%" + constraint.toString() + "%", "%" + constraint.toString() + "%",},
-                                      // ORDER BY is number of visits times a multiplier from 1 - 120 of how recently the site 
-                                      // was accessed with a site accessed today getting 120 and a site accessed 119 or more 
-                                      // days ago getting 1
-                                      Browser.BookmarkColumns.VISITS + " * MAX(1, (" +
-                                      Browser.BookmarkColumns.DATE + " - " + new Date().getTime() + ") / 86400000 + 120) DESC LIMIT " + MAX_RESULTS);
+                return BrowserDB.filter(resolver, constraint, MAX_RESULTS);
             }
         });
 
         final ListView allPagesList = (ListView) findViewById(R.id.all_pages_list);
 
         allPagesList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                 handleItemClick(allPagesList, position);
@@ -685,30 +668,30 @@ public class AwesomeBarTabs extends TabH
         imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
     }
 
     private void handleHistoryItemClick(int groupPosition, int childPosition) {
         @SuppressWarnings("unchecked")
         Map<String,Object> historyItem =
                 (Map<String,Object>) mHistoryAdapter.getChild(groupPosition, childPosition);
 
-        String url = (String) historyItem.get(AwesomeBar.URL_KEY);
+        String url = (String) historyItem.get(URLColumns.URL);
 
         if (mUrlOpenListener != null)
             mUrlOpenListener.onUrlOpen(url);
     }
 
     private void handleItemClick(ListView list, int position) {
         Object item = list.getItemAtPosition(position);
         // If an AwesomeBar entry is clicked, item will be a Cursor containing
         // the entry's data.  Otherwise, a search engine entry was clicked, and
         // item will be a String containing the name of the search engine.
         if (item instanceof Cursor) {
             Cursor cursor = (Cursor) item;
-            String url = cursor.getString(cursor.getColumnIndexOrThrow(AwesomeBar.URL_KEY));
+            String url = cursor.getString(cursor.getColumnIndexOrThrow(URLColumns.URL));
             if (mUrlOpenListener != null)
                 mUrlOpenListener.onUrlOpen(url);
         } else {
             if (mUrlOpenListener != null)
                 mUrlOpenListener.onSearch((String)item);
         }
     }
 
--- a/mobile/android/base/BrowserToolbar.java
+++ b/mobile/android/base/BrowserToolbar.java
@@ -57,53 +57,61 @@ import android.view.View;
 import android.widget.Button;
 import android.widget.ImageButton;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 import android.widget.TextSwitcher;
 import android.widget.ViewSwitcher.ViewFactory;
 
 public class BrowserToolbar extends LinearLayout {
-    final private Button mAwesomeBar;
-    final private ImageButton mTabs;
-    final public ImageButton mFavicon;
-    final public ImageButton mStop;
-    final public ImageButton mSiteSecurity;
-    final private AnimationDrawable mProgressSpinner;
-    final private TextSwitcher mTabsCount;
+    private Button mAwesomeBar;
+    private ImageButton mTabs;
+    public ImageButton mFavicon;
+    public ImageButton mStop;
+    public ImageButton mSiteSecurity;
+    private AnimationDrawable mProgressSpinner;
+    private TextSwitcher mTabsCount;
 
     final private Context mContext;
-    final private Handler mHandler;
-    final private int mColor;
-    final private int mCounterColor;
+    private Handler mHandler;
+    private boolean mInflated;
+    private int mColor;
+    private int mCounterColor;
 
-    final private int mDuration;
-    final private TranslateAnimation mSlideUpIn;
-    final private TranslateAnimation mSlideUpOut;
-    final private TranslateAnimation mSlideDownIn;
-    final private TranslateAnimation mSlideDownOut;
+    private int mDuration;
+    private TranslateAnimation mSlideUpIn;
+    private TranslateAnimation mSlideUpOut;
+    private TranslateAnimation mSlideDownIn;
+    private TranslateAnimation mSlideDownOut;
 
     private int mCount;
 
     public BrowserToolbar(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mContext = context;
+        mInflated = false;
+    }
 
-        mContext = context;
+    @Override
+    protected void onFinishInflate () {
+        super.onFinishInflate();
+
+        // HACK: Without this, the onFinishInflate is called twice
+        // This issue is due to a bug when Android inflates a layout with a
+        // parent. Fixed in Honeycomb
+        if (mInflated)
+            return;
+
+        mInflated = true;
 
         // Get the device's highlight color
         ContextThemeWrapper wrapper = new ContextThemeWrapper(mContext, android.R.style.TextAppearance);
         TypedArray typedArray = wrapper.getTheme().obtainStyledAttributes(new int[] { android.R.attr.textColorHighlight });
         mColor = typedArray.getColor(typedArray.getIndex(0), 0);
 
-        // Load layout into the custom view
-        LayoutInflater inflater =
-                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
-        inflater.inflate(R.layout.browser_toolbar, this);
-
         mAwesomeBar = (Button) findViewById(R.id.awesome_bar);
         mAwesomeBar.setOnClickListener(new Button.OnClickListener() {
             public void onClick(View v) {
                 onAwesomeBarSearch();
             }
         });
 
         Resources resources = getResources();
@@ -130,28 +138,29 @@ public class BrowserToolbar extends Line
                     addTab();
             }
         });
         mTabs.setImageLevel(1);
 
         mCounterColor = 0x99ffffff;
 
         mTabsCount = (TextSwitcher) findViewById(R.id.tabs_count);
+        mTabsCount.removeAllViews();
         mTabsCount.setFactory(new ViewFactory() {
             public View makeView() {
                 TextView text = new TextView(mContext);
                 text.setGravity(Gravity.CENTER);
                 text.setTextSize(16);
                 text.setTextColor(mCounterColor);
                 text.setTypeface(text.getTypeface(), Typeface.BOLD);
-                return text;
-            } 
-        });
+                return (View) text;
+            }
+        }); 
+        mTabsCount.setText("0");
         mCount = 0;
-        mTabsCount.setText("0");
 
         mFavicon = (ImageButton) findViewById(R.id.favicon);
         mSiteSecurity = (ImageButton) findViewById(R.id.site_security);
         mProgressSpinner = (AnimationDrawable) resources.getDrawable(R.drawable.progress_spinner);
         
         mStop = (ImageButton) findViewById(R.id.stop);
         mStop.setOnClickListener(new Button.OnClickListener() {
             public void onClick(View v) {
--- a/mobile/android/base/ConfirmPreference.java
+++ b/mobile/android/base/ConfirmPreference.java
@@ -32,19 +32,20 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 package org.mozilla.gecko;
 
+import org.mozilla.gecko.db.BrowserDB;
+
 import android.content.Context;
 import android.preference.DialogPreference;
-import android.provider.Browser;
 import android.util.AttributeSet;
 import android.util.Log;
 
 class ConfirmPreference extends DialogPreference {
     private static final String LOGTAG = "GeckoConfirmPreference";
 
     private String mAction = null;
     private Context mContext = null;
@@ -59,17 +60,17 @@ class ConfirmPreference extends DialogPr
         mContext = context;
     }
     protected void onDialogClosed(boolean positiveResult) {
         if (!positiveResult)
             return;
         if ("clear_history".equalsIgnoreCase(mAction)) {
             GeckoAppShell.getHandler().post(new Runnable(){
                 public void run() {
-                    Browser.clearHistory(mContext.getContentResolver());
+                    BrowserDB.clearHistory(mContext.getContentResolver());
                 }
             });
         } else if ("clear_private_data".equalsIgnoreCase(mAction)) {
             GeckoAppShell.getHandler().post(new Runnable(){
                 public void run() {
                     GeckoAppShell.sendEventToGecko(new GeckoEvent("Sanitize:ClearAll", null));
                 }
             });
--- a/mobile/android/base/DoorHanger.java
+++ b/mobile/android/base/DoorHanger.java
@@ -51,45 +51,48 @@ import android.widget.TextView;
 import org.json.JSONObject;
 import org.json.JSONException;
 
 public class DoorHanger extends LinearLayout implements Button.OnClickListener {
     private Context mContext;
     private LinearLayout mChoicesLayout;
     private TextView mTextView;
     private Button mButton;
-    private LayoutParams mLayoutParams;
+    static private LayoutParams mLayoutParams;
     public Tab mTab;
     // value used to identify the notification
     private String mValue;
 
+    static private LayoutInflater mInflater;
+
     private int mPersistence = 0;
     private long mTimeout = 0;
 
     public DoorHanger(Context aContext, String aValue) {
         super(aContext);
 
         mContext = aContext;
         mValue = aValue;
 
         setOrientation(VERTICAL);
         setBackgroundResource(R.drawable.doorhanger_shadow_bg);
 
-        // Load layout into the custom view
-        LayoutInflater inflater =
-                (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        inflater.inflate(R.layout.doorhanger, this);
+        if (mInflater == null)
+            mInflater = LayoutInflater.from(mContext);
+
+        mInflater.inflate(R.layout.doorhanger, this);
         hide();
 
         mTextView = (TextView) findViewById(R.id.doorhanger_title);
         mChoicesLayout = (LinearLayout) findViewById(R.id.doorhanger_choices);
 
-        mLayoutParams = new LayoutParams(LayoutParams.FILL_PARENT,
-                                         LayoutParams.FILL_PARENT,
-                                         1.0f);
+        if (mLayoutParams == null)
+            mLayoutParams = new LayoutParams(LayoutParams.FILL_PARENT,
+                                             LayoutParams.FILL_PARENT,
+                                             1.0f);
     }
 
     public void addButton(String aText, int aCallback) {
         Button mButton = new Button(mContext);
         mButton.setText(aText);
         mButton.setTag(Integer.toString(aCallback));
         mButton.setOnClickListener(this);
         mChoicesLayout.addView(mButton, mLayoutParams);
--- a/mobile/android/base/DoorHangerPopup.java
+++ b/mobile/android/base/DoorHangerPopup.java
@@ -64,17 +64,17 @@ public class DoorHangerPopup extends Pop
     public DoorHangerPopup(Context aContext) {
         super(aContext);
         mContext = aContext;
 
         setBackgroundDrawable(new BitmapDrawable());
         setOutsideTouchable(true);
         setWindowLayoutMode(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
 
-        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        LayoutInflater inflater = LayoutInflater.from(mContext);
         RelativeLayout layout = (RelativeLayout) inflater.inflate(R.layout.doorhangerpopup, null);
         mContent = (LinearLayout) layout.findViewById(R.id.doorhanger_container);
         
         setContentView(layout);
     }
 
     public void addDoorHanger(String message, String value, JSONArray buttons,
                               Tab tab, JSONObject options) {
--- a/mobile/android/base/Favicons.java
+++ b/mobile/android/base/Favicons.java
@@ -39,37 +39,35 @@ package org.mozilla.gecko;
 
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.database.sqlite.SQLiteQueryBuilder;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
-import android.provider.Browser;
 import android.util.Log;
 
 import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
+import java.net.URLConnection;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
+import org.mozilla.gecko.db.BrowserDB;
+
 public class Favicons {
     private static final String LOGTAG = "GeckoFavicons";
 
     public static final long NOT_LOADING = 0;
 
     private Context mContext;
     private DatabaseHelper mDbHelper;
 
@@ -230,96 +228,67 @@ public class Favicons {
                           " and favicon URL = " + faviconUrl);
         }
 
         // Runs in background thread
         private BitmapDrawable loadFaviconFromDb() {
             Log.d(LOGTAG, "Loading favicon from DB for URL = " + mPageUrl);
 
             ContentResolver resolver = mContext.getContentResolver();
-
-            Cursor c = resolver.query(Browser.BOOKMARKS_URI,
-                                      new String[] { Browser.BookmarkColumns.FAVICON },
-                                      Browser.BookmarkColumns.URL + " = ?",
-                                      new String[] { mPageUrl },
-                                      null);
-
-            if (!c.moveToFirst()) {
-                c.close();
-                return null;
-            }
+            BitmapDrawable favicon = BrowserDB.getFaviconForUrl(resolver, mPageUrl);
 
-            int faviconIndex = c.getColumnIndexOrThrow(Browser.BookmarkColumns.FAVICON);
-            
-            byte[] b = c.getBlob(faviconIndex);
-            c.close();
-            if (b == null)
-                return null;
+            if (favicon != null)
+                Log.d(LOGTAG, "Loaded favicon from DB successfully for URL = " + mPageUrl);
 
-            Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
-
-            Log.d(LOGTAG, "Loaded favicon from DB successfully for URL = " + mPageUrl);
-
-            return new BitmapDrawable(bitmap);
+            return favicon;
         }
 
         // Runs in background thread
         private void saveFaviconToDb(BitmapDrawable favicon) {
-            Bitmap bitmap = favicon.getBitmap();
-
-            ByteArrayOutputStream stream = new ByteArrayOutputStream();
-            bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
-
-            ContentValues values = new ContentValues();
-            values.put(Browser.BookmarkColumns.FAVICON, stream.toByteArray());
-            values.put(Browser.BookmarkColumns.URL, mPageUrl);
-
+            Log.d(LOGTAG, "Saving favicon on browser database for URL = " + mPageUrl);
             ContentResolver resolver = mContext.getContentResolver();
-
-            Log.d(LOGTAG, "Saving favicon on browser database for URL = " + mPageUrl);
-            resolver.update(Browser.BOOKMARKS_URI,
-                            values,
-                            Browser.BookmarkColumns.URL + " = ?",
-                            new String[] { mPageUrl });
-
+            BrowserDB.updateFaviconForUrl(resolver, mPageUrl, favicon);
 
             Log.d(LOGTAG, "Saving favicon URL for URL = " + mPageUrl);
             mDbHelper.setFaviconUrlForPageUrl(mPageUrl, mFaviconUrl);
         }
 
         // Runs in background thread
         private BitmapDrawable downloadFavicon(URL faviconUrl) {
             Log.d(LOGTAG, "Downloading favicon for URL = " + mPageUrl +
                           " with favicon URL = " + mFaviconUrl);
 
             // due to android bug 6066, we must download the entire image before using it
             // http://code.google.com/p/android/issues/detail?id=6066
-            HttpURLConnection urlConnection = null;
+            URLConnection urlConnection = null;
             BufferedInputStream contentStream = null;
             ByteArrayInputStream byteStream = null;
             BitmapDrawable image = null;
 
             try {
-                urlConnection = (HttpURLConnection) faviconUrl.openConnection();
+                urlConnection = faviconUrl.openConnection();
                 int length = urlConnection.getContentLength();
                 contentStream = new BufferedInputStream(urlConnection.getInputStream(), length);
                 byte[] bytes = new byte[length];
                 int pos = 0;
                 int offset = 0;
                 while ((pos = contentStream.read(bytes, offset, length - offset)) > 0)
                     offset += pos;
                 if (length == offset) {
                     byteStream = new ByteArrayInputStream(bytes);
                     image = (BitmapDrawable) Drawable.createFromStream(byteStream, "src");
                 }
             } catch (Exception e) {
                 Log.d(LOGTAG, "Error downloading favicon: " + e);
             } finally {
-                if (urlConnection != null)
-                    urlConnection.disconnect();
+                if (urlConnection != null && urlConnection instanceof HttpURLConnection) {
+                    HttpURLConnection httpConnection = (HttpURLConnection) urlConnection;
+                    httpConnection.disconnect();
+                }
+
                 try {
                     if (contentStream != null)
                         contentStream.close();
                     if (byteStream != null)
                         byteStream.close();
                 } catch (IOException e) {
                     Log.d(LOGTAG, "error closing favicon stream");
                 }
@@ -331,35 +300,35 @@ public class Favicons {
             }
 
             return image;
         }
 
         @Override
         protected BitmapDrawable doInBackground(Void... unused) {
             BitmapDrawable image = null;
-            URL pageUrl = null;
 
             if (isCancelled())
                 return null;
 
-            // Handle the case of malformed URL
-            try {
-                pageUrl = new URL(mPageUrl);
-            } catch (MalformedURLException e) {
-                Log.d(LOGTAG, "The provided URL is not valid: " + e);
-                return null;
-            }
-
             URL faviconUrl = null;
 
             // Handle the case of malformed favicon URL
             try {
                 // If favicon is empty, fallback to default favicon URI
                 if (mFaviconUrl == null || mFaviconUrl.length() == 0) {
+                    // Handle the case of malformed URL
+                    URL pageUrl = null;
+                    try {
+                        pageUrl = new URL(mPageUrl);
+                    } catch (MalformedURLException e) {
+                        Log.d(LOGTAG, "The provided URL is not valid: " + e);
+                        return null;
+                    }
+
                     faviconUrl = new URL(pageUrl.getProtocol(), pageUrl.getAuthority(), "/favicon.ico");
                     mFaviconUrl = faviconUrl.toString();
                 } else {
                     faviconUrl = new URL(mFaviconUrl);
                 }
             } catch (MalformedURLException e) {
                 Log.d(LOGTAG, "The provided favicon URL is not valid: " + e);
                 return null;
--- a/mobile/android/base/GeckoActionBar.java
+++ b/mobile/android/base/GeckoActionBar.java
@@ -33,20 +33,25 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 package org.mozilla.gecko;
 
 import android.app.Activity;
+import android.graphics.drawable.Drawable;
 import android.view.View;
 
 public class GeckoActionBar {
 
+    public static void setBackgroundDrawable(Activity activity, Drawable drawable) {
+         activity.getActionBar().setBackgroundDrawable(drawable);
+    }
+
     public static void setDisplayOptions(Activity activity, int options, int mask) {
          activity.getActionBar().setDisplayOptions(options, mask);
     }
 
     public static void setCustomView(Activity activity, View view) {
          activity.getActionBar().setCustomView(view);
     }
 
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -718,27 +718,31 @@ abstract public class GeckoApp
         mMainHandler.post(new Runnable() { 
             public void run() {
                 if (Tabs.getInstance().isSelectedTab(tab))
                     mBrowserToolbar.setSecurityMode(mode);
             }
         });
     }
 
-    File getProfileDir() {
+    public File getProfileDir() {
+        // XXX: TO-DO read profiles.ini to get the default profile
+        return getProfileDir("default");
+    }
+
+    public File getProfileDir(final String profileName) {
         if (mProfileDir == null && !mUserDefinedProfile) {
             File mozDir = new File(GeckoAppShell.sHomeDir, "mozilla");
             File[] profiles = mozDir.listFiles(new FileFilter() {
                 public boolean accept(File pathname) {
-                    return pathname.getName().endsWith(".default");
+                    return pathname.getName().endsWith("." + profileName);
                 }
             });
             if (profiles.length == 1)
                 mProfileDir = profiles[0];
-            // XXX: TO-DO read profiles.ini to get the default profile
         }
         return mProfileDir;
     }
 
     void addTab() {
         showAwesomebar(AwesomeBar.Type.ADD);
     }
 
@@ -1125,17 +1129,17 @@ abstract public class GeckoApp
                 if (Tabs.getInstance().isSelectedTab(tab))
                     mBrowserToolbar.setTitle(tab.getDisplayTitle());
                 onTabsChanged(tab);
             }
         });
     }
 
     void handleLinkAdded(final int tabId, String rel, final String href) {
-        if (rel.indexOf("icon") != -1) {
+        if (rel.indexOf("[icon]") != -1) {
             final Tab tab = Tabs.getInstance().getTab(tabId);
             if (tab != null) {
                 tab.updateFaviconURL(href);
 
                 // If tab is not loading and the favicon is updated, we
                 // want to load the image straight away. If tab is still
                 // loading, we only load the favicon once the page's content
                 // is fully loaded (see handleContentLoaded()).
@@ -1263,16 +1267,17 @@ abstract public class GeckoApp
 
         setContentView(R.layout.gecko_app);
         mAppContext = this;
 
         if (Build.VERSION.SDK_INT >= 11) {
             GeckoActionBar actionBar = new GeckoActionBar();
             mBrowserToolbar = (BrowserToolbar) getLayoutInflater().inflate(R.layout.gecko_app_actionbar, null);
 
+            actionBar.setBackgroundDrawable(this, getResources().getDrawable(R.drawable.gecko_actionbar_bg));
             actionBar.setDisplayOptions(this, ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM |
                                                                              ActionBar.DISPLAY_SHOW_HOME |
                                                                              ActionBar.DISPLAY_SHOW_TITLE |
                                                                              ActionBar.DISPLAY_USE_LOGO);
             actionBar.setCustomView(this, mBrowserToolbar);
         } else {
             mBrowserToolbar = (BrowserToolbar) findViewById(R.id.browser_toolbar);
         }
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -952,17 +952,21 @@ public class GeckoAppShell
     }
 
     public static String showFilePicker(String aFilters) {
         return GeckoApp.mAppContext.
             showFilePicker(getMimeTypeFromExtensions(aFilters));
     }
 
     public static void performHapticFeedback(boolean aIsLongPress) {
-        // TODO
+        LayerController layerController = GeckoApp.mAppContext.getLayerController();
+        LayerView layerView = layerController.getView();
+        layerView.performHapticFeedback(aIsLongPress ?
+                                        HapticFeedbackConstants.LONG_PRESS :
+                                        HapticFeedbackConstants.VIRTUAL_KEY);
     }
 
     private static Vibrator vibrator() {
         LayerController layerController = GeckoApp.mAppContext.getLayerController();
         LayerView layerView = layerController.getView();
 
         return (Vibrator) layerView.getContext().getSystemService(Context.VIBRATOR_SERVICE);
     }
--- a/mobile/android/base/GeckoPreferences.java
+++ b/mobile/android/base/GeckoPreferences.java
@@ -110,17 +110,17 @@ public class GeckoPreferences
             if (pref instanceof PreferenceGroup)
                 initGroups((PreferenceGroup)pref);
             else {
                 pref.setOnPreferenceChangeListener(this);
                 mPreferencesList.add(pref.getKey());
             }
         }
     }
-    
+
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
             case android.R.id.home:
                 finish();
                 return true;
         }
 
@@ -128,58 +128,40 @@ public class GeckoPreferences
     }
 
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         String prefName = preference.getKey();
         setPreference(prefName, newValue);
         if (preference instanceof ListPreference)
             ((ListPreference)preference).setSummary((String)newValue);
+        if (preference instanceof LinkPreference)
+            finish();
         return true;
     }
 
     private void refresh(JSONArray jsonPrefs) {
         // enable all preferences once we have them from gecko
         GeckoAppShell.getMainHandler().post(new Runnable() {
             public void run() {
                 mPreferenceScreen.setEnabled(true);
             }
         });
 
         try {
             if (mPreferenceScreen == null)
                 return;
 
-            // set the current page URL for the "Home page" preference
-            final String[] homepageValues = getResources().getStringArray(R.array.pref_homepage_values);
-            final Preference homepagePref = mPreferenceScreen.findPreference("browser.startup.homepage");
-            GeckoAppShell.getMainHandler().post(new Runnable() {
-                public void run() {
-                    Tab tab = Tabs.getInstance().getSelectedTab();
-                    homepageValues[2] = tab.getURL();
-                    ((ListPreference)homepagePref).setEntryValues(homepageValues);
-                }
-            });
-
             final int length = jsonPrefs.length();
             for (int i = 0; i < length; i++) {
                 JSONObject jPref = jsonPrefs.getJSONObject(i);
                 final String prefName = jPref.getString("name");
                 final String prefType = jPref.getString("type");
                 final Preference pref = mPreferenceScreen.findPreference(prefName);
 
-                if (prefName.equals("browser.startup.homepage")) {
-                    final String value = jPref.getString("value");
-                    GeckoAppShell.getMainHandler().post(new Runnable() {
-                        public void run() {
-                            pref.setSummary(value);
-                        }
-                    });
-                }
-
                 if (pref instanceof CheckBoxPreference && "bool".equals(prefType)) {
                     final boolean value = jPref.getBoolean("value");
                     GeckoAppShell.getMainHandler().post(new Runnable() {
                         public void run() {
                             if (((CheckBoxPreference)pref).isChecked() != value)
                                 ((CheckBoxPreference)pref).setChecked(value);
                         }
                     });
--- a/mobile/android/base/GlobalHistory.java
+++ b/mobile/android/base/GlobalHistory.java
@@ -38,22 +38,23 @@
 package org.mozilla.gecko;
 
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.Queue;
 import java.util.Set;
 import java.lang.ref.SoftReference;
 
-import android.content.ContentValues;
+import android.content.ContentResolver;
 import android.database.Cursor;
 import android.os.Handler;
-import android.provider.Browser;
 import android.util.Log;
 
+import org.mozilla.gecko.db.BrowserDB;
+
 class GlobalHistory {
     private static final String LOGTAG = "GeckoGlobalHistory";
 
     private static GlobalHistory sInstance = new GlobalHistory();
 
     static GlobalHistory getInstance() {
         return sInstance;
     }
@@ -75,22 +76,17 @@ class GlobalHistory {
         mVisitedCache = new SoftReference<Set<String>>(null);
         mNotifierRunnable = new Runnable() {
             public void run() {
                 Set<String> visitedSet = mVisitedCache.get();
                 if (visitedSet == null) {
                     // the cache was wiped away, repopulate it
                     Log.w(LOGTAG, "Rebuilding visited link set...");
                     visitedSet = new HashSet<String>();
-                    Cursor c = GeckoApp.mAppContext.getContentResolver().query(Browser.BOOKMARKS_URI,
-                                    new String[] { Browser.BookmarkColumns.URL },
-                                    Browser.BookmarkColumns.BOOKMARK + "=0 AND " +
-                                    Browser.BookmarkColumns.VISITS + ">0",
-                                    null,
-                                    null);
+                    Cursor c = BrowserDB.getAllVisitedHistory(GeckoApp.mAppContext.getContentResolver());
                     if (c.moveToFirst()) {
                         do {
                             visitedSet.add(c.getString(0));
                         } while (c.moveToNext());
                     }
                     mVisitedCache = new SoftReference<Set<String>>(visitedSet);
                     c.close();
                 }
@@ -107,32 +103,27 @@ class GlobalHistory {
                     }
                 }
                 mProcessing = false;
             }
         };
     }
 
     public void add(String uri) {
-        Browser.updateVisitedHistory(GeckoApp.mAppContext.getContentResolver(), uri, true);
+        BrowserDB.updateVisitedHistory(GeckoApp.mAppContext.getContentResolver(), uri);
         Set<String> visitedSet = mVisitedCache.get();
         if (visitedSet != null) {
             visitedSet.add(uri);
         }
         GeckoAppShell.notifyUriVisited(uri);
     }
 
     public void update(String uri, String title) {
-        ContentValues values = new ContentValues();
-        values.put(Browser.BookmarkColumns.TITLE, title);
-        GeckoApp.mAppContext.getContentResolver().update(
-                Browser.BOOKMARKS_URI,
-                values,
-                Browser.BookmarkColumns.URL + " = ?",
-                new String[] { uri });
+        ContentResolver resolver = GeckoApp.mAppContext.getContentResolver();
+        BrowserDB.updateHistoryTitle(resolver, uri, title);
     }
 
     public void checkUriVisited(final String uri) {
         mHandler.post(new Runnable() {
             public void run() {
                 // this runs on the same handler thread as the processing loop,
                 // so synchronization needed
                 mPendingUris.add(uri);
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/LinkPreference.java
@@ -0,0 +1,61 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009-2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Matt Brubeck <mbrubeck@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package org.mozilla.gecko;
+
+import android.content.Context;
+import android.preference.Preference;
+import android.util.AttributeSet;
+
+class LinkPreference extends Preference {
+    private String mUrl = null;
+
+    public LinkPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mUrl = attrs.getAttributeValue(null, "url");
+    }
+    public LinkPreference(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mUrl = attrs.getAttributeValue(null, "url");
+    }
+
+    @Override
+    protected void onClick() {
+        GeckoApp.mAppContext.loadUrl(mUrl, AwesomeBar.Type.ADD);
+        callChangeListener(mUrl);
+    }
+}
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -49,16 +49,21 @@ DIST_FILES = package-name.txt
 
 JAVAFILES = \
   AboutHomeContent.java \
   AlertNotification.java \
   AwesomeBar.java \
   AwesomeBarTabs.java \
   BrowserToolbar.java \
   ConfirmPreference.java \
+  db/BrowserContract.java \
+  db/AndroidBrowserDB.java \
+  db/BrowserDB.java \
+  db/BrowserProvider.java \
+  db/LocalBrowserDB.java \
   DoorHanger.java \
   DoorHangerPopup.java \
   Favicons.java \
   FloatUtils.java \
   GeckoActionBar.java \
   GeckoApp.java \
   GeckoAppShell.java \
   GeckoAsyncTask.java \
@@ -67,16 +72,17 @@ JAVAFILES = \
   GeckoEvent.java \
   GeckoEventListener.java \
   GeckoInputConnection.java \
   GeckoPreferences.java \
   GeckoSmsManager.java \
   GeckoStateListDrawable.java \
   GeckoThread.java \
   GlobalHistory.java \
+  LinkPreference.java \
   PromptService.java \
   SurfaceLockInfo.java \
   Tab.java \
   Tabs.java \
   TabsTray.java \
   gfx/BufferedCairoImage.java \
   gfx/CairoGLInfo.java \
   gfx/CairoImage.java \
@@ -194,17 +200,16 @@ RES_LAYOUT = \
 
 RES_LAYOUT_V11 = \
   res/layout-v11/awesomebar_search.xml \
   res/layout-v11/gecko_app.xml \
   res/layout-v11/gecko_app_actionbar.xml \
   $(NULL)
 
 RES_VALUES = \
-  res/values/arrays.xml \
   res/values/colors.xml \
   res/values/styles.xml \
   res/values/themes.xml \
   $(NULL)
  
 RES_VALUES_V11 = \
   res/values-v11/styles.xml \
   res/values-v11/themes.xml \
@@ -347,16 +352,17 @@ MOZ_ANDROID_DRAWABLES += mobile/android/
                          mobile/android/base/resources/drawable/awesomebar_tab_focus_selected.xml \
                          mobile/android/base/resources/drawable/awesomebar_tab_indicator.xml    \
                          mobile/android/base/resources/drawable/awesomebar_tab_press.xml        \
                          mobile/android/base/resources/drawable/awesomebar_tab_press_selected.xml \
                          mobile/android/base/resources/drawable/awesomebar_tab_selected.xml     \
                          mobile/android/base/resources/drawable/awesomebar_tab_unselected.xml   \
                          mobile/android/base/resources/drawable/desktop_notification.png        \
                          mobile/android/base/resources/drawable/favicon.png                     \
+                         mobile/android/base/resources/drawable/gecko_actionbar_bg.xml          \
                          mobile/android/base/resources/drawable/progress_spinner.xml            \
                          mobile/android/base/resources/drawable/progress_spinner_1.png          \
                          mobile/android/base/resources/drawable/progress_spinner_2.png          \
                          mobile/android/base/resources/drawable/progress_spinner_3.png          \
                          mobile/android/base/resources/drawable/progress_spinner_4.png          \
                          mobile/android/base/resources/drawable/progress_spinner_5.png          \
                          mobile/android/base/resources/drawable/progress_spinner_6.png          \
                          mobile/android/base/resources/drawable/progress_spinner_7.png          \
--- a/mobile/android/base/PromptService.java
+++ b/mobile/android/base/PromptService.java
@@ -71,16 +71,21 @@ import android.graphics.Color;
 import android.text.InputType;
 import android.app.AlertDialog;
 
 public class PromptService implements OnClickListener, OnCancelListener, OnItemClickListener {
     private static final String LOGTAG = "GeckoPromptService";
 
     private PromptInput[] mInputs;
     private AlertDialog mDialog = null;
+    private static LayoutInflater mInflater;
+
+    PromptService() {
+        mInflater = LayoutInflater.from(GeckoApp.mAppContext);
+    }
 
     private class PromptButton {
         public String label = "";
         PromptButton(JSONObject aJSONButton) {
             try {
                 label = aJSONButton.getString("label");
             } catch(Exception ex) { }
         }
@@ -184,18 +189,17 @@ public class PromptService implements On
                     resourceId = android.R.layout.select_dialog_multichoice;
                 } else {
                     resourceId = android.R.layout.select_dialog_singlechoice;
                 }
             }
             PromptListAdapter adapter = new PromptListAdapter(GeckoApp.mAppContext, resourceId, aMenuList);
             if (mSelected != null && mSelected.length > 0) {
                 if (aMultipleSelection) {
-                    LayoutInflater inflater = GeckoApp.mAppContext.getLayoutInflater();
-                    adapter.listView = (ListView) inflater.inflate(R.layout.select_dialog_list, null);
+                    adapter.listView = (ListView) mInflater.inflate(R.layout.select_dialog_list, null);
                     adapter.listView.setOnItemClickListener(this);
                     builder.setInverseBackgroundForced(true);
                     adapter.listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
                     adapter.listView.setAdapter(adapter);
                     builder.setView(adapter.listView);
                 } else {
                     int selectedIndex = -1;
                     for (int i = 0; i < mSelected.length; i++) {
@@ -427,18 +431,17 @@ public class PromptService implements On
         }
 
         public View getView(int position, View convertView, ViewGroup parent) {
             PromptListItem item = getItem(position);
             int resourceId = mResourceId;
             if (item.isGroup) {
                 resourceId = R.layout.list_item_header;
             }
-            LayoutInflater inflater = GeckoApp.mAppContext.getLayoutInflater();
-            View row = inflater.inflate(resourceId, null);
+            View row = mInflater.inflate(resourceId, null);
             if (!item.isGroup){
                 try {
                     CheckedTextView ct = (CheckedTextView)row.findViewById(android.R.id.text1);
                     if (ct != null){
                         ct.setEnabled(!item.disabled);
                         ct.setClickable(item.disabled);
 
                         // Apparently just using ct.setChecked(true) doesn't work, so this
--- a/mobile/android/base/Tab.java
+++ b/mobile/android/base/Tab.java
@@ -33,34 +33,33 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 package org.mozilla.gecko;
 
 import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.database.Cursor;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.Bitmap;
-import android.provider.Browser;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.graphics.Bitmap;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 
 import java.io.ByteArrayOutputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
+import org.mozilla.gecko.db.BrowserDB;
+
 public class Tab {
     public static enum AgentMode { MOBILE, DESKTOP };
     private static final String LOGTAG = "GeckoTab";
 
     static int sMinDim = 0;
     private int mId;
     private String mUrl;
     private String mTitle;
@@ -139,17 +138,17 @@ public class Tab {
                 if (sMinDim == 0) {
                     DisplayMetrics metrics = new DisplayMetrics();
                     GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
                     sMinDim = Math.min(metrics.widthPixels, metrics.heightPixels);
                 }
                 if (b != null) {
                     Bitmap bitmap = Bitmap.createBitmap(b, 0, 0, sMinDim, sMinDim);
                     mThumbnail = new BitmapDrawable(bitmap);
-                    saveThumbnailToDB(bitmap);
+                    saveThumbnailToDB((BitmapDrawable) mThumbnail);
                 } else {
                     mThumbnail = null;
                 }
             }
         });
     }
 
     public String getFaviconURL() {
@@ -350,115 +349,53 @@ public class Tab {
             mHistoryIndex = -1;
         }
     }
 
     private class CheckBookmarkTask extends GeckoAsyncTask<Void, Void, Boolean> {
         @Override
         protected Boolean doInBackground(Void... unused) {
             ContentResolver resolver = Tabs.getInstance().getContentResolver();
-            Cursor cursor = resolver.query(Browser.BOOKMARKS_URI,
-                                           null,
-                                           Browser.BookmarkColumns.URL + " = ? and " + Browser.BookmarkColumns.BOOKMARK + " = ?",
-                                           new String[] { getURL(), "1" },
-                                           Browser.BookmarkColumns.URL);
-            int count = cursor.getCount();
-            cursor.close();
-            if (count == 1)
-                return true;
-            else
-                return false;
+            return BrowserDB.isBookmark(resolver, getURL());
         }
 
         @Override
         protected void onPostExecute(Boolean isBookmark) {
             setBookmark(isBookmark.booleanValue());
         }
     }
 
     private class AddBookmarkTask extends GeckoAsyncTask<Void, Void, Void> {
         @Override
         protected Void doInBackground(Void... unused) {
             ContentResolver resolver = Tabs.getInstance().getContentResolver();
-            Cursor cursor = resolver.query(Browser.BOOKMARKS_URI,
-                                           null,
-                                           Browser.BookmarkColumns.URL + " = ?",
-                                           new String[] { getURL() },
-                                           Browser.BookmarkColumns.URL);
-
-            ContentValues values = new ContentValues();
-            values.put(Browser.BookmarkColumns.BOOKMARK, "1");
-            values.put(Browser.BookmarkColumns.TITLE, getTitle());
-
-            if (cursor.getCount() == 1) {
-                //entry exists, update the bookmark flag
-                resolver.update(Browser.BOOKMARKS_URI,
-                                values,
-                                Browser.BookmarkColumns.URL + " = ?",
-                                new String[] { getURL() });
-            } else {
-                //add a new entry
-                values.put(Browser.BookmarkColumns.URL, mUrl);
-                resolver.insert(Browser.BOOKMARKS_URI,
-                                values);
-            }
-
-            cursor.close();
-
+            BrowserDB.addBookmark(resolver, getTitle(), getURL());
             return null;
         }
 
         @Override
         protected void onPostExecute(Void unused) {
             setBookmark(true);
         }
     }
 
-    private void saveThumbnailToDB(Bitmap bitmap) {
+    private void saveThumbnailToDB(BitmapDrawable thumbnail) {
         try {
             ContentResolver resolver = Tabs.getInstance().getContentResolver();
-            Cursor cursor = resolver.query(Browser.BOOKMARKS_URI,
-                                           null,
-                                           Browser.BookmarkColumns.URL + " = ?",
-                                           new String[] { getURL() },
-                                           Browser.BookmarkColumns.URL);
-
-            ContentValues values = new ContentValues();
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
-            bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);
-            values.put("thumbnail", bos.toByteArray());
-
-            if (cursor.getCount() == 1) {
-                //entry exists, update the bookmark flag
-                resolver.update(Browser.BOOKMARKS_URI,
-                                values,
-                                Browser.BookmarkColumns.URL + " = ?",
-                                new String[] { getURL() });
-            } else {
-                //add a new entry
-                values.put(Browser.BookmarkColumns.URL, mUrl);
-                resolver.insert(Browser.BOOKMARKS_URI,
-                                values);
-            }
-            cursor.close();
+            BrowserDB.updateThumbnailForUrl(resolver, getURL(), thumbnail);
         } catch (Exception e) {
             // ignore
         }
     }
 
     private class RemoveBookmarkTask extends GeckoAsyncTask<Void, Void, Void> {
         @Override
         protected Void doInBackground(Void... unused) {
             ContentResolver resolver = Tabs.getInstance().getContentResolver();
-            ContentValues values = new ContentValues();
-            values.put(Browser.BookmarkColumns.BOOKMARK, "0");
-            resolver.update(Browser.BOOKMARKS_URI,
-                            values,
-                            Browser.BookmarkColumns.URL + " = ?",
-                            new String[] { getURL() });
+            BrowserDB.removeBookmark(resolver, getURL());
             return null;
         }
 
         @Override
         protected void onPostExecute(Void unused) {
             setBookmark(false);
         }
     }
--- a/mobile/android/base/TabsTray.java
+++ b/mobile/android/base/TabsTray.java
@@ -171,32 +171,35 @@ public class TabsTray extends Activity i
             };
 
             mOnCloseClickListener = new Button.OnClickListener() {
                 public void onClick(View v) {
                     if (mWaitingForClose)
                         return;
                 
                     mWaitingForClose = true;
-                
-                    int tabId = Integer.parseInt(v.getTag().toString());
+               
+                    String tabId = v.getTag().toString();
                     Tabs tabs = Tabs.getInstance();
-                    Tab tab = tabs.getTab(tabId);
+                    Tab tab = tabs.getTab(Integer.parseInt(tabId));
+
+                    if (tab == null)
+                        return;
                 
                     if (tabs.isSelectedTab(tab)) {
                         int index = tabs.getIndexOf(tab);
                         if (index >= 1)
                             index--;
                         else
                             index = 1;
                         int id = tabs.getTabAt(index).getId();
                         GeckoAppShell.sendEventToGecko(new GeckoEvent("Tab:Select", String.valueOf(id)));
-                        GeckoAppShell.sendEventToGecko(new GeckoEvent("Tab:Close", v.getTag().toString()));
+                        GeckoAppShell.sendEventToGecko(new GeckoEvent("Tab:Close", tabId));
                     } else {
-                        GeckoAppShell.sendEventToGecko(new GeckoEvent("Tab:Close", v.getTag().toString()));
+                        GeckoAppShell.sendEventToGecko(new GeckoEvent("Tab:Close", tabId));
                         GeckoAppShell.sendEventToGecko(new GeckoEvent("Tab:Select", String.valueOf(tabs.getSelectedTabId())));
                     }
                 }
             };
         }
 
         @Override    
         public int getCount() {
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/db/AndroidBrowserDB.java
@@ -0,0 +1,291 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Lucas Rocha <lucasr@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package org.mozilla.gecko.db;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Date;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.CursorWrapper;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.provider.Browser;
+import android.provider.Browser.BookmarkColumns;
+
+public class AndroidBrowserDB implements BrowserDB.BrowserDBIface {
+    private static final String URL_COLUMN_ID = "_id";
+    private static final String URL_COLUMN_THUMBNAIL = "thumbnail";
+
+    public Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
+        Cursor c = cr.query(Browser.BOOKMARKS_URI,
+                            new String[] { URL_COLUMN_ID,
+                                           BookmarkColumns.URL,
+                                           BookmarkColumns.TITLE,
+                                           BookmarkColumns.FAVICON,
+                                           URL_COLUMN_THUMBNAIL },
+                            // The length restriction on URL is for the same reason as in the general bookmark query
+                            // (see comment earlier in this file).
+                            "(" + Browser.BookmarkColumns.URL + " LIKE ? OR " + Browser.BookmarkColumns.TITLE + " LIKE ?)"
+                            + " AND LENGTH(" + Browser.BookmarkColumns.URL + ") > 0",
+                            new String[] {"%" + constraint.toString() + "%", "%" + constraint.toString() + "%",},
+                            // ORDER BY is number of visits times a multiplier from 1 - 120 of how recently the site
+                            // was accessed with a site accessed today getting 120 and a site accessed 119 or more
+                            // days ago getting 1
+                            Browser.BookmarkColumns.VISITS + " * MAX(1, (" +
+                            Browser.BookmarkColumns.DATE + " - " + new Date().getTime() + ") / 86400000 + 120) DESC LIMIT " + limit);
+
+        return new AndroidDBCursor(c);
+    }
+
+    public void updateVisitedHistory(ContentResolver cr, String uri) {
+        Browser.updateVisitedHistory(cr, uri, true);
+    }
+
+    public void updateHistoryTitle(ContentResolver cr, String uri, String title) {
+        ContentValues values = new ContentValues();
+        values.put(Browser.BookmarkColumns.TITLE, title);
+
+        cr.update(Browser.BOOKMARKS_URI,
+                  values,
+                  Browser.BookmarkColumns.URL + " = ?",
+                  new String[] { uri });
+    }
+
+    public Cursor getAllVisitedHistory(ContentResolver cr) {
+        Cursor c = cr.query(Browser.BOOKMARKS_URI,
+                            new String[] { Browser.BookmarkColumns.URL },
+                            Browser.BookmarkColumns.BOOKMARK + " = 0 AND " +
+                            Browser.BookmarkColumns.VISITS + " > 0",
+                            null,
+                            null);
+
+        return new AndroidDBCursor(c);
+    }
+
+    public Cursor getRecentHistory(ContentResolver cr, int limit) {
+        Cursor c = cr.query(Browser.BOOKMARKS_URI,
+                            new String[] { URL_COLUMN_ID,
+                                           BookmarkColumns.URL,
+                                           BookmarkColumns.TITLE,
+                                           BookmarkColumns.FAVICON,
+                                           BookmarkColumns.DATE },
+                            // Bookmarks that have not been visited have a date value
+                            // of 0, so don't pick them up in the history view.
+                            Browser.BookmarkColumns.DATE + " > 0",
+                            null,
+                            Browser.BookmarkColumns.DATE + " DESC LIMIT " + limit);
+
+        return new AndroidDBCursor(c);
+    }
+
+    public void clearHistory(ContentResolver cr) {
+        Browser.clearHistory(cr);
+    }
+
+    public Cursor getAllBookmarks(ContentResolver cr) {
+        Cursor c = cr.query(Browser.BOOKMARKS_URI,
+                            new String[] { URL_COLUMN_ID,
+                                           BookmarkColumns.URL,
+                                           BookmarkColumns.TITLE,
+                                           BookmarkColumns.FAVICON },
+                            // Select all bookmarks with a non-empty URL. When the history
+                            // is empty there appears to be a dummy entry in the database
+                            // which has a title of "Bookmarks" and no URL; the length restriction
+                            // is to avoid picking that up specifically.
+                            Browser.BookmarkColumns.BOOKMARK + " = 1 AND LENGTH(" + Browser.BookmarkColumns.URL + ") > 0",
+                            null,
+                            Browser.BookmarkColumns.TITLE);
+
+        return new AndroidDBCursor(c);
+    }
+
+    public boolean isBookmark(ContentResolver cr, String uri) {
+        Cursor cursor = cr.query(Browser.BOOKMARKS_URI,
+                                 new String[] { BookmarkColumns.URL },
+                                 Browser.BookmarkColumns.URL + " = ? and " + Browser.BookmarkColumns.BOOKMARK + " = ?",
+                                 new String[] { uri, "1" },
+                                 Browser.BookmarkColumns.URL);
+
+        int count = cursor.getCount();
+        cursor.close();
+
+        return (count == 1);
+    }
+
+    public void addBookmark(ContentResolver cr, String title, String uri) {
+        Cursor cursor = cr.query(Browser.BOOKMARKS_URI,
+                                 new String[] { BookmarkColumns.URL },
+                                 Browser.BookmarkColumns.URL + " = ?",
+                                 new String[] { uri },
+                                 Browser.BookmarkColumns.URL);
+
+        ContentValues values = new ContentValues();
+        values.put(Browser.BookmarkColumns.BOOKMARK, "1");
+        values.put(Browser.BookmarkColumns.TITLE, title);
+
+        if (cursor.getCount() == 1) {
+            // entry exists, update the bookmark flag
+            cr.update(Browser.BOOKMARKS_URI,
+                      values,
+                      Browser.BookmarkColumns.URL + " = ?",
+                      new String[] { uri });
+        } else {
+            // add a new entry
+            values.put(Browser.BookmarkColumns.URL, uri);
+            cr.insert(Browser.BOOKMARKS_URI, values);
+        }
+
+        cursor.close();
+