Bug 1318814 - `ObjectUtils.deepEqual` should not consider objects and primitives as equal. r?mossop draft
authorKit Cambridge <kit@yakshaving.ninja>
Tue, 22 Nov 2016 15:48:42 -0700
changeset 442628 8bc4697bd8bb7bed7e829fa6910e351f34135960
parent 442068 0534254e9a40b4bade2577c631fe4cfa0b5db41d
child 537847 90ae7806420d62d7ab83c350ff74cb06b44025e4
push id36761
push userbmo:kcambridge@mozilla.com
push dateTue, 22 Nov 2016 23:06:44 +0000
reviewersmossop
bugs1318814
milestone53.0a1
Bug 1318814 - `ObjectUtils.deepEqual` should not consider objects and primitives as equal. r?mossop MozReview-Commit-ID: ExWi55h80ag
toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js
toolkit/components/places/tests/bookmarks/test_keywords.js
toolkit/components/places/tests/migration/test_current_from_v34.js
toolkit/components/places/tests/unit/test_keywords.js
toolkit/modules/ObjectUtils.jsm
toolkit/modules/tests/xpcshell/test_ObjectUtils.js
--- a/toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js
+++ b/toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js
@@ -4,77 +4,77 @@
 add_task(function* insert_separator_notification() {
   let observer = expectNotifications();
   let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
                                                 parentGuid: PlacesUtils.bookmarks.unfiledGuid});
   let itemId = yield PlacesUtils.promiseItemId(bm.guid);
   let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
   observer.check([ { name: "onItemAdded",
                      arguments: [ itemId, parentId, bm.index, bm.type,
-                                  null, null, bm.dateAdded,
+                                  null, null, bm.dateAdded * 1000,
                                   bm.guid, bm.parentGuid,
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
 });
 
 add_task(function* insert_folder_notification() {
   let observer = expectNotifications();
   let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
                                                 parentGuid: PlacesUtils.bookmarks.unfiledGuid,
                                                 title: "a folder" });
   let itemId = yield PlacesUtils.promiseItemId(bm.guid);
   let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
   observer.check([ { name: "onItemAdded",
                      arguments: [ itemId, parentId, bm.index, bm.type,
-                                  null, bm.title, bm.dateAdded,
+                                  null, bm.title, bm.dateAdded * 1000,
                                   bm.guid, bm.parentGuid,
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
 });
 
 add_task(function* insert_folder_notitle_notification() {
   let observer = expectNotifications();
   let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
                                                 parentGuid: PlacesUtils.bookmarks.unfiledGuid });
   let itemId = yield PlacesUtils.promiseItemId(bm.guid);
   let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
   observer.check([ { name: "onItemAdded",
                      arguments: [ itemId, parentId, bm.index, bm.type,
-                                  null, null, bm.dateAdded,
+                                  null, null, bm.dateAdded * 1000,
                                   bm.guid, bm.parentGuid,
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
 });
 
 add_task(function* insert_bookmark_notification() {
   let observer = expectNotifications();
   let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
                                                 parentGuid: PlacesUtils.bookmarks.unfiledGuid,
                                                 url: new URL("http://example.com/"),
                                                 title: "a bookmark" });
   let itemId = yield PlacesUtils.promiseItemId(bm.guid);
   let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
   observer.check([ { name: "onItemAdded",
                      arguments: [ itemId, parentId, bm.index, bm.type,
-                                  bm.url, bm.title, bm.dateAdded,
+                                  bm.url, bm.title, bm.dateAdded * 1000,
                                   bm.guid, bm.parentGuid,
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
 });
 
 add_task(function* insert_bookmark_notitle_notification() {
   let observer = expectNotifications();
   let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
                                                 parentGuid: PlacesUtils.bookmarks.unfiledGuid,
                                                 url: new URL("http://example.com/") });
   let itemId = yield PlacesUtils.promiseItemId(bm.guid);
   let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
   observer.check([ { name: "onItemAdded",
                      arguments: [ itemId, parentId, bm.index, bm.type,
-                                  bm.url, null, bm.dateAdded,
+                                  bm.url, null, bm.dateAdded * 1000,
                                   bm.guid, bm.parentGuid,
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
 });
 
 add_task(function* insert_bookmark_tag_notification() {
   let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
                                                 parentGuid: PlacesUtils.bookmarks.unfiledGuid,
@@ -89,22 +89,22 @@ add_task(function* insert_bookmark_tag_n
   let tag = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
                                                  parentGuid: tagFolder.guid,
                                                  url: new URL("http://tag.example.com/") });
   let tagId = yield PlacesUtils.promiseItemId(tag.guid);
   let tagParentId = yield PlacesUtils.promiseItemId(tag.parentGuid);
 
   observer.check([ { name: "onItemAdded",
                      arguments: [ tagId, tagParentId, tag.index, tag.type,
-                                  tag.url, null, tag.dateAdded,
+                                  tag.url, null, tag.dateAdded * 1000,
                                   tag.guid, tag.parentGuid,
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
                    { name: "onItemChanged",
                      arguments: [ itemId, "tags", false, "",
-                                  bm.lastModified, bm.type, parentId,
+                                  bm.lastModified * 1000, bm.type, parentId,
                                   bm.guid, bm.parentGuid, "",
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
 });
 
 add_task(function* update_bookmark_lastModified() {
   let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
                                                 parentGuid: PlacesUtils.bookmarks.unfiledGuid,
@@ -112,17 +112,17 @@ add_task(function* update_bookmark_lastM
   let observer = expectNotifications();
   bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
                                             lastModified: new Date() });
   let itemId = yield PlacesUtils.promiseItemId(bm.guid);
   let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
 
   observer.check([ { name: "onItemChanged",
                      arguments: [ itemId, "lastModified", false,
-                                  `${bm.lastModified * 1000}`, bm.lastModified,
+                                  `${bm.lastModified * 1000}`, bm.lastModified * 1000,
                                   bm.type, parentId, bm.guid, bm.parentGuid, "",
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
 });
 
 add_task(function* update_bookmark_title() {
   let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
                                                 parentGuid: PlacesUtils.bookmarks.unfiledGuid,
@@ -130,34 +130,34 @@ add_task(function* update_bookmark_title
   let observer = expectNotifications();
   bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
                                             title: "new title" });
   let itemId = yield PlacesUtils.promiseItemId(bm.guid);
   let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
 
   observer.check([ { name: "onItemChanged",
                      arguments: [ itemId, "title", false, bm.title,
-                                  bm.lastModified, bm.type, parentId, bm.guid,
+                                  bm.lastModified * 1000, bm.type, parentId, bm.guid,
                                   bm.parentGuid, "", Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
 });
 
 add_task(function* update_bookmark_uri() {
   let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
                                                 parentGuid: PlacesUtils.bookmarks.unfiledGuid,
                                                 url: new URL("http://url.example.com/") });
   let observer = expectNotifications();
   bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
                                             url: "http://mozilla.org/" });
   let itemId = yield PlacesUtils.promiseItemId(bm.guid);
   let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
 
   observer.check([ { name: "onItemChanged",
                      arguments: [ itemId, "uri", false, bm.url.href,
-                                  bm.lastModified, bm.type, parentId, bm.guid,
+                                  bm.lastModified * 1000, bm.type, parentId, bm.guid,
                                   bm.parentGuid, "http://url.example.com/",
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
 });
 
 add_task(function* update_move_same_folder() {
   // Ensure there are at least two items in place (others test do so for us,
   // but we don't have to depend on that).
@@ -273,17 +273,17 @@ add_task(function* remove_bookmark_tag_n
   yield PlacesUtils.bookmarks.remove(tag.guid);
 
   observer.check([ { name: "onItemRemoved",
                      arguments: [ tagId, tagParentId, tag.index, tag.type,
                                   tag.url, tag.guid, tag.parentGuid,
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
                    { name: "onItemChanged",
                      arguments: [ itemId, "tags", false, "",
-                                  bm.lastModified, bm.type, parentId,
+                                  bm.lastModified * 1000, bm.type, parentId,
                                   bm.guid, bm.parentGuid, "",
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
 });
 
 add_task(function* remove_folder_notification() {
   let folder1 = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
                                                      parentGuid: PlacesUtils.bookmarks.unfiledGuid });
--- a/toolkit/components/places/tests/bookmarks/test_keywords.js
+++ b/toolkit/components/places/tests/bookmarks/test_keywords.js
@@ -90,17 +90,17 @@ add_task(function* test_addBookmarkAndKe
                                          URI1,
                                          PlacesUtils.bookmarks.DEFAULT_INDEX,
                                          "test");
 
   PlacesUtils.bookmarks.setKeywordForBookmark(itemId, "keyword");
   let bookmark = yield PlacesUtils.bookmarks.fetch({ url: URI1 });
   observer.check([ { name: "onItemChanged",
                      arguments: [ itemId, "keyword", false, "keyword",
-                                  bookmark.lastModified, bookmark.type,
+                                  bookmark.lastModified * 1000, bookmark.type,
                                   (yield PlacesUtils.promiseItemId(bookmark.parentGuid)),
                                   bookmark.guid, bookmark.parentGuid, "",
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
   yield PlacesTestUtils.promiseAsyncUpdates();
 
   check_keyword(URI1, "keyword");
   Assert.equal((yield foreign_count(URI1)), fc + 2); // + 1 bookmark + 1 keyword
@@ -142,23 +142,23 @@ add_task(function* test_sameKeywordDiffe
 
   PlacesUtils.bookmarks.setKeywordForBookmark(itemId, "kEyWoRd");
 
   let bookmark1 = yield PlacesUtils.bookmarks.fetch({ url: URI1 });
   let bookmark2 = yield PlacesUtils.bookmarks.fetch({ url: URI2 });
   observer.check([ { name: "onItemChanged",
                      arguments: [ (yield PlacesUtils.promiseItemId(bookmark1.guid)),
                                   "keyword", false, "",
-                                  bookmark1.lastModified, bookmark1.type,
+                                  bookmark1.lastModified * 1000, bookmark1.type,
                                   (yield PlacesUtils.promiseItemId(bookmark1.parentGuid)),
                                   bookmark1.guid, bookmark1.parentGuid, "",
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
                     { name: "onItemChanged",
                      arguments: [ itemId, "keyword", false, "keyword",
-                                  bookmark2.lastModified, bookmark2.type,
+                                  bookmark2.lastModified * 1000, bookmark2.type,
                                   (yield PlacesUtils.promiseItemId(bookmark2.parentGuid)),
                                   bookmark2.guid, bookmark2.parentGuid, "",
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
   yield PlacesTestUtils.promiseAsyncUpdates();
 
   // The keyword should have been "moved" to the new URI.
   check_keyword(URI1, null);
@@ -183,24 +183,24 @@ add_task(function* test_sameURIDifferent
 
   PlacesUtils.bookmarks.setKeywordForBookmark(itemId, "keyword2");
 
   let bookmarks = [];
   yield PlacesUtils.bookmarks.fetch({ url: URI2 }, bookmark => bookmarks.push(bookmark));
   observer.check([ { name: "onItemChanged",
                      arguments: [ (yield PlacesUtils.promiseItemId(bookmarks[0].guid)),
                                   "keyword", false, "keyword2",
-                                  bookmarks[0].lastModified, bookmarks[0].type,
+                                  bookmarks[0].lastModified * 1000, bookmarks[0].type,
                                   (yield PlacesUtils.promiseItemId(bookmarks[0].parentGuid)),
                                   bookmarks[0].guid, bookmarks[0].parentGuid, "",
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
                     { name: "onItemChanged",
                      arguments: [ (yield PlacesUtils.promiseItemId(bookmarks[1].guid)),
                                   "keyword", false, "keyword2",
-                                  bookmarks[1].lastModified, bookmarks[1].type,
+                                  bookmarks[1].lastModified * 1000, bookmarks[1].type,
                                   (yield PlacesUtils.promiseItemId(bookmarks[1].parentGuid)),
                                   bookmarks[1].guid, bookmarks[1].parentGuid, "",
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
   yield PlacesTestUtils.promiseAsyncUpdates();
 
   check_keyword(URI2, "keyword2");
   Assert.equal((yield foreign_count(URI2)), fc + 2); // + 1 bookmark + 1 keyword
@@ -241,31 +241,31 @@ add_task(function* test_unsetKeyword() {
   PlacesUtils.bookmarks.setKeywordForBookmark(itemId, null);
 
   let bookmarks = [];
   yield PlacesUtils.bookmarks.fetch({ url: URI2 }, bookmark => bookmarks.push(bookmark));
   do_print(bookmarks.length);
   observer.check([ { name: "onItemChanged",
                      arguments: [ (yield PlacesUtils.promiseItemId(bookmarks[0].guid)),
                                   "keyword", false, "",
-                                  bookmarks[0].lastModified, bookmarks[0].type,
+                                  bookmarks[0].lastModified * 1000, bookmarks[0].type,
                                   (yield PlacesUtils.promiseItemId(bookmarks[0].parentGuid)),
                                   bookmarks[0].guid, bookmarks[0].parentGuid, "",
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
                     { name: "onItemChanged",
                      arguments: [ (yield PlacesUtils.promiseItemId(bookmarks[1].guid)),
                                   "keyword", false, "",
-                                  bookmarks[1].lastModified, bookmarks[1].type,
+                                  bookmarks[1].lastModified * 1000, bookmarks[1].type,
                                   (yield PlacesUtils.promiseItemId(bookmarks[1].parentGuid)),
                                   bookmarks[1].guid, bookmarks[1].parentGuid, "",
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
                     { name: "onItemChanged",
                      arguments: [ (yield PlacesUtils.promiseItemId(bookmarks[2].guid)),
                                   "keyword", false, "",
-                                  bookmarks[2].lastModified, bookmarks[2].type,
+                                  bookmarks[2].lastModified * 1000, bookmarks[2].type,
                                   (yield PlacesUtils.promiseItemId(bookmarks[2].parentGuid)),
                                   bookmarks[2].guid, bookmarks[2].parentGuid, "",
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
 
   check_keyword(URI1, null);
   check_keyword(URI2, null);
   Assert.equal((yield foreign_count(URI2)), fc - 1); // + 1 bookmark - 2 keyword
@@ -286,17 +286,17 @@ add_task(function* test_addRemoveBookmar
   PlacesUtils.bookmarks.setKeywordForBookmark(itemId, "keyword");
   let bookmark = yield PlacesUtils.bookmarks.fetch({ url: URI3 });
   let parentId = yield PlacesUtils.promiseItemId(bookmark.parentGuid);
   PlacesUtils.bookmarks.removeItem(itemId);
 
   observer.check([ { name: "onItemChanged",
                      arguments: [ itemId,
                                   "keyword", false, "keyword",
-                                  bookmark.lastModified, bookmark.type,
+                                  bookmark.lastModified * 1000, bookmark.type,
                                   parentId,
                                   bookmark.guid, bookmark.parentGuid, "",
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
 
   check_keyword(URI3, null);
   // Don't check the foreign count since the process is async.
   // The new test_keywords.js in unit is checking this though.
--- a/toolkit/components/places/tests/migration/test_current_from_v34.js
+++ b/toolkit/components/places/tests/migration/test_current_from_v34.js
@@ -127,15 +127,15 @@ add_task(function* test_mobile_root() {
   equal(fxBmk.index, 0, "Firefox bookmark should be first child of new root");
 
   let tbBmk = yield PlacesUtils.bookmarks.fetch(tbGuid);
   equal(tbBmk.parentGuid, PlacesUtils.bookmarks.mobileGuid,
     "Thunderbird bookmark should be moved to new mobile root");
   equal(tbBmk.index, 1,
     "Thunderbird bookmark should be second child of new root");
 
-  let mobileRootId = PlacesUtils.promiseItemId(
+  let mobileRootId = yield PlacesUtils.promiseItemId(
     PlacesUtils.bookmarks.mobileGuid);
   let annoItemIds = PlacesUtils.annotations.getItemsWithAnnotation(
     PlacesUtils.MOBILE_ROOT_ANNO, {});
   deepEqual(annoItemIds, [mobileRootId],
     "Only mobile root should have mobile anno");
 });
--- a/toolkit/components/places/tests/unit/test_keywords.js
+++ b/toolkit/components/places/tests/unit/test_keywords.js
@@ -178,32 +178,32 @@ add_task(function* test_addBookmarkAndKe
                                                       parentGuid: PlacesUtils.bookmarks.unfiledGuid });
 
   let observer = expectBookmarkNotifications();
   yield PlacesUtils.keywords.insert({ keyword: "keyword", url: "http://example.com/" });
 
   observer.check([{ name: "onItemChanged",
                     arguments: [ (yield PlacesUtils.promiseItemId(bookmark.guid)),
                                  "keyword", false, "keyword",
-                                 bookmark.lastModified, bookmark.type,
+                                 bookmark.lastModified * 1000, bookmark.type,
                                  (yield PlacesUtils.promiseItemId(bookmark.parentGuid)),
                                  bookmark.guid, bookmark.parentGuid, "",
                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT ] } ]);
 
   yield check_keyword(true, "http://example.com/", "keyword");
   Assert.equal((yield foreign_count("http://example.com/")), fc + 2); // +1 bookmark +1 keyword
 
   // Now remove the keyword.
   observer = expectBookmarkNotifications();
   yield PlacesUtils.keywords.remove("keyword");
 
   observer.check([{ name: "onItemChanged",
                     arguments: [ (yield PlacesUtils.promiseItemId(bookmark.guid)),
                                  "keyword", false, "",
-                                 bookmark.lastModified, bookmark.type,
+                                 bookmark.lastModified * 1000, bookmark.type,
                                  (yield PlacesUtils.promiseItemId(bookmark.parentGuid)),
                                  bookmark.guid, bookmark.parentGuid, "",
                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT ] } ]);
 
   yield check_keyword(false, "http://example.com/", "keyword");
   Assert.equal((yield foreign_count("http://example.com/")), fc + 1); // -1 keyword
 
   // Add again the keyword, then remove the bookmark.
@@ -307,40 +307,40 @@ add_task(function* test_sameKeywordDiffe
 
   // Assign the same keyword to another url.
   let observer = expectBookmarkNotifications();
   yield PlacesUtils.keywords.insert({ keyword: "keyword", url: "http://example2.com/" });
 
   observer.check([{ name: "onItemChanged",
                     arguments: [ (yield PlacesUtils.promiseItemId(bookmark1.guid)),
                                  "keyword", false, "",
-                                 bookmark1.lastModified, bookmark1.type,
+                                 bookmark1.lastModified * 1000, bookmark1.type,
                                  (yield PlacesUtils.promiseItemId(bookmark1.parentGuid)),
                                  bookmark1.guid, bookmark1.parentGuid, "",
                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
                   { name: "onItemChanged",
                     arguments: [ (yield PlacesUtils.promiseItemId(bookmark2.guid)),
                                  "keyword", false, "keyword",
-                                 bookmark2.lastModified, bookmark2.type,
+                                 bookmark2.lastModified * 1000, bookmark2.type,
                                  (yield PlacesUtils.promiseItemId(bookmark2.parentGuid)),
                                  bookmark2.guid, bookmark2.parentGuid, "",
                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT ] } ]);
 
   yield check_keyword(false, "http://example1.com/", "keyword");
   Assert.equal((yield foreign_count("http://example1.com/")), fc1 + 1); // -1 keyword
   yield check_keyword(true, "http://example2.com/", "keyword");
   Assert.equal((yield foreign_count("http://example2.com/")), fc2 + 2); // +1 keyword
 
   // Now remove the keyword.
   observer = expectBookmarkNotifications();
   yield PlacesUtils.keywords.remove("keyword");
   observer.check([{ name: "onItemChanged",
                     arguments: [ (yield PlacesUtils.promiseItemId(bookmark2.guid)),
                                  "keyword", false, "",
-                                 bookmark2.lastModified, bookmark2.type,
+                                 bookmark2.lastModified * 1000, bookmark2.type,
                                  (yield PlacesUtils.promiseItemId(bookmark2.parentGuid)),
                                  bookmark2.guid, bookmark2.parentGuid, "",
                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT ] } ]);
 
   yield check_keyword(false, "http://example1.com/", "keyword");
   yield check_keyword(false, "http://example2.com/", "keyword");
   Assert.equal((yield foreign_count("http://example1.com/")), fc1 + 1);
   Assert.equal((yield foreign_count("http://example2.com/")), fc2 + 1); // -1 keyword
@@ -363,30 +363,30 @@ add_task(function* test_sameURIDifferent
   yield PlacesUtils.keywords.insert({keyword: "keyword", url: "http://example.com/" });
 
   yield check_keyword(true, "http://example.com/", "keyword");
   Assert.equal((yield foreign_count("http://example.com/")), fc + 2); // +1 bookmark +1 keyword
 
   observer.check([{ name: "onItemChanged",
                     arguments: [ (yield PlacesUtils.promiseItemId(bookmark.guid)),
                                  "keyword", false, "keyword",
-                                 bookmark.lastModified, bookmark.type,
+                                 bookmark.lastModified * 1000, bookmark.type,
                                  (yield PlacesUtils.promiseItemId(bookmark.parentGuid)),
                                  bookmark.guid, bookmark.parentGuid, "",
                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT ] } ]);
 
   observer = expectBookmarkNotifications();
   yield PlacesUtils.keywords.insert({ keyword: "keyword2", url: "http://example.com/" });
   yield check_keyword(true, "http://example.com/", "keyword");
   yield check_keyword(true, "http://example.com/", "keyword2");
   Assert.equal((yield foreign_count("http://example.com/")), fc + 3); // +1 keyword
   observer.check([{ name: "onItemChanged",
                     arguments: [ (yield PlacesUtils.promiseItemId(bookmark.guid)),
                                  "keyword", false, "keyword2",
-                                 bookmark.lastModified, bookmark.type,
+                                 bookmark.lastModified * 1000, bookmark.type,
                                  (yield PlacesUtils.promiseItemId(bookmark.parentGuid)),
                                  bookmark.guid, bookmark.parentGuid, "",
                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT ] } ]);
 
   // Add a third keyword.
   yield PlacesUtils.keywords.insert({ keyword: "keyword3", url: "http://example.com/" });
   yield check_keyword(true, "http://example.com/", "keyword");
   yield check_keyword(true, "http://example.com/", "keyword2");
@@ -397,17 +397,17 @@ add_task(function* test_sameURIDifferent
   observer = expectBookmarkNotifications();
   yield PlacesUtils.keywords.remove("keyword");
   yield check_keyword(false, "http://example.com/", "keyword");
   yield check_keyword(true, "http://example.com/", "keyword2");
   yield check_keyword(true, "http://example.com/", "keyword3");
   observer.check([{ name: "onItemChanged",
                     arguments: [ (yield PlacesUtils.promiseItemId(bookmark.guid)),
                                  "keyword", false, "",
-                                 bookmark.lastModified, bookmark.type,
+                                 bookmark.lastModified * 1000, bookmark.type,
                                  (yield PlacesUtils.promiseItemId(bookmark.parentGuid)),
                                  bookmark.guid, bookmark.parentGuid, "",
                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT ] } ]);
   Assert.equal((yield foreign_count("http://example.com/")), fc + 3); // -1 keyword
 
   // Now remove the bookmark.
   yield PlacesUtils.bookmarks.remove(bookmark);
   while ((yield foreign_count("http://example.com/")));
@@ -430,43 +430,43 @@ add_task(function* test_deleteKeywordMul
                                                        parentGuid: PlacesUtils.bookmarks.unfiledGuid });
   yield PlacesUtils.keywords.insert({ keyword: "keyword", url: "http://example.com/" });
 
   yield check_keyword(true, "http://example.com/", "keyword");
   Assert.equal((yield foreign_count("http://example.com/")), fc + 3); // +2 bookmark +1 keyword
   observer.check([{ name: "onItemChanged",
                     arguments: [ (yield PlacesUtils.promiseItemId(bookmark2.guid)),
                                  "keyword", false, "keyword",
-                                 bookmark2.lastModified, bookmark2.type,
+                                 bookmark2.lastModified * 1000, bookmark2.type,
                                  (yield PlacesUtils.promiseItemId(bookmark2.parentGuid)),
                                  bookmark2.guid, bookmark2.parentGuid, "",
                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
                   { name: "onItemChanged",
                     arguments: [ (yield PlacesUtils.promiseItemId(bookmark1.guid)),
                                  "keyword", false, "keyword",
-                                 bookmark1.lastModified, bookmark1.type,
+                                 bookmark1.lastModified * 1000, bookmark1.type,
                                  (yield PlacesUtils.promiseItemId(bookmark1.parentGuid)),
                                  bookmark1.guid, bookmark1.parentGuid, "",
                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT ] } ]);
 
   observer = expectBookmarkNotifications();
   yield PlacesUtils.keywords.remove("keyword");
   yield check_keyword(false, "http://example.com/", "keyword");
   Assert.equal((yield foreign_count("http://example.com/")), fc + 2); // -1 keyword
   observer.check([{ name: "onItemChanged",
                     arguments: [ (yield PlacesUtils.promiseItemId(bookmark2.guid)),
                                  "keyword", false, "",
-                                 bookmark2.lastModified, bookmark2.type,
+                                 bookmark2.lastModified * 1000, bookmark2.type,
                                  (yield PlacesUtils.promiseItemId(bookmark2.parentGuid)),
                                  bookmark2.guid, bookmark2.parentGuid, "",
                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
                   { name: "onItemChanged",
                     arguments: [ (yield PlacesUtils.promiseItemId(bookmark1.guid)),
                                  "keyword", false, "",
-                                 bookmark1.lastModified, bookmark1.type,
+                                 bookmark1.lastModified * 1000, bookmark1.type,
                                  (yield PlacesUtils.promiseItemId(bookmark1.parentGuid)),
                                  bookmark1.guid, bookmark1.parentGuid, "",
                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT ] } ]);
 
   // Now remove the bookmarks.
   yield PlacesUtils.bookmarks.remove(bookmark1);
   yield PlacesUtils.bookmarks.remove(bookmark2);
   Assert.equal((yield foreign_count("http://example.com/")), fc); // -2 bookmarks
--- a/toolkit/modules/ObjectUtils.jsm
+++ b/toolkit/modules/ObjectUtils.jsm
@@ -66,34 +66,42 @@ function _deepEqual(a, b) {
   // The numbering below refers to sections in the CommonJS spec.
 
   // 7.1 All identical values are equivalent, as determined by ===.
   if (a === b) {
     return true;
   // 7.2 If the b value is a Date object, the a value is
   // equivalent if it is also a Date object that refers to the same time.
   }
-  if (instanceOf(a, "Date") && instanceOf(b, "Date")) {
+  let aIsDate = instanceOf(a, "Date");
+  let bIsDate = instanceOf(b, "Date");
+  if (aIsDate || bIsDate) {
+    if (!aIsDate || !bIsDate) {
+      return false;
+    }
     if (isNaN(a.getTime()) && isNaN(b.getTime()))
       return true;
     return a.getTime() === b.getTime();
   // 7.3 If the b value is a RegExp object, the a value is
   // equivalent if it is also a RegExp object with the same source and
   // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
   }
-  if (instanceOf(a, "RegExp") && instanceOf(b, "RegExp")) {
-    return a.source === b.source &&
+  let aIsRegExp = instanceOf(a, "RegExp");
+  let bIsRegExp = instanceOf(b, "RegExp");
+  if (aIsRegExp || bIsRegExp) {
+    return aIsRegExp && bIsRegExp &&
+           a.source === b.source &&
            a.global === b.global &&
            a.multiline === b.multiline &&
            a.lastIndex === b.lastIndex &&
            a.ignoreCase === b.ignoreCase;
   // 7.4 Other pairs that do not both pass typeof value == "object",
   // equivalence is determined by ==.
   }
-  if (typeof a != "object" && typeof b != "object") {
+  if (typeof a != "object" || typeof b != "object") {
     return a == b;
   }
   // 7.5 For all other Object pairs, including Array objects, equivalence is
   // determined by having the same number of owned properties (as verified
   // with Object.prototype.hasOwnProperty.call), the same set of keys
   // (although not necessarily the same order), equivalent values for every
   // corresponding key, and an identical 'prototype' property. Note: this
   // accounts for both named and indexed properties on Arrays.
--- a/toolkit/modules/tests/xpcshell/test_ObjectUtils.js
+++ b/toolkit/modules/tests/xpcshell/test_ObjectUtils.js
@@ -7,16 +7,24 @@ function run_test() {
 add_task(function* test_deepEqual() {
   let deepEqual = ObjectUtils.deepEqual.bind(ObjectUtils);
   // CommonJS 7.2
   Assert.ok(deepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14)), "deepEqual date");
   Assert.ok(deepEqual(new Date(NaN), new Date(NaN)), "deepEqual invalid dates");
 
   Assert.ok(!deepEqual(new Date(), new Date(2000, 3, 14)), "deepEqual date");
 
+  let now = Date.now();
+  Assert.ok(!deepEqual(new Date(now), now), "Dates and times should not be equal");
+  Assert.ok(!deepEqual(now, new Date(now)), "Times and dates should not be equal");
+
+  Assert.ok(!deepEqual("", {}), "Objects and primitives should not be equal");
+  Assert.ok(!deepEqual(/a/, "a"), "RegExps and strings should not be equal");
+  Assert.ok(!deepEqual("a", /a/), "Strings and RegExps should not be equal");
+
   // 7.3
   Assert.ok(deepEqual(/a/, /a/));
   Assert.ok(deepEqual(/a/g, /a/g));
   Assert.ok(deepEqual(/a/i, /a/i));
   Assert.ok(deepEqual(/a/m, /a/m));
   Assert.ok(deepEqual(/a/igm, /a/igm));
   Assert.ok(!deepEqual(/ab/, /a/));
   Assert.ok(!deepEqual(/a/g, /a/));