diff --git a/BUILD.gn b/BUILD.gn
index b9be106..a5cccf1 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -620,6 +620,10 @@
 
   deps = []
 
+  if (!is_ios) {
+    deps += [ "//mojo/common:mojo_common_perftests" ]
+  }
+
   if (!is_ios && !is_chromecast) {
     deps += [ "//mandoline:all" ]
   }
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc
index 7bba301..d0fe336c 100644
--- a/android_webview/browser/aw_browser_main_parts.cc
+++ b/android_webview/browser/aw_browser_main_parts.cc
@@ -24,7 +24,6 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/result_codes.h"
-#include "content/public/common/url_utils.h"
 #include "media/base/android/media_client_android.h"
 #include "net/android/network_change_notifier_factory_android.h"
 #include "net/base/network_change_notifier.h"
@@ -89,14 +88,6 @@
       new AwMediaClientAndroid(AwResource::GetConfigKeySystemUuidMapping()));
 
   content::RenderFrameHost::AllowInjectingJavaScriptForAndroidWebView();
-
-  // This is needed for WebView Classic backwards compatibility
-  // See crbug.com/298495. Also see crbug.com/525697 on why it is currently
-  // for single process mode only.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kSingleProcess)) {
-    content::SetMaxURLChars(20 * 1024 * 1024);
-  }
 }
 
 bool AwBrowserMainParts::MainMessageLoopRun(int* result_code) {
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index 451e3bc..8ecc734c 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -1471,9 +1471,6 @@
                 Log.wtf(TAG, "Unable to load data string " + data, e);
                 return;
             }
-            // When loading data with a non-data: base URL, WebView must allow renderers
-            // to access file: URLs.
-            nativeGrantFileSchemeAccesstoChildProcess(mNativeAwContents);
         }
         loadUrl(loadUrlParams);
     }
@@ -1492,6 +1489,7 @@
             // file:///android_res/ URLs. If AwSettings.getAllowFileAccess permits, it will also
             // allow access to file:// URLs (subject to OS level permission checks).
             params.setCanLoadLocalResources(true);
+            nativeGrantFileSchemeAccesstoChildProcess(mNativeAwContents);
         }
 
         // If we are reloading the same url, then set transition type as reload.
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/LoadDataWithBaseUrlTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/LoadDataWithBaseUrlTest.java
index 703db51..9318746a 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/LoadDataWithBaseUrlTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/LoadDataWithBaseUrlTest.java
@@ -349,4 +349,24 @@
             if (!tempImage.delete()) throw new AssertionError();
         }
     }
+
+    @SmallTest
+    @Feature({"AndroidWebView"})
+    public void testLoadLargeData() throws Throwable {
+        // Chrome only allows URLs up to 2MB in IPC. Test something larger than this.
+        // Note that the real URI may be significantly large if it gets encoded into
+        // base64.
+        final int kDataLength = 5 * 1024 * 1024;
+        StringBuilder doc = new StringBuilder();
+        doc.append("<html><head></head><body><!-- ");
+        int i = doc.length();
+        doc.setLength(i + kDataLength);
+        while (i < doc.length()) doc.setCharAt(i++, 'A');
+        doc.append("--><script>window.gotToEndOfBody=true;</script></body></html>");
+
+        enableJavaScriptOnUiThread(mAwContents);
+        loadDataWithBaseUrlSync(doc.toString(), "text/html", false, null, null);
+        assertEquals("true", executeJavaScriptAndWaitForResult(mAwContents, mContentsClient,
+                        "window.gotToEndOfBody"));
+    }
 }
diff --git a/android_webview/native/state_serializer.cc b/android_webview/native/state_serializer.cc
index 22139a2..fc9cf9b 100644
--- a/android_webview/native/state_serializer.cc
+++ b/android_webview/native/state_serializer.cc
@@ -34,7 +34,7 @@
 // Sanity check value that we are restoring from a valid pickle.
 // This can potentially used as an actual serialization version number in the
 // future if we ever decide to support restoring from older versions.
-const uint32 AW_STATE_VERSION = 20130814;
+const uint32 AW_STATE_VERSION = 20151204;
 
 }  // namespace
 
@@ -179,6 +179,20 @@
   if (!pickle->WriteString(entry.GetBaseURLForDataURL().spec()))
     return false;
 
+  {
+    const char* data = nullptr;
+    size_t size = 0;
+    scoped_refptr<const base::RefCountedString> s = entry.GetDataURLAsString();
+    if (s) {
+      data = s->front_as<char>();
+      size = s->size();
+    }
+    // Even when |entry.GetDataForDataURL()| is null we still need to write a
+    // zero-length entry to ensure the fields all line up when read back in.
+    if (!pickle->WriteData(data, size))
+      return false;
+  }
+
   if (!pickle->WriteBool(static_cast<int>(entry.GetIsOverridingUserAgent())))
     return false;
 
@@ -261,6 +275,18 @@
   }
 
   {
+    const char* data;
+    int size;
+    if (!iterator->ReadData(&data, &size))
+      return false;
+    if (size > 0) {
+      scoped_refptr<base::RefCountedString> ref = new base::RefCountedString();
+      ref->data().assign(data, size);
+      entry->SetDataURLAsString(ref);
+    }
+  }
+
+  {
     bool is_overriding_user_agent;
     if (!iterator->ReadBool(&is_overriding_user_agent))
       return false;
diff --git a/android_webview/native/state_serializer_unittest.cc b/android_webview/native/state_serializer_unittest.cc
index fd897d4b..a9671c6 100644
--- a/android_webview/native/state_serializer_unittest.cc
+++ b/android_webview/native/state_serializer_unittest.cc
@@ -52,6 +52,7 @@
   const bool has_post_data = true;
   const GURL original_request_url("http://original_request_url");
   const GURL base_url_for_data_url("http://base_url");
+  const string data_url_as_string("data:text/html;charset=utf-8;base64,");
   const bool is_overriding_user_agent = true;
   const base::Time timestamp = base::Time::FromInternalValue(12345);
   const int http_status_code = 404;
@@ -64,6 +65,11 @@
   entry->SetHasPostData(has_post_data);
   entry->SetOriginalRequestURL(original_request_url);
   entry->SetBaseURLForDataURL(base_url_for_data_url);
+  {
+    scoped_refptr<base::RefCountedString> s = new base::RefCountedString();
+    s->data().assign(data_url_as_string);
+    entry->SetDataURLAsString(s);
+  }
   entry->SetIsOverridingUserAgent(is_overriding_user_agent);
   entry->SetTimestamp(timestamp);
   entry->SetHttpStatusCode(http_status_code);
@@ -86,9 +92,60 @@
   EXPECT_EQ(has_post_data, copy->GetHasPostData());
   EXPECT_EQ(original_request_url, copy->GetOriginalRequestURL());
   EXPECT_EQ(base_url_for_data_url, copy->GetBaseURLForDataURL());
+  EXPECT_EQ(data_url_as_string, copy->GetDataURLAsString()->data());
   EXPECT_EQ(is_overriding_user_agent, copy->GetIsOverridingUserAgent());
   EXPECT_EQ(timestamp, copy->GetTimestamp());
   EXPECT_EQ(http_status_code, copy->GetHttpStatusCode());
 }
 
+TEST(AndroidWebViewStateSerializerTest, TestEmptyDataURLSerialization) {
+  // This is required for NavigationEntry::Create.
+  content::ContentClient content_client;
+  content::SetContentClient(&content_client);
+  content::ContentBrowserClient browser_client;
+  content::SetBrowserClientForTesting(&browser_client);
+
+  scoped_ptr<content::NavigationEntry> entry(
+      content::NavigationEntry::Create());
+  EXPECT_FALSE(entry->GetDataURLAsString());
+
+  base::Pickle pickle;
+  bool result = internal::WriteNavigationEntryToPickle(*entry, &pickle);
+  EXPECT_TRUE(result);
+
+  scoped_ptr<content::NavigationEntry> copy(content::NavigationEntry::Create());
+  base::PickleIterator iterator(pickle);
+  result = internal::RestoreNavigationEntryFromPickle(&iterator, copy.get());
+  EXPECT_TRUE(result);
+  EXPECT_FALSE(entry->GetDataURLAsString());
+}
+
+TEST(AndroidWebViewStateSerializerTest, TestHugeDataURLSerialization) {
+  // This is required for NavigationEntry::Create.
+  content::ContentClient content_client;
+  content::SetContentClient(&content_client);
+  content::ContentBrowserClient browser_client;
+  content::SetBrowserClientForTesting(&browser_client);
+
+  scoped_ptr<content::NavigationEntry> entry(
+      content::NavigationEntry::Create());
+  string huge_data_url(1024 * 1024 * 20 - 1, 'd');
+  huge_data_url.replace(0, strlen(url::kDataScheme), url::kDataScheme);
+  {
+    scoped_refptr<base::RefCountedString> s = new base::RefCountedString();
+    s->data().assign(huge_data_url);
+    entry->SetDataURLAsString(s);
+  }
+
+  base::Pickle pickle;
+  bool result = internal::WriteNavigationEntryToPickle(*entry, &pickle);
+  EXPECT_TRUE(result);
+
+  scoped_ptr<content::NavigationEntry> copy(content::NavigationEntry::Create());
+  base::PickleIterator iterator(pickle);
+  result = internal::RestoreNavigationEntryFromPickle(&iterator, copy.get());
+  EXPECT_TRUE(result);
+  EXPECT_EQ(huge_data_url, copy->GetDataURLAsString()->data());
+}
+
 }  // namespace android_webview
diff --git a/base/files/dir_reader_fallback.h b/base/files/dir_reader_fallback.h
index a435f25..d44c227 100644
--- a/base/files/dir_reader_fallback.h
+++ b/base/files/dir_reader_fallback.h
@@ -21,7 +21,7 @@
   bool Next() { return false; }
 
   // Return the name of the current directory entry.
-  const char* name() { return 0;}
+  const char* name() { return nullptr;}
 
   // Return the file descriptor which is being used.
   int fd() const { return -1; }
diff --git a/base/files/dir_reader_linux.h b/base/files/dir_reader_linux.h
index abf2595..83918e8 100644
--- a/base/files/dir_reader_linux.h
+++ b/base/files/dir_reader_linux.h
@@ -70,7 +70,7 @@
 
   const char* name() const {
     if (!size_)
-      return NULL;
+      return nullptr;
 
     const linux_dirent* dirent =
         reinterpret_cast<const linux_dirent*>(&buf_[offset_]);
@@ -88,7 +88,8 @@
  private:
   const int fd_;
   unsigned char buf_[512];
-  size_t offset_, size_;
+  size_t offset_;
+  size_t size_;
 
   DISALLOW_COPY_AND_ASSIGN(DirReaderLinux);
 };
diff --git a/base/files/file_util.h b/base/files/file_util.h
index 7f169f1..2e53c40 100644
--- a/base/files/file_util.h
+++ b/base/files/file_util.h
@@ -350,6 +350,11 @@
 BASE_EXPORT int GetUniquePathNumber(const FilePath& path,
                                     const FilePath::StringType& suffix);
 
+// Sets the given |fd| to non-blocking mode.
+// Returns true if it was able to set it in the non-blocking mode, otherwise
+// false.
+BASE_EXPORT bool SetNonBlocking(int fd);
+
 #if defined(OS_POSIX)
 // Test that |path| can only be changed by a given user and members of
 // a given set of groups.
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc
index eb8620d0..a38f06d 100644
--- a/base/files/file_util_posix.cc
+++ b/base/files/file_util_posix.cc
@@ -348,6 +348,17 @@
 }
 #endif  // !defined(OS_NACL_NONSFI)
 
+bool SetNonBlocking(int fd) {
+  int flags = fcntl(fd, F_GETFL, 0);
+  if (flags == -1)
+    return false;
+  if (flags & O_NONBLOCK)
+    return true;
+  if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
+    return false;
+  return true;
+}
+
 bool PathExists(const FilePath& path) {
   ThreadRestrictions::AssertIOAllowed();
 #if defined(OS_ANDROID)
diff --git a/base/files/file_util_win.cc b/base/files/file_util_win.cc
index 428b7a6..2bde7ad 100644
--- a/base/files/file_util_win.cc
+++ b/base/files/file_util_win.cc
@@ -11,6 +11,7 @@
 #include <shlobj.h>
 #include <stdint.h>
 #include <time.h>
+#include <winsock2.h>
 
 #include <algorithm>
 #include <limits>
@@ -765,6 +766,13 @@
   return true;
 }
 
+bool SetNonBlocking(int fd) {
+  unsigned long nonblocking = 1;
+  if (ioctlsocket(fd, FIONBIO, &nonblocking) == 0)
+    return true;
+  return false;
+}
+
 // -----------------------------------------------------------------------------
 
 namespace internal {
diff --git a/base/message_loop/message_pump_libevent.cc b/base/message_loop/message_pump_libevent.cc
index 74602a7b..04a1cb9 100644
--- a/base/message_loop/message_pump_libevent.cc
+++ b/base/message_loop/message_pump_libevent.cc
@@ -5,11 +5,11 @@
 #include "base/message_loop/message_pump_libevent.h"
 
 #include <errno.h>
-#include <fcntl.h>
 #include <unistd.h>
 
 #include "base/auto_reset.h"
 #include "base/compiler_specific.h"
+#include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
@@ -42,15 +42,6 @@
 
 namespace base {
 
-// Return 0 on success
-// Too small a function to bother putting in a library?
-static int SetNonBlocking(int fd) {
-  int flags = fcntl(fd, F_GETFL, 0);
-  if (flags == -1)
-    flags = 0;
-  return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-}
-
 MessagePumpLibevent::FileDescriptorWatcher::FileDescriptorWatcher()
     : event_(NULL),
       pump_(NULL),
@@ -322,11 +313,11 @@
     DLOG(ERROR) << "pipe() failed, errno: " << errno;
     return false;
   }
-  if (SetNonBlocking(fds[0])) {
+  if (!SetNonBlocking(fds[0])) {
     DLOG(ERROR) << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
     return false;
   }
-  if (SetNonBlocking(fds[1])) {
+  if (!SetNonBlocking(fds[1])) {
     DLOG(ERROR) << "SetNonBlocking for pipe fd[1] failed, errno: " << errno;
     return false;
   }
diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc
index 10516a4b..4d98772 100644
--- a/base/process/process_metrics_linux.cc
+++ b/base/process/process_metrics_linux.cc
@@ -12,6 +12,7 @@
 #include <unistd.h>
 #include <utility>
 
+#include "base/files/dir_reader_posix.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/process/internal_linux.h"
@@ -291,17 +292,16 @@
   // Use /proc/<pid>/fd to count the number of entries there.
   FilePath fd_path = internal::GetProcPidDir(process_).Append("fd");
 
-  DIR* dir = opendir(fd_path.value().c_str());
-  if (!dir) {
-    DPLOG(ERROR) << "opendir(" << fd_path.value() << ")";
+  DirReaderPosix dir_reader(fd_path.value().c_str());
+  if (!dir_reader.IsValid())
     return -1;
-  }
 
   int total_count = 0;
-  while (readdir(dir))
-    ++total_count;
-
-  closedir(dir);
+  for (; dir_reader.Next(); ) {
+    const char* name = dir_reader.name();
+    if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0)
+      ++total_count;
+  }
 
   return total_count;
 }
diff --git a/base/process/process_metrics_unittest.cc b/base/process/process_metrics_unittest.cc
index b29ceb6..bbf55c33 100644
--- a/base/process/process_metrics_unittest.cc
+++ b/base/process/process_metrics_unittest.cc
@@ -8,10 +8,15 @@
 #include <string>
 
 #include "base/bind.h"
+#include "base/command_line.h"
+#include "base/files/file.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/test/multiprocess_test.h"
 #include "base/threading/thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
-
+#include "testing/multiprocess_func_list.h"
 
 namespace base {
 namespace debug {
@@ -23,7 +28,7 @@
   int64_t test_value = 0;
   for (int i = 0; i < 100000; ++i) {
     ++test_value;
-    vec->push_back(base::Int64ToString(test_value));
+    vec->push_back(Int64ToString(test_value));
   }
 }
 
@@ -292,7 +297,7 @@
 // the number of threads running on the process decreases between two successive
 // calls to it.
 TEST_F(SystemMetricsTest, TestNoNegativeCpuUsage) {
-  base::ProcessHandle handle = base::GetCurrentProcessHandle();
+  ProcessHandle handle = GetCurrentProcessHandle();
   scoped_ptr<ProcessMetrics> metrics(
       ProcessMetrics::CreateProcessMetrics(handle));
 
@@ -313,9 +318,9 @@
   std::vector<std::string> vec2;
   std::vector<std::string> vec3;
 
-  thread1.task_runner()->PostTask(FROM_HERE, base::Bind(&BusyWork, &vec1));
-  thread2.task_runner()->PostTask(FROM_HERE, base::Bind(&BusyWork, &vec2));
-  thread3.task_runner()->PostTask(FROM_HERE, base::Bind(&BusyWork, &vec3));
+  thread1.task_runner()->PostTask(FROM_HERE, Bind(&BusyWork, &vec1));
+  thread2.task_runner()->PostTask(FROM_HERE, Bind(&BusyWork, &vec2));
+  thread3.task_runner()->PostTask(FROM_HERE, Bind(&BusyWork, &vec3));
 
   EXPECT_GE(metrics->GetCPUUsage(), 0.0);
 
@@ -334,8 +339,8 @@
 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) || \
     defined(OS_LINUX) || defined(OS_ANDROID)
 TEST(SystemMetrics2Test, GetSystemMemoryInfo) {
-  base::SystemMemoryInfoKB info;
-  EXPECT_TRUE(base::GetSystemMemoryInfo(&info));
+  SystemMemoryInfoKB info;
+  EXPECT_TRUE(GetSystemMemoryInfo(&info));
 
   // Ensure each field received a value.
   EXPECT_GT(info.total, 0);
@@ -380,7 +385,7 @@
       "20 0 1 0 121946157 15077376 314 18446744073709551615 4194304 "
       "4246868 140733983044336 18446744073709551615 140244213071219 "
       "0 0 0 138047495 0 0 0 17 1 0 0 0 0 0";
-  EXPECT_EQ(12 + 16, base::ParseProcStatCPU(kTopStat));
+  EXPECT_EQ(12 + 16, ParseProcStatCPU(kTopStat));
 
   // cat /proc/self/stat on a random other machine I have.
   const char kSelfStat[] = "5364 (cat) R 5354 5364 5354 34819 5364 "
@@ -389,7 +394,7 @@
       "16 0 1 0 1676099790 2957312 114 4294967295 134512640 134528148 "
       "3221224832 3221224344 3086339742 0 0 0 0 0 0 0 17 0 0 0";
 
-  EXPECT_EQ(0, base::ParseProcStatCPU(kSelfStat));
+  EXPECT_EQ(0, ParseProcStatCPU(kSelfStat));
 
   // Some weird long-running process with a weird name that I created for the
   // purposes of this test.
@@ -400,29 +405,96 @@
       "140735857761568 140735857761160 4195644 0 0 0 0 0 0 0 17 14 0 0 0 0 0 "
       "6295056 6295616 16519168 140735857770710 140735857770737 "
       "140735857770737 140735857774557 0";
-  EXPECT_EQ(5186 + 11, base::ParseProcStatCPU(kWeirdNameStat));
+  EXPECT_EQ(5186 + 11, ParseProcStatCPU(kWeirdNameStat));
 }
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
+#endif  // defined(OS_LINUX) || defined(OS_ANDROID)
 
 // Disable on Android because base_unittests runs inside a Dalvik VM that
 // starts and stop threads (crbug.com/175563).
 #if defined(OS_LINUX)
 // http://crbug.com/396455
 TEST(ProcessMetricsTest, DISABLED_GetNumberOfThreads) {
-  const base::ProcessHandle current = base::GetCurrentProcessHandle();
-  const int initial_threads = base::GetNumberOfThreads(current);
+  const ProcessHandle current = GetCurrentProcessHandle();
+  const int initial_threads = GetNumberOfThreads(current);
   ASSERT_GT(initial_threads, 0);
   const int kNumAdditionalThreads = 10;
   {
-    scoped_ptr<base::Thread> my_threads[kNumAdditionalThreads];
+    scoped_ptr<Thread> my_threads[kNumAdditionalThreads];
     for (int i = 0; i < kNumAdditionalThreads; ++i) {
-      my_threads[i].reset(new base::Thread("GetNumberOfThreadsTest"));
+      my_threads[i].reset(new Thread("GetNumberOfThreadsTest"));
       my_threads[i]->Start();
-      ASSERT_EQ(base::GetNumberOfThreads(current), initial_threads + 1 + i);
+      ASSERT_EQ(GetNumberOfThreads(current), initial_threads + 1 + i);
     }
   }
   // The Thread destructor will stop them.
-  ASSERT_EQ(initial_threads, base::GetNumberOfThreads(current));
+  ASSERT_EQ(initial_threads, GetNumberOfThreads(current));
+}
+#endif  // defined(OS_LINUX)
+
+#if defined(OS_LINUX)
+namespace {
+
+// Keep these in sync so the GetOpenFdCount test can refer to correct test main.
+#define ChildMain ChildFdCount
+#define ChildMainString "ChildFdCount"
+
+// Command line flag name and file name used for synchronization.
+const char kTempDirFlag[] = "temp-dir";
+const char kSignalClosed[] = "closed";
+
+bool SignalEvent(const FilePath& signal_dir, const char* signal_file) {
+  File file(signal_dir.AppendASCII(signal_file),
+            File::FLAG_CREATE | File::FLAG_WRITE);
+  return file.IsValid();
+}
+
+// Check whether an event was signaled.
+bool CheckEvent(const FilePath& signal_dir, const char* signal_file) {
+  File file(signal_dir.AppendASCII(signal_file),
+            File::FLAG_OPEN | File::FLAG_READ);
+  return file.IsValid();
+}
+
+// Busy-wait for an event to be signaled.
+void WaitForEvent(const FilePath& signal_dir, const char* signal_file) {
+  while (!CheckEvent(signal_dir, signal_file))
+    PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
+}
+
+// Subprocess to test the number of open file descriptors.
+MULTIPROCESS_TEST_MAIN(ChildMain) {
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+  const FilePath temp_path = command_line->GetSwitchValuePath(kTempDirFlag);
+  CHECK(DirectoryExists(temp_path));
+
+  // Try to close all the file descriptors, so the open count goes to 0.
+  for (size_t i = 0; i < 1000; ++i)
+    close(i);
+  CHECK(SignalEvent(temp_path, kSignalClosed));
+
+  // Wait to be terminated.
+  while (true)
+    PlatformThread::Sleep(TimeDelta::FromSeconds(1));
+  return 0;
+}
+
+}  // namespace
+
+TEST(ProcessMetricsTest, GetOpenFdCount) {
+  ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  const FilePath temp_path = temp_dir.path();
+  CommandLine child_command_line(GetMultiProcessTestChildBaseCommandLine());
+  child_command_line.AppendSwitchPath(kTempDirFlag, temp_path);
+  Process child = SpawnMultiProcessTestChild(
+      ChildMainString, child_command_line, LaunchOptions());
+  ASSERT_TRUE(child.IsValid());
+  WaitForEvent(temp_path, kSignalClosed);
+
+  scoped_ptr<ProcessMetrics> metrics(
+      ProcessMetrics::CreateProcessMetrics(child.Handle()));
+  EXPECT_EQ(0, metrics->GetOpenFdCount());
+  ASSERT_TRUE(child.Terminate(0, true));
 }
 #endif  // defined(OS_LINUX)
 
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 2a1e3681..192718e 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -716,6 +716,11 @@
   repetitions = (xrange(args.repeat + 1) if args.repeat >= 0
                  else itertools.count())
 
+  code_counts = {constants.INFRA_EXIT_CODE: 0,
+                 constants.ERROR_EXIT_CODE: 0,
+                 constants.WARNING_EXIT_CODE: 0,
+                 0: 0}
+
   def _escalate_code(old, new):
     for x in (constants.INFRA_EXIT_CODE,
               constants.ERROR_EXIT_CODE,
@@ -732,6 +737,7 @@
           test_timeout=None, num_retries=args.num_retries)
       iteration_results.AddTestRunResults(test_results)
 
+      code_counts[test_exit_code] += 1
       exit_code = _escalate_code(exit_code, test_exit_code)
 
     if py_tests:
@@ -740,6 +746,7 @@
           num_retries=args.num_retries)
       iteration_results.AddTestRunResults(test_results)
 
+      code_counts[test_exit_code] += 1
       exit_code = _escalate_code(exit_code, test_exit_code)
 
     results.append(iteration_results)
@@ -750,10 +757,17 @@
         annotation=args.annotations,
         flakiness_server=args.flakiness_dashboard_server)
 
+
     if args.break_on_failure and exit_code in (constants.ERROR_EXIT_CODE,
                                                constants.INFRA_EXIT_CODE):
       break
 
+  logging.critical('Instr tests: %s success, %s infra, %s errors, %s warnings',
+                   str(code_counts[0]),
+                   str(code_counts[constants.INFRA_EXIT_CODE]),
+                   str(code_counts[constants.ERROR_EXIT_CODE]),
+                   str(code_counts[constants.WARNING_EXIT_CODE]))
+
   if args.json_results_file:
     json_results.GenerateJsonResultsFile(results, args.json_results_file)
 
@@ -959,11 +973,16 @@
         results = []
         repetitions = (xrange(args.repeat + 1) if args.repeat >= 0
                        else itertools.count())
+        result_counts = collections.defaultdict(
+            lambda: collections.defaultdict(int))
+        iteration_count = 0
         for _ in repetitions:
           iteration_results = test_run.RunTests()
-
           if iteration_results is not None:
+            iteration_count += 1
             results.append(iteration_results)
+            for r in iteration_results.GetAll():
+              result_counts[r.GetName()][r.GetType()] += 1
             report_results.LogFull(
                 results=iteration_results,
                 test_type=test.TestType(),
@@ -974,6 +993,31 @@
             if args.break_on_failure and not iteration_results.DidRunPass():
               break
 
+        if iteration_count > 1:
+          # display summary results
+          # only display results for a test if at least one test did not pass
+          all_pass = 0
+          tot_tests = 0
+          for test_name in result_counts:
+            tot_tests += 1
+            if any(result_counts[test_name][x] for x in (
+                base_test_result.ResultType.FAIL,
+                base_test_result.ResultType.CRASH,
+                base_test_result.ResultType.TIMEOUT,
+                base_test_result.ResultType.UNKNOWN)):
+              logging.critical(
+                  '%s: %s',
+                  test_name,
+                  ', '.join('%s %s' % (str(result_counts[test_name][i]), i)
+                            for i in base_test_result.ResultType.GetTypes()))
+            else:
+              all_pass += 1
+
+          logging.critical('%s of %s tests passed in all %s runs',
+                           str(all_pass),
+                           str(tot_tests),
+                           str(iteration_count))
+
         if args.json_results_file:
           json_results.GenerateJsonResultsFile(
               results, args.json_results_file)
diff --git a/build/common.gypi b/build/common.gypi
index b81acbe..b2e8e6e 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -233,6 +233,13 @@
             'toolkit_views%': 0,
           }],
 
+          # Chromecast builds on x86 Linux should default to desktop builds.
+          ['chromecast==1 and OS=="linux" and (target_arch=="ia32" or target_arch=="x64")', {
+            'is_cast_desktop_build%': 1,
+          }, {
+            'is_cast_desktop_build%': 0,
+          }],
+
           # Enable HiDPI on Mac OS, Windows and Linux (including Chrome OS).
           ['OS=="mac" or OS=="win" or OS=="linux"', {
             'enable_hidpi%': 1,
@@ -322,6 +329,7 @@
       # Copy conditionally-set variables out one scope.
       'chromeos%': '<(chromeos)',
       'chromecast%': '<(chromecast)',
+      'is_cast_desktop_build%': '<(is_cast_desktop_build)',
       'host_arch%': '<(host_arch)',
       'target_arch%': '<(target_arch)',
       'target_subarch%': '<(target_subarch)',
@@ -847,6 +855,13 @@
           'enable_prod_wallet_service%': 1,
         }],
 
+        # Enable Control Flow Integrity for the official Linux Chrome.
+        # This triggers an LTO build that requires LLVM Gold plugin to be
+        # downloaded. See src/tools/clang/scripts/update.py
+        ['OS=="linux" and target_arch=="x64" and buildtype=="Official" and branding=="Chrome" and chromeos==0', {
+          'cfi_vptr%': 1,
+        }],
+
         # Enable hotwording on Chrome-branded ChromeOS builds.
         ['branding=="Chrome" and chromeos==1', {
           'enable_hotwording%': 1,
@@ -1137,6 +1152,7 @@
     'linux_fpic%': '<(linux_fpic)',
     'chromeos%': '<(chromeos)',
     'chromecast%': '<(chromecast)',
+    'is_cast_desktop_build%': '<(is_cast_desktop_build)',
     'enable_viewport%': '<(enable_viewport)',
     'enable_hidpi%': '<(enable_hidpi)',
     'enable_topchrome_md%': '<(enable_topchrome_md)',
@@ -2392,7 +2408,7 @@
                 # TODO(slan|halliwell): Make the default platform "cast" on
                 # desktop too.
                 'conditions': [
-                  ['OS=="linux" and target_arch!="arm"', {
+                  ['is_cast_desktop_build==1', {
                     'ozone_platform_egltest%': 1,
                     'ozone_platform_ozonex%': 1,
                   }, {
diff --git a/build/config/chromecast_build.gni b/build/config/chromecast_build.gni
index b3d1bc2..b2259704 100644
--- a/build/config/chromecast_build.gni
+++ b/build/config/chromecast_build.gni
@@ -2,8 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# This block should only contain Chromecast-specific build arguments used by
-# by components outside of //chromecast.
+# The args declared in this file should be referenced by components outside of
+# //chromecast. Args needed only in //chromecast should be declared in
+# //chromecast/chromecast.gni.
 declare_args() {
   # Set this true for a Chromecast build. Chromecast builds are supported on
   # Linux and Android.
@@ -13,9 +14,23 @@
   disable_display = false
 }
 
+# Note(slan): This arg depends on the value of is_chromecast, and thus must be
+# declared in a separate block. These blocks can be combined when/if
+# crbug.com/542846 is resolved.
+declare_args() {
+  # True if Chromecast build is targeted for linux desktop. This type of build
+  # is useful for testing and development, but currently supports only a subset
+  # of Cast functionality. Though this defaults to true for x86 Linux devices,
+  # this should be overriden manually for an embedded x86 build.
+  # TODO(slan): Remove instances of this when x86 is a fully supported platform.
+  is_cast_desktop_build = is_chromecast && target_os == "linux" &&
+                          (target_cpu == "x86" || target_cpu == "x64")
+}
+
 # Assert that Chromecast is being built for a supported platform.
 assert(is_linux || is_android || !is_chromecast,
        "Chromecast builds are not supported on $target_os")
 
-# Assert that disable_display is not true on a non-Chromecast build.
-assert(!disable_display || is_chromecast)
+# Assert that disable_display and is_cast_desktop_build are both false on a
+# non-Chromecast build.
+assert(is_chromecast || !(disable_display || is_cast_desktop_build))
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni
index f8f469c..6d12813 100644
--- a/build/config/sanitizers/sanitizers.gni
+++ b/build/config/sanitizers/sanitizers.gni
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chrome_build.gni")
+
 declare_args() {
   # Compile for Address Sanitizer to find memory bugs.
   is_asan = false
@@ -37,10 +39,6 @@
   # https://code.google.com/p/sawbuck/wiki/SyzyASanHowTo
   is_syzyasan = false
 
-  # Compile with Control Flow Integrity to protect virtual calls and casts.
-  # See http://clang.llvm.org/docs/ControlFlowIntegrity.html
-  is_cfi = false
-
   # By default, Control Flow Integrity will crash the program if it detects a
   # violation. Set this to true to print detailed diagnostics instead.
   use_cfi_diag = false
@@ -58,6 +56,11 @@
 # declare_args block. User overrides are only applied at the end of a
 # declare_args block.
 declare_args() {
+  # Compile with Control Flow Integrity to protect virtual calls and casts.
+  # See http://clang.llvm.org/docs/ControlFlowIntegrity.html
+  is_cfi = is_linux && !is_chromeos && target_cpu == "x64" &&
+           is_chrome_branded && is_official_build
+
   # Use libc++ (buildtools/third_party/libc++ and
   # buildtools/third_party/libc++abi) instead of stdlibc++ as standard library.
   # This is intended to be used for instrumented builds.
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index fb77e981..0b5a4af 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -570,6 +570,8 @@
     "test/begin_frame_source_test.h",
     "test/failure_output_surface.cc",
     "test/failure_output_surface.h",
+    "test/fake_channel_impl.cc",
+    "test/fake_channel_impl.h",
     "test/fake_content_layer_client.cc",
     "test/fake_content_layer_client.h",
     "test/fake_delegated_renderer_layer.cc",
@@ -891,6 +893,7 @@
     "trees/occlusion_tracker_unittest.cc",
     "trees/occlusion_unittest.cc",
     "trees/property_tree_unittest.cc",
+    "trees/proxy_impl_unittest.cc",
     "trees/threaded_channel_unittest.cc",
     "trees/tree_synchronizer_unittest.cc",
 
diff --git a/cc/animation/layer_animation_controller.cc b/cc/animation/layer_animation_controller.cc
index 10399eee..721173c 100644
--- a/cc/animation/layer_animation_controller.cc
+++ b/cc/animation/layer_animation_controller.cc
@@ -139,6 +139,19 @@
     UpdatePotentiallyAnimatingTransform();
 }
 
+void LayerAnimationController::AbortAnimation(int animation_id) {
+  bool aborted_transform_animation = false;
+  if (Animation* animation = GetAnimationById(animation_id)) {
+    if (!animation->is_finished()) {
+      animation->SetRunState(Animation::ABORTED, last_tick_time_);
+      if (animation->target_property() == Animation::TRANSFORM)
+        aborted_transform_animation = true;
+    }
+  }
+  if (aborted_transform_animation)
+    UpdatePotentiallyAnimatingTransform();
+}
+
 void LayerAnimationController::AbortAnimations(
     Animation::TargetProperty target_property) {
   bool aborted_transform_animation = false;
@@ -161,6 +174,7 @@
   DCHECK(this != controller_impl);
   if (!has_any_animation() && !controller_impl->has_any_animation())
     return;
+  MarkAbortedAnimationsForDeletion(controller_impl);
   PurgeAnimationsMarkedForDeletion();
   PushNewAnimationsToImplThread(controller_impl);
 
@@ -443,6 +457,7 @@
     if (animations_[i]->group() == event.group_id &&
         animations_[i]->target_property() == event.target_property) {
       animations_[i]->SetRunState(Animation::ABORTED, event.monotonic_time);
+      animations_[i]->set_received_finished_event(true);
       if (event.target_property == Animation::TRANSFORM)
         aborted_transform_animation = true;
     }
@@ -921,9 +936,13 @@
                                      monotonic_time);
         events->push_back(aborted_event);
       }
-      animations_[i]->SetRunState(Animation::WAITING_FOR_DELETION,
-                                  monotonic_time);
-      marked_animations_for_deletions = true;
+      // If on the compositor or on the main thread and received finish event,
+      // animation can be marked for deletion.
+      if (events || animations_[i]->received_finished_event()) {
+        animations_[i]->SetRunState(Animation::WAITING_FOR_DELETION,
+                                    monotonic_time);
+        marked_animations_for_deletions = true;
+      }
       continue;
     }
 
@@ -997,6 +1016,30 @@
     NotifyObserversAnimationWaitingForDeletion();
 }
 
+void LayerAnimationController::MarkAbortedAnimationsForDeletion(
+    LayerAnimationController* controller_impl) const {
+  bool aborted_transform_animation = false;
+  auto& animations_impl = controller_impl->animations_;
+  for (const auto& animation_impl : animations_impl) {
+    // If the animation has been aborted on the main thread, mark it for
+    // deletion.
+    if (Animation* animation = GetAnimationById(animation_impl->id())) {
+      if (animation->run_state() == Animation::ABORTED) {
+        animation_impl->SetRunState(Animation::WAITING_FOR_DELETION,
+                                    controller_impl->last_tick_time_);
+        animation->SetRunState(Animation::WAITING_FOR_DELETION,
+                               last_tick_time_);
+        if (animation_impl->target_property() == Animation::TRANSFORM) {
+          aborted_transform_animation = true;
+        }
+      }
+    }
+  }
+
+  if (aborted_transform_animation)
+    controller_impl->UpdatePotentiallyAnimatingTransform();
+}
+
 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
   animations_.erase(std::remove_if(animations_.begin(), animations_.end(),
                                    [](const scoped_ptr<Animation>& animation) {
diff --git a/cc/animation/layer_animation_controller.h b/cc/animation/layer_animation_controller.h
index 60b70a3..1f85223 100644
--- a/cc/animation/layer_animation_controller.h
+++ b/cc/animation/layer_animation_controller.h
@@ -48,6 +48,7 @@
   void RemoveAnimation(int animation_id);
   void RemoveAnimation(int animation_id,
                        Animation::TargetProperty target_property);
+  void AbortAnimation(int animation_id);
   void AbortAnimations(Animation::TargetProperty target_property);
 
   // Ensures that the list of active animations on the main thread and the impl
@@ -181,6 +182,8 @@
 
   void PushNewAnimationsToImplThread(
       LayerAnimationController* controller_impl) const;
+  void MarkAbortedAnimationsForDeletion(
+      LayerAnimationController* controller_impl) const;
   void RemoveAnimationsCompletedOnMainThread(
       LayerAnimationController* controller_impl) const;
   void PushPropertiesToImplThread(LayerAnimationController* controller_impl);
diff --git a/cc/animation/layer_animation_controller_unittest.cc b/cc/animation/layer_animation_controller_unittest.cc
index 75c61e8..6ec8a34 100644
--- a/cc/animation/layer_animation_controller_unittest.cc
+++ b/cc/animation/layer_animation_controller_unittest.cc
@@ -1848,12 +1848,11 @@
 
   controller->Animate(kInitialTickTime);
   controller->UpdateState(true, nullptr);
-  EXPECT_TRUE(dummy.animation_waiting_for_deletion());
-  EXPECT_EQ(Animation::WAITING_FOR_DELETION,
+  EXPECT_FALSE(dummy.animation_waiting_for_deletion());
+  EXPECT_EQ(Animation::ABORTED,
             controller->GetAnimation(Animation::OPACITY)->run_state());
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
-  controller_impl->ActivateAnimations();
   EXPECT_FALSE(controller->GetAnimationById(animation_id));
   EXPECT_FALSE(controller_impl->GetAnimationById(animation_id));
 }
diff --git a/cc/base/delayed_unique_notifier.h b/cc/base/delayed_unique_notifier.h
index 02051be..0e461fe 100644
--- a/cc/base/delayed_unique_notifier.h
+++ b/cc/base/delayed_unique_notifier.h
@@ -45,6 +45,8 @@
   // Returns true if a notification is currently scheduled to run.
   bool HasPendingNotification() const;
 
+  base::TimeDelta delay() const { return delay_; }
+
  protected:
   // Virtual for testing.
   virtual base::TimeTicks Now() const;
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index d98439c3..ddf3e8d 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -149,6 +149,7 @@
       'trees/occlusion_tracker_unittest.cc',
       'trees/occlusion_unittest.cc',
       'trees/property_tree_unittest.cc',
+      'trees/proxy_impl_unittest.cc',
       'trees/threaded_channel_unittest.cc',
       'trees/tree_synchronizer_unittest.cc',
     ],
@@ -173,6 +174,8 @@
       'test/begin_frame_source_test.h',
       'test/failure_output_surface.cc',
       'test/failure_output_surface.h',
+      'test/fake_channel_impl.cc',
+      'test/fake_channel_impl.h',
       'test/fake_content_layer_client.cc',
       'test/fake_content_layer_client.h',
       'test/fake_delegated_renderer_layer.cc',
diff --git a/cc/debug/micro_benchmark_controller_unittest.cc b/cc/debug/micro_benchmark_controller_unittest.cc
index 6494c866..a66d2dc 100644
--- a/cc/debug/micro_benchmark_controller_unittest.cc
+++ b/cc/debug/micro_benchmark_controller_unittest.cc
@@ -35,7 +35,7 @@
     layer_tree_host_->SetRootLayer(Layer::Create(LayerSettings()));
     layer_tree_host_->InitializeForTesting(
         TaskRunnerProvider::Create(nullptr, nullptr),
-        scoped_ptr<Proxy>(new FakeProxy));
+        scoped_ptr<Proxy>(new FakeProxy), nullptr);
   }
 
   void TearDown() override {
diff --git a/cc/layers/layer_position_constraint_unittest.cc b/cc/layers/layer_position_constraint_unittest.cc
index c1a33de..490ce8e2 100644
--- a/cc/layers/layer_position_constraint_unittest.cc
+++ b/cc/layers/layer_position_constraint_unittest.cc
@@ -77,7 +77,7 @@
         great_grand_child_impl_(nullptr) {
     layer_tree_host_->InitializeForTesting(
         TaskRunnerProvider::Create(nullptr, nullptr),
-        scoped_ptr<Proxy>(new FakeProxy));
+        scoped_ptr<Proxy>(new FakeProxy), nullptr);
     CreateTreeForTest();
     fixed_to_top_left_.set_is_fixed_position(true);
     fixed_to_bottom_right_.set_is_fixed_position(true);
diff --git a/cc/test/fake_channel_impl.cc b/cc/test/fake_channel_impl.cc
new file mode 100644
index 0000000..8b609d4a
--- /dev/null
+++ b/cc/test/fake_channel_impl.cc
@@ -0,0 +1,11 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/test/fake_channel_impl.h"
+
+namespace cc {
+
+FakeChannelImpl::FakeChannelImpl() {}
+
+}  // namespace cc
diff --git a/cc/test/fake_channel_impl.h b/cc/test/fake_channel_impl.h
new file mode 100644
index 0000000..32716ea
--- /dev/null
+++ b/cc/test/fake_channel_impl.h
@@ -0,0 +1,41 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TEST_FAKE_CHANNEL_IMPL_H_
+#define CC_TEST_FAKE_CHANNEL_IMPL_H_
+
+#include "base/macros.h"
+#include "cc/trees/channel_impl.h"
+
+namespace cc {
+
+class FakeChannelImpl : public ChannelImpl {
+ public:
+  FakeChannelImpl();
+
+  ~FakeChannelImpl() override {}
+
+  void DidCompleteSwapBuffers() override {}
+  void SetRendererCapabilitiesMainCopy(
+      const RendererCapabilities& capabilities) override {}
+  void BeginMainFrameNotExpectedSoon() override {}
+  void DidCommitAndDrawFrame() override {}
+  void SetAnimationEvents(scoped_ptr<AnimationEventsVector> queue) override {}
+  void DidLoseOutputSurface() override {}
+  void RequestNewOutputSurface() override {}
+  void DidInitializeOutputSurface(
+      bool success,
+      const RendererCapabilities& capabilities) override {}
+  void DidCompletePageScaleAnimation() override {}
+  void PostFrameTimingEventsOnMain(
+      scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
+      scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events)
+      override {}
+  void BeginMainFrame(scoped_ptr<BeginMainFrameAndCommitState>
+                          begin_main_frame_state) override {}
+};
+
+}  // namespace cc
+
+#endif  // CC_TEST_FAKE_CHANNEL_IMPL_H_
diff --git a/cc/test/fake_proxy.h b/cc/test/fake_proxy.h
index 7998625e..341d541 100644
--- a/cc/test/fake_proxy.h
+++ b/cc/test/fake_proxy.h
@@ -35,7 +35,8 @@
   void MainThreadHasStoppedFlinging() override {}
   bool BeginMainFrameRequested() const override;
   bool CommitRequested() const override;
-  void Start() override {}
+  void Start(
+      scoped_ptr<BeginFrameSource> external_begin_frame_source) override {}
   void Stop() override {}
   bool SupportsImplScrolling() const override;
   bool MainFrameWillHappenForTesting() override;
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index d68ec67..3234d45 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -99,30 +99,22 @@
 // various actions.
 class SingleThreadProxyForTest : public SingleThreadProxy {
  public:
-  static scoped_ptr<Proxy> Create(
-      TestHooks* test_hooks,
-      LayerTreeHost* host,
-      LayerTreeHostSingleThreadClient* client,
-      TaskRunnerProvider* task_runner_provider,
-      scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+  static scoped_ptr<Proxy> Create(TestHooks* test_hooks,
+                                  LayerTreeHost* host,
+                                  LayerTreeHostSingleThreadClient* client,
+                                  TaskRunnerProvider* task_runner_provider) {
     return make_scoped_ptr(new SingleThreadProxyForTest(
-        test_hooks, host, client, task_runner_provider,
-        std::move(external_begin_frame_source)));
+        test_hooks, host, client, task_runner_provider));
   }
 
   ~SingleThreadProxyForTest() override {}
 
  private:
-  SingleThreadProxyForTest(
-      TestHooks* test_hooks,
-      LayerTreeHost* host,
-      LayerTreeHostSingleThreadClient* client,
-      TaskRunnerProvider* task_runner_provider,
-      scoped_ptr<BeginFrameSource> external_begin_frame_source)
-      : SingleThreadProxy(host,
-                          client,
-                          task_runner_provider,
-                          std::move(external_begin_frame_source)),
+  SingleThreadProxyForTest(TestHooks* test_hooks,
+                           LayerTreeHost* host,
+                           LayerTreeHostSingleThreadClient* client,
+                           TaskRunnerProvider* task_runner_provider)
+      : SingleThreadProxy(host, client, task_runner_provider),
         test_hooks_(test_hooks) {}
 
   void ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) override {
@@ -457,16 +449,16 @@
     if (mode == CompositorMode::Threaded) {
       DCHECK(impl_task_runner.get());
       scoped_ptr<ProxyMain> proxy_main = ProxyMainForTest::CreateThreaded(
-          test_hooks, layer_tree_host.get(), task_runner_provider.get(),
-          std::move(external_begin_frame_source));
+          test_hooks, layer_tree_host.get(), task_runner_provider.get());
       proxy = std::move(proxy_main);
     } else {
-      proxy = SingleThreadProxyForTest::Create(
-          test_hooks, layer_tree_host.get(), client, task_runner_provider.get(),
-          std::move(external_begin_frame_source));
+      proxy =
+          SingleThreadProxyForTest::Create(test_hooks, layer_tree_host.get(),
+                                           client, task_runner_provider.get());
     }
-    layer_tree_host->InitializeForTesting(std::move(task_runner_provider),
-                                          std::move(proxy));
+    layer_tree_host->InitializeForTesting(
+        std::move(task_runner_provider), std::move(proxy),
+        std::move(external_begin_frame_source));
     return layer_tree_host;
   }
 
diff --git a/cc/test/proxy_impl_for_test.cc b/cc/test/proxy_impl_for_test.cc
index 3cd542b..457bb32 100644
--- a/cc/test/proxy_impl_for_test.cc
+++ b/cc/test/proxy_impl_for_test.cc
@@ -5,7 +5,7 @@
 #include "cc/test/proxy_impl_for_test.h"
 
 namespace cc {
-scoped_ptr<ProxyImpl> ProxyImplForTest::Create(
+scoped_ptr<ProxyImplForTest> ProxyImplForTest::Create(
     TestHooks* test_hooks,
     ChannelImpl* channel_impl,
     LayerTreeHost* layer_tree_host,
diff --git a/cc/test/proxy_impl_for_test.h b/cc/test/proxy_impl_for_test.h
index b81ece5..ce96154a 100644
--- a/cc/test/proxy_impl_for_test.h
+++ b/cc/test/proxy_impl_for_test.h
@@ -14,7 +14,7 @@
 // actions.
 class ProxyImplForTest : public ProxyImpl {
  public:
-  static scoped_ptr<ProxyImpl> Create(
+  static scoped_ptr<ProxyImplForTest> Create(
       TestHooks* test_hooks,
       ChannelImpl* channel_impl,
       LayerTreeHost* layer_tree_host,
@@ -28,6 +28,9 @@
 
   bool HasCommitCompletionEvent() const;
   bool GetNextCommitWaitsForActivation() const;
+  const DelayedUniqueNotifier& smoothness_priority_expiration_notifier() const {
+    return smoothness_priority_expiration_notifier_;
+  }
 
   ProxyImplForTest(TestHooks* test_hooks,
                    ChannelImpl* channel_impl,
diff --git a/cc/test/proxy_main_for_test.cc b/cc/test/proxy_main_for_test.cc
index 4588422e..dcac9a0 100644
--- a/cc/test/proxy_main_for_test.cc
+++ b/cc/test/proxy_main_for_test.cc
@@ -11,11 +11,9 @@
 scoped_ptr<ProxyMain> ProxyMainForTest::CreateThreaded(
     TestHooks* test_hooks,
     LayerTreeHost* host,
-    TaskRunnerProvider* task_runner_provider,
-    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+    TaskRunnerProvider* task_runner_provider) {
   scoped_ptr<ProxyMain> proxy_main(
-      new ProxyMainForTest(test_hooks, host, task_runner_provider,
-                           std::move(external_begin_frame_source)));
+      new ProxyMainForTest(test_hooks, host, task_runner_provider));
   proxy_main->SetChannel(ThreadedChannelForTest::Create(
       test_hooks, proxy_main.get(), task_runner_provider));
   return proxy_main;
@@ -23,15 +21,10 @@
 
 ProxyMainForTest::~ProxyMainForTest() {}
 
-ProxyMainForTest::ProxyMainForTest(
-    TestHooks* test_hooks,
-    LayerTreeHost* host,
-    TaskRunnerProvider* task_runner_provider,
-    scoped_ptr<BeginFrameSource> external_begin_frame_source)
-    : ProxyMain(host,
-                task_runner_provider,
-                std::move(external_begin_frame_source)),
-      test_hooks_(test_hooks) {}
+ProxyMainForTest::ProxyMainForTest(TestHooks* test_hooks,
+                                   LayerTreeHost* host,
+                                   TaskRunnerProvider* task_runner_provider)
+    : ProxyMain(host, task_runner_provider), test_hooks_(test_hooks) {}
 
 void ProxyMainForTest::SetNeedsUpdateLayers() {
   ProxyMain::SetNeedsUpdateLayers();
diff --git a/cc/test/proxy_main_for_test.h b/cc/test/proxy_main_for_test.h
index 1669cc5a..5631701 100644
--- a/cc/test/proxy_main_for_test.h
+++ b/cc/test/proxy_main_for_test.h
@@ -18,15 +18,13 @@
   static scoped_ptr<ProxyMain> CreateThreaded(
       TestHooks* test_hooks,
       LayerTreeHost* host,
-      TaskRunnerProvider* task_runner_provider,
-      scoped_ptr<BeginFrameSource> external_begin_frame_source);
+      TaskRunnerProvider* task_runner_provider);
 
   ~ProxyMainForTest() override;
 
   ProxyMainForTest(TestHooks* test_hooks,
                    LayerTreeHost* host,
-                   TaskRunnerProvider* task_runner_provider,
-                   scoped_ptr<BeginFrameSource> external_begin_frame_source);
+                   TaskRunnerProvider* task_runner_provider);
 
   void SetNeedsUpdateLayers() override;
   void DidCompleteSwapBuffers() override;
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 6ac4cd38..2ef633b 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -144,9 +144,9 @@
   task_runner_provider_ =
       TaskRunnerProvider::Create(main_task_runner, impl_task_runner);
   scoped_ptr<ProxyMain> proxy_main =
-      ProxyMain::CreateThreaded(this, task_runner_provider_.get(),
-                                std::move(external_begin_frame_source));
-  InitializeProxy(std::move(proxy_main));
+      ProxyMain::CreateThreaded(this, task_runner_provider_.get());
+  InitializeProxy(std::move(proxy_main),
+                  std::move(external_begin_frame_source));
 }
 
 void LayerTreeHost::InitializeSingleThreaded(
@@ -154,16 +154,18 @@
     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
     scoped_ptr<BeginFrameSource> external_begin_frame_source) {
   task_runner_provider_ = TaskRunnerProvider::Create(main_task_runner, nullptr);
-  InitializeProxy(SingleThreadProxy::Create(
-      this, single_thread_client, task_runner_provider_.get(),
-      std::move(external_begin_frame_source)));
+  InitializeProxy(SingleThreadProxy::Create(this, single_thread_client,
+                                            task_runner_provider_.get()),
+                  std::move(external_begin_frame_source));
 }
 
 void LayerTreeHost::InitializeForTesting(
     scoped_ptr<TaskRunnerProvider> task_runner_provider,
-    scoped_ptr<Proxy> proxy_for_testing) {
+    scoped_ptr<Proxy> proxy_for_testing,
+    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
   task_runner_provider_ = std::move(task_runner_provider);
-  InitializeProxy(std::move(proxy_for_testing));
+  InitializeProxy(std::move(proxy_for_testing),
+                  std::move(external_begin_frame_source));
 }
 
 void LayerTreeHost::SetTaskRunnerProviderForTesting(
@@ -172,11 +174,13 @@
   task_runner_provider_ = std::move(task_runner_provider);
 }
 
-void LayerTreeHost::InitializeProxy(scoped_ptr<Proxy> proxy) {
+void LayerTreeHost::InitializeProxy(
+    scoped_ptr<Proxy> proxy,
+    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
   TRACE_EVENT0("cc", "LayerTreeHost::InitializeForReal");
 
   proxy_ = std::move(proxy);
-  proxy_->Start();
+  proxy_->Start(std::move(external_begin_frame_source));
   if (settings_.accelerated_animation_enabled) {
     if (animation_host_)
       animation_host_->SetSupportsScrollAnimations(
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index 2dc93ee..e7e3318f 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -373,8 +373,10 @@
       LayerTreeHostSingleThreadClient* single_thread_client,
       scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
       scoped_ptr<BeginFrameSource> external_begin_frame_source);
-  void InitializeForTesting(scoped_ptr<TaskRunnerProvider> task_runner_provider,
-                            scoped_ptr<Proxy> proxy_for_testing);
+  void InitializeForTesting(
+      scoped_ptr<TaskRunnerProvider> task_runner_provider,
+      scoped_ptr<Proxy> proxy_for_testing,
+      scoped_ptr<BeginFrameSource> external_begin_frame_source);
   void SetOutputSurfaceLostForTesting(bool is_lost) {
     output_surface_lost_ = is_lost;
   }
@@ -399,7 +401,9 @@
   void RecordGpuRasterizationHistogram();
 
  private:
-  void InitializeProxy(scoped_ptr<Proxy> proxy);
+  void InitializeProxy(
+      scoped_ptr<Proxy> proxy,
+      scoped_ptr<BeginFrameSource> external_begin_frame_source);
 
   bool DoUpdateLayers(Layer* root_layer);
   void UpdateHudLayer();
diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h
index 132a4ff6..5798fa8 100644
--- a/cc/trees/proxy.h
+++ b/cc/trees/proxy.h
@@ -16,6 +16,7 @@
 #include "base/values.h"
 #include "cc/base/cc_export.h"
 #include "cc/input/top_controls_state.h"
+#include "cc/scheduler/begin_frame_source.h"
 #include "cc/trees/task_runner_provider.h"
 
 namespace gfx {
@@ -24,6 +25,7 @@
 }
 
 namespace cc {
+class BeginFrameSource;
 class LayerTreeDebugState;
 class OutputSurface;
 struct RendererCapabilities;
@@ -69,7 +71,8 @@
   virtual bool BeginMainFrameRequested() const = 0;
 
   // Must be called before using the proxy.
-  virtual void Start() = 0;
+  virtual void Start(
+      scoped_ptr<BeginFrameSource> external_begin_frame_source) = 0;
   virtual void Stop() = 0;   // Must be called before deleting the proxy.
 
   virtual bool SupportsImplScrolling() const = 0;
diff --git a/cc/trees/proxy_impl.cc b/cc/trees/proxy_impl.cc
index 810e73e..0ba4cc23 100644
--- a/cc/trees/proxy_impl.cc
+++ b/cc/trees/proxy_impl.cc
@@ -57,7 +57,7 @@
       smoothness_priority_expiration_notifier_(
           task_runner_provider->ImplThreadTaskRunner(),
           base::Bind(&ProxyImpl::RenewTreePriority, base::Unretained(this)),
-          base::TimeDelta::FromSeconds(
+          base::TimeDelta::FromSecondsD(
               kSmoothnessTakesPriorityExpirationDelay)),
       external_begin_frame_source_(std::move(external_begin_frame_source)),
       rendering_stats_instrumentation_(
diff --git a/cc/trees/proxy_impl_unittest.cc b/cc/trees/proxy_impl_unittest.cc
new file mode 100644
index 0000000..ad99d53
--- /dev/null
+++ b/cc/trees/proxy_impl_unittest.cc
@@ -0,0 +1,60 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/test/fake_channel_impl.h"
+#include "cc/test/fake_layer_tree_host.h"
+#include "cc/test/fake_layer_tree_host_client.h"
+#include "cc/test/proxy_impl_for_test.h"
+#include "cc/test/test_hooks.h"
+#include "cc/test/test_task_graph_runner.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+
+class ProxyImplTest : public testing::Test, public TestHooks {
+ public:
+  ~ProxyImplTest() override {
+    DebugScopedSetImplThreadAndMainThreadBlocked impl_and_main_blocked(
+        task_runner_provider_);
+    proxy_impl_.reset();
+  }
+
+  void RequestNewOutputSurface() override {}
+
+ protected:
+  ProxyImplTest()
+      : host_client_(FakeLayerTreeHostClient::DIRECT_3D),
+        task_runner_provider_(nullptr) {}
+
+  void Initialize(CompositorMode mode) {
+    layer_tree_host_ = FakeLayerTreeHost::Create(
+        &host_client_, &task_graph_runner_, settings_, mode);
+    task_runner_provider_ = layer_tree_host_->task_runner_provider();
+    {
+      DebugScopedSetImplThreadAndMainThreadBlocked impl_and_main_blocked(
+          task_runner_provider_);
+      proxy_impl_ =
+          ProxyImplForTest::Create(this, &channel_impl_, layer_tree_host_.get(),
+                                   task_runner_provider_, nullptr);
+    }
+  }
+
+  TestTaskGraphRunner task_graph_runner_;
+  LayerTreeSettings settings_;
+  FakeLayerTreeHostClient host_client_;
+  FakeChannelImpl channel_impl_;
+  TaskRunnerProvider* task_runner_provider_;
+  scoped_ptr<ProxyImplForTest> proxy_impl_;
+  scoped_ptr<FakeLayerTreeHost> layer_tree_host_;
+};
+
+// This is a regression test. See crbug/568120.
+TEST_F(ProxyImplTest, NonZeroSmoothnessPriorityExpiration) {
+  Initialize(CompositorMode::Threaded);
+  DebugScopedSetImplThread impl_thread(task_runner_provider_);
+  EXPECT_FALSE(
+      proxy_impl_->smoothness_priority_expiration_notifier().delay().is_zero());
+}
+
+}  // namespace cc
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc
index dd5ac1a..1b06367e 100644
--- a/cc/trees/proxy_main.cc
+++ b/cc/trees/proxy_main.cc
@@ -23,19 +23,16 @@
 
 scoped_ptr<ProxyMain> ProxyMain::CreateThreaded(
     LayerTreeHost* layer_tree_host,
-    TaskRunnerProvider* task_runner_provider,
-    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+    TaskRunnerProvider* task_runner_provider) {
   scoped_ptr<ProxyMain> proxy_main(
-      new ProxyMain(layer_tree_host, task_runner_provider,
-                    std::move(external_begin_frame_source)));
+      new ProxyMain(layer_tree_host, task_runner_provider));
   proxy_main->SetChannel(
       ThreadedChannel::Create(proxy_main.get(), task_runner_provider));
   return proxy_main;
 }
 
 ProxyMain::ProxyMain(LayerTreeHost* layer_tree_host,
-                     TaskRunnerProvider* task_runner_provider,
-                     scoped_ptr<BeginFrameSource> external_begin_frame_source)
+                     TaskRunnerProvider* task_runner_provider)
     : layer_tree_host_(layer_tree_host),
       task_runner_provider_(task_runner_provider),
       layer_tree_host_id_(layer_tree_host->id()),
@@ -44,13 +41,10 @@
       final_pipeline_stage_(NO_PIPELINE_STAGE),
       commit_waits_for_activation_(false),
       started_(false),
-      defer_commits_(false),
-      external_begin_frame_source_(std::move(external_begin_frame_source)) {
+      defer_commits_(false) {
   TRACE_EVENT0("cc", "ProxyMain::ProxyMain");
   DCHECK(task_runner_provider_);
   DCHECK(IsMainThread());
-  DCHECK(!layer_tree_host_->settings().use_external_begin_frame_source ||
-         external_begin_frame_source_);
 }
 
 ProxyMain::~ProxyMain() {
@@ -380,14 +374,17 @@
   channel_main_->MainThreadHasStoppedFlingingOnImpl();
 }
 
-void ProxyMain::Start() {
+void ProxyMain::Start(
+    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
   DCHECK(IsMainThread());
   DCHECK(task_runner_provider_->HasImplThread());
   DCHECK(channel_main_);
+  DCHECK(!layer_tree_host_->settings().use_external_begin_frame_source ||
+         external_begin_frame_source);
 
   // Create LayerTreeHostImpl.
   channel_main_->SynchronouslyInitializeImpl(
-      layer_tree_host_, std::move(external_begin_frame_source_));
+      layer_tree_host_, std::move(external_begin_frame_source));
 
   started_ = true;
 }
diff --git a/cc/trees/proxy_main.h b/cc/trees/proxy_main.h
index edc2a22..bb510b8 100644
--- a/cc/trees/proxy_main.h
+++ b/cc/trees/proxy_main.h
@@ -28,8 +28,7 @@
  public:
   static scoped_ptr<ProxyMain> CreateThreaded(
       LayerTreeHost* layer_tree_host,
-      TaskRunnerProvider* task_runner_provider,
-      scoped_ptr<BeginFrameSource> external_begin_frame_source);
+      TaskRunnerProvider* task_runner_provider);
 
   ~ProxyMain() override;
 
@@ -75,8 +74,7 @@
 
  protected:
   ProxyMain(LayerTreeHost* layer_tree_host,
-            TaskRunnerProvider* task_runner_provider,
-            scoped_ptr<BeginFrameSource> external_begin_frame_source);
+            TaskRunnerProvider* task_runner_provider);
 
  private:
   friend class ProxyMainForTest;
@@ -99,7 +97,7 @@
   bool CommitRequested() const override;
   bool BeginMainFrameRequested() const override;
   void MainThreadHasStoppedFlinging() override;
-  void Start() override;
+  void Start(scoped_ptr<BeginFrameSource> external_begin_frame_source) override;
   void Stop() override;
   bool SupportsImplScrolling() const override;
   bool MainFrameWillHappenForTesting() override;
@@ -145,12 +143,6 @@
 
   RendererCapabilities renderer_capabilities_;
 
-  // This holds a valid value only until ProxyImpl is created on the impl thread
-  // with InitializeImplOnImpl().
-  // TODO(khushalsagar): Remove the use of this temporary variable.
-  // See crbug/567930.
-  scoped_ptr<BeginFrameSource> external_begin_frame_source_;
-
   scoped_ptr<ChannelMain> channel_main_;
 
   DISALLOW_COPY_AND_ASSIGN(ProxyMain);
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index c8e5829..cb669ab 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -25,22 +25,17 @@
 scoped_ptr<Proxy> SingleThreadProxy::Create(
     LayerTreeHost* layer_tree_host,
     LayerTreeHostSingleThreadClient* client,
-    TaskRunnerProvider* task_runner_provider,
-    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+    TaskRunnerProvider* task_runner_provider) {
   return make_scoped_ptr(
-      new SingleThreadProxy(layer_tree_host, client, task_runner_provider,
-                            std::move(external_begin_frame_source)));
+      new SingleThreadProxy(layer_tree_host, client, task_runner_provider));
 }
 
-SingleThreadProxy::SingleThreadProxy(
-    LayerTreeHost* layer_tree_host,
-    LayerTreeHostSingleThreadClient* client,
-    TaskRunnerProvider* task_runner_provider,
-    scoped_ptr<BeginFrameSource> external_begin_frame_source)
+SingleThreadProxy::SingleThreadProxy(LayerTreeHost* layer_tree_host,
+                                     LayerTreeHostSingleThreadClient* client,
+                                     TaskRunnerProvider* task_runner_provider)
     : layer_tree_host_(layer_tree_host),
       client_(client),
       task_runner_provider_(task_runner_provider),
-      external_begin_frame_source_(std::move(external_begin_frame_source)),
       next_frame_is_newly_committed_frame_(false),
 #if DCHECK_IS_ON()
       inside_impl_frame_(false),
@@ -56,17 +51,23 @@
   DCHECK(task_runner_provider_);
   DCHECK(task_runner_provider_->IsMainThread());
   DCHECK(layer_tree_host);
+}
 
-  if (layer_tree_host->settings().single_thread_proxy_scheduler &&
+void SingleThreadProxy::Start(
+    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+  DebugScopedSetImplThread impl(task_runner_provider_);
+  external_begin_frame_source_ = std::move(external_begin_frame_source);
+
+  if (layer_tree_host_->settings().single_thread_proxy_scheduler &&
       !scheduler_on_impl_thread_) {
     SchedulerSettings scheduler_settings(
-        layer_tree_host->settings().ToSchedulerSettings());
+        layer_tree_host_->settings().ToSchedulerSettings());
     scheduler_settings.commit_to_active_tree = CommitToActiveTree();
 
     scoped_ptr<CompositorTimingHistory> compositor_timing_history(
         new CompositorTimingHistory(
             CompositorTimingHistory::BROWSER_UMA,
-            layer_tree_host->rendering_stats_instrumentation()));
+            layer_tree_host_->rendering_stats_instrumentation()));
 
     scheduler_on_impl_thread_ =
         Scheduler::Create(this, scheduler_settings, layer_tree_host_->id(),
@@ -74,10 +75,7 @@
                           external_begin_frame_source_.get(),
                           std::move(compositor_timing_history));
   }
-}
 
-void SingleThreadProxy::Start() {
-  DebugScopedSetImplThread impl(task_runner_provider_);
   layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
 }
 
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index a60f7139..2275106c 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -28,11 +28,9 @@
                                     NON_EXPORTED_BASE(LayerTreeHostImplClient),
                                     SchedulerClient {
  public:
-  static scoped_ptr<Proxy> Create(
-      LayerTreeHost* layer_tree_host,
-      LayerTreeHostSingleThreadClient* client,
-      TaskRunnerProvider* task_runner_provider_,
-      scoped_ptr<BeginFrameSource> external_begin_frame_source);
+  static scoped_ptr<Proxy> Create(LayerTreeHost* layer_tree_host,
+                                  LayerTreeHostSingleThreadClient* client,
+                                  TaskRunnerProvider* task_runner_provider_);
   ~SingleThreadProxy() override;
 
   // Proxy implementation
@@ -54,7 +52,7 @@
   bool CommitRequested() const override;
   bool BeginMainFrameRequested() const override;
   void MainThreadHasStoppedFlinging() override {}
-  void Start() override;
+  void Start(scoped_ptr<BeginFrameSource> external_begin_frame_source) override;
   void Stop() override;
   bool SupportsImplScrolling() const override;
   bool MainFrameWillHappenForTesting() override;
@@ -120,8 +118,7 @@
  protected:
   SingleThreadProxy(LayerTreeHost* layer_tree_host,
                     LayerTreeHostSingleThreadClient* client,
-                    TaskRunnerProvider* task_runner_provider,
-                    scoped_ptr<BeginFrameSource> external_begin_frame_source);
+                    TaskRunnerProvider* task_runner_provider);
 
  private:
   void BeginMainFrame(const BeginFrameArgs& begin_frame_args);
diff --git a/chrome/VERSION b/chrome/VERSION
index ecc59cf..e610619 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=49
 MINOR=0
-BUILD=2593
+BUILD=2594
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java
index 99e3218..6913308 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java
@@ -6,6 +6,7 @@
 
 import android.app.Activity;
 import android.content.Context;
+import android.view.View.MeasureSpec;
 
 import org.chromium.base.ActivityState;
 import org.chromium.base.ApplicationStatus;
@@ -17,6 +18,7 @@
 import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
 import org.chromium.chrome.browser.compositor.scene_layer.SceneLayer;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.content.browser.ContentViewClient;
 import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content_public.common.TopControlsState;
 import org.chromium.ui.base.LocalizationUtils;
@@ -308,12 +310,36 @@
     }
 
     /**
+     * Add any other objects that depend on the OverlayPanelContent having already been created.
+     */
+    private OverlayPanelContent createNewOverlayPanelContentInternal() {
+        OverlayPanelContent content = mContentFactory.createNewOverlayPanelContent();
+        // Adds a ContentViewClient to override the default fullscreen size.
+        content.setContentViewClient(new ContentViewClient() {
+            @Override
+            public int getDesiredWidthMeasureSpec() {
+                return MeasureSpec.makeMeasureSpec(
+                        getSearchContentViewWidthPx(),
+                        MeasureSpec.EXACTLY);
+            }
+
+            @Override
+            public int getDesiredHeightMeasureSpec() {
+                return MeasureSpec.makeMeasureSpec(
+                        getSearchContentViewHeightPx(),
+                        MeasureSpec.EXACTLY);
+            }
+        });
+        return content;
+    }
+
+    /**
      * @return A new OverlayPanelContent if the instance was null or the existing one.
      */
     protected OverlayPanelContent getOverlayPanelContent() {
         // Only create the content when necessary
         if (mContent == null) {
-            mContent = mContentFactory.createNewOverlayPanelContent();
+            mContent = createNewOverlayPanelContentInternal();
         }
         return mContent;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
index 3be5c5f..46e722b1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
@@ -7,7 +7,6 @@
 import android.app.Activity;
 import android.content.Context;
 import android.os.Handler;
-import android.view.View.MeasureSpec;
 
 import org.chromium.base.ActivityState;
 import org.chromium.base.VisibleForTesting;
@@ -21,7 +20,6 @@
 import org.chromium.chrome.browser.compositor.scene_layer.SceneLayer;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchManagementDelegate;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
-import org.chromium.content.browser.ContentViewClient;
 import org.chromium.ui.resources.ResourceManager;
 
 /**
@@ -77,31 +75,8 @@
 
     @Override
     public OverlayPanelContent createNewOverlayPanelContent() {
-        OverlayPanelContent overlayPanelContent = new OverlayPanelContent(
-                mManagementDelegate.getOverlayContentDelegate(),
-                new PanelProgressObserver(),
-                mActivity);
-
-        // Adds a ContentViewClient to override the default fullscreen size.
-        if (!isFullscreenSizePanel()) {
-            overlayPanelContent.setContentViewClient(new ContentViewClient() {
-                @Override
-                public int getDesiredWidthMeasureSpec() {
-                    return MeasureSpec.makeMeasureSpec(
-                            getSearchContentViewWidthPx(),
-                            MeasureSpec.EXACTLY);
-                }
-
-                @Override
-                public int getDesiredHeightMeasureSpec() {
-                    return MeasureSpec.makeMeasureSpec(
-                            getSearchContentViewHeightPx(),
-                            MeasureSpec.EXACTLY);
-                }
-            });
-        }
-
-        return overlayPanelContent;
+        return new OverlayPanelContent(mManagementDelegate.getOverlayContentDelegate(),
+                new PanelProgressObserver(), mActivity);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/readermode/ReaderModePanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/readermode/ReaderModePanel.java
index 6fb41dfe..732ca69 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/readermode/ReaderModePanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/readermode/ReaderModePanel.java
@@ -31,26 +31,24 @@
  */
 public class ReaderModePanel extends OverlayPanel {
 
-    /**
-     * The compositor layer used for drawing the panel.
-     */
+    /** The compositor layer used for drawing the panel. */
     private ContextualSearchSceneLayer mSceneLayer;
 
-    /**
-     * Delegate for calling functions on the ReaderModeManager.
-     */
+    /** Delegate for calling functions on the ReaderModeManager. */
     private ReaderModeManagerDelegate mManagerDelegate;
 
-    /**
-     * Delegate for passing the current ContentViewCore to the layout manager.
-     */
+    /** Delegate for passing the current ContentViewCore to the layout manager. */
     private OverlayPanelContentViewDelegate mContentViewDelegate;
 
-    /**
-     * The opacity of the panel bar text.
-     */
+    /** The opacity of the panel bar text. */
     private float mReaderBarTextOpacity;
 
+    /** If the timer for counting how long a user has been reading is running. */
+    private boolean mTimerRunning;
+
+    /** The start time in ms of the current timer. */
+    private long mStartTime;
+
     // ============================================================================================
     // Constructor
     // ============================================================================================
@@ -250,6 +248,38 @@
     }
 
     @Override
+    protected void onAnimationFinished() {
+        super.onAnimationFinished();
+        boolean animatingToOpenState = getPanelState() == PanelState.EXPANDED
+                || getPanelState() == PanelState.MAXIMIZED;
+        // Start or stop the timer for how long the user has been reading.
+        if (!mTimerRunning && animatingToOpenState) {
+            mStartTime = System.currentTimeMillis();
+            mTimerRunning = true;
+        } else if (mTimerRunning && !animatingToOpenState) {
+            onTimerEnded();
+        }
+    }
+
+    @Override
+    public void closePanel(StateChangeReason reason, boolean animate) {
+        super.closePanel(reason, animate);
+        if (mTimerRunning) {
+            onTimerEnded();
+        }
+    }
+
+    /**
+     * Record the time spent in Reader Mode.
+     */
+    private void onTimerEnded() {
+        mTimerRunning = false;
+        long totalTime = System.currentTimeMillis() - mStartTime;
+        if (mStartTime <= 0 || totalTime < 0) return;
+        mManagerDelegate.recordTimeSpentInReader(totalTime);
+    }
+
+    @Override
     public float getArrowIconOpacity() {
         // TODO(mdjones): This will not be needed once Reader Mode has its own scene layer.
         // Never show the arrow icon.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index 7a1339f3..798c4716 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -37,8 +37,11 @@
 import org.chromium.chrome.browser.rappor.RapporServiceBridge;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabIdManager;
-import org.chromium.chrome.browser.tabmodel.SingleTabModelSelector;
+import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
+import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
+import org.chromium.chrome.browser.tabmodel.TabModelObserver;
+import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl;
 import org.chromium.chrome.browser.toolbar.ToolbarControlContainer;
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.browser.util.IntentUtils;
@@ -55,7 +58,6 @@
     private static final String TAG = "CustomTabActivity";
     private static CustomTabContentHandler sActiveContentHandler;
 
-    private Tab mTab;
     private FindToolbarManager mFindToolbarManager;
     private CustomTabIntentDataProvider mIntentDataProvider;
     private IBinder mSession;
@@ -71,6 +73,24 @@
     private boolean mShouldReplaceCurrentEntry;
     private CustomTabObserver mTabObserver;
 
+    // Only the normal tab model is observed because there is no icognito tabmodel in Custom Tabs.
+    private TabModelObserver mTabModelObserver = new EmptyTabModelObserver() {
+        @Override
+        public void didAddTab(Tab tab, TabLaunchType type) {
+            if (mTabObserver == null) {
+                mTabObserver = new CustomTabObserver(getApplication(), mSession);
+            }
+            tab.addObserver(mTabObserver);
+        }
+
+        @Override
+        public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
+            // TODO(ianwen): If the user selects an background tab by keyboard
+            // shortcuts, close all tabs that are above the selected tab.
+            // http://crbug.com/500058
+        }
+    };
+
     /**
      * Sets the currently active {@link CustomTabContentHandler} in focus.
      * @param contentHandler {@link CustomTabContentHandler} to set.
@@ -142,16 +162,7 @@
     @Override
     public void preInflationStartup() {
         super.preInflationStartup();
-        setTabModelSelector(new SingleTabModelSelector(this, false, true) {
-            @Override
-            public Tab openNewTab(LoadUrlParams loadUrlParams, TabLaunchType type, Tab parent,
-                    boolean incognito) {
-                // A custom tab either loads a url or starts an external activity to handle the url.
-                // It never opens a new tab/chrome activity.
-                mTab.loadUrl(loadUrlParams);
-                return mTab;
-            }
-        });
+
         mIntentDataProvider = new CustomTabIntentDataProvider(getIntent(), this);
         supportRequestWindowFeature(Window.FEATURE_ACTION_MODE_OVERLAY);
     }
@@ -159,6 +170,7 @@
     @Override
     public void postInflationStartup() {
         super.postInflationStartup();
+        setTabModelSelector(new TabModelSelectorImpl(this, 0, getWindowAndroid(), false));
         getToolbarManager().setCloseButtonDrawable(mIntentDataProvider.getCloseButtonDrawable());
         getToolbarManager().setShowTitle(mIntentDataProvider.getTitleVisibilityState()
                 == CustomTabIntentDataProvider.SHOW_PAGE_TITLE);
@@ -183,12 +195,13 @@
         if (IntentHandler.getExtraHeadersFromIntent(getIntent()) != null) {
             CustomTabsConnection.getInstance(getApplication()).cancelPrerender(mSession);
         }
-        createTab();
-        getTabModelSelector().setTab(mTab);
+        Tab mainTab = createMainTab();
+        getTabModelSelector().getModel(false).addObserver(mTabModelObserver);
+        getTabModelSelector().getModel(false).addTab(mainTab, 0, mainTab.getLaunchType());
 
         ToolbarControlContainer controlContainer = (ToolbarControlContainer) findViewById(
                 R.id.control_container);
-        LayoutManagerDocument layoutDriver = new LayoutManagerDocument(getCompositorViewHolder());
+        LayoutManagerDocument layoutDriver = new CustomTabLayoutManager(getCompositorViewHolder());
         initializeCompositorContent(layoutDriver, findViewById(R.id.url_bar),
                 (ViewGroup) findViewById(android.R.id.content), controlContainer);
         mFindToolbarManager = new FindToolbarManager(this, getTabModelSelector(),
@@ -205,7 +218,7 @@
                     }
                 });
 
-        mTab.setFullscreenManager(getFullscreenManager());
+        mainTab.setFullscreenManager(getFullscreenManager());
         mCustomTabContentHandler = new CustomTabContentHandler() {
             @Override
             public void loadUrlAndTrackFromTimestamp(LoadUrlParams params, long timestamp) {
@@ -228,7 +241,7 @@
                 return showActionButton();
             }
         };
-        DataUseTabUIManager.onCustomTabInitialNavigation(mTab,
+        DataUseTabUIManager.onCustomTabInitialNavigation(mainTab,
                 CustomTabsConnection.getInstance(getApplication())
                         .getClientPackageNameForSession(mSession),
                 IntentHandler.getUrlFromIntent(getIntent()));
@@ -238,7 +251,7 @@
         super.finishNativeInitialization();
     }
 
-    private void createTab() {
+    private Tab createMainTab() {
         String url = IntentHandler.getUrlFromIntent(getIntent());
         // Get any referrer that has been explicitly set by the app.
         String referrerUrl = IntentHandler.getReferrerUrlIncludingExtraHeaders(getIntent(), this);
@@ -247,7 +260,7 @@
                     .getReferrerForSession(mSession);
             if (referrer != null) referrerUrl = referrer.getUrl();
         }
-        mTab = new Tab(TabIdManager.getInstance().generateValidId(Tab.INVALID_TAB_ID),
+        Tab tab = new Tab(TabIdManager.getInstance().generateValidId(Tab.INVALID_TAB_ID),
                 Tab.INVALID_TAB_ID, false, this, getWindowAndroid(),
                 TabLaunchType.FROM_EXTERNAL_APP, null, null) {
             @Override
@@ -269,11 +282,16 @@
         if (webContents == null) {
             webContents = WebContentsFactory.createWebContents(false, false);
         }
-        mTab.initialize(webContents, getTabContentManager(),
-                new CustomTabDelegateFactory(getApplication(), mSession), false, false);
-        mTab.getView().requestFocus();
-        mTabObserver = new CustomTabObserver(getApplication(), mSession);
-        mTab.addObserver(mTabObserver);
+        tab.initialize(webContents, getTabContentManager(), new CustomTabDelegateFactory(), false,
+                false);
+        tab.getView().requestFocus();
+        return tab;
+    }
+
+    @Override
+    public void initializeCompositor() {
+        super.initializeCompositor();
+        getTabModelSelector().onNativeLibraryReady(getTabContentManager());
     }
 
     private void recordClientPackageName() {
@@ -319,15 +337,6 @@
     }
 
     /**
-     * @see org.chromium.chrome.browser.ChromeActivity#onDestroyInternal()
-     */
-    @Override
-    protected void onDestroyInternal() {
-        mTab.removeObserver(mTabObserver);
-        super.onDestroyInternal();
-    }
-
-    /**
      * Loads the current tab with the given load params while taking client
      * referrer and extra headers into account.
      */
@@ -341,18 +350,18 @@
         mTabObserver.trackNextPageLoadFromTimestamp(timeStamp);
         if (mShouldReplaceCurrentEntry) params.setShouldReplaceCurrentEntry(true);
         mShouldReplaceCurrentEntry = false;
-        mTab.loadUrl(params);
+        getActivityTab().loadUrl(params);
     }
 
     @Override
     public void createContextualSearchTab(String searchUrl) {
-        if (mTab == null) return;
-        mTab.loadUrl(new LoadUrlParams(searchUrl));
+        if (getActivityTab() == null) return;
+        getActivityTab().loadUrl(new LoadUrlParams(searchUrl));
     }
 
     @Override
-    public SingleTabModelSelector getTabModelSelector() {
-        return (SingleTabModelSelector) super.getTabModelSelector();
+    public TabModelSelectorImpl getTabModelSelector() {
+        return (TabModelSelectorImpl) super.getTabModelSelector();
     }
 
     @Override
@@ -394,14 +403,16 @@
 
     @Override
     protected boolean handleBackPressed() {
-        if (mTab == null) return false;
+        if (getActivityTab() == null) return false;
 
         if (exitFullscreenIfShowing()) return true;
 
-        if (mTab.canGoBack()) {
-            mTab.goBack();
-        } else {
-            finish();
+        if (!getToolbarManager().back()) {
+            if (getCurrentTabModel().getCount() > 1) {
+                getCurrentTabModel().closeTab(getActivityTab(), false, false, false);
+            } else {
+                finish();
+            }
         }
         return true;
     }
@@ -420,7 +431,7 @@
                     @Override
                     public void onClick(View v) {
                         mIntentDataProvider.sendButtonPendingIntentWithUrl(
-                                getApplicationContext(), mTab.getUrl());
+                                getApplicationContext(), getActivityTab().getUrl());
                         RecordUserAction.record("CustomTabsCustomActionButtonClick");
                     }
                 });
@@ -429,7 +440,7 @@
 
     @Override
     public boolean shouldShowAppMenu() {
-        return mTab != null && getToolbarManager().isInitialized();
+        return getActivityTab() != null && getToolbarManager().isInitialized();
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java
index 96a7e69..031a48d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java
@@ -4,12 +4,8 @@
 
 package org.chromium.chrome.browser.customtabs;
 
-import android.app.Application;
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
-import android.graphics.Rect;
-import android.os.IBinder;
-import android.os.SystemClock;
 import android.os.TransactionTooLargeException;
 
 import org.chromium.base.Log;
@@ -26,8 +22,6 @@
 import org.chromium.chrome.browser.tab.TabDelegateFactory;
 import org.chromium.chrome.browser.tab.TabWebContentsDelegateAndroid;
 import org.chromium.chrome.browser.util.UrlUtilities;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.browser.WebContents;
 
 /**
  * A {@link TabDelegateFactory} class to be used in all {@link Tab} owned
@@ -112,8 +106,6 @@
     }
 
     private static class CustomTabWebContentsDelegate extends TabWebContentsDelegateAndroid {
-        private String mTargetUrl;
-
         /**
          * See {@link TabWebContentsDelegateAndroid}.
          */
@@ -127,41 +119,13 @@
         }
 
         @Override
-        public void webContentsCreated(WebContents sourceWebContents, long openerRenderFrameId,
-                String frameName, String targetUrl, WebContents newWebContents) {
-            super.webContentsCreated(
-                    sourceWebContents, openerRenderFrameId, frameName, targetUrl,
-                    newWebContents);
-            mTargetUrl = targetUrl;
-        }
-
-        @Override
-        public boolean addNewContents(WebContents sourceWebContents, WebContents webContents,
-                int disposition, Rect initialPosition, boolean userGesture) {
-            assert mTargetUrl != null;
-            ((CustomTabActivity) mActivity).loadUrlInCurrentTab(
-                    new LoadUrlParams(mTargetUrl), SystemClock.elapsedRealtime());
-            mTargetUrl = null;
-            return false;
-        }
-
-        @Override
         protected void bringActivityToForeground() {
             // No-op here. If client's task is in background Chrome is unable to foreground it.
         }
     }
 
-    private final Application mApplication;
-    private final IBinder mSession;
     private CustomTabNavigationDelegate mNavigationDelegate;
     private ExternalNavigationHandler mNavigationHandler;
-    private CustomTabObserver mTabObserver;
-
-    public CustomTabDelegateFactory(Application application, IBinder session) {
-        super();
-        mApplication = application;
-        mSession = session;
-    }
 
     @Override
     public TabWebContentsDelegateAndroid createWebContentsDelegate(Tab tab,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabLayoutManager.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabLayoutManager.java
new file mode 100644
index 0000000..faa821df
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabLayoutManager.java
@@ -0,0 +1,59 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.customtabs;
+
+import android.view.ViewGroup;
+
+import org.chromium.chrome.browser.compositor.layouts.LayoutManagerDocument;
+import org.chromium.chrome.browser.compositor.layouts.LayoutManagerHost;
+import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchManagementDelegate;
+import org.chromium.chrome.browser.dom_distiller.ReaderModeManagerDelegate;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
+import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
+import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
+import org.chromium.chrome.browser.tabmodel.TabModelObserver;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tabmodel.TabModelUtils;
+import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
+
+/**
+ * A simple {@link LayoutManager} that shows multiple tabs without animation.
+ */
+public class CustomTabLayoutManager extends LayoutManagerDocument {
+
+    TabModelObserver mTabModelObserver = new EmptyTabModelObserver() {
+        @Override
+        public void didAddTab(Tab tab, TabLaunchType type) {
+            int newIndex = TabModelUtils.getTabIndexById(getTabModelSelector().getModel(false),
+                    tab.getId());
+            getActiveLayout().onTabCreated(time(), tab.getId(), newIndex,
+                    getTabModelSelector().getCurrentTabId(), false, false, 0f, 0f);
+        }
+
+        @Override
+        public void didCloseTab(Tab tab) {
+            getActiveLayout().onTabSelected(time(), getTabModelSelector().getCurrentTabId(),
+                    tab.getId(), false);
+        }
+    };
+
+    public CustomTabLayoutManager(LayoutManagerHost host) {
+        super(host);
+    }
+
+    @Override
+    public void init(TabModelSelector selector, TabCreatorManager creator,
+            TabContentManager content, ViewGroup androidContentContainer,
+            ContextualSearchManagementDelegate contextualSearchDelegate,
+            ReaderModeManagerDelegate readerModeDelegate,
+            DynamicResourceLoader dynamicResourceLoader) {
+        super.init(selector, creator, content, androidContentContainer, contextualSearchDelegate,
+                readerModeDelegate, dynamicResourceLoader);
+        for (TabModel model : selector.getModels()) model.addObserver(mTabModelObserver);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
index 2f1ab7b..18fa6402 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
@@ -14,6 +14,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.PanelState;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
 import org.chromium.chrome.browser.compositor.bottombar.readermode.ReaderModePanel;
 import org.chromium.chrome.browser.infobar.InfoBar;
@@ -34,6 +35,7 @@
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Manages UI effects for reader mode including hiding and showing the
@@ -276,7 +278,10 @@
 
     @Override
     public void onCloseButtonPressed() {
-        // TODO(mdjones): Add user metrics for using the close button in the panel bar here.
+        if (mReaderModePanel == null) return;
+        RecordHistogram.recordBooleanHistogram("DomDistiller.BarCloseButtonUsage",
+                mReaderModePanel.getPanelState() == PanelState.EXPANDED
+                || mReaderModePanel.getPanelState() == PanelState.MAXIMIZED);
         // TODO(mdjones): If it is decided that Reader Mode cannot be permanently dismissed for a
         // tab, remove that remaining logic from this class.
     }
@@ -295,6 +300,12 @@
         mReaderModePanel.closePanel(reason, animate);
     }
 
+    @Override
+    public void recordTimeSpentInReader(long timeMs) {
+        RecordHistogram.recordLongTimesHistogram("DomDistiller.Time.ViewingReaderModePanel",
+                timeMs, TimeUnit.MILLISECONDS);
+    }
+
     protected WebContentsObserver createWebContentsObserver(WebContents webContents) {
         final int readerTabId = mTabModelSelector.getCurrentTabId();
         if (readerTabId == Tab.INVALID_TAB_ID) return null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerDelegate.java
index 62fe19e..645eb026 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerDelegate.java
@@ -57,4 +57,10 @@
      * @return The ChromeActivity that owns the manager.
      */
     ChromeActivity getChromeActivity();
+
+    /**
+     * Record the amount of time that a user spent in the Reader Mode panel.
+     * @param timeInMs The amount of time spent in ms.
+     */
+    void recordTimeSpentInReader(long timeInMs);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
index d3b6c57..044f605 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
@@ -333,7 +333,7 @@
         if (!isExternalProtocol) {
             if (!mDelegate.isSpecializedHandlerAvailable(intent)) {
                 return OverrideUrlLoadingResult.NO_OVERRIDE;
-            } else if (params.getReferrerUrl() != null && isLink) {
+            } else if (params.getReferrerUrl() != null && (isLink || isFormSubmit)) {
                 // Current URL has at least one specialized handler available. For navigations
                 // within the same host, keep the navigation inside the browser unless the set of
                 // available apps to handle the new navigation is different. http://crbug.com/463138
@@ -349,11 +349,6 @@
 
                 if (currentUri != null && previousUri != null
                         && TextUtils.equals(currentUri.getHost(), previousUri.getHost())) {
-
-                    if (isFormSubmit && !isRedirectFromFormSubmit) {
-                        return OverrideUrlLoadingResult.NO_OVERRIDE;
-                    }
-
                     Intent previousIntent;
                     try {
                         previousIntent = Intent.parseUri(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
index b6f0a4e..4423ef8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -2704,7 +2704,8 @@
         int mruRank = 0;
         for (int i = 0; i < model.getCount(); i++) {
             Tab otherTab = model.getTabAt(i);
-            if (otherTab != tab && otherTab.getTabUma().getLastShownTimestamp() > tabLastShow) {
+            if (otherTab != tab && otherTab.getTabUma() != null
+                    && otherTab.getTabUma().getLastShownTimestamp() > tabLastShow) {
                 mruRank++;
             }
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/OffTheRecordTabModelImplCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/OffTheRecordTabModelImplCreator.java
index 2fb1d16..2f4fe0c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/OffTheRecordTabModelImplCreator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/OffTheRecordTabModelImplCreator.java
@@ -51,7 +51,7 @@
     @Override
     public TabModel createTabModel() {
         return new TabModelImpl(true, mRegularTabCreator, mIncognitoTabCreator, mUma,
-                mOrderController, mTabContentManager, mTabSaver, mModelDelegate);
+                mOrderController, mTabContentManager, mTabSaver, mModelDelegate, false);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
index 7442aa4..8571ce3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
@@ -7,6 +7,7 @@
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.ObserverList;
 import org.chromium.base.TraceEvent;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.partnercustomizations.HomepageManager;
 import org.chromium.chrome.browser.tab.Tab;
@@ -60,10 +61,15 @@
      */
     private int mIndex = INVALID_TAB_INDEX;
 
+    /**
+     * Whether this tab model supports undoing.
+     */
+    private boolean mIsUndoSupported = true;
+
     public TabModelImpl(boolean incognito, TabCreator regularTabCreator,
             TabCreator incognitoTabCreator, TabModelSelectorUma uma,
             TabModelOrderController orderController, TabContentManager tabContentManager,
-            TabPersistentStore tabSaver, TabModelDelegate modelDelegate) {
+            TabPersistentStore tabSaver, TabModelDelegate modelDelegate, boolean supportUndo) {
         super(incognito);
         initializeNative();
         mRegularTabCreator = regularTabCreator;
@@ -73,6 +79,7 @@
         mTabContentManager = tabContentManager;
         mTabSaver = tabSaver;
         mModelDelegate = modelDelegate;
+        mIsUndoSupported = supportUndo;
         mObservers = new ObserverList<TabModelObserver>();
     }
 
@@ -233,7 +240,7 @@
 
     @Override
     public boolean supportsPendingClosures() {
-        return !isIncognito();
+        return !isIncognito() && mIsUndoSupported;
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java
index d4baa88..82723bfb6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java
@@ -40,6 +40,8 @@
     // has not been destroyed.
     private boolean mActiveState = false;
 
+    private boolean mIsUndoSupported;
+
     private final TabModelOrderController mOrderController;
 
     private OverviewModeBehavior mOverviewModeBehavior;
@@ -56,13 +58,22 @@
     private ChromeTabCreator mIncognitoTabCreator;
 
     /**
+     * @see #TabModelSelectorImpl(ChromeActivity, int, WindowAndroid, boolean)
+     */
+    public TabModelSelectorImpl(ChromeActivity activity, int selectorIndex,
+            WindowAndroid windowAndroid) {
+        this(activity, selectorIndex, windowAndroid, true);
+    }
+
+    /**
      * Builds a {@link TabModelSelectorImpl} instance.
      * @param activity      The {@link ChromeActivity} this model selector lives in.
      * @param selectorIndex The index this selector represents in the list of selectors.
      * @param windowAndroid The {@link WindowAndroid} associated with this model selector.
+     * @param supportUndo   Whether a tab closure can be undone.
      */
     public TabModelSelectorImpl(ChromeActivity activity, int selectorIndex,
-            WindowAndroid windowAndroid) {
+            WindowAndroid windowAndroid, boolean supportUndo) {
         super();
         mActivity = activity;
         mUma = new TabModelSelectorUma(mActivity);
@@ -87,6 +98,7 @@
             public void onMetadataSavedAsynchronously() {
             }
         };
+        mIsUndoSupported = supportUndo;
         mTabSaver = new TabPersistentStore(this, selectorIndex, mActivity, mActivity,
                 persistentStoreObserver);
         mOrderController = new TabModelOrderController(this);
@@ -143,8 +155,8 @@
         assert !mActiveState : "onNativeLibraryReady called twice!";
         mTabContentManager = tabContentProvider;
 
-        TabModel normalModel = new TabModelImpl(false, mRegularTabCreator, mIncognitoTabCreator,
-                mUma, mOrderController, mTabContentManager, mTabSaver, this);
+        TabModelImpl normalModel = new TabModelImpl(false, mRegularTabCreator, mIncognitoTabCreator,
+                mUma, mOrderController, mTabContentManager, mTabSaver, this, mIsUndoSupported);
         TabModel incognitoModel = new OffTheRecordTabModel(new OffTheRecordTabModelImplCreator(
                 mRegularTabCreator, mIncognitoTabCreator, mUma, mOrderController,
                 mTabContentManager, mTabSaver, this));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index b68e047..3432f62 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -44,6 +44,9 @@
 import org.chromium.chrome.browser.document.DocumentActivity;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
+import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.toolbar.CustomTabToolbar;
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.browser.util.FeatureUtilities;
@@ -54,6 +57,7 @@
 import org.chromium.content.browser.test.util.CallbackHelper;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
+import org.chromium.content.browser.test.util.DOMUtils;
 import org.chromium.content_public.browser.LoadUrlParams;
 
 import java.util.ArrayList;
@@ -505,6 +509,33 @@
     }
 
     @SmallTest
+    public void testCreateNewTab() throws InterruptedException, TimeoutException {
+        final String testUrl = TestHttpServerClient.getUrl(
+                "chrome/test/data/android/customtabs/test_window_open.html");
+        startCustomTabActivityWithIntent(CustomTabsTestUtils.createMinimalCustomTabIntent(
+                getInstrumentation().getTargetContext(), testUrl, null));
+        final TabModelSelector tabSelector = getActivity().getTabModelSelector();
+
+        final CallbackHelper openTabHelper = new CallbackHelper();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                tabSelector.getModel(false).addObserver(new EmptyTabModelObserver() {
+                    @Override
+                    public void didAddTab(Tab tab, TabLaunchType type) {
+                        openTabHelper.notifyCalled();
+                    }
+                });
+            }
+        });
+        DOMUtils.clickNode(this, getActivity().getActivityTab().getContentViewCore(), "new_window");
+
+        openTabHelper.waitForCallback(0, 1);
+        assertEquals("A new tab should have been created.", 2,
+                tabSelector.getModel(false).getCount());
+    }
+
+    @SmallTest
     public void testReferrerAddedAutomatically() throws InterruptedException {
         final IBinder session = warmUpAndLaunchUrlWithSession();
         assertEquals(mActivity.getIntentDataProvider().getSession(), session);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java
index 1b9ae1e..b64361c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java
@@ -9,25 +9,16 @@
 import android.test.FlakyTest;
 import android.test.suitebuilder.annotation.SmallTest;
 
-import org.chromium.base.ApplicationStatus;
-import org.chromium.base.ThreadUtils;
 import org.chromium.chrome.browser.customtabs.CustomTabDelegateFactory.CustomTabNavigationDelegate;
 import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler;
 import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler.OverrideUrlLoadingResult;
 import org.chromium.chrome.browser.externalnav.ExternalNavigationParams;
-import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabDelegateFactory;
-import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
-import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.test.util.TestHttpServerClient;
-import org.chromium.content.browser.test.util.CallbackHelper;
-import org.chromium.content_public.browser.LoadUrlParams;
-
-import java.util.concurrent.TimeoutException;
 
 /**
- * Instrumentation test for external navigation handling in a {@link CustomTab}.
+ * Instrumentation test for external navigation handling of a Custom Tab.
  */
 public class CustomTabExternalNavigationTest extends CustomTabActivityTestBase {
 
@@ -104,36 +95,4 @@
         assertFalse("External activities should not be started to handle the url",
                 mNavigationDelegate.hasExternalActivityStarted());
     }
-
-    /**
-     * Tests whether a new tab can be created from a {@link CustomTab}.
-     *
-     * crbug.com/519613
-     * @SmallTest
-     */
-    @FlakyTest
-    public void testNotCreateNewTab() throws InterruptedException, TimeoutException {
-        final String testUrl = TestHttpServerClient.getUrl("chrome/test/data/android/google.html");
-        final TabModelSelector tabSelector = getActivity().getTabModelSelector();
-
-        final CallbackHelper loadUrlHelper = new CallbackHelper();
-        ThreadUtils.runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                tabSelector.getCurrentTab().addObserver(new EmptyTabObserver() {
-                    @Override
-                    public void onLoadUrl(Tab tab, LoadUrlParams params, int loadType) {
-                        loadUrlHelper.notifyCalled();
-                    }
-                });
-                tabSelector.openNewTab(new LoadUrlParams(testUrl), TabLaunchType.FROM_LINK, null,
-                        false);
-            }
-        });
-
-        loadUrlHelper.waitForCallback(0, 1);
-        assertTrue("A new tab should not have been created.",
-                ApplicationStatus.getLastTrackedFocusedActivity() == getActivity());
-        assertEquals(testUrl, getActivity().getActivityTab().getUrl());
-    }
 }
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java
index 6a44e12..60a5d82 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java
@@ -46,6 +46,11 @@
     private static final int NO_REDIRECT = 0x0;
     private static final int REDIRECT = 0x1;
 
+    private static final String NO_REFERRER = null;
+
+    private static final boolean NORMAL_PROFILE = false;
+    private static final boolean INCOGNITO_PROFILE = true;
+
     private static final String SEARCH_RESULT_URL_FOR_TOM_HANKS =
             "https://www.google.com/search?q=tom+hanks";
     private static final String IMDB_WEBPAGE_FOR_TOM_HANKS = "http://m.imdb.com/name/nm0000158";
@@ -91,8 +96,8 @@
     @SmallTest
     public void testOrdinaryIncognitoUri() {
         check("http://youtube.com/",
-                null, /* referrer */
-                true, /* incognito */
+                NO_REFERRER,
+                INCOGNITO_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -107,7 +112,7 @@
         // http://crbug.com/159153: Don't override http or https URLs from the NTP or bookmarks.
         check("http://youtube.com/",
                 "chrome://about", /* referrer */
-                false, /* incognito */
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -117,7 +122,7 @@
                 IGNORE);
         check("tel:012345678",
                 "chrome://about", /* referrer */
-                false, /* incognito */
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -132,8 +137,8 @@
         // http://crbug.com/164194. We shouldn't show the intent picker on
         // forwards or backwards navigations.
         check("http://youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK
                 | PageTransition.FORWARD_BACK,
                 NO_REDIRECT,
@@ -149,8 +154,8 @@
         // http://crbug.com/181186: We need to show the intent picker when we receive a redirect
         // following a form submit. OAuth of native applications rely on this.
         check("market://1234",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.FORM_SUBMIT,
                 REDIRECT,
                 true,
@@ -159,8 +164,30 @@
                 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT,
                 START_ACTIVITY);
         check("http://youtube.com://",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
+                PageTransition.FORM_SUBMIT,
+                REDIRECT,
+                true,
+                false,
+                null,
+                OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT,
+                START_ACTIVITY);
+        // If the page matches the referrer, then continue loading in Chrome.
+        check("http://youtube.com://",
+                "http://youtube.com", /* referrer */
+                NORMAL_PROFILE,
+                PageTransition.FORM_SUBMIT,
+                REDIRECT,
+                true,
+                false,
+                null,
+                OverrideUrlLoadingResult.NO_OVERRIDE,
+                IGNORE);
+        // If the page does not match the referrer, then prompt an intent.
+        check("http://youtube.com://",
+                "http://google.com", /* referrer */
+                NORMAL_PROFILE,
                 PageTransition.FORM_SUBMIT,
                 REDIRECT,
                 true,
@@ -172,8 +199,8 @@
         // is not encoded in the intent (although, in theory, it could be passed in as
         // an extra data in the intent).
         check("http://youtube.com://",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.FORM_SUBMIT,
                 NO_REDIRECT,
                 true,
@@ -187,8 +214,8 @@
     public void testIgnore() {
         // Ensure about: URLs are not broadcast for external navigation.
         check("about:test",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -197,8 +224,8 @@
                 OverrideUrlLoadingResult.NO_OVERRIDE,
                 IGNORE);
         check("about:test",
-                null, /* referrer */
-                true, /* incognito */
+                NO_REFERRER,
+                INCOGNITO_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -209,8 +236,8 @@
 
         // Ensure content: URLs are not broadcast for external navigation.
         check("content:test",
-                null, /* referrer */
-                true, /* incognito */
+                NO_REFERRER,
+                INCOGNITO_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -219,8 +246,8 @@
                 OverrideUrlLoadingResult.NO_OVERRIDE,
                 IGNORE);
         check("content:test",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -231,8 +258,8 @@
 
         // Ensure chrome: URLs are not broadcast for external navigation.
         check("chrome://history",
-                null, /* referrer */
-                true, /* incognito */
+                NO_REFERRER,
+                INCOGNITO_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -241,8 +268,8 @@
                 OverrideUrlLoadingResult.NO_OVERRIDE,
                 IGNORE);
         check("chrome://history",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -253,8 +280,8 @@
 
         // Ensure chrome-native: URLs are not broadcast for external navigation.
         check("chrome-native://newtab",
-                null, /* referrer */
-                true, /* incognito */
+                NO_REFERRER,
+                INCOGNITO_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -263,8 +290,8 @@
                 OverrideUrlLoadingResult.NO_OVERRIDE,
                 IGNORE);
         check("chrome-native://newtab",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -278,8 +305,8 @@
     public void testPageTransitionType() {
         // Non-link page transition type are ignored.
         check("http://youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -288,8 +315,8 @@
                 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT,
                 START_ACTIVITY);
         check("http://youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 REDIRECT,
                 true,
@@ -300,8 +327,8 @@
         // http://crbug.com/143118 - Don't show the picker for directly typed URLs, unless
         // the URL results in a redirect.
         check("http://youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.TYPED,
                 NO_REDIRECT,
                 true,
@@ -311,8 +338,8 @@
                 IGNORE);
         // http://crbug.com/162106 - Don't show the picker on reload.
         check("http://youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.RELOAD,
                 NO_REDIRECT,
                 true,
@@ -326,8 +353,8 @@
     public void testWtai() {
         // Start the telephone application with the given number.
         check("wtai://wp/mc;0123456789",
-                null, /* referrer */
-                true, /* incognito */
+                NO_REFERRER,
+                INCOGNITO_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -337,8 +364,8 @@
                 START_ACTIVITY | INTENT_SANITIZATION_EXCEPTION);
         // These two cases are currently unimplemented.
         check("wtai://wp/sd;0123456789",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -347,8 +374,8 @@
                 OverrideUrlLoadingResult.NO_OVERRIDE,
                 IGNORE | INTENT_SANITIZATION_EXCEPTION);
         check("wtai://wp/ap;0123456789",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -358,8 +385,8 @@
                 IGNORE | INTENT_SANITIZATION_EXCEPTION);
         // Ignore other WTAI urls.
         check("wtai://wp/invalid",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -372,8 +399,8 @@
     @SmallTest
     public void testExternalUri() {
         check("tel:012345678",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -387,8 +414,8 @@
     public void testTypedRedirectToExternalProtocol() {
         // http://crbug.com/169549
         check("market://1234",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.TYPED,
                 REDIRECT,
                 true,
@@ -398,8 +425,8 @@
                 START_ACTIVITY);
         // http://crbug.com/143118
         check("market://1234",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.TYPED,
                 NO_REDIRECT,
                 true,
@@ -415,8 +442,8 @@
                 | PageTransition.FROM_API;
         // http://crbug.com/149218
         check("http://youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 transitionTypeIncomingIntent,
                 NO_REDIRECT,
                 true,
@@ -426,8 +453,8 @@
                 IGNORE);
         // http://crbug.com/170925
         check("http://youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 transitionTypeIncomingIntent,
                 REDIRECT,
                 true,
@@ -445,8 +472,8 @@
                 + "component=package/class;end";
 
         check(url,
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -457,8 +484,8 @@
 
         // http://crbug.com/370399
         check(urlWithSel,
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -476,8 +503,8 @@
 
         // http://crbug/386600 - it makes no sense to switch activities for pairing code URLs.
         check(url,
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 REDIRECT,
                 true,
@@ -487,8 +514,8 @@
                 IGNORE);
 
         check(url,
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 transitionTypeIncomingIntent,
                 REDIRECT,
                 true,
@@ -512,8 +539,8 @@
         redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0);
         redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, true, false, 0, 0);
         check("http://m.youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 transTypeLinkFromIntent,
                 REDIRECT,
                 true,
@@ -526,8 +553,8 @@
         redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0);
         redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, true, false, 0, 0);
         check("http://m.youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 transTypeLinkFromIntent,
                 REDIRECT,
                 true,
@@ -551,8 +578,8 @@
         redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0);
         redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, true, false, 0, 0);
         check("http://m.youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 transTypeLinkFromIntent,
                 REDIRECT,
                 true,
@@ -566,8 +593,8 @@
         redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0);
         redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, true, false, 0, 0);
         check("market://1234",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 transTypeLinkFromIntent,
                 REDIRECT,
                 true,
@@ -584,7 +611,7 @@
 
         check(INTENT_URL_WITH_FALLBACK_URL,
                 SEARCH_RESULT_URL_FOR_TOM_HANKS, /* referrer */
-                false, /* incognito */
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -610,7 +637,7 @@
         // the current tab.
         check(INTENT_URL_WITH_FALLBACK_URL,
                 SEARCH_RESULT_URL_FOR_TOM_HANKS, /* referrer */
-                false, /* incognito */
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -632,7 +659,7 @@
         // Fallback URL should work even when package name isn't given.
         check(INTENT_URL_WITH_FALLBACK_URL_WITHOUT_PACKAGE_NAME,
                 SEARCH_RESULT_URL_FOR_TOM_HANKS, /* referrer */
-                false, /* incognito */
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -653,7 +680,7 @@
 
         check(INTENT_URL_WITH_FALLBACK_URL,
                 SEARCH_RESULT_URL_FOR_TOM_HANKS,
-                true, /* incognito */
+                INCOGNITO_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -675,7 +702,7 @@
         // Will be redirected market since package is given.
         check(INTENT_URL_WITH_JAVASCRIPT_FALLBACK_URL,
                 SEARCH_RESULT_URL_FOR_TOM_HANKS,
-                true, /* incognito */
+                INCOGNITO_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -695,21 +722,21 @@
         TabRedirectHandler redirectHandler = new TabRedirectHandler(null);
 
         redirectHandler.updateNewUrlLoading(PageTransition.TYPED, false, false, 0, 0);
-        check("http://goo.gl/abcdefg", null, /* referrer */
-                false, /* incognito */
+        check("http://goo.gl/abcdefg", NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.TYPED, NO_REDIRECT, true, false, redirectHandler,
                 OverrideUrlLoadingResult.NO_OVERRIDE, IGNORE);
 
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, false, 0, 0);
-        check(INTENT_URL_WITH_FALLBACK_URL_WITHOUT_PACKAGE_NAME, null, /* referrer */
-                false, /* incognito */
+        check(INTENT_URL_WITH_FALLBACK_URL_WITHOUT_PACKAGE_NAME, NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK, NO_REDIRECT, true, false, redirectHandler,
                 OverrideUrlLoadingResult.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
 
         // Now the user opens a link.
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, true, 0, 1);
-        check("http://m.youtube.com/", null, /* referrer */
-                false, /* incognito */
+        check("http://m.youtube.com/", NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK, NO_REDIRECT, true, false, redirectHandler,
                 OverrideUrlLoadingResult.NO_OVERRIDE, IGNORE);
     }
@@ -723,8 +750,8 @@
 
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, true, 0, 0);
         check(INTENT_URL_WITH_CHAIN_FALLBACK_URL,
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -739,8 +766,8 @@
         // override URL loading here.
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, false, 0, 0);
         check(INTENT_URL_WITH_FALLBACK_URL,
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -758,8 +785,8 @@
         redirectHandler.updateNewUrlLoading(
                 PageTransition.LINK, false, true, lastUserInteractionTimeInMillis, 1);
         check(INTENT_URL_WITH_FALLBACK_URL,
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -775,8 +802,8 @@
 
         redirectHandler.updateNewUrlLoading(PageTransition.TYPED, false, false, 0, 0);
         check("http://m.youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.TYPED,
                 NO_REDIRECT,
                 true,
@@ -787,8 +814,8 @@
 
         redirectHandler.updateNewUrlLoading(PageTransition.TYPED, true, false, 0, 0);
         check("http://m.youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.TYPED,
                 REDIRECT,
                 true,
@@ -799,8 +826,8 @@
 
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, false, 0, 1);
         check("http://m.youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -816,8 +843,8 @@
 
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, false, 1, 0);
         check("http://m.youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -828,8 +855,8 @@
 
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, true, false, 1, 0);
         check("http://m.youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 REDIRECT,
                 true,
@@ -840,8 +867,8 @@
 
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, false, 1, 1);
         check("http://m.youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -855,8 +882,8 @@
     public void testChromeAppInBackground() {
         mDelegate.setIsChromeAppInForeground(false);
         check("http://youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -870,8 +897,8 @@
     public void testNotChromeAppInForegroundRequired() {
         mDelegate.setIsChromeAppInForeground(false);
         check("http://youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 false,
@@ -911,7 +938,7 @@
     public void testPlusAppRefresh() {
         check(PLUS_STREAM_URL,
                 PLUS_STREAM_URL,
-                false, /* incognito */
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -925,7 +952,7 @@
     public void testSameDomainDifferentApps() {
         check(CALENDAR_URL,
                 KEEP_URL,
-                false, /* incognito */
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -939,7 +966,7 @@
     public void testFormSubmitSameDomain() {
         check(CALENDAR_URL,
                 KEEP_URL,
-                false, /* incognito */
+                NORMAL_PROFILE,
                 PageTransition.FORM_SUBMIT,
                 NO_REDIRECT,
                 true,
@@ -952,8 +979,8 @@
     @SmallTest
     public void testBackgroundTabNavigation() {
         check("http://youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -968,7 +995,7 @@
         String referrer = "http://www.google.com";
         check("http://youtube.com:90/foo/bar",
                 referrer,
-                false, /* incognito */
+                NORMAL_PROFILE,
                 PageTransition.FORM_SUBMIT,
                 REDIRECT,
                 true,
@@ -988,8 +1015,8 @@
 
         redirectHandler.updateNewUrlLoading(PageTransition.RELOAD, false, false, 1, 0);
         check("http://m.youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -1000,8 +1027,8 @@
 
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, true, false, 1, 0);
         check("http://m.youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 REDIRECT,
                 true,
@@ -1012,8 +1039,8 @@
 
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, false, 1, 1);
         check("http://m.youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -1030,8 +1057,8 @@
         redirectHandler.updateNewUrlLoading(
                 PageTransition.FORM_SUBMIT | PageTransition.FORWARD_BACK, false, false, 1, 0);
         check("http://m.youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -1042,8 +1069,8 @@
 
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, true, false, 1, 0);
         check("http://m.youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 REDIRECT,
                 true,
@@ -1054,8 +1081,8 @@
 
         redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, false, 1, 1);
         check("http://m.youtube.com/",
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -1073,8 +1100,8 @@
         mDelegate.shouldRequestFileAccess = false;
         // Verify no overrides if file access is allowed (under different load conditions).
         check(fileUrl,
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.LINK,
                 NO_REDIRECT,
                 true,
@@ -1083,8 +1110,8 @@
                 OverrideUrlLoadingResult.NO_OVERRIDE,
                 IGNORE);
         check(fileUrl,
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.RELOAD,
                 NO_REDIRECT,
                 true,
@@ -1093,8 +1120,8 @@
                 OverrideUrlLoadingResult.NO_OVERRIDE,
                 IGNORE);
         check(fileUrl,
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.AUTO_TOPLEVEL,
                 NO_REDIRECT,
                 true,
@@ -1106,8 +1133,8 @@
         mDelegate.shouldRequestFileAccess = true;
         // Verify that the file intent action is triggered if file access is not allowed.
         check(fileUrl,
-                null, /* referrer */
-                false, /* incognito */
+                NO_REFERRER,
+                NORMAL_PROFILE,
                 PageTransition.AUTO_TOPLEVEL,
                 NO_REDIRECT,
                 true,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabObserverTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabObserverTest.java
index 0766c25..cb99c4f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabObserverTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabObserverTest.java
@@ -100,20 +100,10 @@
             }
         };
         mNormalTabModel = new TabModelImpl(false, null, null, null, orderController,
-                tabContentManager, tabPersistentStore, delegate) {
-            @Override
-            public boolean supportsPendingClosures() {
-                return false;
-            }
-        };
+                tabContentManager, tabPersistentStore, delegate, false);
 
         mIncognitoTabModel = new TabModelImpl(true, null, null, null, orderController,
-                tabContentManager, tabPersistentStore, delegate) {
-            @Override
-            public boolean supportsPendingClosures() {
-                return false;
-            }
-        };
+                tabContentManager, tabPersistentStore, delegate, false);
 
         mSelector.initialize(false, mNormalTabModel, mIncognitoTabModel);
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
index f464f09..a4881bd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
@@ -145,7 +145,7 @@
                             mTabCreatorManager.getTabCreator(false),
                             mTabCreatorManager.getTabCreator(true),
                             null, mTabModelOrderController, null, mTabPersistentStore,
-                            TestTabModelSelector.this);
+                            TestTabModelSelector.this, true);
                 }
             };
             TabModelImpl regularTabModel = ThreadUtils.runOnUiThreadBlocking(callable);
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 4f8ba8c..c76d906 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -3699,6 +3699,9 @@
         <message name="IDS_TASK_MANAGER_SUBFRAME_INCOGNITO_PREFIX" desc="The prefix for an Incognito out-of-process-iframe process row in the Task Manager (these processes are created when site isolation is enabled, in incognito mode)">
           Incognito Subframe: <ph name="SUBFRAME_SITE">$1<ex>https://youtube.com/</ex></ph>
         </message>
+        <message name="IDS_TASK_MANAGER_ARC_PREFIX" desc="The prefix for an ARC process row">
+          ARC: <ph name="ARC_PROCESS_NAME">$1<ex>com.android.systemui</ex></ph>
+        </message>
       </if>
 
       <message name="IDS_UTILITY_PROCESS_COMPONENT_PATCHER_NAME" desc="The name of the utility process used for patching components.">
@@ -5134,6 +5137,14 @@
         If enabled, the chrome://extensions/ URL loads the Material Design extensions page.
       </message>
 
+      <!-- Device scale factor change in content crbug.com/485650. -->
+      <message name="IDS_FLAGS_ENABLE_USE_ZOOM_FOR_DSF_NAME" desc="Name for the flag to use Blink's zooming mechanism to implement device scale factor.">
+        Use Blink's zoom for device scale factor.
+      </message>
+      <message name="IDS_FLAGS_ENABLE_USE_ZOOM_FOR_DSF_DESCRIPTION" desc="Description for the flag to use Blink's zooming mechanism to implement device scale factor.">
+        If enabled, Blink uses its zooming mechanism to scale content for device scale factor.
+      </message>
+
       <!-- Components -->
       <message name="IDS_COMPONENTS_TITLE" desc="Title for the chrome://components page.">
         Components
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index aecf2cac..8d53d15 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -466,6 +466,12 @@
     sources += rebase_path(gypi_values.chrome_browser_task_manager_sources,
                            ".",
                            "//chrome")
+    if (is_chromeos) {
+      sources +=
+          rebase_path(gypi_values.chrome_browser_task_manager_chromeos_sources,
+                      ".",
+                      "//chrome")
+    }
   }
   if (enable_spellcheck) {
     sources += rebase_path(gypi_values.chrome_browser_spellchecker_sources,
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 2b2b1e8..7a9d373 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1686,6 +1686,11 @@
      IDS_FLAGS_SITE_PER_PROCESS_DESCRIPTION,
      kOsAll,
      SINGLE_VALUE_TYPE(switches::kSitePerProcess)},
+    {"enable-use-zoom-for-dsf",
+     IDS_FLAGS_ENABLE_USE_ZOOM_FOR_DSF_NAME,
+     IDS_FLAGS_ENABLE_USE_ZOOM_FOR_DSF_DESCRIPTION,
+     kOsDesktop,
+     SINGLE_VALUE_TYPE(switches::kEnableUseZoomForDSF)},
 #if defined(OS_MACOSX)
     {"enable-harfbuzz-rendertext",
      IDS_FLAGS_HARFBUZZ_RENDERTEXT_NAME,
diff --git a/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc b/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc
index 8b79b2f5..8a817cd7 100644
--- a/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc
+++ b/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc
@@ -100,6 +100,7 @@
   const std::string& primary_account_id = GetPrimaryAccountId();
   if (token_service->RefreshTokenIsAvailable(primary_account_id)) {
     VLOG(1) << "OAuth2 refresh token is already loaded.";
+    FireRefreshTokensLoaded();
     VerifySessionCookies();
   } else {
     VLOG(1) << "Loading OAuth2 refresh token from database.";
@@ -195,11 +196,17 @@
   DCHECK(!refresh_token_.empty());
   // |account_id| is assumed to be already canonicalized if it's an email.
   GetTokenService()->UpdateCredentials(account_id, refresh_token_);
+  FireRefreshTokensLoaded();
 
   FOR_EACH_OBSERVER(Observer, observer_list_,
                     OnNewRefreshTokenAvaiable(user_profile_));
 }
 
+void OAuth2LoginManager::FireRefreshTokensLoaded() {
+  // TODO(570218): Figure out the right way to plumb this.
+  GetTokenService()->LoadCredentials(std::string());
+}
+
 void OAuth2LoginManager::OnRefreshTokenResponse(
     const std::string& access_token,
     int expires_in_seconds) {
diff --git a/chrome/browser/chromeos/login/signin/oauth2_login_manager.h b/chrome/browser/chromeos/login/signin/oauth2_login_manager.h
index 184a2e54..371781c 100644
--- a/chrome/browser/chromeos/login/signin/oauth2_login_manager.h
+++ b/chrome/browser/chromeos/login/signin/oauth2_login_manager.h
@@ -190,6 +190,9 @@
   // Update the token service and inform listeners of a new refresh token.
   void UpdateCredentials(const std::string& account_id);
 
+  // Notify that the refresh tokens are loaded and ready to use.
+  void FireRefreshTokensLoaded();
+
   // Attempts to fetch OAuth2 tokens by using pre-authenticated cookie jar from
   // provided |auth_profile|.
   void FetchOAuth2Tokens();
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc
index 141c283..623b7c6d6 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -64,6 +64,7 @@
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
@@ -605,9 +606,12 @@
 #endif
     std::string title =
         web_app::GenerateApplicationNameFromExtensionId(extension_id);
+    content::SiteInstance* source_site_instance =
+        render_frame_host()->GetSiteInstance();
     // Note: Panels ignore all but the first url provided.
     Panel* panel = PanelManager::GetInstance()->CreatePanel(
-        title, window_profile, urls[0], window_bounds, panel_create_mode);
+        title, window_profile, urls[0], source_site_instance, window_bounds,
+        panel_create_mode);
 
     // Unlike other window types, Panels do not take focus by default.
     if (!saw_focus_key || !focused)
diff --git a/chrome/browser/extensions/webstore_installer.cc b/chrome/browser/extensions/webstore_installer.cc
index e0639e94..79b73bec 100644
--- a/chrome/browser/extensions/webstore_installer.cc
+++ b/chrome/browser/extensions/webstore_installer.cc
@@ -526,25 +526,29 @@
           FAILURE_REASON_OTHER);
       break;
     case DownloadItem::COMPLETE:
-      // Wait for other notifications if the download is really an extension.
-      if (!download_crx_util::IsExtensionDownload(*download)) {
-        ReportFailure(kInvalidDownloadError, FAILURE_REASON_OTHER);
-      } else {
-        if (crx_installer_.get())
-          return;  // DownloadItemImpl calls the observer twice, ignore it.
-        StartCrxInstaller(*download);
-
-        if (pending_modules_.size() == 1) {
-          // The download is the last module - the extension main module.
-          if (delegate_)
-            delegate_->OnExtensionDownloadProgress(id_, download);
-          extensions::InstallTracker* tracker =
-              extensions::InstallTrackerFactory::GetForBrowserContext(profile_);
-          tracker->OnDownloadProgress(id_, 100);
-        }
-      }
       // Stop the progress timer if it's running.
       download_progress_timer_.Stop();
+
+      // Only wait for other notifications if the download is really
+      // an extension.
+      if (!download_crx_util::IsExtensionDownload(*download)) {
+        ReportFailure(kInvalidDownloadError, FAILURE_REASON_OTHER);
+        return;
+      }
+
+      if (crx_installer_.get())
+        return;  // DownloadItemImpl calls the observer twice, ignore it.
+
+      StartCrxInstaller(*download);
+
+      if (pending_modules_.size() == 1) {
+        // The download is the last module - the extension main module.
+        if (delegate_)
+          delegate_->OnExtensionDownloadProgress(id_, download);
+        extensions::InstallTracker* tracker =
+            extensions::InstallTrackerFactory::GetForBrowserContext(profile_);
+        tracker->OnDownloadProgress(id_, 100);
+      }
       break;
     case DownloadItem::IN_PROGRESS: {
       if (delegate_ && pending_modules_.size() == 1) {
diff --git a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
index 43cfa0c..470706a4 100644
--- a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
+++ b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
@@ -32,6 +32,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/search_engines/default_search_manager.h"
+#include "components/user_prefs/tracked/tracked_preference_histogram_names.h"
 #include "extensions/browser/pref_names.h"
 #include "extensions/common/extension.h"
 
@@ -254,7 +255,7 @@
 
     if (IsPRETest()) {
       num_tracked_prefs_ = GetTrackedPrefHistogramCount(
-          "Settings.TrackedPreferenceNullInitialized", ALLOW_ANY);
+          user_prefs::tracked::kTrackedPrefHistogramNullInitialized, ALLOW_ANY);
       EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM,
                 num_tracked_prefs_ > 0);
 
@@ -262,7 +263,8 @@
       // when an empty dictionary is encountered on first run (this should only
       // hit for pref #5 in the current design).
       int num_split_tracked_prefs = GetTrackedPrefHistogramCount(
-          "Settings.TrackedPreferenceUnchanged", BEGIN_ALLOW_SINGLE_BUCKET + 5);
+          user_prefs::tracked::kTrackedPrefHistogramUnchanged,
+          BEGIN_ALLOW_SINGLE_BUCKET + 5);
       EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
                 num_split_tracked_prefs);
 
@@ -373,37 +375,40 @@
 
   void VerifyReactionToPrefAttack() override {
     // Expect all prefs to be reported as Unchanged with no resets.
-    EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
-                  ? num_tracked_prefs() : 0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceUnchanged", ALLOW_ANY));
+    EXPECT_EQ(
+        protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
+            ? num_tracked_prefs()
+            : 0,
+        GetTrackedPrefHistogramCount(
+            user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
+    EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+                     user_prefs::tracked::kTrackedPrefHistogramWantedReset,
+                     ALLOW_NONE));
     EXPECT_EQ(0,
               GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceWantedReset", ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceReset",
-                                           ALLOW_NONE));
+                  user_prefs::tracked::kTrackedPrefHistogramReset, ALLOW_NONE));
 
     // Nothing else should have triggered.
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceChanged",
-                                           ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceCleared",
-                                           ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceInitialized", ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceTrustedInitialized", ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceNullInitialized", ALLOW_NONE));
     EXPECT_EQ(
-        0,
-        GetTrackedPrefHistogramCount(
-            "Settings.TrackedPreferenceMigratedLegacyDeviceId", ALLOW_NONE));
+        0, GetTrackedPrefHistogramCount(
+               user_prefs::tracked::kTrackedPrefHistogramChanged, ALLOW_NONE));
+    EXPECT_EQ(
+        0, GetTrackedPrefHistogramCount(
+               user_prefs::tracked::kTrackedPrefHistogramCleared, ALLOW_NONE));
+    EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+                     user_prefs::tracked::kTrackedPrefHistogramInitialized,
+                     ALLOW_NONE));
+    EXPECT_EQ(0,
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
+                  ALLOW_NONE));
+    EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+                     user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
+                     ALLOW_NONE));
+    EXPECT_EQ(
+        0, GetTrackedPrefHistogramCount(
+               user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
+               ALLOW_NONE));
   }
 };
 
@@ -460,36 +465,40 @@
     // cleared), but shouldn't have triggered a reset (as there is nothing we
     // can do when the pref is already gone).
     EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceCleared",
-                                           BEGIN_ALLOW_SINGLE_BUCKET + 2));
-    EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
-                  ? num_tracked_prefs() - 1 : 0,
               GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceUnchanged", ALLOW_ANY));
+                  user_prefs::tracked::kTrackedPrefHistogramCleared,
+                  BEGIN_ALLOW_SINGLE_BUCKET + 2));
+    EXPECT_EQ(
+        protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
+            ? num_tracked_prefs() - 1
+            : 0,
+        GetTrackedPrefHistogramCount(
+            user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
+    EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+                     user_prefs::tracked::kTrackedPrefHistogramWantedReset,
+                     ALLOW_NONE));
     EXPECT_EQ(0,
               GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceWantedReset", ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceReset",
-                                           ALLOW_NONE));
+                  user_prefs::tracked::kTrackedPrefHistogramReset, ALLOW_NONE));
 
     // Nothing else should have triggered.
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceChanged",
-                                           ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceInitialized", ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceTrustedInitialized", ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceNullInitialized", ALLOW_NONE));
     EXPECT_EQ(
-        0,
-        GetTrackedPrefHistogramCount(
-            "Settings.TrackedPreferenceMigratedLegacyDeviceId", ALLOW_NONE));
+        0, GetTrackedPrefHistogramCount(
+               user_prefs::tracked::kTrackedPrefHistogramChanged, ALLOW_NONE));
+    EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+                     user_prefs::tracked::kTrackedPrefHistogramInitialized,
+                     ALLOW_NONE));
+    EXPECT_EQ(0,
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
+                  ALLOW_NONE));
+    EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+                     user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
+                     ALLOW_NONE));
+    EXPECT_EQ(
+        0, GetTrackedPrefHistogramCount(
+               user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
+               ALLOW_NONE));
   }
 };
 
@@ -534,7 +543,7 @@
   void VerifyReactionToPrefAttack() override {
     // Preferences that are NULL by default will be NullInitialized.
     int num_null_values = GetTrackedPrefHistogramCount(
-        "Settings.TrackedPreferenceNullInitialized", ALLOW_ANY);
+        user_prefs::tracked::kTrackedPrefHistogramNullInitialized, ALLOW_ANY);
     EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM,
               num_null_values > 0);
     if (num_null_values > 0) {
@@ -546,9 +555,10 @@
     // Expect all non-null prefs to be reported as Initialized (with
     // accompanying resets or wanted resets based on the current protection
     // level).
-    EXPECT_EQ(num_tracked_prefs() - num_null_values,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceInitialized", ALLOW_ANY));
+    EXPECT_EQ(
+        num_tracked_prefs() - num_null_values,
+        GetTrackedPrefHistogramCount(
+            user_prefs::tracked::kTrackedPrefHistogramInitialized, ALLOW_ANY));
 
     int num_protected_prefs = 0;
     // A switch statement falling through each protection level in decreasing
@@ -573,12 +583,13 @@
         break;
     }
 
-    EXPECT_EQ(num_tracked_prefs() - num_null_values - num_protected_prefs,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceWantedReset", ALLOW_ANY));
+    EXPECT_EQ(
+        num_tracked_prefs() - num_null_values - num_protected_prefs,
+        GetTrackedPrefHistogramCount(
+            user_prefs::tracked::kTrackedPrefHistogramWantedReset, ALLOW_ANY));
     EXPECT_EQ(num_protected_prefs,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceReset",
-                                           ALLOW_ANY));
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramReset, ALLOW_ANY));
 
     // Explicitly verify the result of reported resets.
 
@@ -597,19 +608,19 @@
                   SessionStartupPref::URLS);
 
     // Nothing else should have triggered.
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceUnchanged", ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceChanged",
-                                           ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceCleared",
-                                           ALLOW_NONE));
+    EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+                     user_prefs::tracked::kTrackedPrefHistogramUnchanged,
+                     ALLOW_NONE));
     EXPECT_EQ(
-        0,
-        GetTrackedPrefHistogramCount(
-            "Settings.TrackedPreferenceMigratedLegacyDeviceId", ALLOW_NONE));
+        0, GetTrackedPrefHistogramCount(
+               user_prefs::tracked::kTrackedPrefHistogramChanged, ALLOW_NONE));
+    EXPECT_EQ(
+        0, GetTrackedPrefHistogramCount(
+               user_prefs::tracked::kTrackedPrefHistogramCleared, ALLOW_NONE));
+    EXPECT_EQ(
+        0, GetTrackedPrefHistogramCount(
+               user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
+               ALLOW_NONE));
   }
 };
 
@@ -649,21 +660,27 @@
   void VerifyReactionToPrefAttack() override {
     // Expect a single Changed event for tracked pref #4 (startup URLs).
     EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceChanged",
-                                           BEGIN_ALLOW_SINGLE_BUCKET + 4));
-    EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
-                  ? num_tracked_prefs() - 1 : 0,
               GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceUnchanged", ALLOW_ANY));
-
+                  user_prefs::tracked::kTrackedPrefHistogramChanged,
+                  BEGIN_ALLOW_SINGLE_BUCKET + 4));
     EXPECT_EQ(
-        (protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
-         protection_level_ < PROTECTION_ENABLED_BASIC) ? 1 : 0,
-        GetTrackedPrefHistogramCount("Settings.TrackedPreferenceWantedReset",
-                                     BEGIN_ALLOW_SINGLE_BUCKET + 4));
+        protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
+            ? num_tracked_prefs() - 1
+            : 0,
+        GetTrackedPrefHistogramCount(
+            user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
+
+    EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
+               protection_level_ < PROTECTION_ENABLED_BASIC)
+                  ? 1
+                  : 0,
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramWantedReset,
+                  BEGIN_ALLOW_SINGLE_BUCKET + 4));
     EXPECT_EQ(protection_level_ >= PROTECTION_ENABLED_BASIC ? 1 : 0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceReset",
-                                           BEGIN_ALLOW_SINGLE_BUCKET + 4));
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramReset,
+                  BEGIN_ALLOW_SINGLE_BUCKET + 4));
 
 // TODO(gab): This doesn't work on OS_CHROMEOS because we fail to attack
 // Preferences.
@@ -677,22 +694,23 @@
 #endif
 
     // Nothing else should have triggered.
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceCleared",
-                                           ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceInitialized", ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceTrustedInitialized", ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceNullInitialized", ALLOW_NONE));
     EXPECT_EQ(
-        0,
-        GetTrackedPrefHistogramCount(
-            "Settings.TrackedPreferenceMigratedLegacyDeviceId", ALLOW_NONE));
+        0, GetTrackedPrefHistogramCount(
+               user_prefs::tracked::kTrackedPrefHistogramCleared, ALLOW_NONE));
+    EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+                     user_prefs::tracked::kTrackedPrefHistogramInitialized,
+                     ALLOW_NONE));
+    EXPECT_EQ(0,
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
+                  ALLOW_NONE));
+    EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+                     user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
+                     ALLOW_NONE));
+    EXPECT_EQ(
+        0, GetTrackedPrefHistogramCount(
+               user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
+               ALLOW_NONE));
   }
 };
 
@@ -741,48 +759,55 @@
     // Expect a single split pref changed report with a count of 2 for tracked
     // pref #5 (extensions).
     EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceChanged",
-                                           BEGIN_ALLOW_SINGLE_BUCKET + 5));
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramChanged,
+                  BEGIN_ALLOW_SINGLE_BUCKET + 5));
     EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
               GetTrackedPrefHistogramCount(
                   "Settings.TrackedSplitPreferenceChanged.extensions.settings",
                   BEGIN_ALLOW_SINGLE_BUCKET + 2));
 
     // Everything else should have remained unchanged.
-    EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
-                  ? num_tracked_prefs() - 1 : 0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceUnchanged", ALLOW_ANY));
-
     EXPECT_EQ(
-        (protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
-         protection_level_ < PROTECTION_ENABLED_EXTENSIONS) ? 1 : 0,
-        GetTrackedPrefHistogramCount("Settings.TrackedPreferenceWantedReset",
-                                     BEGIN_ALLOW_SINGLE_BUCKET + 5));
+        protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
+            ? num_tracked_prefs() - 1
+            : 0,
+        GetTrackedPrefHistogramCount(
+            user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
+
+    EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
+               protection_level_ < PROTECTION_ENABLED_EXTENSIONS)
+                  ? 1
+                  : 0,
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramWantedReset,
+                  BEGIN_ALLOW_SINGLE_BUCKET + 5));
     EXPECT_EQ(protection_level_ >= PROTECTION_ENABLED_EXTENSIONS ? 1 : 0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceReset",
-                                           BEGIN_ALLOW_SINGLE_BUCKET + 5));
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramReset,
+                  BEGIN_ALLOW_SINGLE_BUCKET + 5));
 
     EXPECT_EQ(protection_level_ < PROTECTION_ENABLED_EXTENSIONS,
               extension_service()->GetExtensionById(kGoodCrxId, true) != NULL);
 
     // Nothing else should have triggered.
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceCleared",
-                                           ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceInitialized", ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceTrustedInitialized", ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceNullInitialized", ALLOW_NONE));
     EXPECT_EQ(
-        0,
-        GetTrackedPrefHistogramCount(
-            "Settings.TrackedPreferenceMigratedLegacyDeviceId", ALLOW_NONE));
+        0, GetTrackedPrefHistogramCount(
+               user_prefs::tracked::kTrackedPrefHistogramCleared, ALLOW_NONE));
+    EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+                     user_prefs::tracked::kTrackedPrefHistogramInitialized,
+                     ALLOW_NONE));
+    EXPECT_EQ(0,
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
+                  ALLOW_NONE));
+    EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+                     user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
+                     ALLOW_NONE));
+    EXPECT_EQ(
+        0, GetTrackedPrefHistogramCount(
+               user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
+               ALLOW_NONE));
   }
 };
 
@@ -813,42 +838,49 @@
     // not protecting; if protection is enabled the change should be a no-op.
     int changed_expected =
         protection_level_ == PROTECTION_DISABLED_FOR_GROUP ? 1 : 0;
-    EXPECT_EQ(
-        (protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
-         protection_level_ < PROTECTION_ENABLED_BASIC) ? changed_expected : 0,
-        GetTrackedPrefHistogramCount("Settings.TrackedPreferenceChanged",
-                                     BEGIN_ALLOW_SINGLE_BUCKET + 3));
-    EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
-                  ? num_tracked_prefs() - changed_expected : 0,
+    EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
+               protection_level_ < PROTECTION_ENABLED_BASIC)
+                  ? changed_expected
+                  : 0,
               GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceUnchanged", ALLOW_ANY));
-
+                  user_prefs::tracked::kTrackedPrefHistogramChanged,
+                  BEGIN_ALLOW_SINGLE_BUCKET + 3));
     EXPECT_EQ(
-        (protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
-         protection_level_ < PROTECTION_ENABLED_BASIC) ? 1 : 0,
-        GetTrackedPrefHistogramCount("Settings.TrackedPreferenceWantedReset",
-                                     BEGIN_ALLOW_SINGLE_BUCKET + 3));
+        protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
+            ? num_tracked_prefs() - changed_expected
+            : 0,
+        GetTrackedPrefHistogramCount(
+            user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
+
+    EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
+               protection_level_ < PROTECTION_ENABLED_BASIC)
+                  ? 1
+                  : 0,
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramWantedReset,
+                  BEGIN_ALLOW_SINGLE_BUCKET + 3));
     EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceReset",
-                                           ALLOW_NONE));
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramReset, ALLOW_NONE));
 
     // Nothing else should have triggered.
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceCleared",
-                                           ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceInitialized", ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceTrustedInitialized", ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceNullInitialized", ALLOW_NONE));
     EXPECT_EQ(
-        0,
-        GetTrackedPrefHistogramCount(
-            "Settings.TrackedPreferenceMigratedLegacyDeviceId", ALLOW_NONE));
+        0, GetTrackedPrefHistogramCount(
+               user_prefs::tracked::kTrackedPrefHistogramCleared, ALLOW_NONE));
+    EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+                     user_prefs::tracked::kTrackedPrefHistogramInitialized,
+                     ALLOW_NONE));
+    EXPECT_EQ(0,
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
+                  ALLOW_NONE));
+    EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+                     user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
+                     ALLOW_NONE));
+    EXPECT_EQ(
+        0, GetTrackedPrefHistogramCount(
+               user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
+               ALLOW_NONE));
   }
 };
 
@@ -886,39 +918,43 @@
         protection_level_ >= PROTECTION_ENABLED_BASIC
         ? 1 : 0;
     EXPECT_EQ(changed_expected,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceChanged",
-                                           BEGIN_ALLOW_SINGLE_BUCKET + 2));
-    EXPECT_EQ(cleared_expected,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceCleared",
-                                           BEGIN_ALLOW_SINGLE_BUCKET + 2));
-    EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
-                  ? num_tracked_prefs() - changed_expected - cleared_expected
-                  : 0,
               GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceUnchanged", ALLOW_ANY));
-
+                  user_prefs::tracked::kTrackedPrefHistogramChanged,
+                  BEGIN_ALLOW_SINGLE_BUCKET + 2));
+    EXPECT_EQ(cleared_expected,
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramCleared,
+                  BEGIN_ALLOW_SINGLE_BUCKET + 2));
     EXPECT_EQ(
-        changed_expected,
-        GetTrackedPrefHistogramCount("Settings.TrackedPreferenceWantedReset",
-                                     BEGIN_ALLOW_SINGLE_BUCKET + 2));
+        protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
+            ? num_tracked_prefs() - changed_expected - cleared_expected
+            : 0,
+        GetTrackedPrefHistogramCount(
+            user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
+
+    EXPECT_EQ(changed_expected,
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramWantedReset,
+                  BEGIN_ALLOW_SINGLE_BUCKET + 2));
     EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount("Settings.TrackedPreferenceReset",
-                                           ALLOW_NONE));
+              GetTrackedPrefHistogramCount(
+                  user_prefs::tracked::kTrackedPrefHistogramReset, ALLOW_NONE));
 
     // Nothing else should have triggered.
+    EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+                     user_prefs::tracked::kTrackedPrefHistogramInitialized,
+                     ALLOW_NONE));
     EXPECT_EQ(0,
               GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceInitialized", ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceTrustedInitialized", ALLOW_NONE));
-    EXPECT_EQ(0,
-              GetTrackedPrefHistogramCount(
-                  "Settings.TrackedPreferenceNullInitialized", ALLOW_NONE));
+                  user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
+                  ALLOW_NONE));
+    EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+                     user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
+                     ALLOW_NONE));
     EXPECT_EQ(
-        0,
-        GetTrackedPrefHistogramCount(
-            "Settings.TrackedPreferenceMigratedLegacyDeviceId", ALLOW_NONE));
+        0, GetTrackedPrefHistogramCount(
+               user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
+               ALLOW_NONE));
   }
 };
 
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc
index 29910137..2b311ed 100644
--- a/chrome/browser/prerender/prerender_contents.cc
+++ b/chrome/browser/prerender/prerender_contents.cc
@@ -92,15 +92,21 @@
                               const OpenURLParams& params) override {
     // |OpenURLFromTab| is typically called when a frame performs a navigation
     // that requires the browser to perform the transition instead of WebKit.
-    // Examples include prerendering a site that redirects to an app URL, or if
-    // --site-per-process is specified and the prerendered frame redirects to a
-    // different origin.
+    // Examples include client redirects to hosted app URLs.
     // TODO(cbentzel): Consider supporting this for CURRENT_TAB dispositions, if
     // it is a common case during prerenders.
     prerender_contents_->Destroy(FINAL_STATUS_OPEN_URL);
     return NULL;
   }
 
+  bool ShouldTransferNavigation() override {
+    // Cancel the prerender if the navigation attempts to transfer to a
+    // different process.  Examples include server redirects to privileged pages
+    // or cross-site subframe navigations in --site-per-process.
+    prerender_contents_->Destroy(FINAL_STATUS_OPEN_URL);
+    return false;
+  }
+
   void CloseContents(content::WebContents* contents) override {
     prerender_contents_->Destroy(FINAL_STATUS_CLOSED);
   }
diff --git a/chrome/browser/process_singleton_posix.cc b/chrome/browser/process_singleton_posix.cc
index 81a5c5f..bc89b11 100644
--- a/chrome/browser/process_singleton_posix.cc
+++ b/chrome/browser/process_singleton_posix.cc
@@ -221,9 +221,8 @@
   int sock = socket(PF_UNIX, SOCK_STREAM, 0);
   PCHECK(sock >= 0) << "socket() failed";
 
-  int rv = net::SetNonBlocking(sock);
-  DCHECK_EQ(0, rv) << "Failed to make non-blocking socket.";
-  rv = SetCloseOnExec(sock);
+  DCHECK(base::SetNonBlocking(sock)) << "Failed to make non-blocking socket.";
+  int rv = SetCloseOnExec(sock);
   DCHECK_EQ(0, rv) << "Failed to set CLOEXEC on socket.";
 
   return sock;
@@ -590,8 +589,8 @@
     PLOG(ERROR) << "accept() failed";
     return;
   }
-  int rv = net::SetNonBlocking(connection_socket);
-  DCHECK_EQ(0, rv) << "Failed to make non-blocking socket.";
+  DCHECK(base::SetNonBlocking(connection_socket))
+      << "Failed to make non-blocking socket.";
   SocketReader* reader = new SocketReader(this,
                                           ui_message_loop_,
                                           connection_socket);
diff --git a/chrome/browser/resources/help/help_page.js b/chrome/browser/resources/help/help_page.js
index 7e075f2..4269098 100644
--- a/chrome/browser/resources/help/help_page.js
+++ b/chrome/browser/resources/help/help_page.js
@@ -165,7 +165,9 @@
       var logo = $('product-logo');
       logo.onclick = function(e) {
         logo.classList.remove('spin');
-        setTimeout(function() { logo.classList.add('spin'); }, 0);
+        // Force a style recalc that cancels the animation specified by "spin".
+        getComputedStyle(logo).getPropertyValue('animation-name');
+        logo.classList.add('spin');
       };
 
       // Attempt to update.
diff --git a/chrome/browser/resources/options/password_manager_list.js b/chrome/browser/resources/options/password_manager_list.js
index 65a388c..58bd5ef 100644
--- a/chrome/browser/resources/options/password_manager_list.js
+++ b/chrome/browser/resources/options/password_manager_list.js
@@ -12,6 +12,7 @@
   // chrome/browser/ui/webui/options/password_manager_handler.cc.
   /** @const */ var ORIGIN_FIELD = 'origin';
   /** @const */ var SHOWN_URL_FIELD = 'shownUrl';
+  /** @const */ var IS_ANDROID_URI_FIELD = 'isAndroidUri';
   /** @const */ var IS_SECURE_FIELD = 'isSecure';
   /** @const */ var USERNAME_FIELD = 'username';
   /** @const */ var PASSWORD_FIELD = 'password';
@@ -22,9 +23,8 @@
    * Creates a new passwords list item.
    * @param {cr.ui.ArrayDataModel} dataModel The data model that contains this
    *     item.
-   * @param {Array} entry An array of the form [url, username, password,
-   *     federation]. When the list has been filtered, a fifth element [index]
-   *     may be present.
+   * @param {Object} entry A dictionary of data on new list item. When the
+   *     list has been filtered, one more element [index] may be present.
    * @param {boolean} showPasswords If true, add a button to the element to
    *     allow the user to reveal the saved password.
    * @constructor
@@ -42,23 +42,53 @@
   }
 
   /**
-   * Returns title for password's origin (removes the scheme if the url is
-   * insecure and removes trailing punctuation symbols).
-   * @param {string} url The url.
-   * @param {boolean} isSecure True if the url is secure.
+   * Returns title for password's origin. If the origin is  Android URI, returns
+   * the origin as it is. Removes the scheme if the url is insecure and removes
+   * trailing punctuation symbols.
+   * @param {Object} item A dictionary of data on the list item.
    * @return {string} The title for password's origin.
    */
-  function getTitleForPasswordOrigin(url, isSecure) {
-    if (!isSecure) {
-      var ind = url.indexOf('://');
+  function getTitleForPasswordOrigin(item) {
+    var title = item.url;
+    if (item.isAndroidUri)
+      return title;
+    if (!item.isSecure) {
+      var ind = title.indexOf('://');
       if (ind >= 0) {
-        url = url.substring(ind + 3);
+        title = title.substring(ind + 3);
       }
     }
     // Since the direction is switched to RTL, punctuation symbols appear on the
     // left side, that is wrong. So, just remove trailing punctuation symbols.
-    url = url.replace(/[^A-Za-z0-9]+$/, '');
-    return url;
+    title = title.replace(/[^A-Za-z0-9]+$/, '');
+    return title;
+  }
+
+  /**
+   * Helper function that creates an HTML element for displaying the origin of
+   * saved password.
+   * @param {Object} item A dictionary of data on the list item.
+   * @param {Element} urlDiv div-element that will enclose the created
+   *     element.
+   * @return {Element} The element for displaying password origin.
+   */
+  function createUrlLink(item, urlDiv) {
+    var urlLink;
+    if (!item.isAndroidUri) {
+      urlLink = item.ownerDocument.createElement('a');
+      urlLink.href = item.url;
+      urlLink.setAttribute('target', '_blank');
+      urlLink.textContent = item.shownUrl.split('').reverse().join('');
+
+      urlDiv.classList.add('left-elided-url');
+    } else {
+      urlLink = item.ownerDocument.createElement('span');
+      urlLink.textContent = item.shownUrl;
+    }
+    urlLink.addEventListener('focus', function() {
+      item.handleFocus();
+    }.bind(item));
+    return urlLink;
   }
 
   PasswordListItem.prototype = {
@@ -70,21 +100,15 @@
 
       // The URL of the site.
       var urlDiv = this.ownerDocument.createElement('div');
-      urlDiv.className = 'favicon-cell left-elided-url url';
-      urlDiv.setAttribute(
-          'title', getTitleForPasswordOrigin(this.url, this.isUrlSecure));
-      var urlLink = this.ownerDocument.createElement('a');
-      urlLink.href = this.url;
-      urlLink.setAttribute('target', '_blank');
-      urlLink.textContent = this.shownUrl.split('').reverse().join('');
-      urlLink.addEventListener('focus', function() {
-        this.handleFocus();
-      }.bind(this));
-      urlDiv.appendChild(urlLink);
+      urlDiv.className = 'favicon-cell url';
+      urlDiv.setAttribute('title', getTitleForPasswordOrigin(this));
       urlDiv.style.backgroundImage = getFaviconImageSet(
           'origin/' + this.url, 16);
+
+      this.urlLink = createUrlLink(this, urlDiv);
+      urlDiv.appendChild(this.urlLink);
+
       this.contentElement.appendChild(urlDiv);
-      this.urlLink = urlLink;
 
       // The stored username.
       var usernameDiv = this.ownerDocument.createElement('div');
@@ -107,6 +131,7 @@
         var federationDiv = this.ownerDocument.createElement('div');
         federationDiv.className = 'federation';
         federationDiv.textContent = this.federation;
+        federationDiv.title = this.federation;
         this.contentElement.appendChild(federationDiv);
       } else {
         // The stored password.
@@ -124,7 +149,6 @@
           this.handleFocus();
         }.bind(this));
         this.passwordField = passwordInput;
-        this.setFocusable_(false);
 
         // The show/hide button.
         if (this.showPasswords_) {
@@ -147,6 +171,7 @@
         }
         this.contentElement.appendChild(passwordInputDiv);
       }
+      this.setFocusable_(false);
     },
 
     /** @override */
@@ -154,21 +179,24 @@
       var usernameInput = this.usernameField;
       var passwordInput = this.passwordField;
       var button = this.passwordShowButton;
-      // The button doesn't exist when passwords can't be shown.
-      if (!button)
-        return;
+
+      this.setFocusable_(this.selected);
 
       if (this.selected) {
         usernameInput.classList.remove('inactive-item');
-        passwordInput.classList.remove('inactive-item');
-        this.setFocusable_(true);
-        button.hidden = false;
-        passwordInput.focus();
+        if (button) {
+          passwordInput.classList.remove('inactive-item');
+          button.hidden = false;
+          passwordInput.focus();
+        } else {
+          usernameInput.focus();
+        }
       } else {
         usernameInput.classList.add('inactive-item');
-        passwordInput.classList.add('inactive-item');
-        this.setFocusable_(false);
-        button.hidden = true;
+        if (button) {
+          passwordInput.classList.add('inactive-item');
+          button.hidden = true;
+        }
       }
     },
 
@@ -181,8 +209,9 @@
       var tabIndex = focusable ? 0 : -1;
       this.urlLink.tabIndex = tabIndex;
       this.usernameField.tabIndex = tabIndex;
-      this.passwordField.tabIndex = tabIndex;
       this.closeButtonElement.tabIndex = tabIndex;
+      if (this.passwordShowButton)
+        this.passwordField.tabIndex = tabIndex;
     },
 
     /**
@@ -255,14 +284,25 @@
     },
 
     /**
+     * Get and set whether the origin is Android URI.
+     * @type {boolean}
+     */
+    get isAndroidUri() {
+      return this.dataItem[IS_ANDROID_URI_FIELD];
+    },
+    set isAndroidUri(isAndroidUri) {
+      this.dataItem[IS_ANDROID_URI_FIELD] = isAndroidUri;
+    },
+
+    /**
      * Get and set whether the origin uses secure scheme.
      * @type {boolean}
      */
-    get isUrlSecure() {
+    get isSecure() {
       return this.dataItem[IS_SECURE_FIELD];
     },
-    set isUrlSecure(isUrlSecure) {
-      this.dataItem[IS_SECURE_FIELD] = isUrlSecure;
+    set isSecure(isSecure) {
+      this.dataItem[IS_SECURE_FIELD] = isSecure;
     },
 
     /**
@@ -301,7 +341,7 @@
 
   /**
    * Creates a new PasswordExceptions list item.
-   * @param {Array} entry A pair of the form [url, username].
+   * @param {Object} entry A dictionary of data on new list item.
    * @constructor
    * @extends {options.DeletableItem}
    */
@@ -325,22 +365,14 @@
 
       // The URL of the site.
       var urlDiv = this.ownerDocument.createElement('div');
-      urlDiv.className = 'url';
-      urlDiv.classList.add('favicon-cell');
-      urlDiv.classList.add('left-elided-url');
-      urlDiv.setAttribute(
-          'title', getTitleForPasswordOrigin(this.url, this.isUrlSecure));
-      var urlLink = this.ownerDocument.createElement('a');
-      urlLink.href = this.url;
-      urlLink.textContent = this.shownUrl.split('').reverse().join('');
-      urlLink.setAttribute('target', '_blank');
-      urlLink.addEventListener('focus', function() {
-        this.handleFocus();
-      }.bind(this));
-      this.urlLink = urlLink;
-      urlDiv.appendChild(urlLink);
+      urlDiv.className = 'favicon-cell url';
+      urlDiv.setAttribute('title', getTitleForPasswordOrigin(this));
       urlDiv.style.backgroundImage = getFaviconImageSet(
-          'origin/' + this.url, 16);
+        'origin/' + this.url, 16);
+
+      this.urlLink = createUrlLink(this, urlDiv);
+      urlDiv.appendChild(this.urlLink);
+
       this.contentElement.appendChild(urlDiv);
     },
 
@@ -388,14 +420,25 @@
     },
 
     /**
+     * Get and set whether the origin is Android URI.
+     * @type {boolean}
+     */
+    get isAndroidUri() {
+      return this.dataItem[IS_ANDROID_URI_FIELD];
+    },
+    set isAndroidUri(isAndroidUri) {
+      this.dataItem[IS_ANDROID_URI_FIELD] = isAndroidUri;
+    },
+
+    /**
      * Get and set whether the origin uses secure scheme.
      * @type {boolean}
      */
-    get isUrlSecure() {
+    get isSecure() {
       return this.dataItem[IS_SECURE_FIELD];
     },
-    set isUrlSecure(isUrlSecure) {
-      this.dataItem[IS_SECURE_FIELD] = isUrlSecure;
+    set isSecure(isSecure) {
+      this.dataItem[IS_SECURE_FIELD] = isSecure;
     },
   };
 
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.html b/chrome/browser/resources/settings/basic_page/basic_page.html
index 17d14058..bad3074b 100644
--- a/chrome/browser/resources/settings/basic_page/basic_page.html
+++ b/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -5,6 +5,7 @@
 <link rel="import" href="chrome://md-settings/settings_page/settings_section.html">
 <link rel="import" href="chrome://md-settings/on_startup_page/on_startup_page.html">
 <link rel="import" href="chrome://md-settings/people_page/people_page.html">
+<link rel="import" href="chrome://md-settings/reset_page/reset_profile_banner.html">
 
 <if expr="chromeos">
 <link rel="import" href="chrome://md-settings/internet_page/internet_page.html">
@@ -17,6 +18,10 @@
 <dom-module id="settings-basic-page">
   <link rel="import" type="css" href="basic_page.css">
   <template>
+    <template is="dom-if" if="[[showResetProfileBanner_]]">
+      <settings-reset-profile-banner on-reset-done="onResetDone_">
+      </settings-reset-profile-banner>
+    </template>
     <template is="dom-if" if="[[showPage(pageVisibility.people)]]" restamp>
       <settings-section i18n-values="page-title:peoplePageTitle"
           current-route="[[currentRoute]]" section="people">
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.js b/chrome/browser/resources/settings/basic_page/basic_page.js
index ab22984..b215d099 100644
--- a/chrome/browser/resources/settings/basic_page/basic_page.js
+++ b/chrome/browser/resources/settings/basic_page/basic_page.js
@@ -35,6 +35,16 @@
       type: Object,
       notify: true,
     },
+
+    showResetProfileBanner_: {
+      type: Boolean,
+      value: loadTimeData.getBoolean('showResetProfileBanner'),
+    },
+
+  },
+
+  onResetDone_: function() {
+    this.showResetProfileBanner_ = false;
   },
 
   behaviors: [SettingsPageVisibility],
diff --git a/chrome/browser/resources/settings/reset_page/reset_profile_banner.css b/chrome/browser/resources/settings/reset_page/reset_profile_banner.css
new file mode 100644
index 0000000..dd6a4c2
--- /dev/null
+++ b/chrome/browser/resources/settings/reset_page/reset_profile_banner.css
@@ -0,0 +1,42 @@
+/* Copyright 2015 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#banner-content {
+  background-color: white;
+  border: 1px solid #c8c8c8;
+  border-radius: 3px;
+  margin-bottom: 24px;
+}
+
+#top-row {
+  display: flex;
+  justify-content: flex-end;
+}
+
+#main-body {
+  align-items: center;
+  display: flex;
+  padding: 0 17px 17px;
+}
+
+#description {
+  -webkit-margin-start: 18px;
+  flex: 1;
+}
+
+#close {
+  height: 30px;
+}
+
+#reset {
+  -webkit-margin-start: 30px;
+  background-color: rgb(66, 133, 244);
+  color: white;
+  font-weight: 500;
+}
+
+a {
+  color: rgb(66, 133, 244);
+  text-decoration: none;
+}
diff --git a/chrome/browser/resources/settings/reset_page/reset_profile_banner.html b/chrome/browser/resources/settings/reset_page/reset_profile_banner.html
new file mode 100644
index 0000000..6881444
--- /dev/null
+++ b/chrome/browser/resources/settings/reset_page/reset_profile_banner.html
@@ -0,0 +1,31 @@
+<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
+<link rel="import" href="chrome://md-settings/reset_page/reset_profile_dialog.html">
+
+<dom-module id="settings-reset-profile-banner">
+  <link rel="import" type="css" href="reset_profile_banner.css">
+  <template>
+    <div id="banner-content">
+      <div id="top-row">
+        <paper-icon-button icon="clear" on-tap="onCloseTap_" id="close">
+        </paper-icon-button>
+      </div>
+      <div id="main-body">
+        <span id="description">
+          <span i18n-content="resetProfileBannerDescription"></span>
+          <a id="learnMore"
+             i18n-values="href:resetProfileBannerLearnMoreUrl"
+             i18n-content="learnMore" target="_blank"></a>
+        </span>
+        <paper-button id="reset" on-tap="showDialog_"
+            i18n-content="resetProfileBannerButton"></paper-button>
+      </div>
+    </div>
+    <template is="dom-if" if="[[showResetProfileDialog_]]">
+      <settings-reset-profile-dialog on-reset-done="onResetDone_">
+      </settings-reset-profile-dialog>
+    </template>
+  </template>
+  <script src="reset_profile_banner.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/settings/reset_page/reset_profile_banner.js b/chrome/browser/resources/settings/reset_page/reset_profile_banner.js
new file mode 100644
index 0000000..549496c8
--- /dev/null
+++ b/chrome/browser/resources/settings/reset_page/reset_profile_banner.js
@@ -0,0 +1,44 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ * 'settings-reset-profile-banner' is the banner shown for clearing profile
+ * settings.
+ *
+ * @group Chrome Settings Elements
+ * @element settings-reset-profile-banner
+ */
+Polymer({
+  is: 'settings-reset-profile-banner',
+
+  properties: {
+    showResetProfileDialog_: {
+      type: Boolean,
+      value: false,
+    },
+  },
+
+  /** @private */
+  onCloseTap_: function() {
+    chrome.send('onHideResetProfileBanner');
+    this.remove();
+  },
+
+  /**
+   * Creates and shows a <settings-reset-profile-dialog>.
+   * @private
+   */
+  showDialog_: function(dialogName) {
+    this.showResetProfileDialog_ = true;
+    this.async(function() {
+      var dialog = this.$$('settings-reset-profile-dialog');
+      dialog.open();
+    }.bind(this));
+  },
+
+  onResetDone_: function() {
+    this.showResetProfileDialog_ = false;
+  },
+});
diff --git a/chrome/browser/resources/settings/reset_page/reset_profile_dialog.js b/chrome/browser/resources/settings/reset_page/reset_profile_dialog.js
index 9ba069b..b639054 100644
--- a/chrome/browser/resources/settings/reset_page/reset_profile_dialog.js
+++ b/chrome/browser/resources/settings/reset_page/reset_profile_dialog.js
@@ -23,6 +23,7 @@
         doneResetting: function() {
           this.$.resetSpinner.active = false;
           this.$.dialog.close();
+          this.dispatchResetDoneEvent();
         }.bind(this),
 
         setFeedbackInfo: function(data) {
@@ -35,6 +36,10 @@
     }.bind(this));
   },
 
+  dispatchResetDoneEvent: function() {
+    this.dispatchEvent(new CustomEvent('reset-done'));
+  },
+
   open: function() {
     this.$.dialog.open();
     chrome.send('onShowResetProfileDialog');
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index 1a10679..80d4cc28 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -260,6 +260,15 @@
       <structure name="IDR_SETTINGS_RESET_PROFILE_DIALOG_JS"
                  file="reset_page/reset_profile_dialog.js"
                  type="chrome_html" />
+      <structure name="IDR_SETTINGS_RESET_PROFILE_BANNER_CSS"
+                 file="reset_page/reset_profile_banner.css"
+                 type="chrome_html" />
+      <structure name="IDR_SETTINGS_RESET_PROFILE_BANNER_HTML"
+                 file="reset_page/reset_profile_banner.html"
+                 type="chrome_html" />
+      <structure name="IDR_SETTINGS_RESET_PROFILE_BANNER_JS"
+                 file="reset_page/reset_profile_banner.js"
+                 type="chrome_html"/>
       <structure name="IDR_SETTINGS_LANGUAGES_HTML"
                  file="languages_page/languages.html"
                  type="chrome_html" />
diff --git a/chrome/browser/task_management/providers/arc/arc_process_task.cc b/chrome/browser/task_management/providers/arc/arc_process_task.cc
new file mode 100644
index 0000000..c24e17b4
--- /dev/null
+++ b/chrome/browser/task_management/providers/arc/arc_process_task.cc
@@ -0,0 +1,47 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/task_management/providers/arc/arc_process_task.h"
+
+#include "base/i18n/rtl.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace task_management {
+
+namespace {
+
+base::string16 MakeTitle(const std::string& process_name) {
+  base::string16 title =
+      l10n_util::GetStringFUTF16(
+          IDS_TASK_MANAGER_ARC_PREFIX, base::UTF8ToUTF16(process_name));
+  base::i18n::AdjustStringForLocaleDirection(&title);
+  return title;
+}
+
+}  // namespace
+
+ArcProcessTask::ArcProcessTask(
+    base::ProcessId pid,
+    base::ProcessId nspid,
+    const std::string& process_name)
+    : Task(MakeTitle(process_name), process_name, nullptr, pid),
+      nspid_(nspid),
+      process_name_(process_name) {
+}
+
+ArcProcessTask::~ArcProcessTask() {
+}
+
+Task::Type ArcProcessTask::GetType() const {
+  return Task::ARC;
+}
+
+int ArcProcessTask::GetChildProcessUniqueID() const {
+  // ARC process is not a child process of the browser.
+  return 0;
+}
+
+}  // namespace task_management
diff --git a/chrome/browser/task_management/providers/arc/arc_process_task.h b/chrome/browser/task_management/providers/arc/arc_process_task.h
new file mode 100644
index 0000000..1e03568
--- /dev/null
+++ b/chrome/browser/task_management/providers/arc/arc_process_task.h
@@ -0,0 +1,40 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_ARC_ARC_PROCESS_TASK_H_
+#define CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_ARC_ARC_PROCESS_TASK_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "chrome/browser/task_management/providers/task.h"
+
+namespace task_management {
+
+// Defines a task that represents an ARC process.
+class ArcProcessTask : public Task {
+ public:
+  ArcProcessTask(
+      base::ProcessId pid,
+      base::ProcessId nspid,
+      const std::string& process_name);
+  ~ArcProcessTask() override;
+
+  // task_management::Task:
+  Type GetType() const override;
+  int GetChildProcessUniqueID() const override;
+
+  base::ProcessId nspid() const { return nspid_; }
+  const std::string& process_name() const { return process_name_; }
+
+ private:
+  const base::ProcessId nspid_;
+  const std::string process_name_;
+
+  DISALLOW_COPY_AND_ASSIGN(ArcProcessTask);
+};
+
+}  // namespace task_management
+
+#endif  // CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_ARC_ARC_PROCESS_TASK_H_
diff --git a/chrome/browser/task_management/providers/arc/arc_process_task_provider.cc b/chrome/browser/task_management/providers/arc/arc_process_task_provider.cc
new file mode 100644
index 0000000..52820a6
--- /dev/null
+++ b/chrome/browser/task_management/providers/arc/arc_process_task_provider.cc
@@ -0,0 +1,181 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/task_management/providers/arc/arc_process_task_provider.h"
+
+#include <queue>
+#include <set>
+#include <utility>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/process/process.h"
+#include "base/process/process_iterator.h"
+#include "base/task_runner_util.h"
+#include "base/threading/worker_pool.h"
+#include "base/trace_event/trace_event.h"
+#include "components/arc/arc_bridge_service.h"
+
+namespace {
+
+// Computes a map from PID in ARC namespace to PID in system namespace.
+// The returned map contains ARC processes only.
+std::map<base::ProcessId, base::ProcessId> ComputeNspidToPidMap() {
+  TRACE_EVENT0("browser", "ComputeNspidToPidMap");
+
+  // NB: Despite of its name, ProcessIterator::Snapshot() may return
+  // inconsistent information because it simply walks procfs. Especially
+  // we must not assume the parent-child relationships are consistent.
+  const base::ProcessIterator::ProcessEntries& entry_list =
+      base::ProcessIterator(nullptr).Snapshot();
+
+  // System may contain many different namespaces so several different
+  // processes may have the same nspid. We need to get the proper subset of
+  // processes to create correct nspid -> pid map.
+
+  // Construct the process tree.
+  // NB: This can contain a loop in case of race conditions.
+  std::map<base::ProcessId, std::vector<base::ProcessId> > process_tree;
+  for (const base::ProcessEntry& entry : entry_list)
+    process_tree[entry.parent_pid()].push_back(entry.pid());
+
+  // Find the ARC init process.
+  base::ProcessId arc_init_pid = base::kNullProcessId;
+  for (const base::ProcessEntry& entry : entry_list) {
+    // TODO(nya): Add more constraints to avoid mismatches.
+    std::string process_name =
+        !entry.cmd_line_args().empty() ? entry.cmd_line_args()[0] : "";
+    if (process_name == "/init") {
+      arc_init_pid = entry.pid();
+      break;
+    }
+  }
+
+  // Enumerate all processes under ARC init and create nspid -> pid map.
+  std::map<base::ProcessId, base::ProcessId> nspid_to_pid;
+  if (arc_init_pid != base::kNullProcessId) {
+    std::queue<base::ProcessId> queue;
+    std::set<base::ProcessId> visited;
+    queue.push(arc_init_pid);
+    while (!queue.empty()) {
+      base::ProcessId pid = queue.front();
+      queue.pop();
+      // Do not visit the same process twice. Otherwise we may enter an infinite
+      // loop if |process_tree| contains a loop.
+      if (!visited.insert(pid).second)
+        continue;
+      base::ProcessId nspid = base::Process(pid).GetPidInNamespace();
+      // All ARC processes should be in namespace so nspid is usually non-null,
+      // but this can happen if the process has already gone.
+      if (nspid != base::kNullProcessId)
+        nspid_to_pid[nspid] = pid;
+      for (base::ProcessId child_pid : process_tree[pid])
+        queue.push(child_pid);
+    }
+  }
+  return nspid_to_pid;
+}
+
+}  // namespace
+
+namespace task_management {
+
+ArcProcessTaskProvider::ArcProcessTaskProvider()
+    : weak_ptr_factory_(this) {
+}
+
+ArcProcessTaskProvider::~ArcProcessTaskProvider() {
+}
+
+Task* ArcProcessTaskProvider::GetTaskOfUrlRequest(int origin_pid,
+                                                  int child_id,
+                                                  int route_id) {
+  // ARC tasks are not associated with any URL request.
+  return nullptr;
+}
+
+void ArcProcessTaskProvider::OnUpdateProcessList(
+    const std::vector<arc::RunningAppProcessInfo>& processes) {
+  TRACE_EVENT0("browser", "ArcProcessTaskProvider::OnUpdateProcessList");
+
+  // NB: |processes| can be already stale here because it is sent via IPC, and
+  // we can never avoid that. See also the comment at the declaration of
+  // ArcProcessTaskProvider.
+
+  std::vector<arc::RunningAppProcessInfo> added_processes;
+  std::set<base::ProcessId> removed_nspids;
+  for (const auto& entry : nspid_to_task_)
+    removed_nspids.insert(entry.first);
+  for (const arc::RunningAppProcessInfo& process : processes) {
+    if (nspid_to_task_.count(process.pid))
+      removed_nspids.erase(process.pid);
+    else
+      added_processes.push_back(process);
+  }
+
+  // Remove stale tasks.
+  RemoveTasks(removed_nspids);
+
+  // Add new tasks.
+  // Note: ComputeNspidToPidMap() is an expensive operation, so try to reduce
+  // the number of times it is called.
+  if (!added_processes.empty()) {
+    base::PostTaskAndReplyWithResult(
+        base::WorkerPool::GetTaskRunner(false /* task_is_slow */).get(),
+        FROM_HERE,
+        base::Bind(&ComputeNspidToPidMap),
+        base::Bind(&ArcProcessTaskProvider::AddTasks,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   added_processes));
+  }
+}
+
+void ArcProcessTaskProvider::RequestProcessList() {
+  arc::ArcBridgeService::Get()->RequestProcessList();
+}
+
+void ArcProcessTaskProvider::RemoveTasks(
+    const std::set<base::ProcessId>& removed_nspids) {
+  for (base::ProcessId nspid : removed_nspids) {
+    NotifyObserverTaskRemoved(nspid_to_task_[nspid].get());
+    nspid_to_task_.erase(nspid);
+  }
+}
+
+void ArcProcessTaskProvider::AddTasks(
+    const std::vector<arc::RunningAppProcessInfo>& added_processes,
+    const std::map<base::ProcessId, base::ProcessId>& nspid_to_pid) {
+  for (const arc::RunningAppProcessInfo& process : added_processes) {
+    auto iter = nspid_to_pid.find(process.pid);
+    if (iter == nspid_to_pid.end()) {
+      // The process may have exited just after the snapshot was generated.
+      continue;
+    }
+    base::ProcessId pid = iter->second;
+    scoped_ptr<ArcProcessTask>& task = nspid_to_task_[process.pid];
+    task.reset(new ArcProcessTask(pid, process.pid, process.process_name));
+    NotifyObserverTaskAdded(task.get());
+  }
+}
+
+void ArcProcessTaskProvider::StartUpdating() {
+  arc::ArcBridgeService::Get()->AddProcessObserver(this);
+  RequestProcessList();
+  // TODO(nya): Remove this timer once ARC starts to send us UpdateProcessList
+  // message when the process list changed. As of today, ARC does not send
+  // the process list unless we request it by RequestProcessList message.
+  timer_.Start(
+      FROM_HERE,
+      base::TimeDelta::FromSeconds(1),
+      this,
+      &ArcProcessTaskProvider::RequestProcessList);
+}
+
+void ArcProcessTaskProvider::StopUpdating() {
+  arc::ArcBridgeService::Get()->RemoveProcessObserver(this);
+  timer_.Stop();
+  nspid_to_task_.clear();
+}
+
+}  // namespace task_management
diff --git a/chrome/browser/task_management/providers/arc/arc_process_task_provider.h b/chrome/browser/task_management/providers/arc/arc_process_task_provider.h
new file mode 100644
index 0000000..b4f7ce2
--- /dev/null
+++ b/chrome/browser/task_management/providers/arc/arc_process_task_provider.h
@@ -0,0 +1,73 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_ARC_ARC_PROCESS_TASK_PROVIDER_H_
+#define CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_ARC_ARC_PROCESS_TASK_PROVIDER_H_
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
+#include "chrome/browser/task_management/providers/arc/arc_process_task.h"
+#include "chrome/browser/task_management/providers/task_provider.h"
+#include "components/arc/arc_bridge_service.h"
+
+namespace base {
+class Timer;
+}  // namespace base
+
+namespace task_management {
+
+// This provides the ARC process tasks.
+//
+// Since this provider obtains ARC process information via IPC and procfs,
+// it can never avoid race conditions. For example, in an extreme case such as
+// fork(2) is called millions of times in a second, this provider can return
+// wrong results. However, its chance is very low, and even if we hit the case,
+// the worst outcome is just that an Android app (non-system) process which
+// the user did not intend to choose is killed. Since Android apps are designed
+// to be killed at any time, it sounds acceptable.
+class ArcProcessTaskProvider : public TaskProvider,
+                               public arc::ArcBridgeService::ProcessObserver {
+ public:
+  ArcProcessTaskProvider();
+  ~ArcProcessTaskProvider() override;
+
+  // task_management::TaskProvider:
+  Task* GetTaskOfUrlRequest(int origin_pid,
+                            int child_id,
+                            int route_id) override;
+
+  // arc::ArcBridgeService::ProcessObserver:
+  void OnUpdateProcessList(
+      const std::vector<arc::RunningAppProcessInfo>& processes) override;
+
+ private:
+  void RequestProcessList();
+
+  void RemoveTasks(const std::set<base::ProcessId>& removed_nspids);
+  void AddTasks(const std::vector<arc::RunningAppProcessInfo>& added_processes,
+                const std::map<base::ProcessId, base::ProcessId>& nspid_to_pid);
+
+  // task_management::TaskProvider:
+  void StartUpdating() override;
+  void StopUpdating() override;
+
+  std::map<base::ProcessId, scoped_ptr<ArcProcessTask> > nspid_to_task_;
+  base::RepeatingTimer timer_;
+
+  // Always keep this the last member of this class to make sure it's the
+  // first thing to be destructed.
+  base::WeakPtrFactory<ArcProcessTaskProvider> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ArcProcessTaskProvider);
+};
+
+}  // namespace task_management
+
+#endif  // CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_ARC_ARC_PROCESS_TASK_PROVIDER_H_
diff --git a/chrome/browser/task_management/providers/task.h b/chrome/browser/task_management/providers/task.h
index da85d86c..441d7b1 100644
--- a/chrome/browser/task_management/providers/task.h
+++ b/chrome/browser/task_management/providers/task.h
@@ -36,6 +36,7 @@
     ZYGOTE,         /* A Linux zygote process. */
     SANDBOX_HELPER, /* A sandbox helper process. */
     GPU,            /* A graphics process. */
+    ARC,            /* An ARC process. */
   };
 
   // Create a task with the given |title| and the given favicon |icon|. This
diff --git a/chrome/browser/task_management/sampling/task_manager_impl.cc b/chrome/browser/task_management/sampling/task_manager_impl.cc
index 57480fb..7f1c6edc 100644
--- a/chrome/browser/task_management/sampling/task_manager_impl.cc
+++ b/chrome/browser/task_management/sampling/task_manager_impl.cc
@@ -11,6 +11,10 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/gpu_data_manager.h"
 
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/task_management/providers/arc/arc_process_task_provider.h"
+#endif  // defined(OS_CHROMEOS)
+
 namespace task_management {
 
 namespace {
@@ -39,6 +43,9 @@
   task_providers_.push_back(new BrowserProcessTaskProvider());
   task_providers_.push_back(new ChildProcessTaskProvider());
   task_providers_.push_back(new WebContentsTaskProvider());
+#if defined(OS_CHROMEOS)
+  task_providers_.push_back(new ArcProcessTaskProvider());
+#endif  // defined(OS_CHROMEOS)
 
   content::GpuDataManager::GetInstance()->AddObserver(this);
 }
diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc
index d802188..4057f28 100644
--- a/chrome/browser/task_manager/task_manager_browsertest.cc
+++ b/chrome/browser/task_manager/task_manager_browsertest.cc
@@ -298,6 +298,7 @@
           last_loaded_extension_id()),
       browser()->profile(),
       url,
+      nullptr,
       gfx::Rect(300, 400),
       PanelManager::CREATE_AS_DOCKED);
 
@@ -351,6 +352,7 @@
           last_loaded_extension_id()),
       browser()->profile(),
       url,
+      nullptr,
       gfx::Rect(300, 400),
       PanelManager::CREATE_AS_DOCKED);
   ASSERT_NO_FATAL_FAILURE(
@@ -398,6 +400,7 @@
           last_loaded_extension_id()),
       browser()->profile(),
       url,
+      nullptr,
       gfx::Rect(300, 400),
       PanelManager::CREATE_AS_DOCKED);
 
@@ -441,6 +444,7 @@
           last_loaded_extension_id()),
       browser()->profile(),
       url,
+      nullptr,
       gfx::Rect(300, 400),
       PanelManager::CREATE_AS_DOCKED);
 
diff --git a/chrome/browser/translate/translate_service.h b/chrome/browser/translate/translate_service.h
index 15340cbc..335f0e1 100644
--- a/chrome/browser/translate/translate_service.h
+++ b/chrome/browser/translate/translate_service.h
@@ -29,11 +29,6 @@
   // test can initialize and use the service.
   static void ShutdownForTesting();
 
-  // Let the caller decide if and when we should fetch the language list from
-  // the translate server. This is a NOOP if switches::kDisableTranslate is set
-  // or if prefs::kEnableTranslate is set to false.
-  static void FetchLanguageListFromTranslateServer(PrefService* prefs);
-
   // Returns true if the new translate bubble is enabled.
   static bool IsTranslateBubbleEnabled();
 
diff --git a/chrome/browser/ui/cocoa/panels/panel_cocoa_unittest.mm b/chrome/browser/ui/cocoa/panels/panel_cocoa_unittest.mm
index d77186a..228a8754 100644
--- a/chrome/browser/ui/cocoa/panels/panel_cocoa_unittest.mm
+++ b/chrome/browser/ui/cocoa/panels/panel_cocoa_unittest.mm
@@ -51,7 +51,7 @@
     int panels_count = manager->num_panels();
 
     Panel* panel = manager->CreatePanel(panel_name, profile(),
-                                        GURL(), gfx::Rect(),
+                                        GURL(), nullptr, gfx::Rect(),
                                         PanelManager::CREATE_AS_DOCKED);
     EXPECT_EQ(panels_count + 1, manager->num_panels());
 
diff --git a/chrome/browser/ui/panels/base_panel_browser_test.cc b/chrome/browser/ui/panels/base_panel_browser_test.cc
index e50cb89..a7739eff 100644
--- a/chrome/browser/ui/panels/base_panel_browser_test.cc
+++ b/chrome/browser/ui/panels/base_panel_browser_test.cc
@@ -337,6 +337,7 @@
       params.name,
       params.profile ? params.profile : browser()->profile(),
       params.url,
+      nullptr,
       params.bounds,
       params.create_mode);
 
diff --git a/chrome/browser/ui/panels/panel.cc b/chrome/browser/ui/panels/panel.cc
index 56618ba..699e705 100644
--- a/chrome/browser/ui/panels/panel.cc
+++ b/chrome/browser/ui/panels/panel.cc
@@ -514,6 +514,7 @@
 }
 
 void Panel::Initialize(const GURL& url,
+                       content::SiteInstance* source_site_instance,
                        const gfx::Rect& bounds,
                        bool always_on_top) {
   DCHECK(!initialized_);
@@ -531,7 +532,7 @@
 
   // Set up hosting for web contents.
   panel_host_.reset(new PanelHost(this, profile_));
-  panel_host_->Init(url);
+  panel_host_->Init(url, source_site_instance);
   content::WebContents* web_contents = GetWebContents();
   // The contents might be NULL for most of our tests.
   if (web_contents) {
diff --git a/chrome/browser/ui/panels/panel.h b/chrome/browser/ui/panels/panel.h
index a9bd1b3..9153e04e 100644
--- a/chrome/browser/ui/panels/panel.h
+++ b/chrome/browser/ui/panels/panel.h
@@ -31,6 +31,7 @@
 class StackedPanelCollection;
 
 namespace content {
+class SiteInstance;
 class WebContents;
 struct NativeWebKeyboardEvent;
 }
@@ -214,7 +215,10 @@
   // Panel must be initialized to be "fully created" and ready for use.
   // Only called by PanelManager.
   bool initialized() const { return initialized_; }
-  void Initialize(const GURL& url, const gfx::Rect& bounds, bool always_on_top);
+  void Initialize(const GURL& url,
+                  content::SiteInstance* source_site_instance,
+                  const gfx::Rect& bounds,
+                  bool always_on_top);
 
   // This is different from BaseWindow::SetBounds():
   // * SetPanelBounds() is only called by PanelManager to manage its position.
diff --git a/chrome/browser/ui/panels/panel_extension_browsertest.cc b/chrome/browser/ui/panels/panel_extension_browsertest.cc
index c5a88a11..7e17d3e 100644
--- a/chrome/browser/ui/panels/panel_extension_browsertest.cc
+++ b/chrome/browser/ui/panels/panel_extension_browsertest.cc
@@ -54,6 +54,7 @@
         web_app::GenerateApplicationNameFromExtensionId(extension->id()),
         browser()->profile(),
         GURL(),
+        nullptr,
         gfx::Rect(),
         PanelManager::CREATE_AS_DETACHED);
     panel->ShowInactive();
diff --git a/chrome/browser/ui/panels/panel_host.cc b/chrome/browser/ui/panels/panel_host.cc
index 5de546f..3a5a07a 100644
--- a/chrome/browser/ui/panels/panel_host.cc
+++ b/chrome/browser/ui/panels/panel_host.cc
@@ -47,12 +47,15 @@
 PanelHost::~PanelHost() {
 }
 
-void PanelHost::Init(const GURL& url) {
+void PanelHost::Init(const GURL& url,
+                     content::SiteInstance* source_site_instance) {
   if (url.is_empty())
     return;
 
-  content::WebContents::CreateParams create_params(
-      profile_, content::SiteInstance::CreateForURL(profile_, url));
+  content::SiteInstance* instance =
+      source_site_instance ? source_site_instance->GetRelatedSiteInstance(url)
+                           : content::SiteInstance::CreateForURL(profile_, url);
+  content::WebContents::CreateParams create_params(profile_, instance);
   web_contents_.reset(content::WebContents::Create(create_params));
   extensions::SetViewType(web_contents_.get(), extensions::VIEW_TYPE_PANEL);
   web_contents_->SetDelegate(this);
diff --git a/chrome/browser/ui/panels/panel_host.h b/chrome/browser/ui/panels/panel_host.h
index dc5159a..d63307bc 100644
--- a/chrome/browser/ui/panels/panel_host.h
+++ b/chrome/browser/ui/panels/panel_host.h
@@ -18,6 +18,7 @@
 class Profile;
 
 namespace content {
+class SiteInstance;
 class WebContents;
 }
 
@@ -39,7 +40,7 @@
   PanelHost(Panel* panel, Profile* profile);
   ~PanelHost() override;
 
-  void Init(const GURL& url);
+  void Init(const GURL& url, content::SiteInstance* source_site_instance);
   content::WebContents* web_contents() { return web_contents_.get(); }
   void DestroyWebContents();
 
diff --git a/chrome/browser/ui/panels/panel_manager.cc b/chrome/browser/ui/panels/panel_manager.cc
index 1846ea65..9d397d2 100644
--- a/chrome/browser/ui/panels/panel_manager.cc
+++ b/chrome/browser/ui/panels/panel_manager.cc
@@ -215,6 +215,7 @@
 Panel* PanelManager::CreatePanel(const std::string& app_name,
                                  Profile* profile,
                                  const GURL& url,
+                                 content::SiteInstance* source_site_instance,
                                  const gfx::Rect& requested_bounds,
                                  CreateMode mode) {
   // Need to sync the display area if no panel is present. This is because:
@@ -264,7 +265,8 @@
       adjusted_requested_bounds);
   bounds.AdjustToFit(work_area);
 
-  panel->Initialize(url, bounds, collection->UsesAlwaysOnTopPanels());
+  panel->Initialize(url, source_site_instance, bounds,
+                    collection->UsesAlwaysOnTopPanels());
 
   // Auto resizable feature is enabled only if no initial size is requested.
   if (auto_sizing_enabled() && requested_bounds.width() == 0 &&
diff --git a/chrome/browser/ui/panels/panel_manager.h b/chrome/browser/ui/panels/panel_manager.h
index 9fe42c3b..43d4b76 100644
--- a/chrome/browser/ui/panels/panel_manager.h
+++ b/chrome/browser/ui/panels/panel_manager.h
@@ -24,6 +24,10 @@
 class PanelMouseWatcher;
 class StackedPanelCollection;
 
+namespace content {
+class SiteInstance;
+}
+
 // This class manages a set of panels.
 class PanelManager : public DisplaySettingsProvider::DisplayObserver,
                      public DisplaySettingsProvider::FullScreenObserver {
@@ -63,12 +67,15 @@
   // |app_name| is the default title for Panels when the page content does not
   // provide a title. For extensions, this is usually the application name
   // generated from the extension id.
+  // |source_site_instance| indicates the SiteInstance that requested to create
+  // this panel.
   // |requested_bounds| is the desired bounds for the panel, but actual
   // bounds may differ after panel layout depending on create |mode|.
   // |mode| indicates whether panel should be created as docked or detached.
   Panel* CreatePanel(const std::string& app_name,
                      Profile* profile,
                      const GURL& url,
+                     content::SiteInstance* source_site_instance,
                      const gfx::Rect& requested_bounds,
                      CreateMode mode);
 
diff --git a/chrome/browser/ui/webui/options/password_manager_handler.cc b/chrome/browser/ui/webui/options/password_manager_handler.cc
index 7523e5cc..dc51759 100644
--- a/chrome/browser/ui/webui/options/password_manager_handler.cc
+++ b/chrome/browser/ui/webui/options/password_manager_handler.cc
@@ -45,13 +45,14 @@
 // chrome/browser/resources/options/password_manager_list.js.
 const char kOriginField[] = "origin";
 const char kShownUrlField[] = "shownUrl";
+const char kIsAndroidUriField[] = "isAndroidUri";
 const char kIsSecureField[] = "isSecure";
 const char kUsernameField[] = "username";
 const char kPasswordField[] = "password";
 const char kFederationField[] = "federation";
 
-// Copies from |form| to |entry| the origin, shown origin and whether the
-// origin is secure or not.
+// Copies from |form| to |entry| the origin, shown origin, whether the origin is
+// Android URI, and whether the origin is secure.
 void CopyOriginInfoOfPasswordForm(const autofill::PasswordForm& form,
                                   const std::string& languages,
                                   base::DictionaryValue* entry) {
@@ -60,8 +61,10 @@
       url_formatter::FormatUrl(
           form.origin, languages, url_formatter::kFormatUrlOmitNothing,
           net::UnescapeRule::SPACES, nullptr, nullptr, nullptr));
-  entry->SetString(kShownUrlField,
-                   password_manager::GetShownOrigin(form, languages));
+  bool is_android_uri = false;
+  entry->SetString(kShownUrlField, password_manager::GetShownOrigin(
+                                       form, languages, &is_android_uri));
+  entry->SetBoolean(kIsAndroidUriField, is_android_uri);
   entry->SetBoolean(kIsSecureField, content::IsOriginSecure(form.origin));
 }
 
@@ -126,8 +129,7 @@
   localized_strings->SetString("passwordsManagePasswordsBeforeLinkText",
                                full_text.substr(0, offset));
   localized_strings->SetString("passwordsManagePasswordsLinkText",
-                               full_text.substr(offset,
-                                                link_text.size()));
+                               full_text.substr(offset, link_text.size()));
   localized_strings->SetString("passwordsManagePasswordsAfterLinkText",
                                full_text.substr(offset + link_text.size()));
 
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index 0821f2a..f82a0b3 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -278,6 +278,17 @@
   html_source->AddLocalizedString(
       "powerwashLearnMoreUrl", IDS_FACTORY_RESET_HELP_URL);
 #endif
+
+  // Automatic reset banner.
+  html_source->AddLocalizedString(
+      "resetProfileBannerButton",
+      IDS_AUTOMATIC_SETTINGS_RESET_BANNER_RESET_BUTTON_TEXT);
+  html_source->AddLocalizedString(
+      "resetProfileBannerDescription",
+      IDS_AUTOMATIC_SETTINGS_RESET_BANNER_TEXT);
+  html_source->AddString(
+      "resetProfileBannerLearnMoreUrl",
+      chrome::kAutomaticSettingsResetLearnMoreURL);
 }
 
 void AddDateTimeStrings(content::WebUIDataSource* html_source) {
diff --git a/chrome/browser/ui/webui/settings/reset_settings_handler.cc b/chrome/browser/ui/webui/settings/reset_settings_handler.cc
index f901606c..b3eda6e 100644
--- a/chrome/browser/ui/webui/settings/reset_settings_handler.cc
+++ b/chrome/browser/ui/webui/settings/reset_settings_handler.cc
@@ -9,8 +9,10 @@
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string16.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/google/google_brand.h"
+#include "chrome/browser/prefs/chrome_pref_service_factory.h"
 #include "chrome/browser/profile_resetter/brandcode_config_fetcher.h"
 #include "chrome/browser/profile_resetter/brandcoded_default_settings.h"
 #include "chrome/browser/profile_resetter/profile_reset_report.pb.h"
@@ -65,6 +67,15 @@
   html_source->AddBoolean("allowPowerwash", allow_powerwash);
 #endif  // defined(OS_CHROMEOS)
 
+  bool show_reset_profile_banner = false;
+  static const int kBannerShowTimeInDays = 5;
+  const base::Time then = chrome_prefs::GetResetTime(profile);
+  if (!then.is_null()) {
+    show_reset_profile_banner =
+        (base::Time::Now() - then).InDays() < kBannerShowTimeInDays;
+  }
+  html_source->AddBoolean("showResetProfileBanner", show_reset_profile_banner);
+
   // Inject |allow_powerwash| for testing.
   return new ResetSettingsHandler(profile, allow_powerwash);
 }
@@ -79,6 +90,9 @@
   web_ui()->RegisterMessageCallback("onHideResetProfileDialog",
       base::Bind(&ResetSettingsHandler::OnHideResetProfileDialog,
                  base::Unretained(this)));
+  web_ui()->RegisterMessageCallback("onHideResetProfileBanner",
+      base::Bind(&ResetSettingsHandler::OnHideResetProfileBanner,
+                 base::Unretained(this)));
 #if defined(OS_CHROMEOS)
   web_ui()->RegisterMessageCallback(
        "onPowerwashDialogShow",
@@ -155,6 +169,11 @@
     setting_snapshot_.reset();
 }
 
+void ResetSettingsHandler::OnHideResetProfileBanner(
+    const base::ListValue* value) {
+  chrome_prefs::ClearResetTime(profile_);
+}
+
 void ResetSettingsHandler::OnSettingsFetched() {
   DCHECK(config_fetcher_);
   DCHECK(!config_fetcher_->IsActive());
diff --git a/chrome/browser/ui/webui/settings/reset_settings_handler.h b/chrome/browser/ui/webui/settings/reset_settings_handler.h
index 6238dec..6c8215ac 100644
--- a/chrome/browser/ui/webui/settings/reset_settings_handler.h
+++ b/chrome/browser/ui/webui/settings/reset_settings_handler.h
@@ -57,12 +57,15 @@
   // Closes the dialog once all requested settings has been reset.
   void OnResetProfileSettingsDone(bool send_feedback);
 
-  // Called when the confirmation box appears.
+  // Called when the reset profile dialog is shown.
   void OnShowResetProfileDialog(const base::ListValue* value);
 
-  // Called when the confirmation box disappears.
+  // Called when the reset profile dialog is hidden.
   void OnHideResetProfileDialog(const base::ListValue* value);
 
+  // Called when the reset profile banner is shown.
+  void OnHideResetProfileBanner(const base::ListValue* value);
+
   // Called when BrandcodeConfigFetcher completed fetching settings.
   void OnSettingsFetched();
 
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 0b2364d3..f3e9685 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -3059,6 +3059,12 @@
       'browser/task_manager/web_contents_resource_provider.cc',
       'browser/task_manager/web_contents_resource_provider.h',
     ],
+    'chrome_browser_task_manager_chromeos_sources': [
+      'browser/task_management/providers/arc/arc_process_task.cc',
+      'browser/task_management/providers/arc/arc_process_task.h',
+      'browser/task_management/providers/arc/arc_process_task_provider.cc',
+      'browser/task_management/providers/arc/arc_process_task_provider.h',
+    ],
     'chrome_browser_themes_sources': [
       'browser/sync/glue/theme_data_type_controller.cc',
       'browser/sync/glue/theme_data_type_controller.h',
@@ -3458,6 +3464,11 @@
         }],
         ['enable_task_manager==1', {
           'sources': [ '<@(chrome_browser_task_manager_sources)' ],
+          'conditions': [
+            ['chromeos==1', {
+              'sources': [ '<@(chrome_browser_task_manager_chromeos_sources)' ],
+            }],
+          ],
         }],
         ['enable_media_router==1', {
           'dependencies': [
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index ad6a146..ea544c7f 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -367,11 +367,6 @@
             'renderer/spellchecker/hunspell_engine.h',
           ]
         }],
-        ['OS=="mac"', {
-          'dependencies': [
-            '../third_party/mach_override/mach_override.gyp:mach_override',
-          ],
-        }],
         ['enable_basic_printing==1 or enable_print_preview==1', {
           'dependencies': [
             '../components/components.gyp:printing_renderer',
diff --git a/chrome/installer/linux/debian/expected_deps_x64 b/chrome/installer/linux/debian/expected_deps_x64
index f1d0084..24d6a3f 100644
--- a/chrome/installer/linux/debian/expected_deps_x64
+++ b/chrome/installer/linux/debian/expected_deps_x64
@@ -4,7 +4,7 @@
 libc6 (>= 2.12)
 libcairo2 (>= 1.6.0)
 libcups2 (>= 1.4.0)
-libdbus-1-3 (>= 1.2.14)
+libdbus-1-3 (>= 1.1.4)
 libexpat1 (>= 1.95.8)
 libfontconfig1 (>= 2.8.0)
 libfreetype6 (>= 2.3.9)
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index 41b08b7..eb198438 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -169,9 +169,6 @@
     }
   }
 
-  if (is_mac) {
-    deps += [ "//third_party/mach_override" ]
-  }
   if (is_win) {
     deps += [ "//third_party/wtl" ]
   }
diff --git a/chrome/test/data/android/contextualsearch/tap_test.html b/chrome/test/data/android/contextualsearch/tap_test.html
index ad7598c3..e3d8ea8a 100644
--- a/chrome/test/data/android/contextualsearch/tap_test.html
+++ b/chrome/test/data/android/contextualsearch/tap_test.html
@@ -46,10 +46,6 @@
   <div>United States Intelligence</div>
   <div>United States Intelligence</div>
   <div>United States Intelligence</div>
-  <div>United States Intelligence</div>
-  <div>United States Intelligence</div>
-  <div>United States Intelligence</div>
-  <div>United States Intelligence</div>
   <script>
     function consume(e) {
       console.log('consuming event ' + e.type);
diff --git a/chrome/test/data/android/customtabs/test_window_open.html b/chrome/test/data/android/customtabs/test_window_open.html
new file mode 100644
index 0000000..f6ceb57c
--- /dev/null
+++ b/chrome/test/data/android/customtabs/test_window_open.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+
+<p>Click the button to open a new browser window.</p>
+
+<button id="new_window" onclick="myFunction()">Click me</button>
+
+<script>
+function myFunction() {
+    window.open("about:blank");
+}
+</script>
+
+</body>
+</html>
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js
index 0724a15..042f327 100644
--- a/chrome/test/data/webui/settings/cr_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -66,6 +66,7 @@
 
 
 TEST_F('CrSettingsBrowserTest', 'ResetPage', function() {
-  settings_reset_page.registerTests();
+  settings_reset_page.registerDialogTests();
+  settings_reset_page.registerBannerTests();
   mocha.run();
 });
diff --git a/chrome/test/data/webui/settings/reset_page_test.js b/chrome/test/data/webui/settings/reset_page_test.js
index d2576638..471fa04 100644
--- a/chrome/test/data/webui/settings/reset_page_test.js
+++ b/chrome/test/data/webui/settings/reset_page_test.js
@@ -7,6 +7,8 @@
   var TestNames = {
     PowerwashDialogAction: 'PowerwashDialogAction',
     PowerwashDialogOpenClose: 'PowerwashDialogOpenClose',
+    ResetBannerClose: 'ResetBannerClose',
+    ResetBannerReset: 'ResetBannerReset',
     ResetProfileDialogAction: 'ResetProfileDialogAction',
     ResetProfileDialogOpenClose: 'ResetProfileDialogOpenClose',
   };
@@ -23,7 +25,55 @@
     });
   }
 
-  function registerTests() {
+  function registerBannerTests() {
+    suite('BannerTests', function() {
+      var resetBanner = null;
+
+      suiteSetup(function() {
+        return Promise.all([
+          PolymerTest.importHtml('chrome://md-settings/i18n_setup.html'),
+          PolymerTest.importHtml(
+              'chrome://md-settings/reset_page/reset_profile_banner.html')
+        ]);
+      });
+
+      setup(function() {
+        PolymerTest.clearBody();
+        resetBanner = document.createElement('settings-reset-profile-banner');
+        document.body.appendChild(resetBanner);
+      });
+
+      // Tests that the reset profile banner
+      //  - opens the reset profile dialog when the reset button is clicked.
+      //  - the reset profile dialog is closed after reset is done.
+      test(TestNames.ResetBannerReset, function() {
+        var dialog = resetBanner.$$('settings-reset-profile-dialog');
+        assertEquals(undefined, dialog);
+        MockInteractions.tap(resetBanner.$['reset']);
+        Polymer.dom.flush();
+        dialog = resetBanner.$$('settings-reset-profile-dialog');
+        assertNotEquals(undefined, dialog);
+
+        dialog.dispatchResetDoneEvent();
+        Polymer.dom.flush();
+        assertEquals('none', dialog.style.display);
+        return Promise.resolve();
+      });
+
+      // Tests that the reset profile banner removes itself from the DOM when
+      // the close button is clicked and that
+      // chrome.send('onHideResetProfileBanner') is called.
+      test(TestNames.ResetBannerClose, function() {
+        var whenOnHideResetProfileBanner = whenChromeSendCalled(
+            'onHideResetProfileBanner');
+        MockInteractions.tap(resetBanner.$['close']);
+        assertEquals(null, resetBanner.parentNode);
+        return whenOnHideResetProfileBanner;
+      });
+    });
+  }
+
+  function registerDialogTests() {
     suite('DialogTests', function() {
       var resetPage = null;
 
@@ -140,6 +190,7 @@
   }
 
   return {
-    registerTests: registerTests,
+    registerBannerTests: registerBannerTests,
+    registerDialogTests: registerDialogTests
   };
 });
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index bc1a8a0..4a939804 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -50,7 +50,8 @@
 
   filters = []
 
-  if (target_cpu == "arm" && target_os == "linux") {
+  # Apply filters to embedded linux devices.
+  if (target_os == "linux" && !is_cast_desktop_build) {
     filters += [
       # Run net_unittests first to avoid random failures due to slow python startup
       # KeygenHandlerTest.SmokeTest and KeygenHandlerTest.ConcurrencyTest fail due to
@@ -94,7 +95,7 @@
       # DoAppendUTF8Invalid fails because of dcheck_always_on flag in Eng builds
       "url_unittests --gtest_filter=-URLCanonTest.DoAppendUTF8Invalid",
     ]
-  } else if (target_cpu != "arm" || target_os == "android") {
+  } else if (is_cast_desktop_build || target_os == "android") {
     filters += [
       # Disable PipelineIntegrationTest.BasicPlayback_MediaSource_VP9_WebM (not supported)
       "media_unittests --gtest_filter=-PipelineIntegrationTest.BasicPlayback_MediaSource_VP9_WebM",
diff --git a/chromecast/chromecast.gni b/chromecast/chromecast.gni
index fa36ec98..7c2c776 100644
--- a/chromecast/chromecast.gni
+++ b/chromecast/chromecast.gni
@@ -12,9 +12,6 @@
   # Set it to "public" for a Chromium build.
   chromecast_branding = "public"
 
-  # True if Chromecast build is targetted for linux desktop.
-  is_chromecast_desktop_build = is_linux && target_cpu != "arm"
-
   # Use Playready CDMs.
   use_playready = false
 }
diff --git a/chromecast/chromecast_tests.gypi b/chromecast/chromecast_tests.gypi
index c889bbc8..fb373fb 100644
--- a/chromecast/chromecast_tests.gypi
+++ b/chromecast/chromecast_tests.gypi
@@ -111,7 +111,7 @@
         '../url/url.gyp:url_unittests',
       ],
       'conditions': [
-        ['target_arch=="arm" and OS!="android"', {
+        ['OS=="linux" and is_cast_desktop_build==0', {
           'variables': {
             'filters': [
               # Run net_unittests first to avoid random failures due to slow python startup
@@ -153,7 +153,7 @@
               'url_unittests --gtest_filter=-URLCanonTest.DoAppendUTF8Invalid',
             ],
           },
-        }, { # else "x86" or "android"
+        }, { # else desktop or android
           'variables': {
             'filters': [
               # Disable PipelineIntegrationTest.BasicPlayback_MediaSource_VP9_WebM (not supported)
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 8281d371..57c5445 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-7742.0.0
\ No newline at end of file
+7745.0.0
\ No newline at end of file
diff --git a/chromeos/binder/command_stream.cc b/chromeos/binder/command_stream.cc
index 3e7705a..3a0d00c3 100644
--- a/chromeos/binder/command_stream.cc
+++ b/chromeos/binder/command_stream.cc
@@ -6,19 +6,27 @@
 
 #include <linux/android/binder.h>
 
+#include "base/bind.h"
 #include "chromeos/binder/buffer_reader.h"
 #include "chromeos/binder/driver.h"
+#include "chromeos/binder/transaction_data.h"
+#include "chromeos/binder/transaction_data_from_driver.h"
 #include "chromeos/binder/util.h"
 
 namespace binder {
 
 CommandStream::CommandStream(Driver* driver,
                              IncomingCommandHandler* incoming_command_handler)
-    : driver_(driver), incoming_command_handler_(incoming_command_handler) {}
+    : driver_(driver),
+      incoming_command_handler_(incoming_command_handler),
+      weak_ptr_factory_(this) {}
 
-CommandStream::~CommandStream() {}
+CommandStream::~CommandStream() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+}
 
 bool CommandStream::Fetch() {
+  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!CanProcessIncomingCommand());
   // Use the same value as libbinder's IPCThreadState.
   const size_t kIncomingDataSize = 256;
@@ -37,10 +45,12 @@
 }
 
 bool CommandStream::CanProcessIncomingCommand() {
+  DCHECK(thread_checker_.CalledOnValidThread());
   return incoming_data_reader_ && incoming_data_reader_->HasMoreData();
 }
 
 bool CommandStream::ProcessIncomingCommand() {
+  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(CanProcessIncomingCommand());
   uint32 command = 0;
   if (!incoming_data_reader_->Read(&command, sizeof(command)) ||
@@ -54,6 +64,7 @@
 void CommandStream::AppendOutgoingCommand(uint32 command,
                                           const void* data,
                                           size_t size) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   VLOG(1) << "Appending " << CommandToString(command) << ", this = " << this;
 
   DCHECK_EQ(0u, size % 4);  // Must be 4-byte aligned.
@@ -66,6 +77,7 @@
 }
 
 bool CommandStream::Flush() {
+  DCHECK(thread_checker_.CalledOnValidThread());
   for (size_t pos = 0; pos < outgoing_data_.size();) {
     size_t written_bytes = 0, read_bytes = 0;
     if (!driver_->WriteRead(outgoing_data_.data() + pos,
@@ -82,6 +94,7 @@
 }
 
 bool CommandStream::OnIncomingCommand(uint32 command, BufferReader* reader) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   // TODO(hashimoto): Replace all NOTIMPLEMENTED with logic to handle incoming
   // commands.
   VLOG(1) << "Processing " << CommandToString(command) << ", this = " << this;
@@ -99,18 +112,27 @@
     case BR_TRANSACTION:
       NOTIMPLEMENTED();
       break;
-    case BR_REPLY:
-      NOTIMPLEMENTED();
+    case BR_REPLY: {
+      scoped_ptr<TransactionDataFromDriver> data(new TransactionDataFromDriver(
+          base::Bind(&CommandStream::FreeTransactionBuffer,
+                     weak_ptr_factory_.GetWeakPtr())));
+      binder_transaction_data* data_struct = data->mutable_data();
+      if (!reader->Read(data_struct, sizeof(*data_struct))) {
+        LOG(ERROR) << "Failed to read transaction data.";
+        return false;
+      }
+      incoming_command_handler_->OnReply(data.Pass());
       break;
+    }
     case BR_ACQUIRE_RESULT:
       // Kernel's binder.h says this is not currently supported.
       NOTREACHED();
       break;
     case BR_DEAD_REPLY:
-      NOTIMPLEMENTED();
+      incoming_command_handler_->OnDeadReply();
       break;
     case BR_TRANSACTION_COMPLETE:
-      NOTIMPLEMENTED();
+      incoming_command_handler_->OnTransactionComplete();
       break;
     case BR_INCREFS:
     case BR_ACQUIRE:
@@ -135,7 +157,7 @@
       NOTIMPLEMENTED();
       break;
     case BR_FAILED_REPLY:
-      NOTIMPLEMENTED();
+      incoming_command_handler_->OnFailedReply();
       break;
     default:
       LOG(ERROR) << "Unexpected command: " << command;
@@ -144,4 +166,9 @@
   return true;
 }
 
+void CommandStream::FreeTransactionBuffer(const void* ptr) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  AppendOutgoingCommand(BC_FREE_BUFFER, &ptr, sizeof(ptr));
+}
+
 }  // namespace binder
diff --git a/chromeos/binder/command_stream.h b/chromeos/binder/command_stream.h
index 823abda5..32ca83e 100644
--- a/chromeos/binder/command_stream.h
+++ b/chromeos/binder/command_stream.h
@@ -10,11 +10,14 @@
 #include "base/basictypes.h"
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
 
 namespace binder {
 
 class BufferReader;
 class Driver;
+class TransactionData;
 
 // Stream of incoming (binder driver to user process) BR_* commands and outgoing
 // (user process to binder driver) BC_* commands.
@@ -25,6 +28,19 @@
    public:
     virtual ~IncomingCommandHandler() {}
     // TODO(hashimoto): Add methods to handle incoming commands.
+
+    // Called to handle BR_REPLY.
+    // |data| is the reply for the previous transaction.
+    virtual void OnReply(scoped_ptr<TransactionData> data) = 0;
+
+    // Called to handle BR_DEAD_REPLY.
+    virtual void OnDeadReply() = 0;
+
+    // Called to handle BR_TRANSACTION_COMPLETE.
+    virtual void OnTransactionComplete() = 0;
+
+    // Called to handle BR_FAILED_REPLY.
+    virtual void OnFailedReply() = 0;
   };
 
   CommandStream(Driver* driver,
@@ -52,6 +68,11 @@
   // Calls the appropriate delegate method to handle the incoming command.
   bool OnIncomingCommand(uint32 command, BufferReader* reader);
 
+  // Frees the buffer used by the driver to pass transaction data payload.
+  void FreeTransactionBuffer(const void* ptr);
+
+  base::ThreadChecker thread_checker_;
+
   Driver* driver_;
   IncomingCommandHandler* incoming_command_handler_;
 
@@ -59,6 +80,8 @@
   std::vector<char> incoming_data_;  // Buffer for incoming commands.
   scoped_ptr<BufferReader> incoming_data_reader_;
 
+  base::WeakPtrFactory<CommandStream> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(CommandStream);
 };
 
diff --git a/chromeos/binder/command_stream_unittest.cc b/chromeos/binder/command_stream_unittest.cc
index ae67ab3..2fb0e56 100644
--- a/chromeos/binder/command_stream_unittest.cc
+++ b/chromeos/binder/command_stream_unittest.cc
@@ -5,15 +5,17 @@
 #include <unistd.h>
 #include <linux/android/binder.h>
 
+#include "base/message_loop/message_loop.h"
 #include "chromeos/binder/command_stream.h"
+#include "chromeos/binder/constants.h"
 #include "chromeos/binder/driver.h"
+#include "chromeos/binder/transaction_data.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace binder {
 
 namespace {
 
-// TODO(hashimoto): Add tests for Fetch() and ProcessCommand().
 class BinderCommandStreamTest : public ::testing::Test,
                                 public CommandStream::IncomingCommandHandler {
  public:
@@ -22,9 +24,34 @@
 
   void SetUp() override { ASSERT_TRUE(driver_.Initialize()); }
 
+  // CommandStream::IncomingCommandHandler override:
+  void OnReply(scoped_ptr<TransactionData> data) override {
+    received_response_ = RESPONSE_REPLY;
+    ASSERT_TRUE(data);
+    EXPECT_FALSE(data->HasStatus());  // No error.
+  }
+
+  void OnDeadReply() override { received_response_ = RESPONSE_DEAD; }
+
+  void OnTransactionComplete() override {
+    received_response_ = RESPONSE_COMPLETE;
+  }
+
+  void OnFailedReply() override { received_response_ = RESPONSE_FAILED; }
+
  protected:
+  base::MessageLoop message_loop_;
   Driver driver_;
   CommandStream command_stream_;
+
+  enum ResponseType {
+    RESPONSE_NONE,
+    RESPONSE_REPLY,
+    RESPONSE_DEAD,
+    RESPONSE_COMPLETE,
+    RESPONSE_FAILED,
+  };
+  ResponseType received_response_ = RESPONSE_NONE;
 };
 
 }  // namespace
@@ -44,4 +71,34 @@
   EXPECT_FALSE(command_stream_.Flush());
 }
 
+TEST_F(BinderCommandStreamTest, PingContextManager) {
+  // Perform ping transaction with the context manager.
+  binder_transaction_data data = {};
+  data.target.handle = kContextManagerHandle;
+  data.code = kPingTransactionCode;
+  command_stream_.AppendOutgoingCommand(BC_TRANSACTION, &data, sizeof(data));
+  ASSERT_TRUE(command_stream_.Flush());
+
+  // Wait for transaction complete.
+  while (received_response_ == RESPONSE_NONE) {
+    if (command_stream_.CanProcessIncomingCommand()) {
+      ASSERT_TRUE(command_stream_.ProcessIncomingCommand());
+    } else {
+      ASSERT_TRUE(command_stream_.Fetch());
+    }
+  }
+  ASSERT_EQ(RESPONSE_COMPLETE, received_response_);
+
+  // Wait for transaction reply.
+  received_response_ = RESPONSE_NONE;
+  while (received_response_ == RESPONSE_NONE) {
+    if (command_stream_.CanProcessIncomingCommand()) {
+      ASSERT_TRUE(command_stream_.ProcessIncomingCommand());
+    } else {
+      ASSERT_TRUE(command_stream_.Fetch());
+    }
+  }
+  ASSERT_EQ(RESPONSE_REPLY, received_response_);
+}
+
 }  // namespace binder
diff --git a/chromeos/binder/constants.h b/chromeos/binder/constants.h
new file mode 100644
index 0000000..336033a7
--- /dev/null
+++ b/chromeos/binder/constants.h
@@ -0,0 +1,23 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BINDER_CONSTANTS_H_
+#define BINDER_CONSTANTS_H_
+
+#define BINDER_PACK_CHARS(c1, c2, c3, c4) \
+  (((c1) << 24) | ((c2) << 16) | ((c3) << 8) | (c4))
+
+namespace binder {
+
+// Context manager's handle is always 0.
+const uint32 kContextManagerHandle = 0;
+
+// Transaction code constants.
+const uint32 kFirstTransactionCode = 0x00000001;
+const uint32 kLastTransactionCode = 0x00ffffff;
+const uint32 kPingTransactionCode = BINDER_PACK_CHARS('_', 'P', 'N', 'G');
+
+}  // namespace binder
+
+#endif  // BINDER_CONSTANTS_H_
diff --git a/chromeos/binder/driver.cc b/chromeos/binder/driver.cc
index 2e33509..f82470c 100644
--- a/chromeos/binder/driver.cc
+++ b/chromeos/binder/driver.cc
@@ -22,10 +22,15 @@
 
 }  // namespace
 
-Driver::Driver() {}
+Driver::Driver() : mmap_address_(MAP_FAILED) {}
 
 Driver::~Driver() {
   base::ThreadRestrictions::AssertIOAllowed();
+  if (mmap_address_ != MAP_FAILED) {
+    if (munmap(mmap_address_, GetBinderMmapSize()) == -1) {
+      PLOG(ERROR) << "Failed to munmap";
+    }
+  }
   fd_.reset();  // Close FD.
 }
 
@@ -39,7 +44,7 @@
   }
   // Version check.
   int version = 0;
-  if (ioctl(fd_.get(), BINDER_VERSION, &version) != 0 ||
+  if (HANDLE_EINTR(ioctl(fd_.get(), BINDER_VERSION, &version)) != 0 ||
       version != BINDER_CURRENT_PROTOCOL_VERSION) {
     PLOG(ERROR) << "Version check failure: version = " << version;
     return false;
@@ -50,10 +55,9 @@
     return false;
   }
   // Allocate buffer for transaction data.
-  // Subtract PAGESIZE * 2 to make room for guard pages. https://goo.gl/4Q6sPe
-  const int kBinderMmapSize = 1024 * 1024 - sysconf(_SC_PAGESIZE) * 2;
-  if (mmap(0, kBinderMmapSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE,
-           fd_.get(), 0) == MAP_FAILED) {
+  mmap_address_ = mmap(0, GetBinderMmapSize(), PROT_READ,
+                       MAP_PRIVATE | MAP_NORESERVE, fd_.get(), 0);
+  if (mmap_address_ == MAP_FAILED) {
     PLOG(ERROR) << "Failed to mmap";
     return false;
   }
@@ -66,7 +70,8 @@
 
 bool Driver::SetMaxThreads(int max_threads) {
   base::ThreadRestrictions::AssertIOAllowed();
-  return ioctl(fd_.get(), BINDER_SET_MAX_THREADS, &max_threads) != -1;
+  return HANDLE_EINTR(ioctl(fd_.get(), BINDER_SET_MAX_THREADS, &max_threads)) !=
+         -1;
 }
 
 bool Driver::WriteRead(const char* write_buf,
@@ -81,7 +86,7 @@
   params.write_size = write_buf_size;
   params.read_buffer = reinterpret_cast<uintptr_t>(read_buf);
   params.read_size = read_buf_size;
-  if (ioctl(fd_.get(), BINDER_WRITE_READ, &params) < 0) {
+  if (HANDLE_EINTR(ioctl(fd_.get(), BINDER_WRITE_READ, &params)) < 0) {
     PLOG(ERROR) << "BINDER_WRITE_READ failed: write_buf_size = "
                 << write_buf_size << ", read_buf_size = " << read_buf_size;
     return false;
@@ -93,7 +98,12 @@
 
 bool Driver::NotifyCurrentThreadExiting() {
   base::ThreadRestrictions::AssertIOAllowed();
-  return ioctl(fd_.get(), BINDER_THREAD_EXIT, 0) != -1;
+  return HANDLE_EINTR(ioctl(fd_.get(), BINDER_THREAD_EXIT, 0)) != -1;
+}
+
+size_t Driver::GetBinderMmapSize() const {
+  // Subtract PAGESIZE * 2 to make room for guard pages. https://goo.gl/4Q6sPe
+  return 1024 * 1024 - sysconf(_SC_PAGESIZE) * 2;
 }
 
 }  // namespace binder
diff --git a/chromeos/binder/driver.h b/chromeos/binder/driver.h
index 8f94a54..ce280f9 100644
--- a/chromeos/binder/driver.h
+++ b/chromeos/binder/driver.h
@@ -11,6 +11,8 @@
 namespace binder {
 
 // Use this class to communicate with the binder driver provided by the kernel.
+// This class is stateless and it's safe to access this class from multiple
+// threads.
 class Driver {
  public:
   Driver();
@@ -46,7 +48,11 @@
   bool NotifyCurrentThreadExiting();
 
  private:
+  // Returns the size of the mmap region for transaction data.
+  size_t GetBinderMmapSize() const;
+
   base::ScopedFD fd_;
+  void* mmap_address_;
 
   DISALLOW_COPY_AND_ASSIGN(Driver);
 };
diff --git a/chromeos/binder/status.h b/chromeos/binder/status.h
new file mode 100644
index 0000000..8646d23
--- /dev/null
+++ b/chromeos/binder/status.h
@@ -0,0 +1,42 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BINDER_STATUS_H_
+#define BINDER_STATUS_H_
+
+#include <errno.h>
+
+#include "base/basictypes.h"
+
+namespace binder {
+
+// Status code.
+// Using the same values as used by libbinder.
+enum class Status : int32 {
+  OK = 0,
+
+  UNKNOWN_ERROR = INT32_MIN,
+
+  NO_MEMORY = -ENOMEM,
+  INVALID_OPERATION = -ENOSYS,
+  BAD_VALUE = -EINVAL,
+  BAD_TYPE = (UNKNOWN_ERROR + 1),
+  NAME_NOT_FOUND = -ENOENT,
+  PERMISSION_DENIED = -EPERM,
+  NO_INIT = -ENODEV,
+  ALREADY_EXISTS = -EEXIST,
+  DEAD_OBJECT = -EPIPE,
+  FAILED_TRANSACTION = (UNKNOWN_ERROR + 2),
+  BAD_INDEX = -EOVERFLOW,
+  NOT_ENOUGH_DATA = -ENODATA,
+  WOULD_BLOCK = -EWOULDBLOCK,
+  TIMED_OUT = -ETIMEDOUT,
+  UNKNOWN_TRANSACTION = -EBADMSG,
+  FDS_NOT_ALLOWED = (UNKNOWN_ERROR + 7),
+  UNEXPECTED_NULL = (UNKNOWN_ERROR + 8),
+};
+
+}  // namespace binder
+
+#endif  // BINDER_STATUS_H_
diff --git a/chromeos/binder/transaction_data.h b/chromeos/binder/transaction_data.h
new file mode 100644
index 0000000..52a35691
--- /dev/null
+++ b/chromeos/binder/transaction_data.h
@@ -0,0 +1,55 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BINDER_TRANSACTION_DATA_H_
+#define BINDER_TRANSACTION_DATA_H_
+
+#include "base/basictypes.h"
+#include "chromeos/binder/status.h"
+
+namespace binder {
+
+// Data passed via transactions.
+class TransactionData {
+ public:
+  virtual ~TransactionData() {}
+
+  // Returns the cookie which can be used to identify the target object.
+  virtual uintptr_t GetCookie() const = 0;
+
+  // Returns the transaction code.
+  virtual uint32 GetCode() const = 0;
+
+  // Returns the PID of the sender.
+  virtual pid_t GetSenderPID() const = 0;
+
+  // Returns the EUID of the sender.
+  virtual uid_t GetSenderEUID() const = 0;
+
+  // Returns true if there is no need to send reply for the transaction.
+  virtual bool IsOneWay() const = 0;
+
+  // Returns true if the payload is a status code.
+  virtual bool HasStatus() const = 0;
+
+  // Returns the status code.
+  // This method should be called only when HasStatus() returns true.
+  virtual Status GetStatus() const = 0;
+
+  // Returns the payload data.
+  virtual const void* GetData() const = 0;
+
+  // Returns the size of the payload.
+  virtual size_t GetDataSize() const = 0;
+
+  // Returns the offsets of objects stored in the payload.
+  virtual const uintptr_t* GetObjectOffsets() const = 0;
+
+  // Returns the number of objects.
+  virtual size_t GetNumObjectOffsets() const = 0;
+};
+
+}  // namespace binder
+
+#endif  // BINDER_TRANSACTION_DATA_H_
diff --git a/chromeos/binder/transaction_data_from_driver.cc b/chromeos/binder/transaction_data_from_driver.cc
new file mode 100644
index 0000000..9b76ebf
--- /dev/null
+++ b/chromeos/binder/transaction_data_from_driver.cc
@@ -0,0 +1,89 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/binder/transaction_data_from_driver.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/single_thread_task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "chromeos/binder/command_stream.h"
+
+namespace binder {
+
+TransactionDataFromDriver::TransactionDataFromDriver(
+    const BufferDeleter& buffer_deleter)
+    : delete_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      buffer_deleter_(buffer_deleter) {
+  memset(&data_, 0, sizeof(data_));
+}
+
+TransactionDataFromDriver::~TransactionDataFromDriver() {
+  if (!HasStatus()) {  // Need to free the payload.
+    // Close FDs.
+    for (size_t i = 0; i < GetNumObjectOffsets(); ++i) {
+      const auto& object = *reinterpret_cast<const flat_binder_object*>(
+          reinterpret_cast<const char*>(GetData()) + GetObjectOffsets()[i]);
+      if (object.type == BINDER_TYPE_FD) {
+        close(object.handle);
+      }
+    }
+    // Free data buffer.
+    if (delete_task_runner_->BelongsToCurrentThread()) {
+      buffer_deleter_.Run(GetData());
+    } else {
+      delete_task_runner_->PostTask(FROM_HERE,
+                                    base::Bind(buffer_deleter_, GetData()));
+    }
+  }
+}
+
+uintptr_t TransactionDataFromDriver::GetCookie() const {
+  return data_.cookie;
+}
+
+uint32 TransactionDataFromDriver::GetCode() const {
+  return data_.code;
+}
+
+pid_t TransactionDataFromDriver::GetSenderPID() const {
+  return data_.sender_pid;
+}
+
+uid_t TransactionDataFromDriver::GetSenderEUID() const {
+  return data_.sender_euid;
+}
+
+bool TransactionDataFromDriver::IsOneWay() const {
+  return data_.flags & TF_ONE_WAY;
+}
+
+bool TransactionDataFromDriver::HasStatus() const {
+  return data_.flags & TF_STATUS_CODE;
+}
+
+Status TransactionDataFromDriver::GetStatus() const {
+  DCHECK(HasStatus());
+  return *reinterpret_cast<const Status*>(data_.data.ptr.buffer);
+}
+
+const void* TransactionDataFromDriver::GetData() const {
+  return reinterpret_cast<const void*>(data_.data.ptr.buffer);
+}
+
+size_t TransactionDataFromDriver::GetDataSize() const {
+  return data_.data_size;
+}
+
+const uintptr_t* TransactionDataFromDriver::GetObjectOffsets() const {
+  return reinterpret_cast<const uintptr_t*>(data_.data.ptr.offsets);
+}
+
+size_t TransactionDataFromDriver::GetNumObjectOffsets() const {
+  DCHECK_EQ(0u, data_.offsets_size % sizeof(size_t));
+  return data_.offsets_size / sizeof(size_t);
+}
+
+}  // namespace binder
diff --git a/chromeos/binder/transaction_data_from_driver.h b/chromeos/binder/transaction_data_from_driver.h
new file mode 100644
index 0000000..ec10342
--- /dev/null
+++ b/chromeos/binder/transaction_data_from_driver.h
@@ -0,0 +1,58 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BINDER_TRANSACTION_DATA_FROM_DRIVER_H_
+#define BINDER_TRANSACTION_DATA_FROM_DRIVER_H_
+
+#include <unistd.h>
+#include <linux/android/binder.h>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "chromeos/binder/transaction_data.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace binder {
+
+class CommandStream;
+
+// TransactionData passed by the driver, whose data needs to be freed with
+// BC_FREE_BUFFER command.
+class TransactionDataFromDriver : public TransactionData {
+ public:
+  typedef base::Callback<void(const void* ptr)> BufferDeleter;
+  explicit TransactionDataFromDriver(const BufferDeleter& buffer_deleter);
+  ~TransactionDataFromDriver() override;
+
+  const binder_transaction_data& data() const { return data_; }
+  binder_transaction_data* mutable_data() { return &data_; }
+
+  // TransactionData override:
+  uintptr_t GetCookie() const override;
+  uint32 GetCode() const override;
+  pid_t GetSenderPID() const override;
+  uid_t GetSenderEUID() const override;
+  bool IsOneWay() const override;
+  bool HasStatus() const override;
+  Status GetStatus() const override;
+  const void* GetData() const override;
+  size_t GetDataSize() const override;
+  const uintptr_t* GetObjectOffsets() const override;
+  size_t GetNumObjectOffsets() const override;
+
+ private:
+  scoped_refptr<base::SingleThreadTaskRunner> delete_task_runner_;
+  BufferDeleter buffer_deleter_;
+  binder_transaction_data data_;
+
+  DISALLOW_COPY_AND_ASSIGN(TransactionDataFromDriver);
+};
+
+}  // namespace binder
+
+#endif  // BINDER_TRANSACTION_DATA_FROM_DRIVER_H_
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp
index 28b3957..ec5d4e82 100644
--- a/chromeos/chromeos.gyp
+++ b/chromeos/chromeos.gyp
@@ -391,8 +391,13 @@
       'binder/buffer_reader.h',
       'binder/command_stream.cc',
       'binder/command_stream.h',
+      'binder/constants.h',
       'binder/driver.cc',
       'binder/driver.h',
+      'binder/status.h',
+      'binder/transaction_data.h',
+      'binder/transaction_data_from_driver.cc',
+      'binder/transaction_data_from_driver.h',
       'binder/util.cc',
       'binder/util.h',
     ],
diff --git a/components/arc/arc_bridge_service.cc b/components/arc/arc_bridge_service.cc
index 5e6bcad..c0559d3 100644
--- a/components/arc/arc_bridge_service.cc
+++ b/components/arc/arc_bridge_service.cc
@@ -77,6 +77,16 @@
   app_observer_list_.RemoveObserver(observer);
 }
 
+void ArcBridgeService::AddProcessObserver(ProcessObserver* observer) {
+  DCHECK(CalledOnValidThread());
+  process_observer_list_.AddObserver(observer);
+}
+
+void ArcBridgeService::RemoveProcessObserver(ProcessObserver* observer) {
+  DCHECK(CalledOnValidThread());
+  process_observer_list_.RemoveObserver(observer);
+}
+
 void ArcBridgeService::SetState(State state) {
   DCHECK(CalledOnValidThread());
   // DCHECK on enum classes not supported.
diff --git a/components/arc/arc_bridge_service.h b/components/arc/arc_bridge_service.h
index 3f02b272..98902e6 100644
--- a/components/arc/arc_bridge_service.h
+++ b/components/arc/arc_bridge_service.h
@@ -110,6 +110,24 @@
     virtual ~AppObserver() {}
   };
 
+  // Notifies ARC process related events.
+  class ProcessObserver {
+   public:
+    // Called when the latest process list has been received after
+    // ArcBridgeService::RequestProcessList() was called.
+    //
+    // NB: Due to the nature of Linux PID, we can not avoid the race condition
+    // that the process info is already outdated when the message is received.
+    // Do not use the process list obtained here for security-sensitive purpose.
+    // Good news is that Android processes are designed to be ready to be killed
+    // at any time, so killing a wrong process is not a disaster.
+    virtual void OnUpdateProcessList(
+        const std::vector<RunningAppProcessInfo>& processes) {}
+
+   protected:
+    virtual ~ProcessObserver() {}
+  };
+
   virtual ~ArcBridgeService();
 
   // Gets the global instance of the ARC Bridge Service. This can only be
@@ -146,6 +164,11 @@
   void AddAppObserver(AppObserver* observer);
   void RemoveAppObserver(AppObserver* observer);
 
+  // Adds or removes ARC process observers. This can only be called on the
+  // thread that this class was created on.
+  void AddProcessObserver(ProcessObserver* observer);
+  void RemoveProcessObserver(ProcessObserver* observer);
+
   // Gets the current state of the bridge service.
   State state() const { return state_; }
 
@@ -178,6 +201,10 @@
                               const std::string& activity,
                               ScaleFactor scale_factor) = 0;
 
+  // Requests a list of processes from the ARC instance.
+  // When the result comes back, Observer::OnUpdateProcessList() is called.
+  virtual bool RequestProcessList() = 0;
+
  protected:
   ArcBridgeService();
 
@@ -188,6 +215,7 @@
   void SetAvailable(bool availability);
 
   base::ObserverList<Observer>& observer_list() { return observer_list_; }
+
   base::ObserverList<NotificationObserver>& notification_observer_list() {
     return notification_observer_list_;
   }
@@ -196,6 +224,10 @@
     return app_observer_list_;
   }
 
+  base::ObserverList<ProcessObserver>& process_observer_list() {
+    return process_observer_list_;
+  }
+
   bool CalledOnValidThread();
 
  private:
@@ -206,8 +238,8 @@
 
   base::ObserverList<Observer> observer_list_;
   base::ObserverList<NotificationObserver> notification_observer_list_;
-
   base::ObserverList<AppObserver> app_observer_list_;
+  base::ObserverList<ProcessObserver> process_observer_list_;
 
   base::ThreadChecker thread_checker_;
 
diff --git a/components/arc/arc_bridge_service_impl.cc b/components/arc/arc_bridge_service_impl.cc
index ddd1b6a..d5485b4d 100644
--- a/components/arc/arc_bridge_service_impl.cc
+++ b/components/arc/arc_bridge_service_impl.cc
@@ -29,6 +29,15 @@
   }
 };
 
+template <>
+struct TypeConverter<arc::RunningAppProcessInfo,
+                     arc::RunningAppProcessInfoPtr> {
+  static arc::RunningAppProcessInfo Convert(
+      const arc::RunningAppProcessInfoPtr& process_ptr) {
+    return *process_ptr;
+  }
+};
+
 }  // namespace mojo
 
 namespace arc {
@@ -160,6 +169,16 @@
   return true;
 }
 
+bool ArcBridgeServiceImpl::RequestProcessList() {
+  DCHECK(CalledOnValidThread());
+  if (state() != State::READY) {
+    LOG(ERROR) << "Called RequestProcessList when the service is not ready";
+    return false;
+  }
+  instance_ptr_->RequestProcessList();
+  return true;
+}
+
 void ArcBridgeServiceImpl::OnInstanceBootPhase(InstanceBootPhase phase) {
   DCHECK(CalledOnValidThread());
   // The state can be CONNECTED the first time this is called, and will then
@@ -203,6 +222,17 @@
       OnAppIcon(package, activity, scale_factor, icon_png_data.storage()));
 }
 
+void ArcBridgeServiceImpl::OnUpdateProcessList(
+    mojo::Array<RunningAppProcessInfoPtr> processes_ptr) {
+  DCHECK(CalledOnValidThread());
+  std::vector<RunningAppProcessInfo> processes(
+      processes_ptr.To<std::vector<RunningAppProcessInfo>>());
+  FOR_EACH_OBSERVER(
+      ProcessObserver,
+      process_observer_list(),
+      OnUpdateProcessList(processes));
+}
+
 void ArcBridgeServiceImpl::OnAcquireDisplayWakeLock(DisplayWakeLockType type) {
   DCHECK(CalledOnValidThread());
   // TODO(ejcaruso): Implement.
diff --git a/components/arc/arc_bridge_service_impl.h b/components/arc/arc_bridge_service_impl.h
index 90e9b92..8c744e1 100644
--- a/components/arc/arc_bridge_service_impl.h
+++ b/components/arc/arc_bridge_service_impl.h
@@ -55,6 +55,9 @@
                       const std::string& activity,
                       ScaleFactor scale_factor) override;
 
+  // Requests ARC process list.
+  bool RequestProcessList() override;
+
  private:
   friend class ArcBridgeTest;
   FRIEND_TEST_ALL_PREFIXES(ArcBridgeTest, Basic);
@@ -85,6 +88,10 @@
                  ScaleFactor scale_factor,
                  mojo::Array<uint8_t> icon_png_data) override;
 
+  // Called when the latest process list is reported from ARC.
+  void OnUpdateProcessList(
+      mojo::Array<RunningAppProcessInfoPtr> processes_ptr) override;
+
   // Called when the instance requests wake lock services
   void OnAcquireDisplayWakeLock(DisplayWakeLockType type) override;
   void OnReleaseDisplayWakeLock(DisplayWakeLockType type) override;
diff --git a/components/arc/common/arc_bridge.mojom b/components/arc/common/arc_bridge.mojom
index d6cdd7b..f555fbcc 100644
--- a/components/arc/common/arc_bridge.mojom
+++ b/components/arc/common/arc_bridge.mojom
@@ -87,6 +87,73 @@
   DIM = 1
 };
 
+// Describes the current process state, as defined by AOSP in
+// android.app.ActivityManager.
+enum ProcessState {
+  // Process does not exist.
+  NONEXISTENT = -1,
+
+  // Process is a persistent system process.
+  PERSISTENT = 0,
+
+  // Process is a persistent system process and is doing UI.
+  PERSISTENT_UI = 1,
+
+  // Process is hosting the current top activities.  Note that this covers
+  // all activities that are visible to the user.
+  TOP = 2,
+
+  // Process is hosting a foreground service due to a system binding.
+  BOUND_FOREGROUND_SERVICE = 3,
+
+  // Process is hosting a foreground service.
+  FOREGROUND_SERVICE = 4,
+
+  // Same as PROCESS_STATE_TOP but while device is sleeping.
+  TOP_SLEEPING = 5,
+
+  // Process is important to the user, and something they are aware of.
+  IMPORTANT_FOREGROUND = 6,
+
+  // Process is important to the user, but not something they are aware of.
+  IMPORTANT_BACKGROUND = 7,
+
+  // Process is in the background running a backup/restore operation.
+  BACKUP = 8,
+
+  // Process is in the background, but it can't restore its state so we want
+  // to try to avoid killing it.
+  HEAVY_WEIGHT = 9,
+
+  // Process is in the background running a service.  Unlike oom_adj, this level
+  // is used for both the normal running in background state and the executing
+  // operations state.
+  SERVICE = 10,
+
+  // Process is in the background running a receiver.   Note that from the
+  // perspective of oom_adj receivers run at a higher foreground level, but for
+  // our prioritization here that is not necessary and putting them below
+  // services means many fewer changes in some process states as they receive
+  // broadcasts.
+  RECEIVER = 11,
+
+  // Process is in the background but hosts the home activity.
+  HOME = 12,
+
+  // Process is in the background but hosts the last shown activity.
+  LAST_ACTIVITY = 13,
+
+  // Process is being cached for later use and contains activities.
+  CACHED_ACTIVITY = 14,
+
+  // Process is being cached for later use and is a client of another cached
+  // process that contains activities.
+  CACHED_ACTIVITY_CLIENT = 15,
+
+  // Process is being cached for later use and is empty.
+  CACHED_EMPTY = 16,
+};
+
 struct ArcNotificationData {
   // Identifier of notification
   string key;
@@ -110,6 +177,19 @@
   int32 progress_max;
 };
 
+// Describes a running ARC process.
+// This struct is a subset of android.app.ActivityManager.RunningAppProcessInfo.
+struct RunningAppProcessInfo {
+  // Name of the process.
+  string process_name;
+
+  // PID (within ARC's PID namespace) of the process.
+  uint32 pid;
+
+  // Current process state.
+  ProcessState process_state;
+};
+
 // TODO(lhchavez): Migrate all request/response messages to Mojo.
 interface ArcBridgeHost {
   OnInstanceBootPhase(InstanceBootPhase phase);
@@ -140,6 +220,9 @@
   // Acquire and release wake locks on the host side.
   OnAcquireDisplayWakeLock(DisplayWakeLockType type);
   OnReleaseDisplayWakeLock(DisplayWakeLockType type);
+
+  // Notifies Chrome that the ARC process list has been updated.
+  OnUpdateProcessList(array<RunningAppProcessInfo> processes);
 };
 
 interface ArcBridgeInstance {
@@ -177,4 +260,7 @@
   // Sends an event from Chrome notification UI to Android.
   // |event| is a type of occured event.
   SendNotificationEventToAndroid(string key, ArcNotificationEvent event);
+
+  // Requests ARC instance to return the current process list.
+  RequestProcessList();
 };
diff --git a/components/arc/test/fake_arc_bridge_instance.cc b/components/arc/test/fake_arc_bridge_instance.cc
index a60b6c1..ffba237 100644
--- a/components/arc/test/fake_arc_bridge_instance.cc
+++ b/components/arc/test/fake_arc_bridge_instance.cc
@@ -34,6 +34,8 @@
                                            const mojo::String& activity,
                                            ScaleFactor scale_factor) {}
 
+void FakeArcBridgeInstance::RequestProcessList() {}
+
 void FakeArcBridgeInstance::Bind(
     mojo::InterfaceRequest<ArcBridgeInstance> interface_request) {
   binding_.Bind(std::move(interface_request));
diff --git a/components/arc/test/fake_arc_bridge_instance.h b/components/arc/test/fake_arc_bridge_instance.h
index 43ba82a..82bad56 100644
--- a/components/arc/test/fake_arc_bridge_instance.h
+++ b/components/arc/test/fake_arc_bridge_instance.h
@@ -34,6 +34,7 @@
   void RequestAppIcon(const mojo::String& package,
                       const mojo::String& activity,
                       ScaleFactor scale_factor) override;
+  void RequestProcessList() override;
 
  private:
   // Mojo endpoints.
diff --git a/components/arc/test/fake_arc_bridge_service.cc b/components/arc/test/fake_arc_bridge_service.cc
index 1971a27..2c69080 100644
--- a/components/arc/test/fake_arc_bridge_service.cc
+++ b/components/arc/test/fake_arc_bridge_service.cc
@@ -58,6 +58,10 @@
   return true;
 }
 
+bool FakeArcBridgeService::RequestProcessList() {
+  return true;
+}
+
 void FakeArcBridgeService::SetReady() {
   SetState(State::READY);
 }
diff --git a/components/arc/test/fake_arc_bridge_service.h b/components/arc/test/fake_arc_bridge_service.h
index ef4e20d..70d862e 100644
--- a/components/arc/test/fake_arc_bridge_service.h
+++ b/components/arc/test/fake_arc_bridge_service.h
@@ -79,6 +79,7 @@
                       ScaleFactor scale_factor) override;
   bool SendNotificationEventToAndroid(const std::string& key,
                                       ArcNotificationEvent event) override;
+  bool RequestProcessList() override;
 
   int refresh_app_list_count() const { return refresh_app_list_count_; }
 
diff --git a/components/autofill.gypi b/components/autofill.gypi
index b9cb375e..0b47168 100644
--- a/components/autofill.gypi
+++ b/components/autofill.gypi
@@ -11,8 +11,6 @@
       'dependencies': [
         '../base/base.gyp:base',
         '../base/base.gyp:base_i18n',
-        '../ui/base/ui_base.gyp:ui_base',
-        '../ui/gfx/gfx.gyp:gfx',
         '../url/url.gyp:url_lib',
       ],
       'include_dirs': [
diff --git a/components/autofill/core/common/BUILD.gn b/components/autofill/core/common/BUILD.gn
index 05ef7bd..d6213b21 100644
--- a/components/autofill/core/common/BUILD.gn
+++ b/components/autofill/core/common/BUILD.gn
@@ -39,8 +39,6 @@
   deps = [
     "//base",
     "//base:i18n",
-    "//ui/base",
-    "//ui/gfx",
     "//url",
   ]
 
diff --git a/components/dom_distiller/content/browser/test/dom_distiller_js_browsertest.cc b/components/dom_distiller/content/browser/test/dom_distiller_js_browsertest.cc
index b49545e..849fdab 100644
--- a/components/dom_distiller/content/browser/test/dom_distiller_js_browsertest.cc
+++ b/components/dom_distiller/content/browser/test/dom_distiller_js_browsertest.cc
@@ -48,9 +48,7 @@
 
 const char* kExternalTestResourcesPath =
     "third_party/dom_distiller_js/dist/test/data";
-// TODO(wychen) Remove filter when crbug.com/471854 is fixed.
-const char* kTestFilePath =
-    "/war/test.html?console_log=0&filter=-*.SchemaOrgParserAccessorTest.*";
+const char* kTestFilePath = "/war/test.html?console_log=0";
 const char* kRunJsTestsJs =
     "(function() {return org.chromium.distiller.JsTestEntry.run();})();";
 
@@ -120,7 +118,7 @@
   // Add timeout in case JS Test execution fails. It is safe to call the
   // QuitClosure multiple times.
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-      FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromSeconds(15));
+      FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromSeconds(30));
   web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
       base::UTF8ToUTF16(kRunJsTestsJs),
       base::Bind(&DomDistillerJsTest::OnJsTestExecutionDone,
diff --git a/components/password_manager/core/browser/password_ui_utils.cc b/components/password_manager/core/browser/password_ui_utils.cc
index 11d12df..a718f429 100644
--- a/components/password_manager/core/browser/password_ui_utils.cc
+++ b/components/password_manager/core/browser/password_ui_utils.cc
@@ -22,11 +22,15 @@
 }  // namespace
 
 std::string GetShownOrigin(const autofill::PasswordForm& password_form,
-                           const std::string& languages) {
+                           const std::string& languages,
+                           bool* is_android_uri) {
+  DCHECK(is_android_uri != nullptr);
+
   password_manager::FacetURI facet_uri =
       password_manager::FacetURI::FromPotentiallyInvalidSpec(
           password_form.signon_realm);
-  if (facet_uri.IsValidAndroidFacetURI())
+  *is_android_uri = facet_uri.IsValidAndroidFacetURI();
+  if (*is_android_uri)
     return GetHumanReadableOriginForAndroidUri(facet_uri);
 
   std::string original =
diff --git a/components/password_manager/core/browser/password_ui_utils.h b/components/password_manager/core/browser/password_ui_utils.h
index b0cb41e7..28cabd2 100644
--- a/components/password_manager/core/browser/password_ui_utils.h
+++ b/components/password_manager/core/browser/password_ui_utils.h
@@ -20,9 +20,12 @@
 // Returns a string suitable for security display to the user (just like
 // |FormatUrlForSecurityDisplayOmitScheme| based on origin of |password_form|
 // and |languages|) and without prefixes "m.", "mobile." or "www.". For Android
-// URIs, returns the result of GetHumanReadableOriginForAndroidUri.
+// URIs, returns the result of GetHumanReadableOriginForAndroidUri and sets
+// |*is_android_uri| to true, otherwise |*is_android_uri| is set to false.
+// |is_android_uri| is required to be non-null.
 std::string GetShownOrigin(const autofill::PasswordForm& password_form,
-                           const std::string& languages);
+                           const std::string& languages,
+                           bool* is_android_uri);
 
 }  // namespace password_manager
 
diff --git a/components/password_manager/core/browser/password_ui_utils_unittest.cc b/components/password_manager/core/browser/password_ui_utils_unittest.cc
index 25e4b59..c5a66d8 100644
--- a/components/password_manager/core/browser/password_ui_utils_unittest.cc
+++ b/components/password_manager/core/browser/password_ui_utils_unittest.cc
@@ -33,8 +33,11 @@
     autofill::PasswordForm password_form;
     password_form.signon_realm = "https://non.android.signon.com";
     password_form.origin = GURL(test_case.input);
-    EXPECT_EQ(test_case.output, GetShownOrigin(password_form, ""))
+    bool is_android_uri;
+    EXPECT_EQ(test_case.output,
+              GetShownOrigin(password_form, "", &is_android_uri))
         << "for input " << test_case.input;
+    EXPECT_FALSE(is_android_uri) << "for input " << test_case.input;
   }
 }
 
@@ -45,7 +48,10 @@
       "m3HSJL1i83hdltRq0-o9czGb-8KJDKra4t_"
       "3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw=="
       "@com.example.android";
-  EXPECT_EQ(GetShownOrigin(android_form, ""), "android://com.example.android");
+  bool is_android_uri;
+  EXPECT_EQ(GetShownOrigin(android_form, "", &is_android_uri),
+            "android://com.example.android");
+  EXPECT_TRUE(is_android_uri);
 }
 
 }  // namespace password_manager
diff --git a/components/user_prefs.gypi b/components/user_prefs.gypi
index cfeff21..db5590f 100644
--- a/components/user_prefs.gypi
+++ b/components/user_prefs.gypi
@@ -60,6 +60,8 @@
         'user_prefs/tracked/tracked_preference.h',
         'user_prefs/tracked/tracked_preference_helper.cc',
         'user_prefs/tracked/tracked_preference_helper.h',
+        'user_prefs/tracked/tracked_preference_histogram_names.cc',
+        'user_prefs/tracked/tracked_preference_histogram_names.h',
         'user_prefs/tracked/tracked_preference_validation_delegate.h',
         'user_prefs/tracked/tracked_preferences_migration.cc',
         'user_prefs/tracked/tracked_preferences_migration.h',
diff --git a/components/user_prefs/tracked/BUILD.gn b/components/user_prefs/tracked/BUILD.gn
index 8c32ec7..25fc09c 100644
--- a/components/user_prefs/tracked/BUILD.gn
+++ b/components/user_prefs/tracked/BUILD.gn
@@ -32,6 +32,8 @@
     "tracked_preference.h",
     "tracked_preference_helper.cc",
     "tracked_preference_helper.h",
+    "tracked_preference_histogram_names.cc",
+    "tracked_preference_histogram_names.h",
     "tracked_preference_validation_delegate.h",
     "tracked_preferences_migration.cc",
     "tracked_preferences_migration.h",
diff --git a/components/user_prefs/tracked/tracked_preference_helper.cc b/components/user_prefs/tracked/tracked_preference_helper.cc
index ade75ae..f2e6883 100644
--- a/components/user_prefs/tracked/tracked_preference_helper.cc
+++ b/components/user_prefs/tracked/tracked_preference_helper.cc
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
+#include "components/user_prefs/tracked/tracked_preference_histogram_names.h"
 
 TrackedPreferenceHelper::TrackedPreferenceHelper(
     const std::string& pref_path,
@@ -53,33 +54,39 @@
     PrefHashStoreTransaction::ValueState value_state) const {
   switch (value_state) {
     case PrefHashStoreTransaction::UNCHANGED:
-      UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferenceUnchanged",
-                                reporting_id_, reporting_ids_count_);
+      UMA_HISTOGRAM_ENUMERATION(
+          user_prefs::tracked::kTrackedPrefHistogramUnchanged, reporting_id_,
+          reporting_ids_count_);
       return;
     case PrefHashStoreTransaction::CLEARED:
-      UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferenceCleared",
-                                reporting_id_, reporting_ids_count_);
+      UMA_HISTOGRAM_ENUMERATION(
+          user_prefs::tracked::kTrackedPrefHistogramCleared, reporting_id_,
+          reporting_ids_count_);
       return;
     case PrefHashStoreTransaction::SECURE_LEGACY:
       UMA_HISTOGRAM_ENUMERATION(
-          "Settings.TrackedPreferenceMigratedLegacyDeviceId", reporting_id_,
-          reporting_ids_count_);
+          user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
+          reporting_id_, reporting_ids_count_);
       return;
     case PrefHashStoreTransaction::CHANGED:
-      UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferenceChanged",
-                                reporting_id_, reporting_ids_count_);
+      UMA_HISTOGRAM_ENUMERATION(
+          user_prefs::tracked::kTrackedPrefHistogramChanged, reporting_id_,
+          reporting_ids_count_);
       return;
     case PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE:
-      UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferenceInitialized",
-                                reporting_id_, reporting_ids_count_);
+      UMA_HISTOGRAM_ENUMERATION(
+          user_prefs::tracked::kTrackedPrefHistogramInitialized, reporting_id_,
+          reporting_ids_count_);
       return;
     case PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE:
-      UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferenceTrustedInitialized",
-                                reporting_id_, reporting_ids_count_);
+      UMA_HISTOGRAM_ENUMERATION(
+          user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
+          reporting_id_, reporting_ids_count_);
       return;
     case PrefHashStoreTransaction::TRUSTED_NULL_VALUE:
-      UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferenceNullInitialized",
-                                reporting_id_, reporting_ids_count_);
+      UMA_HISTOGRAM_ENUMERATION(
+          user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
+          reporting_id_, reporting_ids_count_);
       return;
   }
   NOTREACHED() << "Unexpected PrefHashStoreTransaction::ValueState: "
@@ -92,11 +99,12 @@
       // No report for DONT_RESET.
       break;
     case WANTED_RESET:
-      UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferenceWantedReset",
-                                reporting_id_, reporting_ids_count_);
+      UMA_HISTOGRAM_ENUMERATION(
+          user_prefs::tracked::kTrackedPrefHistogramWantedReset, reporting_id_,
+          reporting_ids_count_);
       break;
     case DO_RESET:
-      UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferenceReset",
+      UMA_HISTOGRAM_ENUMERATION(user_prefs::tracked::kTrackedPrefHistogramReset,
                                 reporting_id_, reporting_ids_count_);
       break;
   }
@@ -107,12 +115,9 @@
   // The histogram below is an expansion of the UMA_HISTOGRAM_COUNTS_100 macro
   // adapted to allow for a dynamically suffixed histogram name.
   // Note: The factory creates and owns the histogram.
-  base::HistogramBase* histogram =
-      base::LinearHistogram::FactoryGet(
-          "Settings.TrackedSplitPreferenceChanged." + pref_path_,
-          1,
-          100,  // Allow counts up to 100.
-          101,
-          base::HistogramBase::kUmaTargetedHistogramFlag);
+  base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
+      user_prefs::tracked::kTrackedSplitPrefHistogramChanged + pref_path_, 1,
+      100,  // Allow counts up to 100.
+      101, base::HistogramBase::kUmaTargetedHistogramFlag);
   histogram->Add(count);
 }
diff --git a/components/user_prefs/tracked/tracked_preference_histogram_names.cc b/components/user_prefs/tracked/tracked_preference_histogram_names.cc
new file mode 100644
index 0000000..deb4236d
--- /dev/null
+++ b/components/user_prefs/tracked/tracked_preference_histogram_names.cc
@@ -0,0 +1,30 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/user_prefs/tracked/tracked_preference_histogram_names.h"
+
+namespace user_prefs {
+namespace tracked {
+
+// Tracked pref histogram names.
+const char kTrackedPrefHistogramUnchanged[] =
+    "Settings.TrackedPreferenceUnchanged";
+const char kTrackedPrefHistogramCleared[] = "Settings.TrackedPreferenceCleared";
+const char kTrackedPrefHistogramMigratedLegacyDeviceId[] =
+    "Settings.TrackedPreferenceMigratedLegacyDeviceId";
+const char kTrackedPrefHistogramChanged[] = "Settings.TrackedPreferenceChanged";
+const char kTrackedPrefHistogramInitialized[] =
+    "Settings.TrackedPreferenceInitialized";
+const char kTrackedPrefHistogramTrustedInitialized[] =
+    "Settings.TrackedPreferenceTrustedInitialized";
+const char kTrackedPrefHistogramNullInitialized[] =
+    "Settings.TrackedPreferenceNullInitialized";
+const char kTrackedPrefHistogramWantedReset[] =
+    "Settings.TrackedPreferenceWantedReset";
+const char kTrackedPrefHistogramReset[] = "Settings.TrackedPreferenceReset";
+const char kTrackedSplitPrefHistogramChanged[] =
+    "Settings.TrackedSplitPreferenceChanged.";
+
+}  // namespace tracked
+}  // namespace user_prefs
diff --git a/components/user_prefs/tracked/tracked_preference_histogram_names.h b/components/user_prefs/tracked/tracked_preference_histogram_names.h
new file mode 100644
index 0000000..c5a82a5
--- /dev/null
+++ b/components/user_prefs/tracked/tracked_preference_histogram_names.h
@@ -0,0 +1,25 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_USER_PREFS_TRACKED_TRACKED_PREFERENCE_HISTOGRAM_NAMES_H_
+#define COMPONENTS_USER_PREFS_TRACKED_TRACKED_PREFERENCE_HISTOGRAM_NAMES_H_
+
+namespace user_prefs {
+namespace tracked {
+
+extern const char kTrackedPrefHistogramUnchanged[];
+extern const char kTrackedPrefHistogramCleared[];
+extern const char kTrackedPrefHistogramMigratedLegacyDeviceId[];
+extern const char kTrackedPrefHistogramChanged[];
+extern const char kTrackedPrefHistogramInitialized[];
+extern const char kTrackedPrefHistogramTrustedInitialized[];
+extern const char kTrackedPrefHistogramNullInitialized[];
+extern const char kTrackedPrefHistogramWantedReset[];
+extern const char kTrackedPrefHistogramReset[];
+extern const char kTrackedSplitPrefHistogramChanged[];
+
+}  // namespace tracked
+}  // namespace user_prefs
+
+#endif  // COMPONENTS_USER_PREFS_TRACKED_TRACKED_PREFERENCE_HISTOGRAM_NAMES_H_
diff --git a/content/browser/cross_site_transfer_browsertest.cc b/content/browser/cross_site_transfer_browsertest.cc
index ce57011..560547d 100644
--- a/content/browser/cross_site_transfer_browsertest.cc
+++ b/content/browser/cross_site_transfer_browsertest.cc
@@ -144,22 +144,9 @@
  public:
   NoTransferRequestDelegate() {}
 
-  WebContents* OpenURLFromTab(WebContents* source,
-                              const OpenURLParams& params) override {
-    bool is_transfer =
-        (params.transferred_global_request_id != GlobalRequestID());
-    if (is_transfer)
-      return nullptr;
-    NavigationController::LoadURLParams load_url_params(params.url);
-    load_url_params.referrer = params.referrer;
-    load_url_params.frame_tree_node_id = params.frame_tree_node_id;
-    load_url_params.transition_type = params.transition;
-    load_url_params.extra_headers = params.extra_headers;
-    load_url_params.should_replace_current_entry =
-        params.should_replace_current_entry;
-    load_url_params.is_renderer_initiated = true;
-    source->GetController().LoadURLWithParams(load_url_params);
-    return source;
+  bool ShouldTransferNavigation() override {
+    // Intentionally cancel the transfer.
+    return false;
   }
 
  private:
diff --git a/content/browser/frame_host/navigation_controller_android.cc b/content/browser/frame_host/navigation_controller_android.cc
index fad0caf..7a76f5d 100644
--- a/content/browser/frame_host/navigation_controller_android.cc
+++ b/content/browser/frame_host/navigation_controller_android.cc
@@ -12,6 +12,7 @@
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/ssl_host_state_delegate.h"
 #include "jni/NavigationControllerImpl_jni.h"
+#include "net/base/data_url.h"
 #include "ui/gfx/android/java_bitmap.h"
 
 using base::android::AttachCurrentThread;
@@ -202,6 +203,7 @@
     const JavaParamRef<jbyteArray>& post_data,
     const JavaParamRef<jstring>& base_url_for_data_url,
     const JavaParamRef<jstring>& virtual_url_for_data_url,
+    const JavaParamRef<jstring>& data_url_as_string,
     jboolean can_load_local_resources,
     jboolean is_renderer_initiated,
     jboolean should_replace_current_entry) {
@@ -239,6 +241,24 @@
         GURL(ConvertJavaStringToUTF8(env, virtual_url_for_data_url));
   }
 
+  if (data_url_as_string) {
+    // Treat |data_url_as_string| as if we were intending to put it into a GURL
+    // field. Note that kMaxURLChars is only enforced when serializing URLs
+    // for IPC.
+    GURL data_url = GURL(ConvertJavaStringToUTF8(env, data_url_as_string));
+    DCHECK(data_url.SchemeIs(url::kDataScheme));
+    DCHECK(params.url.SchemeIs(url::kDataScheme));
+#if DCHECK_IS_ON()
+    {
+      std::string mime_type, charset, data;
+      DCHECK(net::DataURL::Parse(params.url, &mime_type, &charset, &data));
+      DCHECK(data.empty());
+    }
+#endif
+    std::string s = data_url.spec();
+    params.data_url_as_string = base::RefCountedString::TakeString(&s);
+  }
+
   if (j_referrer_url) {
     params.referrer = content::Referrer(
         GURL(ConvertJavaStringToUTF8(env, j_referrer_url)),
diff --git a/content/browser/frame_host/navigation_controller_android.h b/content/browser/frame_host/navigation_controller_android.h
index 962b41cd..fba0ec71 100644
--- a/content/browser/frame_host/navigation_controller_android.h
+++ b/content/browser/frame_host/navigation_controller_android.h
@@ -83,6 +83,7 @@
       const base::android::JavaParamRef<jbyteArray>& post_data,
       const base::android::JavaParamRef<jstring>& base_url_for_data_url,
       const base::android::JavaParamRef<jstring>& virtual_url_for_data_url,
+      const base::android::JavaParamRef<jstring>& data_url_as_string,
       jboolean can_load_local_resources,
       jboolean is_renderer_initiated,
       jboolean should_replace_current_entry);
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc
index 3ff0d6b..3d0d934 100644
--- a/content/browser/frame_host/navigation_controller_impl.cc
+++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -805,6 +805,9 @@
     case LOAD_TYPE_DATA:
       entry->SetBaseURLForDataURL(params.base_url_for_data_url);
       entry->SetVirtualURL(params.virtual_url_for_data_url);
+#if defined(OS_ANDROID)
+      entry->SetDataURLAsString(params.data_url_as_string);
+#endif
       entry->SetCanLoadLocalResources(params.can_load_local_resources);
       break;
     default:
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc
index 35d8319..de8d39c 100644
--- a/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -540,6 +540,9 @@
   if (!load_params.virtual_url_for_data_url.is_empty()) {
     EXPECT_EQ(load_params.virtual_url_for_data_url, entry->GetVirtualURL());
   }
+#if defined(OS_ANDROID)
+  EXPECT_EQ(load_params.data_url_as_string, entry->GetDataURLAsString());
+#endif
   if (NavigationController::UA_OVERRIDE_INHERIT !=
       load_params.override_user_agent) {
     bool should_override = (NavigationController::UA_OVERRIDE_TRUE ==
@@ -595,6 +598,25 @@
   CheckNavigationEntryMatchLoadParams(load_params, entry);
 }
 
+#if defined(OS_ANDROID)
+TEST_F(NavigationControllerTest, LoadURLWithExtraParams_Data_Android) {
+  NavigationControllerImpl& controller = controller_impl();
+
+  NavigationController::LoadURLParams load_params(GURL("data:,"));
+  load_params.load_type = NavigationController::LOAD_TYPE_DATA;
+  load_params.base_url_for_data_url = GURL("http://foo");
+  load_params.virtual_url_for_data_url = GURL(url::kAboutBlankURL);
+  std::string s("data:,data");
+  load_params.data_url_as_string = base::RefCountedString::TakeString(&s);
+  load_params.override_user_agent = NavigationController::UA_OVERRIDE_FALSE;
+
+  controller.LoadURLWithParams(load_params);
+  NavigationEntryImpl* entry = controller.GetPendingEntry();
+
+  CheckNavigationEntryMatchLoadParams(load_params, entry);
+}
+#endif
+
 TEST_F(NavigationControllerTest, LoadURLWithExtraParams_HttpPost) {
   NavigationControllerImpl& controller = controller_impl();
 
diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc
index 343951e..e72549e 100644
--- a/content/browser/frame_host/navigation_entry_impl.cc
+++ b/content/browser/frame_host/navigation_entry_impl.cc
@@ -10,6 +10,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/url_formatter/url_formatter.h"
+#include "content/common/content_constants_internal.h"
 #include "content/common/navigation_params.h"
 #include "content/common/page_state_serialization.h"
 #include "content/common/site_isolation_policy.h"
@@ -211,6 +212,23 @@
   return base_url_for_data_url_;
 }
 
+#if defined(OS_ANDROID)
+void NavigationEntryImpl::SetDataURLAsString(
+    scoped_refptr<base::RefCountedString> data_url) {
+  if (data_url) {
+    // A quick check that it's actually a data URL.
+    DCHECK(base::StartsWith(data_url->front_as<char>(), url::kDataScheme,
+                            base::CompareCase::SENSITIVE));
+  }
+  data_url_as_string_ = data_url;
+}
+
+const scoped_refptr<const base::RefCountedString>
+NavigationEntryImpl::GetDataURLAsString() const {
+  return data_url_as_string_;
+}
+#endif
+
 void NavigationEntryImpl::SetReferrer(const Referrer& referrer) {
   frame_tree_->frame_entry->set_referrer(referrer);
 }
@@ -520,6 +538,9 @@
   copy->extra_headers_ = extra_headers_;
   // ResetForCommit: source_site_instance_
   copy->base_url_for_data_url_ = base_url_for_data_url_;
+#if defined(OS_ANDROID)
+  copy->data_url_as_string_ = data_url_as_string_;
+#endif
   // ResetForCommit: is_renderer_initiated_
   copy->cached_display_title_ = cached_display_title_;
   // ResetForCommit: transferred_global_request_id_
@@ -602,12 +623,28 @@
     current_length_to_send = 0;
   }
 
-  return RequestNavigationParams(
+  RequestNavigationParams request_params(
       GetIsOverridingUserAgent(), redirects, GetCanLoadLocalResources(),
       base::Time::Now(), frame_entry.page_state(), GetPageID(), GetUniqueID(),
       is_same_document_history_load, has_committed_real_load,
       intended_as_new_entry, pending_offset_to_send, current_offset_to_send,
       current_length_to_send, IsViewSourceMode(), should_clear_history_list());
+#if defined(OS_ANDROID)
+  if (GetDataURLAsString() &&
+      GetDataURLAsString()->size() <= kMaxLengthOfDataURLString) {
+    // The number of characters that is enough for validating a data: URI.  From
+    // the GURL's POV, the only important part here is scheme, it doesn't check
+    // the actual content. Thus we can take only the prefix of the url, to avoid
+    // unneeded copying of a potentially long string.
+    const size_t kDataUriPrefixMaxLen = 64;
+    GURL data_url(std::string(
+        GetDataURLAsString()->front_as<char>(),
+        std::min(GetDataURLAsString()->size(), kDataUriPrefixMaxLen)));
+    if (data_url.is_valid() && data_url.SchemeIs(url::kDataScheme))
+      request_params.data_url_as_string = GetDataURLAsString()->data();
+  }
+#endif
+  return request_params;
 }
 
 void NavigationEntryImpl::ResetForCommit() {
diff --git a/content/browser/frame_host/navigation_entry_impl.h b/content/browser/frame_host/navigation_entry_impl.h
index 9a13f65..000504b2 100644
--- a/content/browser/frame_host/navigation_entry_impl.h
+++ b/content/browser/frame_host/navigation_entry_impl.h
@@ -82,6 +82,12 @@
   const GURL& GetURL() const override;
   void SetBaseURLForDataURL(const GURL& url) override;
   const GURL& GetBaseURLForDataURL() const override;
+#if defined(OS_ANDROID)
+  void SetDataURLAsString(
+      scoped_refptr<base::RefCountedString> data_url) override;
+  const scoped_refptr<const base::RefCountedString> GetDataURLAsString()
+      const override;
+#endif
   void SetReferrer(const Referrer& referrer) override;
   const Referrer& GetReferrer() const override;
   void SetVirtualURL(const GURL& url) override;
@@ -420,6 +426,12 @@
   // persisted by Android WebView.
   GURL base_url_for_data_url_;
 
+#if defined(OS_ANDROID)
+  // Used for passing really big data URLs from browser to renderers. Only used
+  // and persisted by Android WebView.
+  scoped_refptr<const base::RefCountedString> data_url_as_string_;
+#endif
+
   // Whether the entry, while loading, was created for a renderer-initiated
   // navigation.  This dictates whether the URL should be displayed before the
   // navigation commits.  It is cleared in |ResetForCommit| and not persisted.
diff --git a/content/browser/frame_host/navigator.h b/content/browser/frame_host/navigator.h
index 6f9e52d..4eedff5 100644
--- a/content/browser/frame_host/navigator.h
+++ b/content/browser/frame_host/navigator.h
@@ -130,8 +130,7 @@
       ui::PageTransition page_transition,
       WindowOpenDisposition disposition,
       const GlobalRequestID& transferred_global_request_id,
-      bool should_replace_current_entry,
-      bool user_gesture) {}
+      bool should_replace_current_entry) {}
 
   // PlzNavigate
   // Called after receiving a BeforeUnloadACK IPC from the renderer. If
diff --git a/content/browser/frame_host/navigator_delegate.cc b/content/browser/frame_host/navigator_delegate.cc
index 4389c81..416be62 100644
--- a/content/browser/frame_host/navigator_delegate.cc
+++ b/content/browser/frame_host/navigator_delegate.cc
@@ -10,6 +10,10 @@
   return false;
 }
 
+bool NavigatorDelegate::ShouldTransferNavigation() {
+  return true;
+}
+
 bool NavigatorDelegate::ShouldPreserveAbortedURLs() {
   return false;
 }
diff --git a/content/browser/frame_host/navigator_delegate.h b/content/browser/frame_host/navigator_delegate.h
index 79fb796..3263ffd 100644
--- a/content/browser/frame_host/navigator_delegate.h
+++ b/content/browser/frame_host/navigator_delegate.h
@@ -108,6 +108,10 @@
   virtual void RequestOpenURL(RenderFrameHostImpl* render_frame_host,
                               const OpenURLParams& params) {}
 
+  // Returns whether to continue a navigation that needs to transfer to a
+  // different process between the load start and commit.
+  virtual bool ShouldTransferNavigation();
+
   // Returns whether URLs for aborted browser-initiated navigations should be
   // preserved in the omnibox.  Defaults to false.
   virtual bool ShouldPreserveAbortedURLs();
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index 7050456..28344a15b 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -36,10 +36,10 @@
 #include "content/public/browser/user_metrics.h"
 #include "content/public/common/bindings_policy.h"
 #include "content/public/common/content_client.h"
+#include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/resource_response.h"
 #include "content/public/common/url_constants.h"
-#include "content/public/common/url_utils.h"
 #include "net/base/net_errors.h"
 
 namespace content {
@@ -281,8 +281,8 @@
 
   // The renderer will reject IPC messages with URLs longer than
   // this limit, so don't attempt to navigate with a longer URL.
-  if (dest_url.spec().size() > GetMaxURLChars()) {
-    LOG(WARNING) << "Refusing to load URL as it exceeds " << GetMaxURLChars()
+  if (dest_url.spec().size() > kMaxURLChars) {
+    LOG(WARNING) << "Refusing to load URL as it exceeds " << kMaxURLChars
                  << " characters.";
     return false;
   }
@@ -579,33 +579,11 @@
     return;
   }
 
-  // Delegate to RequestTransferURL because this is just the generic
-  // case where |old_request_id| is empty.
   // TODO(creis): Pass the redirect_chain into this method to support client
   // redirects.  http://crbug.com/311721.
   std::vector<GURL> redirect_chain;
-  RequestTransferURL(render_frame_host, url, source_site_instance,
-                     redirect_chain, referrer, ui::PAGE_TRANSITION_LINK,
-                     disposition, GlobalRequestID(),
-                     should_replace_current_entry, user_gesture);
-}
 
-void NavigatorImpl::RequestTransferURL(
-    RenderFrameHostImpl* render_frame_host,
-    const GURL& url,
-    SiteInstance* source_site_instance,
-    const std::vector<GURL>& redirect_chain,
-    const Referrer& referrer,
-    ui::PageTransition page_transition,
-    WindowOpenDisposition disposition,
-    const GlobalRequestID& transferred_global_request_id,
-    bool should_replace_current_entry,
-    bool user_gesture) {
   GURL dest_url(url);
-  RenderFrameHostImpl* current_render_frame_host =
-      GetRenderManager(render_frame_host)->current_frame_host();
-  SiteInstance* current_site_instance =
-      current_render_frame_host->GetSiteInstance();
   if (!GetContentClient()->browser()->ShouldAllowOpenURL(
           current_site_instance, url)) {
     dest_url = GURL(url::kAboutBlankURL);
@@ -622,25 +600,26 @@
         render_frame_host->frame_tree_node()->frame_tree_node_id();
   }
 
-  OpenURLParams params(
-      dest_url, referrer, frame_tree_node_id, disposition, page_transition,
-      true /* is_renderer_initiated */);
+  OpenURLParams params(dest_url, referrer, frame_tree_node_id, disposition,
+                       ui::PAGE_TRANSITION_LINK,
+                       true /* is_renderer_initiated */);
   params.source_site_instance = source_site_instance;
   if (redirect_chain.size() > 0)
     params.redirect_chain = redirect_chain;
-  params.transferred_global_request_id = transferred_global_request_id;
+  // TODO(creis): Remove transferred_global_request_id from OpenURLParams.
+  // See https://crbug.com/495161.
+  params.transferred_global_request_id = GlobalRequestID();
   params.should_replace_current_entry = should_replace_current_entry;
   params.user_gesture = user_gesture;
 
-  if (current_render_frame_host->web_ui()) {
+  if (render_frame_host->web_ui()) {
     // Web UI pages sometimes want to override the page transition type for
     // link clicks (e.g., so the new tab page can specify AUTO_BOOKMARK for
     // automatically generated suggestions).  We don't override other types
     // like TYPED because they have different implications (e.g., autocomplete).
     if (ui::PageTransitionCoreTypeIs(
         params.transition, ui::PAGE_TRANSITION_LINK))
-      params.transition =
-          current_render_frame_host->web_ui()->GetLinkTransitionType();
+      params.transition = render_frame_host->web_ui()->GetLinkTransitionType();
 
     // Note also that we hide the referrer for Web UI pages. We don't really
     // want web sites to see a referrer of "chrome://blah" (and some
@@ -656,6 +635,65 @@
     delegate_->RequestOpenURL(render_frame_host, params);
 }
 
+void NavigatorImpl::RequestTransferURL(
+    RenderFrameHostImpl* render_frame_host,
+    const GURL& url,
+    SiteInstance* source_site_instance,
+    const std::vector<GURL>& redirect_chain,
+    const Referrer& referrer,
+    ui::PageTransition page_transition,
+    WindowOpenDisposition disposition,
+    const GlobalRequestID& transferred_global_request_id,
+    bool should_replace_current_entry) {
+  // Allow the delegate to cancel the transfer.
+  if (!delegate_->ShouldTransferNavigation())
+    return;
+
+  GURL dest_url(url);
+  Referrer referrer_to_use(referrer);
+  FrameTreeNode* node = render_frame_host->frame_tree_node();
+  SiteInstance* current_site_instance = render_frame_host->GetSiteInstance();
+  if (!GetContentClient()->browser()->ShouldAllowOpenURL(current_site_instance,
+                                                         url)) {
+    dest_url = GURL(url::kAboutBlankURL);
+  }
+
+  DCHECK_EQ(CURRENT_TAB, disposition);
+
+  // TODO(creis): Determine if this transfer started as a browser-initiated
+  // navigation.  See https://crbug.com/495161.
+  bool is_renderer_initiated = true;
+  if (render_frame_host->web_ui()) {
+    // Web UI pages sometimes want to override the page transition type for
+    // link clicks (e.g., so the new tab page can specify AUTO_BOOKMARK for
+    // automatically generated suggestions).  We don't override other types
+    // like TYPED because they have different implications (e.g., autocomplete).
+    if (ui::PageTransitionCoreTypeIs(page_transition, ui::PAGE_TRANSITION_LINK))
+      page_transition = render_frame_host->web_ui()->GetLinkTransitionType();
+
+    // Note also that we hide the referrer for Web UI pages. We don't really
+    // want web sites to see a referrer of "chrome://blah" (and some
+    // chrome: URLs might have search terms or other stuff we don't want to
+    // send to the site), so we send no referrer.
+    referrer_to_use = Referrer();
+
+    // Navigations in Web UI pages count as browser-initiated navigations.
+    is_renderer_initiated = false;
+  }
+
+  NavigationController::LoadURLParams load_url_params(dest_url);
+  load_url_params.source_site_instance = source_site_instance;
+  load_url_params.transition_type = page_transition;
+  load_url_params.frame_tree_node_id = node->frame_tree_node_id();
+  load_url_params.referrer = referrer_to_use;
+  load_url_params.redirect_chain = redirect_chain;
+  load_url_params.is_renderer_initiated = is_renderer_initiated;
+  load_url_params.transferred_global_request_id = transferred_global_request_id;
+  load_url_params.should_replace_current_entry = should_replace_current_entry;
+
+  controller_->LoadURLWithParams(load_url_params);
+}
+
 // PlzNavigate
 void NavigatorImpl::OnBeforeUnloadACK(FrameTreeNode* frame_tree_node,
                                       bool proceed) {
diff --git a/content/browser/frame_host/navigator_impl.h b/content/browser/frame_host/navigator_impl.h
index 5a7a21cd..91c172e 100644
--- a/content/browser/frame_host/navigator_impl.h
+++ b/content/browser/frame_host/navigator_impl.h
@@ -73,8 +73,7 @@
                           ui::PageTransition page_transition,
                           WindowOpenDisposition disposition,
                           const GlobalRequestID& transferred_global_request_id,
-                          bool should_replace_current_entry,
-                          bool user_gesture) override;
+                          bool should_replace_current_entry) override;
   void OnBeforeUnloadACK(FrameTreeNode* frame_tree_node, bool proceed) override;
   void OnBeginNavigation(FrameTreeNode* frame_tree_node,
                          const CommonNavigationParams& common_params,
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index 87c139ca..8956d72 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -649,13 +649,10 @@
   std::vector<GURL> rest_of_chain = transfer_url_chain;
   rest_of_chain.pop_back();
 
-  // We don't know whether the original request had |user_action| set to true.
-  // However, since we force the navigation to be in the current tab, it
-  // doesn't matter.
   pending_render_frame_host->frame_tree_node()->navigator()->RequestTransferURL(
       pending_render_frame_host, transfer_url, nullptr, rest_of_chain, referrer,
       page_transition, CURRENT_TAB, global_request_id,
-      should_replace_current_entry, true);
+      should_replace_current_entry);
 
   // The transferring request was only needed during the RequestTransferURL
   // call, so it is safe to clear at this point.
diff --git a/content/browser/service_worker/service_worker_database.cc b/content/browser/service_worker/service_worker_database.cc
index 5d9a74b..ac96e43 100644
--- a/content/browser/service_worker/service_worker_database.cc
+++ b/content/browser/service_worker/service_worker_database.cc
@@ -75,11 +75,13 @@
 //   key: "REGID_TO_ORIGIN:" + <int64 'registration_id'>
 //   value: <GURL 'origin'>
 //
+//   OBSOLETE: http://crbug.com/539713
 //   key: "INITDATA_DISKCACHE_MIGRATION_NOT_NEEDED"
 //   value: <empty>
 //     - This entry represents that the diskcache uses the Simple backend and
 //       does not have to do diskcache migration (http://crbug.com/487482).
 //
+//   OBSOLETE: http://crbug.com/539713
 //   key: "INITDATA_OLD_DISKCACHE_DELETION_NOT_NEEDED"
 //   value: <empty>
 //     - This entry represents that the old BlockFile diskcache was deleted
@@ -96,10 +98,6 @@
 const char kNextResIdKey[] = "INITDATA_NEXT_RESOURCE_ID";
 const char kNextVerIdKey[] = "INITDATA_NEXT_VERSION_ID";
 const char kUniqueOriginKey[] = "INITDATA_UNIQUE_ORIGIN:";
-const char kDiskCacheMigrationNotNeededKey[] =
-    "INITDATA_DISKCACHE_MIGRATION_NOT_NEEDED";
-const char kOldDiskCacheDeletionNotNeededKey[] =
-    "INITDATA_OLD_DISKCACHE_DELETION_NOT_NEEDED";
 const char kForeignFetchOriginKey[] = "INITDATA_FOREIGN_FETCH_ORIGIN:";
 
 const char kRegKeyPrefix[] = "REG:";
@@ -108,7 +106,6 @@
 const char kRegIdToOriginKeyPrefix[] = "REGID_TO_ORIGIN:";
 const char kResKeyPrefix[] = "RES:";
 const char kKeySeparator = '\x00';
-const char kEmptyValue[] = "";
 
 const char kUncommittedResIdKeyPrefix[] = "URES:";
 const char kPurgeableResIdKeyPrefix[] = "PRES:";
@@ -426,8 +423,7 @@
       next_avail_registration_id_(0),
       next_avail_resource_id_(0),
       next_avail_version_id_(0),
-      state_(UNINITIALIZED),
-      skip_writing_diskcache_migration_state_on_init_for_testing_(false) {
+      state_(UNINITIALIZED) {
   sequence_checker_.DetachFromSequence();
 }
 
@@ -471,92 +467,6 @@
   return STATUS_OK;
 }
 
-ServiceWorkerDatabase::Status ServiceWorkerDatabase::IsDiskCacheMigrationNeeded(
-    bool* migration_needed) {
-  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
-
-  Status status = LazyOpen(false);
-  if (IsNewOrNonexistentDatabase(status)) {
-    *migration_needed = false;
-    return STATUS_OK;
-  }
-  if (status != STATUS_OK)
-    return status;
-
-  std::string value;
-  status = LevelDBStatusToStatus(db_->Get(
-      leveldb::ReadOptions(), kDiskCacheMigrationNotNeededKey, &value));
-  if (status == STATUS_ERROR_NOT_FOUND) {
-    *migration_needed = true;
-    HandleReadResult(FROM_HERE, STATUS_OK);
-    return STATUS_OK;
-  }
-  if (status != STATUS_OK) {
-    HandleReadResult(FROM_HERE, status);
-    return status;
-  }
-
-  *migration_needed = false;
-  HandleReadResult(FROM_HERE, status);
-  return status;
-}
-
-ServiceWorkerDatabase::Status
-ServiceWorkerDatabase::SetDiskCacheMigrationNotNeeded() {
-  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
-
-  Status status = LazyOpen(true);
-  if (status != STATUS_OK)
-    return status;
-
-  leveldb::WriteBatch batch;
-  batch.Put(kDiskCacheMigrationNotNeededKey, kEmptyValue);
-  return WriteBatch(&batch);
-}
-
-ServiceWorkerDatabase::Status
-ServiceWorkerDatabase::IsOldDiskCacheDeletionNeeded(bool* deletion_needed) {
-  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
-
-  Status status = LazyOpen(false);
-  if (IsNewOrNonexistentDatabase(status)) {
-    *deletion_needed = false;
-    return STATUS_OK;
-  }
-  if (status != STATUS_OK)
-    return status;
-
-  std::string value;
-  status = LevelDBStatusToStatus(db_->Get(
-      leveldb::ReadOptions(), kOldDiskCacheDeletionNotNeededKey, &value));
-  if (status == STATUS_ERROR_NOT_FOUND) {
-    *deletion_needed = true;
-    HandleReadResult(FROM_HERE, STATUS_OK);
-    return STATUS_OK;
-  }
-  if (status != STATUS_OK) {
-    HandleReadResult(FROM_HERE, status);
-    return status;
-  }
-
-  *deletion_needed = false;
-  HandleReadResult(FROM_HERE, status);
-  return status;
-}
-
-ServiceWorkerDatabase::Status
-ServiceWorkerDatabase::SetOldDiskCacheDeletionNotNeeded() {
-  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
-
-  Status status = LazyOpen(true);
-  if (status != STATUS_OK)
-    return status;
-
-  leveldb::WriteBatch batch;
-  batch.Put(kOldDiskCacheDeletionNotNeededKey, kEmptyValue);
-  return WriteBatch(&batch);
-}
-
 ServiceWorkerDatabase::Status
 ServiceWorkerDatabase::GetOriginsWithRegistrations(std::set<GURL>* origins) {
   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
@@ -1625,8 +1535,6 @@
   if (state_ == UNINITIALIZED) {
     // Write database default values.
     batch->Put(kDatabaseVersionKey, base::Int64ToString(kCurrentSchemaVersion));
-    if (!skip_writing_diskcache_migration_state_on_init_for_testing_)
-      batch->Put(kDiskCacheMigrationNotNeededKey, kEmptyValue);
     state_ = INITIALIZED;
   }
 
diff --git a/content/browser/service_worker/service_worker_database.h b/content/browser/service_worker/service_worker_database.h
index 6e44dd4..7fa022f 100644
--- a/content/browser/service_worker/service_worker_database.h
+++ b/content/browser/service_worker/service_worker_database.h
@@ -94,16 +94,6 @@
       int64* next_avail_version_id,
       int64* next_avail_resource_id);
 
-  // Used for diskcache migration (http://crbug.com/487482). Returns true if the
-  // storage needs to migrate a disk cache.
-  Status IsDiskCacheMigrationNeeded(bool* migration_needed);
-  Status SetDiskCacheMigrationNotNeeded();
-
-  // Used for diskcache migration (http://crbug.com/487482). Returns true if the
-  // storage needs to delete an old disk cache.
-  Status IsOldDiskCacheDeletionNeeded(bool* deletion_needed);
-  Status SetOldDiskCacheDeletionNotNeeded();
-
   // Reads origins that have one or more than one registration from the
   // database. Returns OK if they are successfully read or not found.
   // Otherwise, returns an error.
@@ -374,11 +364,6 @@
 
   bool IsDatabaseInMemory() const;
 
-  void set_skip_writing_diskcache_migration_state_on_init_for_testing() {
-    skip_writing_diskcache_migration_state_on_init_for_testing_ = true;
-  }
-  bool skip_writing_diskcache_migration_state_on_init_for_testing_;
-
   base::SequenceChecker sequence_checker_;
 
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, OpenDatabase);
@@ -390,12 +375,7 @@
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest,
                            UserData_UninitializedDatabase);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, DestroyDatabase);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, DiskCacheMigrationState);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, UpgradeSchemaToVersion2);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDiskCacheMigratorTest,
-                           MigrateOnDiskCacheAccess);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDiskCacheMigratorTest,
-                           NotMigrateOnDatabaseAccess);
 
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDatabase);
 };
diff --git a/content/browser/service_worker/service_worker_database_unittest.cc b/content/browser/service_worker/service_worker_database_unittest.cc
index 7b1525d5..33a5f09 100644
--- a/content/browser/service_worker/service_worker_database_unittest.cc
+++ b/content/browser/service_worker/service_worker_database_unittest.cc
@@ -138,75 +138,6 @@
   EXPECT_LT(0, db_version);
 }
 
-TEST(ServiceWorkerDatabaseTest, DiskCacheMigrationState) {
-  GURL origin("http://example.com");
-  base::ScopedTempDir database_dir;
-  ASSERT_TRUE(database_dir.CreateUniqueTempDir());
-  scoped_ptr<ServiceWorkerDatabase> database(
-      CreateDatabase(database_dir.path()));
-
-  // An empty database should return false.
-  bool migration_needed = false;
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->IsDiskCacheMigrationNeeded(&migration_needed));
-  EXPECT_FALSE(migration_needed);
-  bool deletion_needed = false;
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->IsOldDiskCacheDeletionNeeded(&deletion_needed));
-  EXPECT_FALSE(deletion_needed);
-
-  // Simulate an existing database created before diskcache migration.
-  database->set_skip_writing_diskcache_migration_state_on_init_for_testing();
-  std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
-  ServiceWorkerDatabase::RegistrationData deleted_version;
-  std::vector<int64> newly_purgeable_resources;
-  ServiceWorkerDatabase::RegistrationData data;
-  data.registration_id = 100;
-  data.scope = URL(origin, "/foo");
-  data.script = URL(origin, "/script.js");
-  data.version_id = 200;
-  data.resources_total_size_bytes = 300;
-  resources.push_back(CreateResource(1, data.script, 300));
-  ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->WriteRegistration(data, resources, &deleted_version,
-                                        &newly_purgeable_resources));
-  migration_needed = false;
-  ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->IsDiskCacheMigrationNeeded(&migration_needed));
-  ASSERT_TRUE(migration_needed);
-  deletion_needed = false;
-  ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->IsOldDiskCacheDeletionNeeded(&deletion_needed));
-  ASSERT_TRUE(deletion_needed);
-
-  // Opening the existing database should not update the migration states.
-  database.reset(CreateDatabase(database_dir.path()));
-  migration_needed = false;
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->IsDiskCacheMigrationNeeded(&migration_needed));
-  EXPECT_TRUE(migration_needed);
-  deletion_needed = false;
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->IsOldDiskCacheDeletionNeeded(&deletion_needed));
-  EXPECT_TRUE(deletion_needed);
-
-  // Test SetDiskCacheMigrationNotNeeded().
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->SetDiskCacheMigrationNotNeeded());
-  migration_needed = false;
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->IsDiskCacheMigrationNeeded(&migration_needed));
-  EXPECT_FALSE(migration_needed);
-
-  // Test SetOldDiskCacheDeletionNotNeeded().
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->SetOldDiskCacheDeletionNotNeeded());
-  deletion_needed = false;
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->IsOldDiskCacheDeletionNeeded(&deletion_needed));
-  EXPECT_FALSE(deletion_needed);
-}
-
 TEST(ServiceWorkerDatabaseTest, UpgradeSchemaToVersion2) {
   base::ScopedTempDir database_dir;
   ASSERT_TRUE(database_dir.CreateUniqueTempDir());
diff --git a/content/browser/service_worker/service_worker_disk_cache.cc b/content/browser/service_worker/service_worker_disk_cache.cc
index 3041b44..98f6845 100644
--- a/content/browser/service_worker/service_worker_disk_cache.cc
+++ b/content/browser/service_worker/service_worker_disk_cache.cc
@@ -6,21 +6,8 @@
 
 namespace content {
 
-scoped_ptr<ServiceWorkerDiskCache>
-ServiceWorkerDiskCache::CreateWithBlockFileBackend() {
-  return make_scoped_ptr(
-      new ServiceWorkerDiskCache(false /* use_simple_cache*/));
-}
-
-scoped_ptr<ServiceWorkerDiskCache>
-ServiceWorkerDiskCache::CreateWithSimpleBackend() {
-  return make_scoped_ptr(
-      new ServiceWorkerDiskCache(true /* use_simple_cache */));
-}
-
-ServiceWorkerDiskCache::ServiceWorkerDiskCache(bool use_simple_cache)
-    : AppCacheDiskCache(use_simple_cache) {
-}
+ServiceWorkerDiskCache::ServiceWorkerDiskCache()
+    : AppCacheDiskCache(true /* use_simple_cache */) {}
 
 ServiceWorkerResponseReader::ServiceWorkerResponseReader(
     int64 resource_id,
diff --git a/content/browser/service_worker/service_worker_disk_cache.h b/content/browser/service_worker/service_worker_disk_cache.h
index 894ec55..603614f 100644
--- a/content/browser/service_worker/service_worker_disk_cache.h
+++ b/content/browser/service_worker/service_worker_disk_cache.h
@@ -19,21 +19,13 @@
 class CONTENT_EXPORT ServiceWorkerDiskCache
     : public AppCacheDiskCache {
  public:
-  static scoped_ptr<ServiceWorkerDiskCache> CreateWithBlockFileBackend();
-  static scoped_ptr<ServiceWorkerDiskCache> CreateWithSimpleBackend();
-
- private:
-  friend class ServiceWorkerDiskCacheMigrator;
-  friend class ServiceWorkerDiskCacheMigratorTest;
-  explicit ServiceWorkerDiskCache(bool use_simple_cache);
+  ServiceWorkerDiskCache();
 };
 
 class CONTENT_EXPORT ServiceWorkerResponseReader
     : public AppCacheResponseReader {
  protected:
   // Should only be constructed by the storage class.
-  friend class ServiceWorkerDiskCacheMigrator;
-  friend class ServiceWorkerDiskCacheMigratorTest;
   friend class ServiceWorkerStorage;
   ServiceWorkerResponseReader(int64 resource_id,
                               ServiceWorkerDiskCache* disk_cache);
@@ -43,8 +35,6 @@
     : public AppCacheResponseWriter {
  protected:
   // Should only be constructed by the storage class.
-  friend class ServiceWorkerDiskCacheMigrator;
-  friend class ServiceWorkerDiskCacheMigratorTest;
   friend class ServiceWorkerStorage;
   ServiceWorkerResponseWriter(int64 resource_id,
                               ServiceWorkerDiskCache* disk_cache);
@@ -54,8 +44,6 @@
     : public AppCacheResponseMetadataWriter {
  protected:
   // Should only be constructed by the storage class.
-  friend class ServiceWorkerDiskCacheMigrator;
-  friend class ServiceWorkerDiskCacheMigratorTest;
   friend class ServiceWorkerStorage;
   ServiceWorkerResponseMetadataWriter(int64 resource_id,
                                       ServiceWorkerDiskCache* disk_cache);
diff --git a/content/browser/service_worker/service_worker_disk_cache_migrator.cc b/content/browser/service_worker/service_worker_disk_cache_migrator.cc
deleted file mode 100644
index dfdfd53..0000000
--- a/content/browser/service_worker/service_worker_disk_cache_migrator.cc
+++ /dev/null
@@ -1,504 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/service_worker/service_worker_disk_cache_migrator.h"
-
-#include "base/barrier_closure.h"
-#include "base/files/file_util.h"
-#include "base/location.h"
-#include "base/memory/ref_counted.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/task_runner_util.h"
-#include "base/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "content/common/service_worker/service_worker_types.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/disk_cache/disk_cache.h"
-
-namespace content {
-
-namespace {
-
-// Disk cache entry data indices (Copied from appcache_diskcache.cc).
-enum { kResponseInfoIndex, kResponseContentIndex, kResponseMetadataIndex };
-
-}  // namespace
-
-// A task to move a cached resource from the src DiskCache to the dest
-// DiskCache. This is owned by ServiceWorkerDiskCacheMigrator.
-class ServiceWorkerDiskCacheMigrator::Task {
- public:
-  using MigrationStatusCallback = base::Callback<void(MigrationStatus)>;
-
-  Task(InflightTaskMap::KeyType task_id,
-       int64 resource_id,
-       int32 data_size,
-       ServiceWorkerDiskCache* src,
-       ServiceWorkerDiskCache* dest,
-       const MigrationStatusCallback& callback);
-  ~Task();
-
-  void Run();
-
-  InflightTaskMap::KeyType task_id() const { return task_id_; }
-
- private:
-  void ReadResponseInfo();
-  void OnReadResponseInfo(
-      const scoped_refptr<HttpResponseInfoIOBuffer>& info_buffer,
-      int result);
-  void OnWriteResponseInfo(
-      const scoped_refptr<HttpResponseInfoIOBuffer>& info_buffer,
-      int result);
-  void WriteResponseMetadata(
-      const scoped_refptr<HttpResponseInfoIOBuffer>& info_buffer);
-  void OnWriteResponseMetadata(
-      const scoped_refptr<HttpResponseInfoIOBuffer>& info_buffer,
-      int result);
-  void ReadResponseData();
-  void OnReadResponseData(const scoped_refptr<net::IOBuffer>& buffer,
-                          int result);
-  void OnWriteResponseData(int result);
-
-  InflightTaskMap::KeyType task_id_;
-  int64 resource_id_;
-  int32 data_size_;
-  MigrationStatusCallback callback_;
-
-  scoped_ptr<ServiceWorkerResponseReader> reader_;
-  scoped_ptr<ServiceWorkerResponseWriter> writer_;
-  scoped_ptr<ServiceWorkerResponseMetadataWriter> metadata_writer_;
-
-  base::WeakPtrFactory<Task> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(Task);
-};
-
-// A wrapper class for disk_cache::Entry. This is used for holding an open entry
-// and ensuring that the entry gets closed on the dtor.
-class ServiceWorkerDiskCacheMigrator::WrappedEntry {
- public:
-  WrappedEntry() {}
-
-  ~WrappedEntry() {
-    if (entry_)
-      entry_->Close();
-  }
-
-  disk_cache::Entry* Unwrap() {
-    disk_cache::Entry* entry = entry_;
-    entry_ = nullptr;
-    return entry;
-  }
-
-  disk_cache::Entry** GetPtr() { return &entry_; }
-
- private:
-  disk_cache::Entry* entry_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(WrappedEntry);
-};
-
-ServiceWorkerDiskCacheMigrator::Task::Task(
-    InflightTaskMap::KeyType task_id,
-    int64 resource_id,
-    int32 data_size,
-    ServiceWorkerDiskCache* src,
-    ServiceWorkerDiskCache* dest,
-    const MigrationStatusCallback& callback)
-    : task_id_(task_id),
-      resource_id_(resource_id),
-      data_size_(data_size),
-      callback_(callback),
-      weak_factory_(this) {
-  DCHECK_LE(0, data_size_);
-  reader_.reset(new ServiceWorkerResponseReader(resource_id, src));
-  writer_.reset(new ServiceWorkerResponseWriter(resource_id, dest));
-  metadata_writer_.reset(
-      new ServiceWorkerResponseMetadataWriter(resource_id, dest));
-}
-
-ServiceWorkerDiskCacheMigrator::Task::~Task() {
-}
-
-void ServiceWorkerDiskCacheMigrator::Task::Run() {
-  ReadResponseInfo();
-}
-
-void ServiceWorkerDiskCacheMigrator::Task::ReadResponseInfo() {
-  scoped_refptr<HttpResponseInfoIOBuffer> info_buffer(
-      new HttpResponseInfoIOBuffer);
-  reader_->ReadInfo(info_buffer.get(),
-                    base::Bind(&Task::OnReadResponseInfo,
-                               weak_factory_.GetWeakPtr(), info_buffer));
-}
-
-void ServiceWorkerDiskCacheMigrator::Task::OnReadResponseInfo(
-    const scoped_refptr<HttpResponseInfoIOBuffer>& info_buffer,
-    int result) {
-  if (result < 0) {
-    LOG(ERROR) << "Failed to read the response info";
-    callback_.Run(MigrationStatus::ERROR_READ_RESPONSE_INFO);
-    return;
-  }
-  writer_->WriteInfo(info_buffer.get(),
-                     base::Bind(&Task::OnWriteResponseInfo,
-                                weak_factory_.GetWeakPtr(), info_buffer));
-}
-
-void ServiceWorkerDiskCacheMigrator::Task::OnWriteResponseInfo(
-    const scoped_refptr<HttpResponseInfoIOBuffer>& buffer,
-    int result) {
-  if (result < 0) {
-    LOG(ERROR) << "Failed to write the response info";
-    callback_.Run(MigrationStatus::ERROR_WRITE_RESPONSE_INFO);
-    return;
-  }
-
-  const net::HttpResponseInfo* http_info = buffer->http_info.get();
-  if (http_info->metadata && http_info->metadata->size()) {
-    WriteResponseMetadata(buffer);
-    return;
-  }
-  ReadResponseData();
-}
-
-void ServiceWorkerDiskCacheMigrator::Task::WriteResponseMetadata(
-    const scoped_refptr<HttpResponseInfoIOBuffer>& info_buffer) {
-  const net::HttpResponseInfo* http_info = info_buffer->http_info.get();
-  DCHECK(http_info->metadata);
-  DCHECK(http_info->metadata->size());
-
-  // |wrapped_buffer| does not own the given metadata buffer, so a callback
-  // for WriteMetadata keeps |info_buffer| which is the real owner of the
-  // metadata buffer.
-  scoped_refptr<net::WrappedIOBuffer> wrapped_buffer =
-      new net::WrappedIOBuffer(http_info->metadata->data());
-  metadata_writer_->WriteMetadata(
-      wrapped_buffer.get(), http_info->metadata->size(),
-      base::Bind(&Task::OnWriteResponseMetadata, weak_factory_.GetWeakPtr(),
-                 info_buffer));
-}
-
-void ServiceWorkerDiskCacheMigrator::Task::OnWriteResponseMetadata(
-    const scoped_refptr<HttpResponseInfoIOBuffer>& info_buffer,
-    int result) {
-  if (result < 0) {
-    LOG(ERROR) << "Failed to write the response metadata";
-    callback_.Run(MigrationStatus::ERROR_WRITE_RESPONSE_METADATA);
-    return;
-  }
-  DCHECK_EQ(info_buffer->http_info->metadata->size(), result);
-  ReadResponseData();
-}
-
-void ServiceWorkerDiskCacheMigrator::Task::ReadResponseData() {
-  scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(data_size_);
-  reader_->ReadData(buffer.get(), data_size_,
-                    base::Bind(&Task::OnReadResponseData,
-                               weak_factory_.GetWeakPtr(), buffer));
-}
-
-void ServiceWorkerDiskCacheMigrator::Task::OnReadResponseData(
-    const scoped_refptr<net::IOBuffer>& buffer,
-    int result) {
-  if (result < 0) {
-    LOG(ERROR) << "Failed to read the response data";
-    callback_.Run(MigrationStatus::ERROR_READ_RESPONSE_DATA);
-    return;
-  }
-  DCHECK_EQ(data_size_, result);
-  writer_->WriteData(
-      buffer.get(), result,
-      base::Bind(&Task::OnWriteResponseData, weak_factory_.GetWeakPtr()));
-}
-
-void ServiceWorkerDiskCacheMigrator::Task::OnWriteResponseData(int result) {
-  if (result < 0) {
-    LOG(ERROR) << "Failed to write the response data";
-    callback_.Run(MigrationStatus::ERROR_WRITE_RESPONSE_DATA);
-    return;
-  }
-  DCHECK_EQ(data_size_, result);
-  callback_.Run(MigrationStatus::OK);
-}
-
-ServiceWorkerDiskCacheMigrator::ServiceWorkerDiskCacheMigrator(
-    const base::FilePath& src_path,
-    const base::FilePath& dest_path,
-    int max_disk_cache_size,
-    const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread)
-    : src_path_(src_path),
-      dest_path_(dest_path),
-      max_disk_cache_size_(max_disk_cache_size),
-      disk_cache_thread_(disk_cache_thread),
-      weak_factory_(this) {
-}
-
-ServiceWorkerDiskCacheMigrator::~ServiceWorkerDiskCacheMigrator() {
-}
-
-void ServiceWorkerDiskCacheMigrator::Start(const StatusCallback& callback) {
-  callback_ = callback;
-  start_time_ = base::TimeTicks::Now();
-
-#if defined(OS_ANDROID)
-  PostTaskAndReplyWithResult(
-      disk_cache_thread_.get(), FROM_HERE,
-      base::Bind(&MigrateForAndroid, src_path_, dest_path_),
-      base::Bind(&ServiceWorkerDiskCacheMigrator::Complete,
-                 weak_factory_.GetWeakPtr()));
-#else
-  PostTaskAndReplyWithResult(
-      disk_cache_thread_.get(), FROM_HERE,
-      base::Bind(&base::DeleteFile, dest_path_, true),
-      base::Bind(&ServiceWorkerDiskCacheMigrator::DidDeleteDestDirectory,
-                 weak_factory_.GetWeakPtr()));
-#endif  // defined(OS_ANDROID)
-}
-
-#if defined(OS_ANDROID)
-// static
-ServiceWorkerDiskCacheMigrator::MigrationStatus
-ServiceWorkerDiskCacheMigrator::MigrateForAndroid(
-    const base::FilePath& src_path,
-    const base::FilePath& dest_path) {
-  // Continue the migration regardless of the deletion result. If the migrator
-  // cannot proceed or the diskcache gets corrupted due to the failure, the
-  // storage detects it and recovers by DeleteAndStartOver.
-  base::DeleteFile(dest_path, true);
-
-  if (!base::DirectoryExists(src_path))
-    return MigrationStatus::OK;
-
-  // Android has alredy used the Simple backend. Just move the existing
-  // diskcache files to a new location.
-  if (base::Move(src_path, dest_path))
-    return MigrationStatus::OK;
-  return MigrationStatus::ERROR_MOVE_DISKCACHE;
-}
-#endif  // defined(OS_ANDROID)
-
-void ServiceWorkerDiskCacheMigrator::DidDeleteDestDirectory(bool deleted) {
-  // Continue the migration regardless of the deletion result. If the migrator
-  // cannot proceed or the diskcache gets corrupted due to the failure, the
-  // storage detects it and recovers by DeleteAndStartOver.
-
-  src_ = ServiceWorkerDiskCache::CreateWithBlockFileBackend();
-  dest_ = ServiceWorkerDiskCache::CreateWithSimpleBackend();
-
-  scoped_ptr<MigrationStatus> status(new MigrationStatus(MigrationStatus::OK));
-  MigrationStatus* status_ptr = status.get();
-
-  // This closure is called when both diskcaches are initialized.
-  base::Closure barrier_closure = base::BarrierClosure(
-      2, base::Bind(&ServiceWorkerDiskCacheMigrator::DidInitializeAllDiskCaches,
-                    weak_factory_.GetWeakPtr(), base::Passed(status.Pass())));
-
-  // Initialize the src DiskCache. |status_ptr| is guaranteed to be valid until
-  // calling |barrier_closure| which is the owner of the object.
-  net::CompletionCallback src_callback =
-      base::Bind(&ServiceWorkerDiskCacheMigrator::DidInitializeSrcDiskCache,
-                 weak_factory_.GetWeakPtr(), barrier_closure, status_ptr);
-  int result = src_->InitWithDiskBackend(src_path_, max_disk_cache_size_,
-                                         false /* force */, disk_cache_thread_,
-                                         src_callback);
-  if (result != net::ERR_IO_PENDING)
-    src_callback.Run(result);
-
-  // Initialize the dest DiskCache. |status_ptr| is guaranteed to be valid until
-  // calling |barrier_closure| which is the owner of the object.
-  net::CompletionCallback dest_callback =
-      base::Bind(&ServiceWorkerDiskCacheMigrator::DidInitializeDestDiskCache,
-                 weak_factory_.GetWeakPtr(), barrier_closure, status_ptr);
-  result = dest_->InitWithDiskBackend(dest_path_, max_disk_cache_size_,
-                                      false /* force */, disk_cache_thread_,
-                                      dest_callback);
-  if (result != net::ERR_IO_PENDING)
-    dest_callback.Run(result);
-}
-
-void ServiceWorkerDiskCacheMigrator::DidInitializeSrcDiskCache(
-    const base::Closure& barrier_closure,
-    MigrationStatus* status_ptr,
-    int result) {
-  if (result != net::OK)
-    *status_ptr = MigrationStatus::ERROR_INIT_SRC_DISKCACHE;
-  barrier_closure.Run();
-}
-
-void ServiceWorkerDiskCacheMigrator::DidInitializeDestDiskCache(
-    const base::Closure& barrier_closure,
-    MigrationStatus* status_ptr,
-    int result) {
-  if (result != net::OK)
-    *status_ptr = MigrationStatus::ERROR_INIT_DEST_DISKCACHE;
-  barrier_closure.Run();
-}
-
-void ServiceWorkerDiskCacheMigrator::DidInitializeAllDiskCaches(
-    scoped_ptr<MigrationStatus> status) {
-  if (*status != MigrationStatus::OK) {
-    LOG(ERROR) << "Failed to initialize the diskcache";
-    Complete(*status);
-    return;
-  }
-
-  // Iterate through existing entries in the src DiskCache.
-  iterator_ = src_->disk_cache()->CreateIterator();
-  OpenNextEntry();
-}
-
-void ServiceWorkerDiskCacheMigrator::OpenNextEntry() {
-  DCHECK(!pending_task_);
-  DCHECK(!is_iterating_);
-  is_iterating_ = true;
-
-  scoped_ptr<WrappedEntry> wrapped_entry(new WrappedEntry);
-  disk_cache::Entry** entry_ptr = wrapped_entry->GetPtr();
-
-  net::CompletionCallback callback = base::Bind(
-      &ServiceWorkerDiskCacheMigrator::OnNextEntryOpened,
-      weak_factory_.GetWeakPtr(), base::Passed(wrapped_entry.Pass()));
-  int result = iterator_->OpenNextEntry(entry_ptr, callback);
-  if (result == net::ERR_IO_PENDING)
-    return;
-  callback.Run(result);
-}
-
-void ServiceWorkerDiskCacheMigrator::OnNextEntryOpened(
-    scoped_ptr<WrappedEntry> wrapped_entry,
-    int result) {
-  DCHECK(!pending_task_);
-  is_iterating_ = false;
-
-  if (result == net::ERR_FAILED) {
-    // ERR_FAILED means the iterator reached the end of the enumeration.
-    if (inflight_tasks_.IsEmpty())
-      Complete(MigrationStatus::OK);
-    return;
-  }
-
-  if (result != net::OK) {
-    LOG(ERROR) << "Failed to open the next entry";
-    inflight_tasks_.Clear();
-    Complete(MigrationStatus::ERROR_OPEN_NEXT_ENTRY);
-    return;
-  }
-
-  disk_cache::ScopedEntryPtr scoped_entry(wrapped_entry->Unwrap());
-  DCHECK(scoped_entry);
-
-  int64 resource_id = kInvalidServiceWorkerResourceId;
-  if (!base::StringToInt64(scoped_entry->GetKey(), &resource_id)) {
-    LOG(ERROR) << "Failed to read the resource id";
-    inflight_tasks_.Clear();
-    Complete(MigrationStatus::ERROR_READ_ENTRY_KEY);
-    return;
-  }
-
-  InflightTaskMap::KeyType task_id = next_task_id_++;
-  pending_task_.reset(new Task(
-      task_id, resource_id, scoped_entry->GetDataSize(kResponseContentIndex),
-      src_.get(), dest_.get(),
-      base::Bind(&ServiceWorkerDiskCacheMigrator::OnEntryMigrated,
-                 weak_factory_.GetWeakPtr(), task_id)));
-  if (inflight_tasks_.size() < max_number_of_inflight_tasks_) {
-    RunPendingTask();
-    OpenNextEntry();
-    return;
-  }
-  // |pending_task_| will run when an inflight task is completed.
-}
-
-void ServiceWorkerDiskCacheMigrator::RunPendingTask() {
-  DCHECK(pending_task_);
-  DCHECK_GT(max_number_of_inflight_tasks_, inflight_tasks_.size());
-  InflightTaskMap::KeyType task_id = pending_task_->task_id();
-  pending_task_->Run();
-  inflight_tasks_.AddWithID(pending_task_.release(), task_id);
-}
-
-void ServiceWorkerDiskCacheMigrator::OnEntryMigrated(
-    InflightTaskMap::KeyType task_id,
-    MigrationStatus status) {
-  DCHECK(inflight_tasks_.Lookup(task_id));
-  inflight_tasks_.Remove(task_id);
-
-  if (status != MigrationStatus::OK) {
-    inflight_tasks_.Clear();
-    pending_task_.reset();
-    Complete(status);
-    return;
-  }
-
-  ++number_of_migrated_resources_;
-
-  if (pending_task_) {
-    RunPendingTask();
-    OpenNextEntry();
-    return;
-  }
-
-  if (is_iterating_)
-    return;
-
-  if (inflight_tasks_.IsEmpty())
-    Complete(MigrationStatus::OK);
-}
-
-void ServiceWorkerDiskCacheMigrator::Complete(MigrationStatus status) {
-  DCHECK(inflight_tasks_.IsEmpty());
-  DCHECK(!pending_task_);
-
-  if (status == MigrationStatus::OK) {
-    RecordMigrationTime(base::TimeTicks().Now() - start_time_);
-    RecordNumberOfMigratedResources(number_of_migrated_resources_);
-  }
-  RecordMigrationResult(status);
-
-  // Invalidate weakptrs to ensure that other running operations do not call
-  // OnEntryMigrated().
-  weak_factory_.InvalidateWeakPtrs();
-
-  // Use PostTask to avoid deleting AppCacheDiskCache in the middle of the
-  // execution (see http://crbug.com/502420).
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::Bind(&ServiceWorkerDiskCacheMigrator::RunUserCallback,
-                 weak_factory_.GetWeakPtr(),
-                 status == MigrationStatus::OK ? SERVICE_WORKER_OK
-                                               : SERVICE_WORKER_ERROR_FAILED));
-}
-
-void ServiceWorkerDiskCacheMigrator::RunUserCallback(
-    ServiceWorkerStatusCode status) {
-  src_.reset();
-  dest_.reset();
-  callback_.Run(status);
-}
-
-void ServiceWorkerDiskCacheMigrator::RecordMigrationResult(
-    MigrationStatus status) {
-  UMA_HISTOGRAM_ENUMERATION("ServiceWorker.DiskCacheMigrator.MigrationResult",
-                            static_cast<int>(status),
-                            static_cast<int>(MigrationStatus::NUM_TYPES));
-}
-
-void ServiceWorkerDiskCacheMigrator::RecordNumberOfMigratedResources(
-    size_t migrated_resources) {
-  UMA_HISTOGRAM_COUNTS_1000(
-      "ServiceWorker.DiskCacheMigrator.NumberOfMigratedResources",
-      migrated_resources);
-}
-
-void ServiceWorkerDiskCacheMigrator::RecordMigrationTime(
-    const base::TimeDelta& time) {
-  UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.DiskCacheMigrator.MigrationTime",
-                             time);
-}
-
-}  // namespace content
diff --git a/content/browser/service_worker/service_worker_disk_cache_migrator.h b/content/browser/service_worker/service_worker_disk_cache_migrator.h
deleted file mode 100644
index 46fce29..0000000
--- a/content/browser/service_worker/service_worker_disk_cache_migrator.h
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DISK_CACHE_MIGRATOR_H_
-#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DISK_CACHE_MIGRATOR_H_
-
-#include "content/browser/service_worker/service_worker_disk_cache.h"
-
-#include "base/gtest_prod_util.h"
-#include "base/id_map.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/browser/service_worker/service_worker_database.h"
-#include "content/common/service_worker/service_worker_status_code.h"
-
-namespace content {
-
-// This is used for migrating the ServiceWorkerDiskCache from the BlockFile
-// backend to the Simple backend. The migrator iterates over resources in the
-// src DiskCache and copies them into the dest DiskCache one by one. This does
-// not delete the resources in the src DiskCache.
-//
-// TODO(nhiroki): Remove this migrator after several milestones pass
-// (http://crbug.com/487482)
-class CONTENT_EXPORT ServiceWorkerDiskCacheMigrator {
- public:
-  using StatusCallback = base::Callback<void(ServiceWorkerStatusCode)>;
-
-  ServiceWorkerDiskCacheMigrator(
-      const base::FilePath& src_path,
-      const base::FilePath& dest_path,
-      int max_disk_cache_size,
-      const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread);
-  ~ServiceWorkerDiskCacheMigrator();
-
-  // Returns SERVICE_WORKER_OK if all resources are successfully migrated. The
-  // caller should delete the src DiskCache after migration.
-  void Start(const StatusCallback& callback);
-
- private:
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDiskCacheMigratorTest,
-                           ThrottleInflightTasks);
-
-  class Task;
-  class WrappedEntry;
-
-  using InflightTaskMap = IDMap<Task, IDMapOwnPointer>;
-
-  // Used for UMA. Append only.
-  enum class MigrationStatus {
-    OK = 0,
-    ERROR_FAILED = 1,  // unused, for backwards compatibility.
-    ERROR_MOVE_DISKCACHE = 2,
-    ERROR_INIT_SRC_DISKCACHE = 3,
-    ERROR_INIT_DEST_DISKCACHE = 4,
-    ERROR_OPEN_NEXT_ENTRY = 5,
-    ERROR_READ_ENTRY_KEY = 6,
-    ERROR_READ_RESPONSE_INFO = 7,
-    ERROR_WRITE_RESPONSE_INFO = 8,
-    ERROR_WRITE_RESPONSE_METADATA = 9,
-    ERROR_READ_RESPONSE_DATA = 10,
-    ERROR_WRITE_RESPONSE_DATA = 11,
-    NUM_TYPES,
-  };
-
-#if defined(OS_ANDROID)
-  static MigrationStatus MigrateForAndroid(const base::FilePath& src_path,
-                                           const base::FilePath& dest_path);
-#endif  // defined(OS_ANDROID)
-
-  void DidDeleteDestDirectory(bool deleted);
-  void DidInitializeSrcDiskCache(const base::Closure& barrier_closure,
-                                 MigrationStatus* status_ptr,
-                                 int result);
-  void DidInitializeDestDiskCache(const base::Closure& barrier_closure,
-                                  MigrationStatus* status_ptr,
-                                  int result);
-  void DidInitializeAllDiskCaches(scoped_ptr<MigrationStatus> status);
-
-  void OpenNextEntry();
-  void OnNextEntryOpened(scoped_ptr<WrappedEntry> entry, int result);
-  void RunPendingTask();
-  void OnEntryMigrated(InflightTaskMap::KeyType task_id,
-                       MigrationStatus status);
-  void Complete(MigrationStatus status);
-  void RunUserCallback(ServiceWorkerStatusCode status);
-
-  void RecordMigrationResult(MigrationStatus status);
-  void RecordNumberOfMigratedResources(size_t migrated_resources);
-  void RecordMigrationTime(const base::TimeDelta& time);
-
-  void set_max_number_of_inflight_tasks(size_t max_number) {
-    max_number_of_inflight_tasks_ = max_number;
-  }
-
-  scoped_ptr<disk_cache::Backend::Iterator> iterator_;
-  bool is_iterating_ = false;
-
-  base::FilePath src_path_;
-  base::FilePath dest_path_;
-  scoped_ptr<ServiceWorkerDiskCache> src_;
-  scoped_ptr<ServiceWorkerDiskCache> dest_;
-  const int max_disk_cache_size_;
-  scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread_;
-
-  InflightTaskMap::KeyType next_task_id_ = 0;
-  InflightTaskMap inflight_tasks_;
-  scoped_ptr<Task> pending_task_;
-  size_t max_number_of_inflight_tasks_ = 10;
-
-  base::TimeTicks start_time_;
-  size_t number_of_migrated_resources_ = 0;
-
-  StatusCallback callback_;
-
-  base::WeakPtrFactory<ServiceWorkerDiskCacheMigrator> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDiskCacheMigrator);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DISK_CACHE_MIGRATOR_H_
diff --git a/content/browser/service_worker/service_worker_disk_cache_migrator_unittest.cc b/content/browser/service_worker/service_worker_disk_cache_migrator_unittest.cc
deleted file mode 100644
index 12e0995..0000000
--- a/content/browser/service_worker/service_worker_disk_cache_migrator_unittest.cc
+++ /dev/null
@@ -1,539 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/service_worker/service_worker_disk_cache_migrator.h"
-
-#include <string>
-#include <vector>
-
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/run_loop.h"
-#include "base/thread_task_runner_handle.h"
-#include "content/browser/service_worker/service_worker_context_core.h"
-#include "content/browser/service_worker/service_worker_storage.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/test_completion_callback.h"
-#include "net/http/http_response_headers.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-
-const int kMaxDiskCacheSize = 250 * 1024 * 1024;
-
-struct ResponseData {
-  int64 resource_id;
-  std::string headers;
-  std::string body;
-  std::string metadata;
-
-  ResponseData(int64 resource_id,
-               const std::string& headers,
-               const std::string& body,
-               const std::string& metadata)
-      : resource_id(resource_id),
-        headers(headers),
-        body(body),
-        metadata(metadata) {}
-};
-
-void OnDiskCacheMigrated(const base::Closure& callback,
-                         ServiceWorkerStatusCode status) {
-  EXPECT_EQ(SERVICE_WORKER_OK, status);
-  callback.Run();
-}
-
-void OnRegistrationFound(
-    const base::Closure& callback,
-    ServiceWorkerStatusCode status,
-    const scoped_refptr<ServiceWorkerRegistration>& registration) {
-  callback.Run();
-}
-
-}  // namespace
-
-class ServiceWorkerDiskCacheMigratorTest : public testing::Test {
- public:
-  ServiceWorkerDiskCacheMigratorTest()
-      : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
-
-  void SetUp() override {
-    ASSERT_TRUE(user_data_directory_.CreateUniqueTempDir());
-    scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager(
-        new MockServiceWorkerDatabaseTaskManager(
-            base::ThreadTaskRunnerHandle::Get()));
-
-    context_.reset(new ServiceWorkerContextCore(
-        user_data_directory_.path(), database_task_manager.Pass(),
-        base::ThreadTaskRunnerHandle::Get(), nullptr, nullptr, nullptr,
-        nullptr));
-  }
-
-  void TearDown() override {
-    context_.reset();
-    base::RunLoop().RunUntilIdle();
-  }
-
-  scoped_ptr<ServiceWorkerDiskCache> CreateSrcDiskCache() {
-#if defined(OS_ANDROID)
-    // Android has already used the Simple backend.
-    scoped_ptr<ServiceWorkerDiskCache> src(
-        ServiceWorkerDiskCache::CreateWithSimpleBackend());
-#else
-    scoped_ptr<ServiceWorkerDiskCache> src(
-        ServiceWorkerDiskCache::CreateWithBlockFileBackend());
-#endif  // defined(OS_ANDROID)
-
-    net::TestCompletionCallback cb;
-    src->InitWithDiskBackend(
-        storage()->GetOldDiskCachePath(), kMaxDiskCacheSize, false /* force */,
-        base::ThreadTaskRunnerHandle::Get(), cb.callback());
-    EXPECT_EQ(net::OK, cb.WaitForResult());
-    return src.Pass();
-  }
-
-  scoped_ptr<ServiceWorkerDiskCache> CreateDestDiskCache() {
-    scoped_ptr<ServiceWorkerDiskCache> dest(
-        ServiceWorkerDiskCache::CreateWithSimpleBackend());
-    net::TestCompletionCallback cb;
-    dest->InitWithDiskBackend(
-        storage()->GetDiskCachePath(), kMaxDiskCacheSize, false /* force */,
-        base::ThreadTaskRunnerHandle::Get(), cb.callback());
-    EXPECT_EQ(net::OK, cb.WaitForResult());
-    return dest.Pass();
-  }
-
-  scoped_ptr<ServiceWorkerDiskCacheMigrator> CreateMigrator() {
-    return make_scoped_ptr(new ServiceWorkerDiskCacheMigrator(
-        storage()->GetOldDiskCachePath(), storage()->GetDiskCachePath(),
-        kMaxDiskCacheSize, base::ThreadTaskRunnerHandle::Get()));
-  }
-
-  bool WriteResponse(ServiceWorkerDiskCache* disk_cache,
-                     const ResponseData& response) {
-    scoped_ptr<ServiceWorkerResponseWriter> writer(
-        new ServiceWorkerResponseWriter(response.resource_id, disk_cache));
-
-    // Write the response info.
-    scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
-    info->request_time = base::Time() + base::TimeDelta::FromSeconds(10);
-    info->response_time = info->request_time + base::TimeDelta::FromSeconds(10);
-    info->was_cached = false;
-    info->headers = new net::HttpResponseHeaders(response.headers);
-    scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
-        new HttpResponseInfoIOBuffer(info.release());
-    net::TestCompletionCallback cb1;
-    writer->WriteInfo(info_buffer.get(), cb1.callback());
-    int rv = cb1.WaitForResult();
-    EXPECT_LT(0, rv);
-    if (rv < 0)
-      return false;
-
-    // Write the response metadata.
-    scoped_ptr<ServiceWorkerResponseMetadataWriter> metadata_writer(
-        new ServiceWorkerResponseMetadataWriter(response.resource_id,
-                                                disk_cache));
-    scoped_refptr<net::IOBuffer> metadata_buffer(
-        new net::WrappedIOBuffer(response.metadata.data()));
-    const int metadata_length = response.metadata.length();
-    net::TestCompletionCallback cb2;
-    metadata_writer->WriteMetadata(metadata_buffer.get(), metadata_length,
-                                   cb2.callback());
-    rv = cb2.WaitForResult();
-    EXPECT_EQ(metadata_length, rv);
-    if (metadata_length != rv)
-      return false;
-
-    // Write the response body.
-    scoped_refptr<net::IOBuffer> body_buffer(
-        new net::WrappedIOBuffer(response.body.data()));
-    const int body_length = response.body.length();
-    net::TestCompletionCallback cb3;
-    writer->WriteData(body_buffer.get(), body_length, cb3.callback());
-    rv = cb3.WaitForResult();
-    EXPECT_EQ(body_length, rv);
-    if (body_length != rv)
-      return false;
-
-    return true;
-  }
-
-  void VerifyResponse(ServiceWorkerDiskCache* disk_cache,
-                      const ResponseData& expected) {
-    scoped_ptr<ServiceWorkerResponseReader> reader(
-        new ServiceWorkerResponseReader(expected.resource_id, disk_cache));
-
-    // Verify the response info.
-    scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
-        new HttpResponseInfoIOBuffer;
-    net::TestCompletionCallback cb1;
-    reader->ReadInfo(info_buffer.get(), cb1.callback());
-    int rv = cb1.WaitForResult();
-    EXPECT_LT(0, rv);
-    ASSERT_TRUE(info_buffer->http_info);
-    ASSERT_TRUE(info_buffer->http_info->headers);
-    EXPECT_EQ("OK", info_buffer->http_info->headers->GetStatusText());
-
-    // Verify the response metadata.
-    if (!expected.metadata.empty()) {
-      ASSERT_TRUE(info_buffer->http_info->metadata);
-      const int data_size = info_buffer->http_info->metadata->size();
-      ASSERT_EQ(static_cast<int>(expected.metadata.length()), data_size);
-      EXPECT_EQ(0, memcmp(expected.metadata.data(),
-                          info_buffer->http_info->metadata->data(),
-                          expected.metadata.length()));
-    }
-
-    // Verify the response body.
-    const int kBigEnough = 512;
-    scoped_refptr<net::IOBuffer> body_buffer = new net::IOBuffer(kBigEnough);
-    net::TestCompletionCallback cb2;
-    reader->ReadData(body_buffer.get(), kBigEnough, cb2.callback());
-    rv = cb2.WaitForResult();
-    ASSERT_EQ(static_cast<int>(expected.body.length()), rv);
-    EXPECT_EQ(0, memcmp(expected.body.data(), body_buffer->data(), rv));
-  }
-
-  int32 GetEntryCount(ServiceWorkerDiskCache* disk_cache) {
-    return disk_cache->disk_cache()->GetEntryCount();
-  }
-
-  ServiceWorkerStorage* storage() { return context_->storage(); }
-
- private:
-  TestBrowserThreadBundle browser_thread_bundle_;
-  base::ScopedTempDir user_data_directory_;
-
-  scoped_ptr<ServiceWorkerContextCore> context_;
-};
-
-TEST_F(ServiceWorkerDiskCacheMigratorTest, MigrateDiskCache) {
-  std::vector<ResponseData> responses;
-  responses.push_back(ResponseData(1, "HTTP/1.1 200 OK\0\0", "Hello", ""));
-  responses.push_back(ResponseData(2, "HTTP/1.1 200 OK\0\0", "Service", ""));
-  responses.push_back(ResponseData(5, "HTTP/1.1 200 OK\0\0", "Worker", ""));
-  responses.push_back(ResponseData(3, "HTTP/1.1 200 OK\0\0", "World", "meta"));
-  responses.push_back(ResponseData(10, "HTTP/1.1 200 OK\0\0", "", "meta"));
-  responses.push_back(ResponseData(11, "HTTP/1.1 200 OK\0\0", "body", ""));
-  responses.push_back(ResponseData(12, "HTTP/1.1 200 OK\0\0", "", ""));
-  responses.push_back(ResponseData(
-      20, "HTTP/1.1 200 OK\0\0", std::string(256, 'a'), std::string(128, 'b')));
-
-  // Populate initial data in the src diskcache.
-  scoped_ptr<ServiceWorkerDiskCache> src(CreateSrcDiskCache());
-  for (const ResponseData& response : responses) {
-    ASSERT_TRUE(WriteResponse(src.get(), response));
-    VerifyResponse(src.get(), response);
-  }
-  ASSERT_EQ(static_cast<int>(responses.size()), GetEntryCount(src.get()));
-  src.reset();
-
-  // Start the migrator.
-  base::RunLoop run_loop;
-  scoped_ptr<ServiceWorkerDiskCacheMigrator> migrator(CreateMigrator());
-  migrator->Start(base::Bind(&OnDiskCacheMigrated, run_loop.QuitClosure()));
-  run_loop.Run();
-
-  // Verify the migrated contents in the dest diskcache.
-  scoped_ptr<ServiceWorkerDiskCache> dest(CreateDestDiskCache());
-  for (const ResponseData& response : responses)
-    VerifyResponse(dest.get(), response);
-  EXPECT_EQ(static_cast<int>(responses.size()), GetEntryCount(dest.get()));
-}
-
-TEST_F(ServiceWorkerDiskCacheMigratorTest, MigrateEmptyDiskCache) {
-  scoped_ptr<ServiceWorkerDiskCache> src(CreateSrcDiskCache());
-  ASSERT_EQ(0, GetEntryCount(src.get()));
-  src.reset();
-
-  // Start the migrator.
-  base::RunLoop run_loop;
-  scoped_ptr<ServiceWorkerDiskCacheMigrator> migrator(CreateMigrator());
-  migrator->Start(base::Bind(&OnDiskCacheMigrated, run_loop.QuitClosure()));
-  run_loop.Run();
-
-  scoped_ptr<ServiceWorkerDiskCache> dest(CreateDestDiskCache());
-  ASSERT_EQ(0, GetEntryCount(dest.get()));
-}
-
-// Tests that the migrator properly removes existing resources in the dest
-// diskcache before starting the migration.
-TEST_F(ServiceWorkerDiskCacheMigratorTest, RemoveExistingResourcesFromDest) {
-  std::vector<ResponseData> responses1;
-  responses1.push_back(ResponseData(1, "HTTP/1.1 200 OK\0\0", "Hello", ""));
-  responses1.push_back(ResponseData(3, "HTTP/1.1 200 OK\0\0", "World", ""));
-
-  std::vector<ResponseData> responses2;
-  responses2.push_back(ResponseData(10, "HTTP/1.1 200 OK\0\0", "Hello", ""));
-  responses2.push_back(ResponseData(11, "HTTP/1.1 200 OK\0\0", "Service", ""));
-  responses2.push_back(ResponseData(12, "HTTP/1.1 200 OK\0\0", "", "Worker"));
-
-  // Populate initial resources in the src diskcache.
-  scoped_ptr<ServiceWorkerDiskCache> src(CreateSrcDiskCache());
-  for (const ResponseData& response : responses1) {
-    ASSERT_TRUE(WriteResponse(src.get(), response));
-    VerifyResponse(src.get(), response);
-  }
-  ASSERT_EQ(static_cast<int>(responses1.size()), GetEntryCount(src.get()));
-  src.reset();
-
-  // Populate different resources in the dest diskcache in order to simulate
-  // a previous partial migration.
-  scoped_ptr<ServiceWorkerDiskCache> dest(CreateDestDiskCache());
-  for (const ResponseData& response : responses2) {
-    ASSERT_TRUE(WriteResponse(dest.get(), response));
-    VerifyResponse(dest.get(), response);
-  }
-  ASSERT_EQ(static_cast<int>(responses2.size()), GetEntryCount(dest.get()));
-  dest.reset();
-
-  // Start the migrator.
-  base::RunLoop run_loop;
-  scoped_ptr<ServiceWorkerDiskCacheMigrator> migrator(CreateMigrator());
-  migrator->Start(base::Bind(&OnDiskCacheMigrated, run_loop.QuitClosure()));
-  run_loop.Run();
-
-  // Verify that only newly migrated resources exist in the dest diskcache.
-  dest = CreateDestDiskCache();
-  for (const ResponseData& response : responses1)
-    VerifyResponse(dest.get(), response);
-  EXPECT_EQ(static_cast<int>(responses1.size()), GetEntryCount(dest.get()));
-}
-
-TEST_F(ServiceWorkerDiskCacheMigratorTest, ThrottleInflightTasks) {
-  std::vector<ResponseData> responses;
-  for (int i = 0; i < 10; ++i)
-    responses.push_back(ResponseData(i, "HTTP/1.1 200 OK\0\0", "foo", "bar"));
-
-  // Populate initial data in the src diskcache.
-  scoped_ptr<ServiceWorkerDiskCache> src(CreateSrcDiskCache());
-  for (const ResponseData& response : responses) {
-    ASSERT_TRUE(WriteResponse(src.get(), response));
-    VerifyResponse(src.get(), response);
-  }
-  ASSERT_EQ(static_cast<int>(responses.size()), GetEntryCount(src.get()));
-  src.reset();
-
-  scoped_ptr<ServiceWorkerDiskCacheMigrator> migrator(CreateMigrator());
-
-  // Tighten the max number of inflight tasks.
-  migrator->set_max_number_of_inflight_tasks(2);
-
-  // Migration should hit the limit, but should successfully complete.
-  base::RunLoop run_loop;
-  migrator->Start(base::Bind(&OnDiskCacheMigrated, run_loop.QuitClosure()));
-  run_loop.Run();
-
-  // Verify the migrated contents in the dest diskcache.
-  scoped_ptr<ServiceWorkerDiskCache> dest(CreateDestDiskCache());
-  for (const ResponseData& response : responses)
-    VerifyResponse(dest.get(), response);
-  EXPECT_EQ(static_cast<int>(responses.size()), GetEntryCount(dest.get()));
-}
-
-TEST_F(ServiceWorkerDiskCacheMigratorTest, MigrateOnDiskCacheAccess) {
-  std::vector<ResponseData> responses;
-  responses.push_back(ResponseData(1, "HTTP/1.1 200 OK\0\0", "Hello", ""));
-  responses.push_back(ResponseData(2, "HTTP/1.1 200 OK\0\0", "Service", ""));
-  responses.push_back(ResponseData(5, "HTTP/1.1 200 OK\0\0", "Worker", ""));
-  responses.push_back(ResponseData(3, "HTTP/1.1 200 OK\0\0", "World", "meta"));
-
-  // Populate initial resources in the src diskcache.
-  scoped_ptr<ServiceWorkerDiskCache> src(CreateSrcDiskCache());
-  for (const ResponseData& response : responses) {
-    ASSERT_TRUE(WriteResponse(src.get(), response));
-    VerifyResponse(src.get(), response);
-  }
-  ASSERT_EQ(static_cast<int>(responses.size()), GetEntryCount(src.get()));
-  ASSERT_TRUE(base::DirectoryExists(storage()->GetOldDiskCachePath()));
-  src.reset();
-
-  scoped_ptr<ServiceWorkerDatabase> database(
-      new ServiceWorkerDatabase(storage()->GetDatabasePath()));
-
-  // This is necessary to make the storage schedule diskcache migration.
-  database->set_skip_writing_diskcache_migration_state_on_init_for_testing();
-
-  // Simulate an existing database.
-  std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
-  resources.push_back(ServiceWorkerDatabase::ResourceRecord(
-      1, GURL("https://example.com/foo"), 10));
-  ServiceWorkerDatabase::RegistrationData deleted_version;
-  std::vector<int64> newly_purgeable_resources;
-  ServiceWorkerDatabase::RegistrationData data;
-  data.registration_id = 100;
-  data.scope = GURL("https://example.com/");
-  data.script = GURL("https://example.com/script.js");
-  data.version_id = 200;
-  data.resources_total_size_bytes = 10;
-  ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->WriteRegistration(data, resources, &deleted_version,
-                                        &newly_purgeable_resources));
-  database.reset();
-
-  // LazyInitialize() reads initial data and should schedule to migrate.
-  ASSERT_FALSE(storage()->disk_cache_migration_needed_);
-  base::RunLoop run_loop;
-  storage()->LazyInitialize(run_loop.QuitClosure());
-  run_loop.Run();
-  EXPECT_TRUE(storage()->disk_cache_migration_needed_);
-
-  // DiskCache access should start the migration.
-  ServiceWorkerDiskCache* dest = storage()->disk_cache();
-
-  // Verify the migrated contents in the dest diskcache.
-  for (const ResponseData& response : responses)
-    VerifyResponse(dest, response);
-  EXPECT_EQ(static_cast<int>(responses.size()), GetEntryCount(dest));
-
-  // After the migration, the src diskcache should be deleted.
-  EXPECT_FALSE(base::DirectoryExists(storage()->GetOldDiskCachePath()));
-
-  // After the migration, the migration state should be updated.
-  bool migration_needed = false;
-  EXPECT_EQ(
-      ServiceWorkerDatabase::STATUS_OK,
-      storage()->database_->IsDiskCacheMigrationNeeded(&migration_needed));
-  EXPECT_FALSE(migration_needed);
-  bool deletion_needed = false;
-  EXPECT_EQ(
-      ServiceWorkerDatabase::STATUS_OK,
-      storage()->database_->IsOldDiskCacheDeletionNeeded(&deletion_needed));
-  EXPECT_FALSE(deletion_needed);
-}
-
-TEST_F(ServiceWorkerDiskCacheMigratorTest, NotMigrateOnDatabaseAccess) {
-  std::vector<ResponseData> responses;
-  responses.push_back(ResponseData(1, "HTTP/1.1 200 OK\0\0", "Hello", ""));
-  responses.push_back(ResponseData(2, "HTTP/1.1 200 OK\0\0", "Service", ""));
-  responses.push_back(ResponseData(5, "HTTP/1.1 200 OK\0\0", "Worker", ""));
-  responses.push_back(ResponseData(3, "HTTP/1.1 200 OK\0\0", "World", "meta"));
-
-  // Populate initial resources in the src diskcache.
-  scoped_ptr<ServiceWorkerDiskCache> src(CreateSrcDiskCache());
-  for (const ResponseData& response : responses) {
-    ASSERT_TRUE(WriteResponse(src.get(), response));
-    VerifyResponse(src.get(), response);
-  }
-  ASSERT_EQ(static_cast<int>(responses.size()), GetEntryCount(src.get()));
-  ASSERT_TRUE(base::DirectoryExists(storage()->GetOldDiskCachePath()));
-
-  scoped_ptr<ServiceWorkerDatabase> database(
-      new ServiceWorkerDatabase(storage()->GetDatabasePath()));
-
-  // This is necessary to make the storage schedule diskcache migration.
-  database->set_skip_writing_diskcache_migration_state_on_init_for_testing();
-
-  // Simulate an existing database.
-  std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
-  resources.push_back(ServiceWorkerDatabase::ResourceRecord(
-      1, GURL("https://example.com/foo"), 10));
-  ServiceWorkerDatabase::RegistrationData deleted_version;
-  std::vector<int64> newly_purgeable_resources;
-  ServiceWorkerDatabase::RegistrationData data;
-  data.registration_id = 100;
-  data.scope = GURL("https://example.com/");
-  data.script = GURL("https://example.com/script.js");
-  data.version_id = 200;
-  data.resources_total_size_bytes = 10;
-  ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->WriteRegistration(data, resources, &deleted_version,
-                                        &newly_purgeable_resources));
-  database.reset();
-
-  // LazyInitialize() reads initial data and should schedule to migrate.
-  ASSERT_FALSE(storage()->disk_cache_migration_needed_);
-  base::RunLoop run_loop1;
-  storage()->LazyInitialize(run_loop1.QuitClosure());
-  run_loop1.Run();
-  EXPECT_TRUE(storage()->disk_cache_migration_needed_);
-
-  // Database access should not start the migration.
-  base::RunLoop run_loop2;
-  storage()->FindRegistrationForDocument(
-      GURL("http://example.com/"),
-      base::Bind(&OnRegistrationFound, run_loop2.QuitClosure()));
-  run_loop2.Run();
-
-  // Verify that the migration didn't happen.
-  scoped_ptr<ServiceWorkerDiskCache> dest(CreateDestDiskCache());
-  EXPECT_EQ(static_cast<int>(responses.size()), GetEntryCount(src.get()));
-  EXPECT_EQ(0, GetEntryCount(dest.get()));
-  EXPECT_TRUE(base::DirectoryExists(storage()->GetOldDiskCachePath()));
-}
-
-TEST_F(ServiceWorkerDiskCacheMigratorTest, NotMigrateForEmptyDatabase) {
-  std::vector<ResponseData> responses;
-  responses.push_back(ResponseData(1, "HTTP/1.1 200 OK\0\0", "Hello", ""));
-  responses.push_back(ResponseData(2, "HTTP/1.1 200 OK\0\0", "Service", ""));
-  responses.push_back(ResponseData(5, "HTTP/1.1 200 OK\0\0", "Worker", ""));
-  responses.push_back(ResponseData(3, "HTTP/1.1 200 OK\0\0", "World", "meta"));
-
-  // Populate initial resources in the src diskcache.
-  scoped_ptr<ServiceWorkerDiskCache> src(CreateSrcDiskCache());
-  for (const ResponseData& response : responses) {
-    ASSERT_TRUE(WriteResponse(src.get(), response));
-    VerifyResponse(src.get(), response);
-  }
-  ASSERT_EQ(static_cast<int>(responses.size()), GetEntryCount(src.get()));
-  ASSERT_TRUE(base::DirectoryExists(storage()->GetOldDiskCachePath()));
-  src.reset();
-
-  // LazyInitialize() reads initial data and should not schedule to migrate
-  // because the database is empty.
-  ASSERT_FALSE(storage()->disk_cache_migration_needed_);
-  base::RunLoop run_loop;
-  storage()->LazyInitialize(run_loop.QuitClosure());
-  run_loop.Run();
-  EXPECT_FALSE(storage()->disk_cache_migration_needed_);
-
-  // DiskCache access should not start the migration.
-  ServiceWorkerDiskCache* dest = storage()->disk_cache();
-
-  // Verify that the migration didn't happen.
-  src = CreateSrcDiskCache();
-  for (const ResponseData& response : responses)
-    VerifyResponse(src.get(), response);
-  EXPECT_EQ(static_cast<int>(responses.size()), GetEntryCount(src.get()));
-  EXPECT_TRUE(base::DirectoryExists(storage()->GetOldDiskCachePath()));
-  EXPECT_EQ(0, GetEntryCount(dest));
-
-  // Write a registration into the database to start database initialization.
-  std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
-  resources.push_back(ServiceWorkerDatabase::ResourceRecord(
-      1, GURL("https://example.com/foo"), 10));
-  ServiceWorkerDatabase::RegistrationData deleted_version;
-  std::vector<int64> newly_purgeable_resources;
-  ServiceWorkerDatabase::RegistrationData data;
-  data.registration_id = 100;
-  data.scope = GURL("https://example.com/");
-  data.script = GURL("https://example.com/script.js");
-  data.version_id = 200;
-  data.resources_total_size_bytes = 10;
-  ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            storage()->database_->WriteRegistration(
-                data, resources, &deleted_version, &newly_purgeable_resources));
-
-  // After the database initialization, the migration state should be
-  // initialized.
-  bool migration_needed = false;
-  EXPECT_EQ(
-      ServiceWorkerDatabase::STATUS_OK,
-      storage()->database_->IsDiskCacheMigrationNeeded(&migration_needed));
-  EXPECT_FALSE(migration_needed);
-  bool deletion_needed = false;
-  EXPECT_EQ(
-      ServiceWorkerDatabase::STATUS_OK,
-      storage()->database_->IsOldDiskCacheDeletionNeeded(&deletion_needed));
-
-  // The deletion flag should be set for the case that the database is empty but
-  // the old diskcache exists.
-  EXPECT_TRUE(deletion_needed);
-}
-
-}  // namespace content
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.h b/content/browser/service_worker/service_worker_dispatcher_host.h
index 7e8a9fe..d907f9d 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host.h
+++ b/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -135,7 +135,6 @@
       int handle_id,
       const base::string16& message,
       const std::vector<TransferredMessagePort>& sent_message_ports);
-  void OnServiceWorkerObjectDestroyed(int handle_id);
   void OnTerminateWorker(int handle_id);
 
   ServiceWorkerRegistrationHandle* FindRegistrationHandle(
diff --git a/content/browser/service_worker/service_worker_metrics.cc b/content/browser/service_worker/service_worker_metrics.cc
index 8b709022..a900d4d 100644
--- a/content/browser/service_worker/service_worker_metrics.cc
+++ b/content/browser/service_worker/service_worker_metrics.cc
@@ -99,12 +99,6 @@
                               std::abs(net_error));
 }
 
-void ServiceWorkerMetrics::RecordDiskCacheMigrationResult(
-    DiskCacheMigrationResult result) {
-  UMA_HISTOGRAM_ENUMERATION("ServiceWorker.Storage.DiskCacheMigrationResult",
-                            result, NUM_MIGRATION_RESULT_TYPES);
-}
-
 void ServiceWorkerMetrics::RecordDeleteAndStartOverResult(
     DeleteAndStartOverResult result) {
   UMA_HISTOGRAM_ENUMERATION("ServiceWorker.Storage.DeleteAndStartOverResult",
diff --git a/content/browser/service_worker/service_worker_metrics.h b/content/browser/service_worker/service_worker_metrics.h
index d4ec38a3..b02e4da1 100644
--- a/content/browser/service_worker/service_worker_metrics.h
+++ b/content/browser/service_worker/service_worker_metrics.h
@@ -30,14 +30,6 @@
     NUM_WRITE_RESPONSE_RESULT_TYPES,
   };
 
-  enum DiskCacheMigrationResult {
-    MIGRATION_OK,
-    MIGRATION_NOT_NECESSARY,
-    MIGRATION_ERROR_MIGRATION_FAILED,
-    MIGRATION_ERROR_UPDATE_DATABASE,
-    NUM_MIGRATION_RESULT_TYPES,
-  };
-
   enum DeleteAndStartOverResult {
     DELETE_OK,
     DELETE_DATABASE_ERROR,
@@ -108,7 +100,6 @@
   // Used for ServiceWorkerStorage.
   static void RecordPurgeResourceResult(int net_error);
   static void RecordDeleteAndStartOverResult(DeleteAndStartOverResult result);
-  static void RecordDiskCacheMigrationResult(DiskCacheMigrationResult result);
 
   // Counts the number of page loads controlled by a Service Worker.
   static void CountControlledPageLoad(const GURL& url);
diff --git a/content/browser/service_worker/service_worker_read_from_cache_job.cc b/content/browser/service_worker/service_worker_read_from_cache_job.cc
index 8ce3d8f..3b0d658c 100644
--- a/content/browser/service_worker/service_worker_read_from_cache_job.cc
+++ b/content/browser/service_worker/service_worker_read_from_cache_job.cc
@@ -31,10 +31,9 @@
     int64 resource_id)
     : net::URLRequestJob(request, network_delegate),
       resource_type_(resource_type),
+      resource_id_(resource_id),
       context_(context),
       version_(version),
-      resource_id_(resource_id),
-      has_been_killed_(false),
       weak_factory_(this) {}
 
 ServiceWorkerReadFromCacheJob::~ServiceWorkerReadFromCacheJob() {
@@ -53,7 +52,7 @@
   has_been_killed_ = true;
   reader_.reset();
   context_.reset();
-  http_info_io_buffer_ = NULL;
+  http_info_io_buffer_ = nullptr;
   http_info_.reset();
   range_response_info_.reset();
   net::URLRequestJob::Kill();
@@ -145,7 +144,7 @@
 
 const net::HttpResponseInfo* ServiceWorkerReadFromCacheJob::http_info() const {
   if (!http_info_)
-    return NULL;
+    return nullptr;
   if (range_response_info_)
     return range_response_info_.get();
   return http_info_.get();
@@ -166,7 +165,7 @@
   http_info_.reset(http_info_io_buffer_->http_info.release());
   if (is_range_request())
     SetupRangeResponse(http_info_io_buffer_->response_data_size);
-  http_info_io_buffer_ = NULL;
+  http_info_io_buffer_ = nullptr;
   if (request_->url() == version_->script_url())
     version_->SetMainScriptHttpResponseInfo(*http_info_);
   TRACE_EVENT_ASYNC_END1("ServiceWorker",
diff --git a/content/browser/service_worker/service_worker_read_from_cache_job.h b/content/browser/service_worker/service_worker_read_from_cache_job.h
index a62893d..0ee30e64 100644
--- a/content/browser/service_worker/service_worker_read_from_cache_job.h
+++ b/content/browser/service_worker/service_worker_read_from_cache_job.h
@@ -34,9 +34,10 @@
       base::WeakPtr<ServiceWorkerContextCore> context,
       const scoped_refptr<ServiceWorkerVersion>& version,
       int64 resource_id);
+  ~ServiceWorkerReadFromCacheJob() override;
 
  private:
-  ~ServiceWorkerReadFromCacheJob() override;
+  friend class ServiceWorkerReadFromCacheJobTest;
 
   bool is_main_script() const {
     return resource_type_ == RESOURCE_TYPE_SERVICE_WORKER;
@@ -64,16 +65,18 @@
   void SetupRangeResponse(int response_data_size);
   void Done(const net::URLRequestStatus& status);
 
-  ResourceType resource_type_;
+  const ResourceType resource_type_;
+  const int64 resource_id_;
+
   base::WeakPtr<ServiceWorkerContextCore> context_;
   scoped_refptr<ServiceWorkerVersion> version_;
-  int64 resource_id_;
   scoped_ptr<ServiceWorkerResponseReader> reader_;
   scoped_refptr<HttpResponseInfoIOBuffer> http_info_io_buffer_;
   scoped_ptr<net::HttpResponseInfo> http_info_;
   net::HttpByteRange range_requested_;
   scoped_ptr<net::HttpResponseInfo> range_response_info_;
-  bool has_been_killed_;
+  bool has_been_killed_ = false;
+
   base::WeakPtrFactory<ServiceWorkerReadFromCacheJob> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerReadFromCacheJob);
diff --git a/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc b/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
new file mode 100644
index 0000000..93c86a13
--- /dev/null
+++ b/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
@@ -0,0 +1,231 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/service_worker/service_worker_read_from_cache_job.h"
+
+#include "base/run_loop.h"
+#include "content/browser/fileapi/mock_url_request_delegate.h"
+#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_version.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/base/io_buffer.h"
+#include "net/base/test_completion_callback.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "net/url_request/url_request_status.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+const int64 kRegistrationId = 1;
+const int64 kVersionId = 2;
+const int64 kMainScriptResourceId = 10;
+const int64 kImportedScriptResourceId = 11;
+const int64 kResourceSize = 100;
+
+void DidStoreRegistration(ServiceWorkerStatusCode* status_out,
+                          const base::Closure& quit_closure,
+                          ServiceWorkerStatusCode status) {
+  *status_out = status;
+  quit_closure.Run();
+}
+
+void DidFindRegistration(
+    ServiceWorkerStatusCode* status_out,
+    const base::Closure& quit_closure,
+    ServiceWorkerStatusCode status,
+    const scoped_refptr<ServiceWorkerRegistration>& registration) {
+  *status_out = status;
+  quit_closure.Run();
+}
+
+}  // namespace
+
+class ServiceWorkerReadFromCacheJobTest : public testing::Test {
+ public:
+  ServiceWorkerReadFromCacheJobTest()
+      : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
+        main_script_(kMainScriptResourceId,
+                     GURL("http://example.com/main.js"),
+                     kResourceSize),
+        imported_script_(kImportedScriptResourceId,
+                         GURL("http://example.com/imported.js"),
+                         kResourceSize) {}
+  ~ServiceWorkerReadFromCacheJobTest() override {}
+
+  void SetUp() override {
+    helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
+    InitializeStorage();
+
+    url_request_context_.reset(new net::URLRequestContext);
+    url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
+    url_request_context_->set_job_factory(url_request_job_factory_.get());
+  }
+
+  void InitializeStorage() {
+    base::RunLoop run_loop;
+    context()->storage()->LazyInitialize(run_loop.QuitClosure());
+    run_loop.Run();
+
+    // Populate a registration in the storage.
+    registration_ =
+        new ServiceWorkerRegistration(GURL("http://example.com/scope"),
+                                      kRegistrationId, context()->AsWeakPtr());
+    version_ = new ServiceWorkerVersion(registration_.get(), main_script_.url,
+                                        kVersionId, context()->AsWeakPtr());
+    std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
+    resources.push_back(main_script_);
+    resources.push_back(imported_script_);
+    version_->script_cache_map()->SetResources(resources);
+    ASSERT_EQ(SERVICE_WORKER_OK, StoreRegistration());
+    ASSERT_TRUE(WriteResource(main_script_.resource_id));
+    ASSERT_TRUE(WriteResource(imported_script_.resource_id));
+  }
+
+  bool WriteResource(int64 resource_id) {
+    const char kHttpHeaders[] = "HTTP/1.0 200 OK\0Content-Length: 5\0\0";
+    const char kHttpBody[] = "Hello";
+    const int length = arraysize(kHttpBody);
+    std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
+    scoped_refptr<net::IOBuffer> body(new net::WrappedIOBuffer(kHttpBody));
+
+    scoped_ptr<ServiceWorkerResponseWriter> writer =
+        context()->storage()->CreateResponseWriter(resource_id);
+
+    scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
+    info->request_time = base::Time::Now();
+    info->response_time = base::Time::Now();
+    info->was_cached = false;
+    info->headers = new net::HttpResponseHeaders(headers);
+    scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
+        new HttpResponseInfoIOBuffer(info.release());
+    {
+      net::TestCompletionCallback cb;
+      writer->WriteInfo(info_buffer.get(), cb.callback());
+      int rv = cb.WaitForResult();
+      if (rv < 0)
+        return false;
+    }
+    {
+      net::TestCompletionCallback cb;
+      writer->WriteData(body.get(), length, cb.callback());
+      int rv = cb.WaitForResult();
+      if (rv < 0)
+        return false;
+    }
+    return true;
+  }
+
+  ServiceWorkerStatusCode StoreRegistration() {
+    base::RunLoop run_loop;
+    ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+    context()->storage()->StoreRegistration(
+        registration_.get(), version_.get(),
+        base::Bind(&DidStoreRegistration, &status, run_loop.QuitClosure()));
+    run_loop.Run();
+    return status;
+  }
+
+  ServiceWorkerStatusCode FindRegistration() {
+    base::RunLoop run_loop;
+    ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+    context()->storage()->FindRegistrationForId(
+        registration_->id(), registration_->pattern().GetOrigin(),
+        base::Bind(&DidFindRegistration, &status, run_loop.QuitClosure()));
+    run_loop.Run();
+    return status;
+  }
+
+  void StartAndWaitForJob(
+      const scoped_ptr<ServiceWorkerReadFromCacheJob>& job) {
+    job->Start();
+    // MockURLRequestDelegate quits the loop when the request is completed.
+    base::RunLoop().RunUntilIdle();
+  }
+
+  ServiceWorkerStatusCode DeduceStartWorkerFailureReason(
+      ServiceWorkerStatusCode default_code) {
+    return version_->DeduceStartWorkerFailureReason(default_code);
+  }
+
+  ServiceWorkerContextCore* context() const { return helper_->context(); }
+
+ protected:
+  TestBrowserThreadBundle thread_bundle_;
+  scoped_ptr<EmbeddedWorkerTestHelper> helper_;
+
+  scoped_refptr<ServiceWorkerRegistration> registration_;
+  scoped_refptr<ServiceWorkerVersion> version_;
+  ServiceWorkerDatabase::ResourceRecord main_script_;
+  ServiceWorkerDatabase::ResourceRecord imported_script_;
+
+  scoped_ptr<net::URLRequestContext> url_request_context_;
+  scoped_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
+  MockURLRequestDelegate delegate_;
+};
+
+TEST_F(ServiceWorkerReadFromCacheJobTest, ReadMainScript) {
+  // Read the main script from the diskcache.
+  scoped_ptr<net::URLRequest> request = url_request_context_->CreateRequest(
+      main_script_.url, net::DEFAULT_PRIORITY, &delegate_);
+  scoped_ptr<ServiceWorkerReadFromCacheJob> job(
+      new ServiceWorkerReadFromCacheJob(
+          request.get(), nullptr /* NetworkDelegate */,
+          RESOURCE_TYPE_SERVICE_WORKER, context()->AsWeakPtr(), version_,
+          main_script_.resource_id));
+  StartAndWaitForJob(job);
+
+  EXPECT_EQ(net::URLRequestStatus::SUCCESS, request->status().status());
+  EXPECT_EQ(0, request->status().error());
+  EXPECT_EQ(SERVICE_WORKER_OK,
+            DeduceStartWorkerFailureReason(SERVICE_WORKER_OK));
+}
+
+TEST_F(ServiceWorkerReadFromCacheJobTest, ReadImportedScript) {
+  // Read the imported script from the diskcache.
+  scoped_ptr<net::URLRequest> request = url_request_context_->CreateRequest(
+      imported_script_.url, net::DEFAULT_PRIORITY, &delegate_);
+  scoped_ptr<ServiceWorkerReadFromCacheJob> job(
+      new ServiceWorkerReadFromCacheJob(
+          request.get(), nullptr /* NetworkDelegate */, RESOURCE_TYPE_SCRIPT,
+          context()->AsWeakPtr(), version_, imported_script_.resource_id));
+  StartAndWaitForJob(job);
+
+  EXPECT_EQ(net::URLRequestStatus::SUCCESS, request->status().status());
+  EXPECT_EQ(0, request->status().error());
+  EXPECT_EQ(SERVICE_WORKER_OK,
+            DeduceStartWorkerFailureReason(SERVICE_WORKER_OK));
+}
+
+TEST_F(ServiceWorkerReadFromCacheJobTest, ResourceNotFound) {
+  ASSERT_EQ(SERVICE_WORKER_OK, FindRegistration());
+
+  // Try to read a nonexistent resource from the diskcache.
+  scoped_ptr<net::URLRequest> request = url_request_context_->CreateRequest(
+      GURL("http://example.com/nonexistent"), net::DEFAULT_PRIORITY,
+      &delegate_);
+  const int64 kNonexistentResourceId = 100;
+  scoped_ptr<ServiceWorkerReadFromCacheJob> job(
+      new ServiceWorkerReadFromCacheJob(
+          request.get(), nullptr /* NetworkDelegate */,
+          RESOURCE_TYPE_SERVICE_WORKER, context()->AsWeakPtr(), version_,
+          kNonexistentResourceId));
+  StartAndWaitForJob(job);
+
+  EXPECT_EQ(net::URLRequestStatus::FAILED, request->status().status());
+  EXPECT_EQ(net::ERR_CACHE_MISS, request->status().error());
+  EXPECT_EQ(SERVICE_WORKER_ERROR_DISK_CACHE,
+            DeduceStartWorkerFailureReason(SERVICE_WORKER_OK));
+
+  // The version should be doomed by the job.
+  EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version_->status());
+  EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, FindRegistration());
+}
+
+}  // namespace content
diff --git a/content/browser/service_worker/service_worker_register_job.h b/content/browser/service_worker/service_worker_register_job.h
index 848a2718..a439b0c 100644
--- a/content/browser/service_worker/service_worker_register_job.h
+++ b/content/browser/service_worker/service_worker_register_job.h
@@ -120,8 +120,6 @@
   void OnStoreRegistrationComplete(ServiceWorkerStatusCode status);
   void InstallAndContinue();
   void OnInstallFinished(ServiceWorkerStatusCode status);
-  void ActivateAndContinue();
-  void OnActivateFinished(ServiceWorkerStatusCode status);
   void Complete(ServiceWorkerStatusCode status);
   void Complete(ServiceWorkerStatusCode status,
                 const std::string& status_message);
diff --git a/content/browser/service_worker/service_worker_registration.cc b/content/browser/service_worker/service_worker_registration.cc
index 7517b51..1a2f536 100644
--- a/content/browser/service_worker/service_worker_registration.cc
+++ b/content/browser/service_worker/service_worker_registration.cc
@@ -236,29 +236,6 @@
                  most_recent_version));
 }
 
-void ServiceWorkerRegistration::GetUserData(
-    const std::string& key,
-    const GetUserDataCallback& callback) {
-  DCHECK(context_);
-  context_->storage()->GetUserData(registration_id_, key, callback);
-}
-
-void ServiceWorkerRegistration::StoreUserData(
-    const std::string& key,
-    const std::string& data,
-    const StatusCallback& callback) {
-  DCHECK(context_);
-  context_->storage()->StoreUserData(
-      registration_id_, pattern().GetOrigin(), key, data, callback);
-}
-
-void ServiceWorkerRegistration::ClearUserData(
-    const std::string& key,
-    const StatusCallback& callback) {
-  DCHECK(context_);
-  context_->storage()->ClearUserData(registration_id_, key, callback);
-}
-
 void ServiceWorkerRegistration::OnNoControllees(ServiceWorkerVersion* version) {
   if (!context_)
     return;
diff --git a/content/browser/service_worker/service_worker_registration.h b/content/browser/service_worker/service_worker_registration.h
index 8a8cbec..accb464d 100644
--- a/content/browser/service_worker/service_worker_registration.h
+++ b/content/browser/service_worker/service_worker_registration.h
@@ -129,17 +129,6 @@
   base::Time last_update_check() const { return last_update_check_; }
   void set_last_update_check(base::Time last) { last_update_check_ = last; }
 
-  // Provide a storage mechanism to read/write arbitrary data associated with
-  // this registration in the storage. Stored data is deleted when this
-  // registration is deleted from the storage.
-  void GetUserData(const std::string& key,
-                   const GetUserDataCallback& callback);
-  void StoreUserData(const std::string& key,
-                     const std::string& data,
-                     const StatusCallback& callback);
-  void ClearUserData(const std::string& key,
-                     const StatusCallback& callback);
-
   // Unsets the version and deletes its resources. Also deletes this
   // registration from storage if there is no longer a stored version.
   void DeleteVersion(const scoped_refptr<ServiceWorkerVersion>& version);
diff --git a/content/browser/service_worker/service_worker_script_cache_map.cc b/content/browser/service_worker/service_worker_script_cache_map.cc
index 3607240..c99fef87 100644
--- a/content/browser/service_worker/service_worker_script_cache_map.cc
+++ b/content/browser/service_worker/service_worker_script_cache_map.cc
@@ -31,13 +31,6 @@
   return found->second.resource_id;
 }
 
-int64 ServiceWorkerScriptCacheMap::LookupResourceSize(const GURL& url) {
-  ResourceMap::const_iterator found = resource_map_.find(url);
-  if (found == resource_map_.end())
-    return kInvalidServiceWorkerResourceId;
-  return found->second.size_bytes;
-}
-
 void ServiceWorkerScriptCacheMap::NotifyStartedCaching(
     const GURL& url, int64 resource_id) {
   DCHECK_EQ(kInvalidServiceWorkerResourceId, LookupResourceId(url));
diff --git a/content/browser/service_worker/service_worker_script_cache_map.h b/content/browser/service_worker/service_worker_script_cache_map.h
index 7d3366a..b4cf74b 100644
--- a/content/browser/service_worker/service_worker_script_cache_map.h
+++ b/content/browser/service_worker/service_worker_script_cache_map.h
@@ -28,9 +28,6 @@
 class CONTENT_EXPORT ServiceWorkerScriptCacheMap {
  public:
   int64 LookupResourceId(const GURL& url);
-  // A size of -1 means that we don't know the size yet
-  // (it has not finished caching).
-  int64 LookupResourceSize(const GURL& url);
 
   // Used during the initial run of a new version to build the map
   // of resources ids.
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc
index 9f12df7b..76cf507 100644
--- a/content/browser/service_worker/service_worker_storage.cc
+++ b/content/browser/service_worker/service_worker_storage.cc
@@ -14,7 +14,6 @@
 #include "base/trace_event/trace_event.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_disk_cache.h"
-#include "content/browser/service_worker/service_worker_disk_cache_migrator.h"
 #include "content/browser/service_worker/service_worker_info.h"
 #include "content/browser/service_worker/service_worker_registration.h"
 #include "content/browser/service_worker/service_worker_version.h"
@@ -61,7 +60,6 @@
     FILE_PATH_LITERAL("Database");
 const base::FilePath::CharType kDiskCacheName[] =
     FILE_PATH_LITERAL("ScriptCache");
-const base::FilePath::CharType kOldDiskCacheName[] = FILE_PATH_LITERAL("Cache");
 
 const int kMaxMemDiskCacheSize = 10 * 1024 * 1024;
 const int kMaxDiskCacheSize = 250 * 1024 * 1024;
@@ -85,10 +83,7 @@
 ServiceWorkerStorage::InitialData::InitialData()
     : next_registration_id(kInvalidServiceWorkerRegistrationId),
       next_version_id(kInvalidServiceWorkerVersionId),
-      next_resource_id(kInvalidServiceWorkerResourceId),
-      disk_cache_migration_needed(false),
-      old_disk_cache_deletion_needed(false) {
-}
+      next_resource_id(kInvalidServiceWorkerResourceId) {}
 
 ServiceWorkerStorage::InitialData::~InitialData() {
 }
@@ -793,8 +788,6 @@
       disk_cache_thread_(disk_cache_thread),
       quota_manager_proxy_(quota_manager_proxy),
       special_storage_policy_(special_storage_policy),
-      disk_cache_migration_needed_(false),
-      old_disk_cache_deletion_needed_(false),
       is_purge_pending_(false),
       has_checked_for_stale_resources_(false),
       weak_factory_(this) {
@@ -816,13 +809,6 @@
       .Append(kDiskCacheName);
 }
 
-base::FilePath ServiceWorkerStorage::GetOldDiskCachePath() {
-  if (path_.empty())
-    return base::FilePath();
-  return path_.Append(ServiceWorkerContextCore::kServiceWorkerDirectory)
-      .Append(kOldDiskCacheName);
-}
-
 bool ServiceWorkerStorage::LazyInitialize(const base::Closure& callback) {
   switch (state_) {
     case INITIALIZED:
@@ -859,8 +845,6 @@
     next_version_id_ = data->next_version_id;
     next_resource_id_ = data->next_resource_id;
     registered_origins_.swap(data->origins);
-    disk_cache_migration_needed_ = data->disk_cache_migration_needed;
-    old_disk_cache_deletion_needed_ = data->old_disk_cache_deletion_needed;
     foreign_fetch_origins_.swap(data->foreign_fetch_origins);
     state_ = INITIALIZED;
   } else {
@@ -1297,7 +1281,7 @@
   if (disk_cache_)
     return disk_cache_.get();
 
-  disk_cache_ = ServiceWorkerDiskCache::CreateWithSimpleBackend();
+  disk_cache_.reset(new ServiceWorkerDiskCache);
 
   base::FilePath path = GetDiskCachePath();
   if (path.empty()) {
@@ -1307,87 +1291,10 @@
     return disk_cache_.get();
   }
 
-  if (disk_cache_migration_needed_) {
-    // Defer the start of initialization until a migration is complete.
-    disk_cache_->set_is_waiting_to_initialize(true);
-    DCHECK(!disk_cache_migrator_);
-    disk_cache_migrator_.reset(new ServiceWorkerDiskCacheMigrator(
-        GetOldDiskCachePath(), GetDiskCachePath(), kMaxDiskCacheSize,
-        disk_cache_thread_));
-    disk_cache_migrator_->Start(
-        base::Bind(&ServiceWorkerStorage::DidMigrateDiskCache,
-                   weak_factory_.GetWeakPtr()));
-    return disk_cache_.get();
-  }
-
-  if (old_disk_cache_deletion_needed_) {
-    // Lazily delete the old diskcache.
-    BrowserThread::PostAfterStartupTask(
-        FROM_HERE, base::ThreadTaskRunnerHandle::Get(),
-        base::Bind(&ServiceWorkerStorage::DeleteOldDiskCache,
-                   weak_factory_.GetWeakPtr()));
-  }
-
-  ServiceWorkerMetrics::RecordDiskCacheMigrationResult(
-      ServiceWorkerMetrics::MIGRATION_NOT_NECESSARY);
-
   InitializeDiskCache();
   return disk_cache_.get();
 }
 
-void ServiceWorkerStorage::DidMigrateDiskCache(ServiceWorkerStatusCode status) {
-  disk_cache_migrator_.reset();
-  if (status != SERVICE_WORKER_OK) {
-    OnDiskCacheMigrationFailed(
-        ServiceWorkerMetrics::MIGRATION_ERROR_MIGRATION_FAILED);
-    return;
-  }
-
-  PostTaskAndReplyWithResult(
-      database_task_manager_->GetTaskRunner(), FROM_HERE,
-      base::Bind(&ServiceWorkerDatabase::SetDiskCacheMigrationNotNeeded,
-                 base::Unretained(database_.get())),
-      base::Bind(&ServiceWorkerStorage::DidSetDiskCacheMigrationNotNeeded,
-                 weak_factory_.GetWeakPtr()));
-}
-
-void ServiceWorkerStorage::DidSetDiskCacheMigrationNotNeeded(
-    ServiceWorkerDatabase::Status status) {
-  if (status != ServiceWorkerDatabase::STATUS_OK) {
-    OnDiskCacheMigrationFailed(
-        ServiceWorkerMetrics::MIGRATION_ERROR_UPDATE_DATABASE);
-    return;
-  }
-
-  // Lazily delete the old diskcache and update the database.
-  BrowserThread::PostAfterStartupTask(
-      FROM_HERE, base::ThreadTaskRunnerHandle::Get(),
-      base::Bind(&ServiceWorkerStorage::DeleteOldDiskCache,
-                 weak_factory_.GetWeakPtr()));
-
-  ServiceWorkerMetrics::RecordDiskCacheMigrationResult(
-      ServiceWorkerMetrics::MIGRATION_OK);
-  InitializeDiskCache();
-}
-
-void ServiceWorkerStorage::OnDiskCacheMigrationFailed(
-    ServiceWorkerMetrics::DiskCacheMigrationResult result) {
-  DCHECK(ServiceWorkerMetrics::MIGRATION_ERROR_MIGRATION_FAILED == result ||
-         ServiceWorkerMetrics::MIGRATION_ERROR_UPDATE_DATABASE == result)
-      << result;
-  ServiceWorkerMetrics::RecordDiskCacheMigrationResult(result);
-
-  // Give up migration and recreate the whole storage.
-  ScheduleDeleteAndStartOver();
-
-  // Lazily delete the old diskcache. Don't have to update the database
-  // because it will be deleted by DeleteAndStartOver.
-  BrowserThread::PostAfterStartupTask(
-      FROM_HERE, disk_cache_thread_.get(),
-      base::Bind(base::IgnoreResult(&base::DeleteFile), GetOldDiskCachePath(),
-                 true));
-}
-
 void ServiceWorkerStorage::InitializeDiskCache() {
   disk_cache_->set_is_waiting_to_initialize(false);
   int rv = disk_cache_->InitWithDiskBackend(
@@ -1407,15 +1314,6 @@
   ServiceWorkerMetrics::CountInitDiskCacheResult(rv == net::OK);
 }
 
-void ServiceWorkerStorage::DeleteOldDiskCache() {
-  DCHECK(state_ == INITIALIZED || state_ == DISABLED) << state_;
-  if (IsDisabled())
-    return;
-  database_task_manager_->GetTaskRunner()->PostTask(
-      FROM_HERE, base::Bind(&ServiceWorkerStorage::DeleteOldDiskCacheInDB,
-                            database_.get(), GetOldDiskCachePath()));
-}
-
 void ServiceWorkerStorage::StartPurgingResources(
     const std::set<int64>& resource_ids) {
   DCHECK(has_checked_for_stale_resources_);
@@ -1573,22 +1471,6 @@
     return;
   }
 
-  status =
-      database->IsDiskCacheMigrationNeeded(&data->disk_cache_migration_needed);
-  if (status != ServiceWorkerDatabase::STATUS_OK) {
-    original_task_runner->PostTask(
-        FROM_HERE, base::Bind(callback, base::Passed(data.Pass()), status));
-    return;
-  }
-
-  status = database->IsOldDiskCacheDeletionNeeded(
-      &data->old_disk_cache_deletion_needed);
-  if (status != ServiceWorkerDatabase::STATUS_OK) {
-    original_task_runner->PostTask(
-        FROM_HERE, base::Bind(callback, base::Passed(data.Pass()), status));
-    return;
-  }
-
   status = database->GetOriginsWithRegistrations(&data->origins);
   if (status != ServiceWorkerDatabase::STATUS_OK) {
     original_task_runner->PostTask(
@@ -1602,15 +1484,6 @@
       FROM_HERE, base::Bind(callback, base::Passed(data.Pass()), status));
 }
 
-void ServiceWorkerStorage::DeleteOldDiskCacheInDB(
-    ServiceWorkerDatabase* database,
-    const base::FilePath& disk_cache_path) {
-  // Ignore a failure. A retry will happen on the next initialization.
-  if (!base::DeleteFile(disk_cache_path, true))
-    return;
-  database->SetOldDiskCacheDeletionNotNeeded();
-}
-
 void ServiceWorkerStorage::DeleteRegistrationFromDB(
     ServiceWorkerDatabase* database,
     scoped_refptr<base::SequencedTaskRunner> original_task_runner,
diff --git a/content/browser/service_worker/service_worker_storage.h b/content/browser/service_worker/service_worker_storage.h
index 64650b7..7317a631 100644
--- a/content/browser/service_worker/service_worker_storage.h
+++ b/content/browser/service_worker/service_worker_storage.h
@@ -37,7 +37,6 @@
 
 class ServiceWorkerContextCore;
 class ServiceWorkerDiskCache;
-class ServiceWorkerDiskCacheMigrator;
 class ServiceWorkerRegistration;
 class ServiceWorkerResponseMetadataWriter;
 class ServiceWorkerResponseReader;
@@ -221,18 +220,12 @@
   friend class ServiceWorkerResourceStorageTest;
   friend class ServiceWorkerControlleeRequestHandlerTest;
   friend class ServiceWorkerContextRequestHandlerTest;
-  friend class ServiceWorkerDiskCacheMigratorTest;
+  friend class ServiceWorkerReadFromCacheJobTest;
   friend class ServiceWorkerRequestHandlerTest;
   friend class ServiceWorkerURLRequestJobTest;
   friend class ServiceWorkerVersionBrowserTest;
   friend class ServiceWorkerVersionTest;
   friend class ServiceWorkerWriteToCacheJobTest;
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDiskCacheMigratorTest,
-                           MigrateOnDiskCacheAccess);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDiskCacheMigratorTest,
-                           NotMigrateOnDatabaseAccess);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDiskCacheMigratorTest,
-                           NotMigrateForEmptyDatabase);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDispatcherHostTest,
                            CleanupOnRendererCrash);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerResourceStorageTest,
@@ -259,8 +252,6 @@
     int64 next_version_id;
     int64 next_resource_id;
     std::set<GURL> origins;
-    bool disk_cache_migration_needed;
-    bool old_disk_cache_deletion_needed;
     std::set<GURL> foreign_fetch_origins;
 
     InitialData();
@@ -331,12 +322,6 @@
   base::FilePath GetDatabasePath();
   base::FilePath GetDiskCachePath();
 
-  // Returns a path to an old diskcache backed with BlockFile. This is used for
-  // the diskcache migration (see service_worker_disk_cache_migrator.h).
-  // TODO(nhiroki): Remove this after several milestones pass
-  // (http://crbug.com/487482)
-  base::FilePath GetOldDiskCachePath();
-
   bool LazyInitialize(
       const base::Closure& callback);
   void DidReadInitialData(scoped_ptr<InitialData> data,
@@ -418,16 +403,9 @@
 
   // Lazy disk_cache getter.
   ServiceWorkerDiskCache* disk_cache();
-  void MigrateDiskCache();
-  void DidMigrateDiskCache(ServiceWorkerStatusCode status);
-  void DidSetDiskCacheMigrationNotNeeded(ServiceWorkerDatabase::Status status);
-  void OnDiskCacheMigrationFailed(
-      ServiceWorkerMetrics::DiskCacheMigrationResult result);
   void InitializeDiskCache();
   void OnDiskCacheInitialized(int rv);
 
-  void DeleteOldDiskCache();
-
   void StartPurgingResources(const std::set<int64>& resource_ids);
   void StartPurgingResources(const std::vector<int64>& resource_ids);
   void StartPurgingResources(const ResourceList& resources);
@@ -453,8 +431,6 @@
       ServiceWorkerDatabase* database,
       scoped_refptr<base::SequencedTaskRunner> original_task_runner,
       const InitializeCallback& callback);
-  static void DeleteOldDiskCacheInDB(ServiceWorkerDatabase* database,
-                                     const base::FilePath& disk_cache_path);
   static void DeleteRegistrationFromDB(
       ServiceWorkerDatabase* database,
       scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -548,9 +524,6 @@
   scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
 
   scoped_ptr<ServiceWorkerDiskCache> disk_cache_;
-  scoped_ptr<ServiceWorkerDiskCacheMigrator> disk_cache_migrator_;
-  bool disk_cache_migration_needed_;
-  bool old_disk_cache_deletion_needed_;
 
   std::deque<int64> purgeable_resource_ids_;
   bool is_purge_pending_;
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index 244378b..5aedb9c 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -340,8 +340,9 @@
  private:
   friend class base::RefCounted<ServiceWorkerVersion>;
   friend class ServiceWorkerMetrics;
-  friend class ServiceWorkerURLRequestJobTest;
+  friend class ServiceWorkerReadFromCacheJobTest;
   friend class ServiceWorkerStallInStoppingTest;
+  friend class ServiceWorkerURLRequestJobTest;
   friend class ServiceWorkerVersionBrowserTest;
 
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest,
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 9f6355e..b8f4e5c 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2995,6 +2995,12 @@
   }
 }
 
+bool WebContentsImpl::ShouldTransferNavigation() {
+  if (!delegate_)
+    return true;
+  return delegate_->ShouldTransferNavigation();
+}
+
 bool WebContentsImpl::ShouldPreserveAbortedURLs() {
   if (!delegate_)
     return false;
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index f41c780..2b867cc 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -553,6 +553,7 @@
       NavigationController::ReloadType reload_type) override;
   void RequestOpenURL(RenderFrameHostImpl* render_frame_host,
                       const OpenURLParams& params) override;
+  bool ShouldTransferNavigation() override;
   bool ShouldPreserveAbortedURLs() override;
   void DidStartLoading(FrameTreeNode* frame_tree_node,
                        bool to_different_document) override;
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index c66ac28..5ba80e0 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -33,7 +33,6 @@
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
-#include "content/public/common/url_utils.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_utils.h"
 #include "content/test/test_content_browser_client.h"
@@ -482,7 +481,7 @@
 TEST_F(WebContentsImplTest, NavigateToExcessivelyLongURL) {
   // Construct a URL that's kMaxURLChars + 1 long of all 'a's.
   const GURL url(std::string("http://example.org/").append(
-      GetMaxURLChars() + 1, 'a'));
+      kMaxURLChars + 1, 'a'));
 
   controller().LoadURL(
       url, Referrer(), ui::PAGE_TRANSITION_GENERATED, std::string());
diff --git a/content/child/service_worker/service_worker_dispatcher.cc b/content/child/service_worker/service_worker_dispatcher.cc
index 30304f01..23a0c59 100644
--- a/content/child/service_worker/service_worker_dispatcher.cc
+++ b/content/child/service_worker/service_worker_dispatcher.cc
@@ -19,7 +19,7 @@
 #include "content/child/webmessageportchannel_impl.h"
 #include "content/common/service_worker/service_worker_messages.h"
 #include "content/common/service_worker/service_worker_types.h"
-#include "content/public/common/url_utils.h"
+#include "content/public/common/content_constants.h"
 #include "third_party/WebKit/public/platform/WebString.h"
 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProviderClient.h"
 
@@ -100,10 +100,6 @@
   DCHECK(handled) << "Unhandled message:" << msg.type();
 }
 
-bool ServiceWorkerDispatcher::Send(IPC::Message* msg) {
-  return thread_safe_sender_->Send(msg);
-}
-
 void ServiceWorkerDispatcher::RegisterServiceWorker(
     int provider_id,
     const GURL& pattern,
@@ -111,8 +107,8 @@
     WebServiceWorkerRegistrationCallbacks* callbacks) {
   DCHECK(callbacks);
 
-  if (pattern.possibly_invalid_spec().size() > GetMaxURLChars() ||
-      script_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
+  if (pattern.possibly_invalid_spec().size() > kMaxURLChars ||
+      script_url.possibly_invalid_spec().size() > kMaxURLChars) {
     scoped_ptr<WebServiceWorkerRegistrationCallbacks>
         owned_callbacks(callbacks);
     std::string error_message(kServiceWorkerRegisterErrorPrefix);
@@ -162,7 +158,7 @@
     WebServiceWorkerGetRegistrationCallbacks* callbacks) {
   DCHECK(callbacks);
 
-  if (document_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
+  if (document_url.possibly_invalid_spec().size() > kMaxURLChars) {
     scoped_ptr<WebServiceWorkerGetRegistrationCallbacks> owned_callbacks(
         callbacks);
     std::string error_message(kServiceWorkerGetRegistrationErrorPrefix);
diff --git a/content/child/service_worker/service_worker_dispatcher.h b/content/child/service_worker/service_worker_dispatcher.h
index 08da580..f99504b 100644
--- a/content/child/service_worker/service_worker_dispatcher.h
+++ b/content/child/service_worker/service_worker_dispatcher.h
@@ -70,7 +70,6 @@
   ~ServiceWorkerDispatcher() override;
 
   void OnMessageReceived(const IPC::Message& msg);
-  bool Send(IPC::Message* msg);
 
   // Corresponds to navigator.serviceWorker.register().
   void RegisterServiceWorker(
diff --git a/content/child/service_worker/service_worker_handle_reference.h b/content/child/service_worker/service_worker_handle_reference.h
index c81e3ece..3d0fd9c 100644
--- a/content/child/service_worker/service_worker_handle_reference.h
+++ b/content/child/service_worker/service_worker_handle_reference.h
@@ -37,7 +37,6 @@
   int handle_id() const { return info_.handle_id; }
   const GURL& url() const { return info_.url; }
   blink::WebServiceWorkerState state() const { return info_.state; }
-  void set_state(blink::WebServiceWorkerState state) { info_.state = state; }
   int64 version_id() const { return info_.version_id; }
 
  private:
diff --git a/content/child/service_worker/service_worker_provider_context.cc b/content/child/service_worker/service_worker_provider_context.cc
index ffabed0..d286f2c 100644
--- a/content/child/service_worker/service_worker_provider_context.cc
+++ b/content/child/service_worker/service_worker_provider_context.cc
@@ -133,8 +133,6 @@
   scoped_ptr<ServiceWorkerHandleReference> waiting_;
   scoped_ptr<ServiceWorkerHandleReference> active_;
 
-  ServiceWorkerProviderContext* context_;
-
   DISALLOW_COPY_AND_ASSIGN(ControllerDelegate);
 };
 
diff --git a/content/common/common_param_traits_unittest.cc b/content/common/common_param_traits_unittest.cc
index aefab1c..31491df 100644
--- a/content/common/common_param_traits_unittest.cc
+++ b/content/common/common_param_traits_unittest.cc
@@ -8,7 +8,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/values.h"
 #include "content/public/common/common_param_traits.h"
-#include "content/public/common/url_utils.h"
+#include "content/public/common/content_constants.h"
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_message_utils.h"
 #include "net/base/host_port_pair.h"
@@ -53,7 +53,7 @@
   // Test an excessively long GURL.
   {
     const std::string url = std::string("http://example.org/").append(
-        content::GetMaxURLChars() + 1, 'a');
+        content::kMaxURLChars + 1, 'a');
     GURL input(url.c_str());
     IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
     IPC::ParamTraits<GURL>::Write(&msg, input);
diff --git a/content/common/content_constants_internal.cc b/content/common/content_constants_internal.cc
index e7174ef..3b0608e9 100644
--- a/content/common/content_constants_internal.cc
+++ b/content/common/content_constants_internal.cc
@@ -20,8 +20,8 @@
 // 8m pixels.
 const uint32 kMaxPluginSize = 8 << 20;
 
-// 10MiB
-const size_t kMaxLengthOfDataURLString = 1024 * 1024 * 10;
+// 20MiB
+const size_t kMaxLengthOfDataURLString = 1024 * 1024 * 20;
 
 const int kTraceEventBrowserProcessSortIndex = -6;
 const int kTraceEventRendererProcessSortIndex = -5;
diff --git a/content/common/dwrite_font_proxy_messages.h b/content/common/dwrite_font_proxy_messages.h
index 84cb751..727fd20 100644
--- a/content/common/dwrite_font_proxy_messages.h
+++ b/content/common/dwrite_font_proxy_messages.h
@@ -13,9 +13,14 @@
 #define IPC_MESSAGE_EXPORT CONTENT_EXPORT
 #define IPC_MESSAGE_START DWriteFontProxyMsgStart
 
+#ifndef CONTENT_COMMON_DWRITE_FONT_PROXY_MESSAGES_H_
+#define CONTENT_COMMON_DWRITE_FONT_PROXY_MESSAGES_H_
+
 // The macros can't handle a complex template declaration, so we typedef it.
 typedef std::pair<base::string16, base::string16> DWriteStringPair;
 
+#endif  // CONTENT_COMMON_DWRITE_FONT_PROXY_MESSAGES_H_
+
 // Locates the index of the specified font family within the system collection.
 IPC_SYNC_MESSAGE_CONTROL1_1(DWriteFontProxyMsg_FindFamily,
                             base::string16 /* family_name */,
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index be2f16ef..03404df 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -341,6 +341,9 @@
   IPC_STRUCT_TRAITS_MEMBER(should_clear_history_list)
   IPC_STRUCT_TRAITS_MEMBER(should_create_service_worker)
   IPC_STRUCT_TRAITS_MEMBER(service_worker_provider_id)
+#if defined(OS_ANDROID)
+  IPC_STRUCT_TRAITS_MEMBER(data_url_as_string)
+#endif
 IPC_STRUCT_TRAITS_END()
 
 IPC_STRUCT_TRAITS_BEGIN(content::FrameReplicationState)
diff --git a/content/common/gpu/client/command_buffer_proxy_impl.cc b/content/common/gpu/client/command_buffer_proxy_impl.cc
index 22afb00..b247bf3f 100644
--- a/content/common/gpu/client/command_buffer_proxy_impl.cc
+++ b/content/common/gpu/client/command_buffer_proxy_impl.cc
@@ -449,8 +449,8 @@
     return -1;
 
   if (image_fence_sync) {
-    gpu::SyncToken sync_token(GetNamespaceID(), GetCommandBufferID(),
-                              GetExtraCommandBufferData(), image_fence_sync);
+    gpu::SyncToken sync_token(GetNamespaceID(), GetExtraCommandBufferData(),
+                              GetCommandBufferID(), image_fence_sync);
 
     // Force a synchronous IPC to validate sync token.
     channel_->ValidateFlushIDReachedServer(stream_id_, true);
diff --git a/content/common/navigation_params.cc b/content/common/navigation_params.cc
index f54e876..27e2a21 100644
--- a/content/common/navigation_params.cc
+++ b/content/common/navigation_params.cc
@@ -5,7 +5,6 @@
 #include "content/common/navigation_params.h"
 
 #include "base/command_line.h"
-#include "base/memory/ref_counted_memory.h"
 #include "content/common/service_worker/service_worker_types.h"
 #include "content/public/common/content_switches.h"
 
diff --git a/content/common/navigation_params.h b/content/common/navigation_params.h
index 7caceeb9..f43bbd4 100644
--- a/content/common/navigation_params.h
+++ b/content/common/navigation_params.h
@@ -17,10 +17,6 @@
 #include "ui/base/page_transition_types.h"
 #include "url/gurl.h"
 
-namespace base {
-class RefCountedMemory;
-}
-
 namespace content {
 
 // The LoFi state which determines whether to add the Lo-Fi header.
@@ -305,6 +301,14 @@
   // This parameter is not used in the current navigation architecture, where
   // it will always be equal to kInvalidServiceWorkerProviderId.
   int service_worker_provider_id;
+
+#if defined(OS_ANDROID)
+  // The real content of the data: URL. Only used in Android WebView for
+  // implementing LoadDataWithBaseUrl API method to circumvent the restriction
+  // on the GURL max length in the IPC layer. Short data: URLs can still be
+  // passed in the |CommonNavigationParams::url| field.
+  std::string data_url_as_string;
+#endif
 };
 
 // Helper struct keeping track in one place of all the parameters the browser
diff --git a/content/common/service_worker/service_worker_types.h b/content/common/service_worker/service_worker_types.h
index dd1cab8..aff102a 100644
--- a/content/common/service_worker/service_worker_types.h
+++ b/content/common/service_worker/service_worker_types.h
@@ -30,11 +30,6 @@
 // messaging between the browser process and the child process.
 static const int kDocumentMainThreadId = 0;
 
-// Indicates invalid request ID (i.e. the sender does not expect it gets
-// response for the message) for messaging between browser process
-// and embedded worker.
-static const int kInvalidServiceWorkerRequestId = -1;
-
 // Constants for error messages.
 extern const char kServiceWorkerRegisterErrorPrefix[];
 extern const char kServiceWorkerUpdateErrorPrefix[];
@@ -51,7 +46,6 @@
 static const int64 kInvalidServiceWorkerVersionId = -1;
 static const int64 kInvalidServiceWorkerResourceId = -1;
 static const int kInvalidEmbeddedWorkerThreadId = -1;
-static const int kInvalidServiceWorkerClientId = 0;
 
 // The HTTP cache is bypassed for Service Worker scripts if the last network
 // fetch occurred over 24 hours ago.
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 517932f..9f5c2366 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -1357,8 +1357,6 @@
       'browser/service_worker/service_worker_database_task_manager.h',
       'browser/service_worker/service_worker_disk_cache.cc',
       'browser/service_worker/service_worker_disk_cache.h',
-      'browser/service_worker/service_worker_disk_cache_migrator.cc',
-      'browser/service_worker/service_worker_disk_cache_migrator.h',
       'browser/service_worker/service_worker_dispatcher_host.cc',
       'browser/service_worker/service_worker_dispatcher_host.h',
       'browser/service_worker/service_worker_fetch_dispatcher.cc',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index cf3427c..077d65ac9 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -586,12 +586,12 @@
       'browser/service_worker/service_worker_context_unittest.cc',
       'browser/service_worker/service_worker_controllee_request_handler_unittest.cc',
       'browser/service_worker/service_worker_database_unittest.cc',
-      'browser/service_worker/service_worker_disk_cache_migrator_unittest.cc',
       'browser/service_worker/service_worker_dispatcher_host_unittest.cc',
       'browser/service_worker/service_worker_handle_unittest.cc',
       'browser/service_worker/service_worker_job_unittest.cc',
       'browser/service_worker/service_worker_process_manager_unittest.cc',
       'browser/service_worker/service_worker_provider_host_unittest.cc',
+      'browser/service_worker/service_worker_read_from_cache_job_unittest.cc',
       'browser/service_worker/service_worker_registration_unittest.cc',
       'browser/service_worker/service_worker_request_handler_unittest.cc',
       'browser/service_worker/service_worker_storage_unittest.cc',
diff --git a/content/public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java b/content/public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java
index 436d463..c3dca05 100644
--- a/content/public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java
@@ -157,8 +157,8 @@
                     params.getReferrer() != null ? params.getReferrer().getPolicy() : 0,
                     params.getUserAgentOverrideOption(), params.getExtraHeadersString(),
                     params.getPostData(), params.getBaseUrl(), params.getVirtualUrlForDataUrl(),
-                    params.getCanLoadLocalResources(), params.getIsRendererInitiated(),
-                    params.getShouldReplaceCurrentEntry());
+                    params.getDataUrlAsString(), params.getCanLoadLocalResources(),
+                    params.getIsRendererInitiated(), params.getShouldReplaceCurrentEntry());
         }
     }
 
@@ -319,8 +319,8 @@
     private native void nativeLoadUrl(long nativeNavigationControllerAndroid, String url,
             int loadUrlType, int transitionType, String referrerUrl, int referrerPolicy,
             int uaOverrideOption, String extraHeaders, byte[] postData, String baseUrlForDataUrl,
-            String virtualUrlForDataUrl, boolean canLoadLocalResources, boolean isRendererInitiated,
-            boolean shouldReplaceCurrentEntry);
+            String virtualUrlForDataUrl, String dataUrlAsString, boolean canLoadLocalResources,
+            boolean isRendererInitiated, boolean shouldReplaceCurrentEntry);
     private native void nativeClearHistory(long nativeNavigationControllerAndroid);
     private native int nativeGetNavigationHistory(long nativeNavigationControllerAndroid,
             Object history);
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/LoadUrlParams.java b/content/public/android/java/src/org/chromium/content_public/browser/LoadUrlParams.java
index f3c0992..7194f8ed 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/LoadUrlParams.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/LoadUrlParams.java
@@ -36,6 +36,7 @@
     byte[] mPostData;
     String mBaseUrlForDataUrl;
     String mVirtualUrlForDataUrl;
+    String mDataUrlAsString;
     boolean mCanLoadLocalResources;
     boolean mIsRendererInitiated;
     boolean mShouldReplaceCurrentEntry;
@@ -66,6 +67,7 @@
         mPostData = null;
         mBaseUrlForDataUrl = null;
         mVirtualUrlForDataUrl = null;
+        mDataUrlAsString = null;
     }
 
     /**
@@ -89,6 +91,15 @@
      */
     public static LoadUrlParams createLoadDataParams(
             String data, String mimeType, boolean isBase64Encoded, String charset) {
+        LoadUrlParams params = new LoadUrlParams(
+                buildDataUri(data, mimeType, isBase64Encoded, charset));
+        params.setLoadType(LoadURLType.DATA);
+        params.setTransitionType(PageTransition.TYPED);
+        return params;
+    }
+
+    private static String buildDataUri(
+            String data, String mimeType, boolean isBase64Encoded, String charset) {
         StringBuilder dataUrl = new StringBuilder("data:");
         dataUrl.append(mimeType);
         if (charset != null && !charset.isEmpty()) {
@@ -99,11 +110,7 @@
         }
         dataUrl.append(",");
         dataUrl.append(data);
-
-        LoadUrlParams params = new LoadUrlParams(dataUrl.toString());
-        params.setLoadType(LoadURLType.DATA);
-        params.setTransitionType(PageTransition.TYPED);
-        return params;
+        return dataUrl.toString();
     }
 
     /**
@@ -144,15 +151,19 @@
     public static LoadUrlParams createLoadDataParamsWithBaseUrl(
             String data, String mimeType, boolean isBase64Encoded,
             String baseUrl, String historyUrl, String charset) {
-        LoadUrlParams params = createLoadDataParams(data, mimeType, isBase64Encoded, charset);
+        LoadUrlParams params;
         // For WebView compatibility, when the base URL has the 'data:'
         // scheme, we treat it as a regular data URL load and skip setting
         // baseUrl and historyUrl.
         // TODO(joth): we should just append baseURL and historyURL here, and move the
         // WebView specific transform up to a wrapper factory function in android_webview/.
         if (baseUrl == null || !baseUrl.toLowerCase(Locale.US).startsWith("data:")) {
+            params = createLoadDataParams("", mimeType, isBase64Encoded, charset);
             params.setBaseUrlForDataUrl(baseUrl != null ? baseUrl : "about:blank");
             params.setVirtualUrlForDataUrl(historyUrl != null ? historyUrl : "about:blank");
+            params.setDataUrlAsString(buildDataUri(data, mimeType, isBase64Encoded, charset));
+        } else {
+            params = createLoadDataParams(data, mimeType, isBase64Encoded, charset);
         }
         return params;
     }
@@ -361,6 +372,24 @@
     }
 
     /**
+     * Get the data for data load. This is then passed to the renderer as
+     * a string, not as a GURL object to circumvent GURL size restriction.
+     * @return The data url.
+     */
+    public String getDataUrlAsString() {
+        return mDataUrlAsString;
+    }
+
+    /**
+     * Set the data for data load. This is then passed to the renderer as
+     * a string, not as a GURL object to circumvent GURL size restriction.
+     * @param url The data url.
+     */
+    public void setDataUrlAsString(String url) {
+        mDataUrlAsString = url;
+    }
+
+    /**
      * Set whether the load should be able to access local resources. This
      * defaults to false.
      */
diff --git a/content/public/browser/navigation_controller.h b/content/public/browser/navigation_controller.h
index 0301ab6..4be76e7d 100644
--- a/content/public/browser/navigation_controller.h
+++ b/content/public/browser/navigation_controller.h
@@ -22,6 +22,7 @@
 namespace base {
 
 class RefCountedMemory;
+class RefCountedString;
 
 }  // namespace base
 
@@ -161,6 +162,14 @@
     // data loads.
     GURL virtual_url_for_data_url;
 
+#if defined(OS_ANDROID)
+    // Used in LOAD_TYPE_DATA loads only. The real data URI is represented
+    // as a string to circumvent the restriction on GURL size. This is only
+    // needed to pass URLs that exceed the IPC limit (kMaxURLChars). Short
+    // data: URLs can be passed in the |url| field.
+    scoped_refptr<base::RefCountedString> data_url_as_string;
+#endif
+
     // Used in LOAD_TYPE_BROWSER_INITIATED_HTTP_POST loads only. Carries the
     // post data of the load. Ownership is transferred to NavigationController
     // after LoadURLWithParams call.
diff --git a/content/public/browser/navigation_entry.h b/content/public/browser/navigation_entry.h
index 850fdb4..af9d5481 100644
--- a/content/public/browser/navigation_entry.h
+++ b/content/public/browser/navigation_entry.h
@@ -55,6 +55,16 @@
   virtual void SetBaseURLForDataURL(const GURL& url) = 0;
   virtual const GURL& GetBaseURLForDataURL() const = 0;
 
+#if defined(OS_ANDROID)
+  // The real data: URL when it is received via WebView.loadDataWithBaseUrl
+  // method. Represented as a string to circumvent the size restriction
+  // of GURLs for compatibility with legacy Android WebView apps.
+  virtual void SetDataURLAsString(
+      scoped_refptr<base::RefCountedString> data_url) = 0;
+  virtual const scoped_refptr<const base::RefCountedString> GetDataURLAsString()
+      const = 0;
+#endif
+
   // The referring URL. Can be empty.
   virtual void SetReferrer(const content::Referrer& referrer) = 0;
   virtual const content::Referrer& GetReferrer() const = 0;
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc
index 70a1f062..306f6eab 100644
--- a/content/public/browser/web_contents_delegate.cc
+++ b/content/public/browser/web_contents_delegate.cc
@@ -51,6 +51,10 @@
   return source;
 }
 
+bool WebContentsDelegate::ShouldTransferNavigation() {
+  return true;
+}
+
 bool WebContentsDelegate::IsPopupOrPanel(const WebContents* source) const {
   return false;
 }
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index f6a04a5..d8f6ac2 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -84,6 +84,11 @@
   virtual WebContents* OpenURLFromTab(WebContents* source,
                                       const OpenURLParams& params);
 
+  // Allows the delegate to optionally cancel navigations that attempt to
+  // transfer to a different process between the start of the network load and
+  // commit.  Defaults to true.
+  virtual bool ShouldTransferNavigation();
+
   // Called to inform the delegate that the WebContents's navigation state
   // changed. The |changed_flags| indicates the parts of the navigation state
   // that have been updated.
diff --git a/content/public/common/common_param_traits.cc b/content/public/common/common_param_traits.cc
index dfe7a7f..ab16aea1 100644
--- a/content/public/common/common_param_traits.cc
+++ b/content/public/common/common_param_traits.cc
@@ -9,14 +9,13 @@
 #include "content/public/common/content_constants.h"
 #include "content/public/common/page_state.h"
 #include "content/public/common/referrer.h"
-#include "content/public/common/url_utils.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/ip_endpoint.h"
 
 namespace IPC {
 
 void ParamTraits<GURL>::Write(Message* m, const GURL& p) {
-  if (p.possibly_invalid_spec().length() > content::GetMaxURLChars()) {
+  if (p.possibly_invalid_spec().length() > content::kMaxURLChars) {
     m->WriteString(std::string());
     return;
   }
@@ -40,7 +39,7 @@
                              base::PickleIterator* iter,
                              GURL* p) {
   std::string s;
-  if (!iter->ReadString(&s) || s.length() > content::GetMaxURLChars()) {
+  if (!iter->ReadString(&s) || s.length() > content::kMaxURLChars) {
     *p = GURL();
     return false;
   }
diff --git a/content/public/common/content_constants.cc b/content/public/common/content_constants.cc
index 5034cb4..9af16a24 100644
--- a/content/public/common/content_constants.cc
+++ b/content/public/common/content_constants.cc
@@ -26,6 +26,7 @@
 const size_t kMaxRendererProcessCount = 82;
 const int kMaxSessionHistoryEntries = 50;
 const size_t kMaxTitleChars = 4 * 1024;
+const size_t kMaxURLChars = 2 * 1024 * 1024;
 const size_t kMaxURLDisplayChars = 32 * 1024;
 
 #if defined(GOOGLE_CHROME_BUILD)
diff --git a/content/public/common/content_constants.h b/content/public/common/content_constants.h
index df9d557..5d05b55 100644
--- a/content/public/common/content_constants.h
+++ b/content/public/common/content_constants.h
@@ -42,6 +42,13 @@
 // to accept in the browser process.
 extern const size_t kMaxTitleChars;
 
+// The maximum number of characters in the URL that we're willing to accept
+// in the browser process. It is set low enough to avoid damage to the browser
+// but high enough that a web site can abuse location.hash for a little storage.
+// We have different values for "max accepted" and "max displayed" because
+// a data: URI may be legitimately massive, but the full URI would kill all
+// known operating systems if you dropped it into a UI control.
+CONTENT_EXPORT extern const size_t kMaxURLChars;
 CONTENT_EXPORT extern const size_t kMaxURLDisplayChars;
 
 extern const char kStatsFilename[];
diff --git a/content/public/common/url_utils.cc b/content/public/common/url_utils.cc
index f977df0..40cd67c2 100644
--- a/content/public/common/url_utils.cc
+++ b/content/public/common/url_utils.cc
@@ -4,19 +4,13 @@
 
 #include "content/public/common/url_utils.h"
 
-#include "base/base_switches.h"
-#include "base/command_line.h"
-#include "base/logging.h"
 #include "build/build_config.h"
 #include "content/common/savable_url_schemes.h"
-#include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
 #include "url/gurl.h"
 
 namespace content {
 
-static size_t g_max_url_size = 2 * 1024 * 1024;
-
 const char* const* GetSavableSchemes() {
   return GetSavableSchemesInternal();
 }
@@ -37,17 +31,4 @@
   return false;
 }
 
-#if defined(OS_ANDROID)
-void SetMaxURLChars(size_t max_chars) {
-  // Check that it is not used by a multiprocesses embedder
-  base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
-  CHECK(cmd->HasSwitch(switches::kSingleProcess));
-  g_max_url_size = max_chars;
-}
-#endif
-
-size_t GetMaxURLChars() {
-  return g_max_url_size;
-}
-
 }  // namespace content
diff --git a/content/public/common/url_utils.h b/content/public/common/url_utils.h
index 1d1f68d2..0b67ab8 100644
--- a/content/public/common/url_utils.h
+++ b/content/public/common/url_utils.h
@@ -5,9 +5,6 @@
 #ifndef CONTENT_PUBLIC_COMMON_URL_UTILS_H_
 #define CONTENT_PUBLIC_COMMON_URL_UTILS_H_
 
-#include <stddef.h>         // For size_t
-
-#include "build/build_config.h"
 #include "content/common/content_export.h"
 
 class GURL;
@@ -25,28 +22,6 @@
 // Check whether we can do the saving page operation for the specified URL.
 CONTENT_EXPORT bool IsSavableURL(const GURL& url);
 
-#if defined(OS_ANDROID)
-// Set a new max size for URL's that we are willing to accept in the browser
-// process.
-// Should not be used except by Android WebView for backwards compatibility.
-// Should be called early in start up before forking child processes.
-//
-// This is for supporting legacy android apps, android webview needs to
-// support loading long data urls. In chrome, the url length is limited to 2M to
-// prevent renderer process DOS-ing the browser process. So only for android
-// webview, increase the limit to 20M, which is a large enough value to satisfy
-// legacy app compatibility requirements.
-CONTENT_EXPORT void SetMaxURLChars(size_t max_chars);
-#endif
-
-// The maximum number of characters in the URL that we're willing to accept
-// in the browser process. It is set low enough to avoid damage to the browser
-// but high enough that a web site can abuse location.hash for a little storage.
-// We have different values for "max accepted" and "max displayed" because
-// a data: URI may be legitimately massive, but the full URI would kill all
-// known operating systems if you dropped it into a UI control.
-CONTENT_EXPORT size_t GetMaxURLChars();
-
 }  // namespace content
 
 #endif  // CONTENT_PUBLIC_COMMON_URL_UTILS_H_
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 9e014065..ea397c1 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -16,6 +16,7 @@
 #include "base/files/file.h"
 #include "base/i18n/char_iterator.h"
 #include "base/logging.h"
+#include "base/memory/shared_memory.h"
 #include "base/memory/weak_ptr.h"
 #include "base/metrics/histogram.h"
 #include "base/process/process.h"
@@ -3472,7 +3473,7 @@
   // in the context menu.
   // TODO(jcivelli): http://crbug.com/45160 This prevents us from saving large
   //                 data encoded images.  We should have a way to save them.
-  if (params.src_url.spec().size() > GetMaxURLChars())
+  if (params.src_url.spec().size() > kMaxURLChars)
     params.src_url = GURL();
   context_menu_node_ = data.node;
 
@@ -5072,7 +5073,7 @@
     if (!common_params.base_url_for_data_url.is_empty() ||
         (browser_side_navigation &&
          common_params.url.SchemeIs(url::kDataScheme))) {
-      LoadDataURL(common_params, frame_, load_type);
+      LoadDataURL(common_params, request_params, frame_, load_type);
     } else {
       // Load the request.
       frame_->toWebLocalFrame()->load(request, load_type,
@@ -5312,11 +5313,28 @@
 }
 
 void RenderFrameImpl::LoadDataURL(const CommonNavigationParams& params,
+                                  const RequestNavigationParams& request_params,
                                   WebFrame* frame,
                                   blink::WebFrameLoadType load_type) {
   // A loadData request with a specified base URL.
+  GURL data_url = params.url;
+#if defined(OS_ANDROID)
+  if (!request_params.data_url_as_string.empty()) {
+#if DCHECK_IS_ON()
+    {
+      std::string mime_type, charset, data;
+      DCHECK(net::DataURL::Parse(data_url, &mime_type, &charset, &data));
+      DCHECK(data.empty());
+    }
+#endif
+    data_url = GURL(request_params.data_url_as_string);
+    if (!data_url.is_valid() || !data_url.SchemeIs(url::kDataScheme)) {
+      data_url = params.url;
+    }
+  }
+#endif
   std::string mime_type, charset, data;
-  if (net::DataURL::Parse(params.url, &mime_type, &charset, &data)) {
+  if (net::DataURL::Parse(data_url, &mime_type, &charset, &data)) {
     const GURL base_url = params.base_url_for_data_url.is_empty() ?
         params.url : params.base_url_for_data_url;
     bool replace = load_type == blink::WebFrameLoadType::ReloadFromOrigin ||
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index f743bbf..ac57eb9 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -874,6 +874,7 @@
 
   // Loads a data url.
   void LoadDataURL(const CommonNavigationParams& params,
+                   const RequestNavigationParams& request_params,
                    blink::WebFrame* frame,
                    blink::WebFrameLoadType load_type);
 
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index e509aa9..ba4a345 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -442,7 +442,7 @@
   ProcessPendingMessages();
   render_thread_->sink().ClearMessages();
 
-  const std::string large_data_url(1024 * 1024 * 10 - 1, 'd');
+  const std::string large_data_url(1024 * 1024 * 20 - 1, 'd');
 
   view()->saveImageFromDataURL(WebString::fromUTF8(large_data_url));
   ProcessPendingMessages();
@@ -458,7 +458,7 @@
   ProcessPendingMessages();
   render_thread_->sink().ClearMessages();
 
-  const std::string exceeded_data_url(1024 * 1024 * 10 + 1, 'd');
+  const std::string exceeded_data_url(1024 * 1024 * 20 + 1, 'd');
 
   view()->saveImageFromDataURL(WebString::fromUTF8(exceeded_data_url));
   ProcessPendingMessages();
@@ -542,6 +542,34 @@
   EXPECT_EQ(0, memcmp(raw_data, element.data.data(), length));
 }
 
+#if defined(OS_ANDROID)
+TEST_F(RenderViewImplTest, OnNavigationLoadDataWithBaseURL) {
+  CommonNavigationParams common_params;
+  common_params.url = GURL("data:text/html,");
+  common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+  common_params.transition = ui::PAGE_TRANSITION_TYPED;
+  common_params.base_url_for_data_url = GURL("about:blank");
+  common_params.history_url_for_data_url = GURL("about:blank");
+  RequestNavigationParams request_params;
+  request_params.data_url_as_string =
+      "data:text/html,<html><head><title>Data page</title></head></html>";
+
+  frame()->Navigate(common_params, StartNavigationParams(),
+                    request_params);
+  const IPC::Message* frame_title_msg = nullptr;
+  do {
+    ProcessPendingMessages();
+    frame_title_msg = render_thread_->sink().GetUniqueMessageMatching(
+        FrameHostMsg_UpdateTitle::ID);
+  } while (!frame_title_msg);
+
+  // Check post data sent to browser matches.
+  FrameHostMsg_UpdateTitle::Param title_params;
+  EXPECT_TRUE(FrameHostMsg_UpdateTitle::Read(frame_title_msg, &title_params));
+  EXPECT_EQ(base::ASCIIToUTF16("Data page"), base::get<0>(title_params));
+}
+#endif
+
 TEST_F(RenderViewImplTest, DecideNavigationPolicy) {
   WebUITestWebUIControllerFactory factory;
   WebUIControllerFactory::RegisterFactory(&factory);
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index a570420..72317b9d 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -64,7 +64,6 @@
 #include "content/public/common/ssl_status.h"
 #include "content/public/common/three_d_api_types.h"
 #include "content/public/common/url_constants.h"
-#include "content/public/common/url_utils.h"
 #include "content/public/common/web_preferences.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/public/renderer/document_state.h"
@@ -1881,9 +1880,9 @@
     pending_target_url_ = latest_url;
     target_url_status_ = TARGET_PENDING;
   } else {
-    // URLs larger than |MaxURLChars()| cannot be sent through IPC -
+    // URLs larger than |kMaxURLChars| cannot be sent through IPC -
     // see |ParamTraits<GURL>|.
-    if (latest_url.possibly_invalid_spec().size() > GetMaxURLChars())
+    if (latest_url.possibly_invalid_spec().size() > kMaxURLChars)
       latest_url = GURL();
     Send(new ViewHostMsg_UpdateTargetURL(routing_id_, latest_url));
     target_url_ = latest_url;
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h
index 14bec2d..d313e473 100644
--- a/content/renderer/service_worker/service_worker_context_client.h
+++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -235,11 +235,6 @@
   // Not owned; this object is destroyed when proxy_ becomes invalid.
   blink::WebServiceWorkerContextProxy* proxy_;
 
-  // Used for incoming messages from the browser for which an outgoing response
-  // back to the browser is expected, the id must be sent back with the
-  // response.
-  int current_request_id_;
-
   // Initialized on the worker thread in workerContextStarted and
   // destructed on the worker thread in willDestroyWorkerContext.
   scoped_ptr<WorkerContextData> context_;
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index db4e015..806bf6e5 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -195,6 +195,8 @@
         ['mac'], bug=483282)
     self.Skip('deqp/functional/gles3/shaderswitch.html',
         ['mavericks'], bug=483282)
+    self.Fail('deqp/functional/gles3/rbostatequery.html',
+        ['mac'], bug=569808)
     self.Fail('conformance2/attribs/gl-vertex-attrib-i-render.html',
         ['mac'], bug=483282)
     self.Fail('conformance2/buffers/buffer-overflow-test.html',
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc
index 68869aca..a1311740 100644
--- a/content/test/layouttest_support.cc
+++ b/content/test/layouttest_support.cc
@@ -222,7 +222,7 @@
 
   std::vector<char> color_profile;
 
-  struct TestColorProfile {
+  struct TestColorProfile { // A whacked (aka color spin) profile.
     char* data() {
       static unsigned char color_profile_data[] = {
         0x00,0x00,0x01,0xea,0x54,0x45,0x53,0x54,0x00,0x00,0x00,0x00,
@@ -340,7 +340,7 @@
 
   if (name == "sRGB") {
     color_profile.assign(name.data(), name.data() + name.size());
-  } else if (name == "test") {
+  } else if (name == "test" || name == "whacked") {
     TestColorProfile test;
     color_profile.assign(test.data(), test.data() + test.size());
   } else if (name == "adobeRGB") {
diff --git a/device/hid/hid_service_linux.cc b/device/hid/hid_service_linux.cc
index 36abff2..94abfcc 100644
--- a/device/hid/hid_service_linux.cc
+++ b/device/hid/hid_service_linux.cc
@@ -23,7 +23,6 @@
 #include "device/hid/hid_connection_linux.h"
 #include "device/hid/hid_device_info_linux.h"
 #include "device/udev_linux/scoped_udev.h"
-#include "net/base/net_util.h"
 
 #if defined(OS_CHROMEOS)
 #include "base/sys_info.h"
@@ -318,8 +317,7 @@
   base::ThreadRestrictions::AssertIOAllowed();
   scoped_refptr<base::SingleThreadTaskRunner> task_runner = params->task_runner;
 
-  int result = net::SetNonBlocking(params->device_file.GetPlatformFile());
-  if (result == -1) {
+  if (!base::SetNonBlocking(params->device_file.GetPlatformFile())) {
     HID_PLOG(ERROR) << "Failed to set the non-blocking flag on the device fd";
     task_runner->PostTask(FROM_HERE, base::Bind(params->callback, nullptr));
     return;
diff --git a/extensions/browser/api/bluetooth/bluetooth_event_router.cc b/extensions/browser/api/bluetooth/bluetooth_event_router.cc
index 5de177d..b60b827 100644
--- a/extensions/browser/api/bluetooth/bluetooth_event_router.cc
+++ b/extensions/browser/api/bluetooth/bluetooth_event_router.cc
@@ -32,6 +32,18 @@
 
 namespace extensions {
 
+namespace {
+
+void IgnoreAdapterResult(scoped_refptr<device::BluetoothAdapter> adapter) {}
+
+void IgnoreAdapterResultAndThen(
+    const base::Closure& callback,
+    scoped_refptr<device::BluetoothAdapter> adapter) {
+  callback.Run();
+}
+
+}  // namespace
+
 namespace bluetooth = api::bluetooth;
 namespace bt_private = api::bluetooth_private;
 
@@ -73,7 +85,9 @@
     return;
   }
 
-  device::BluetoothAdapterFactory::GetAdapter(callback);
+  device::BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothEventRouter::OnAdapterInitialized,
+                 weak_ptr_factory_.GetWeakPtr(), callback));
 }
 
 void BluetoothEventRouter::StartDiscoverySession(
@@ -85,8 +99,7 @@
     // If |adapter_| isn't set yet, call GetAdapter() which will synchronously
     // invoke the callback (StartDiscoverySessionImpl).
     GetAdapter(base::Bind(
-        &BluetoothEventRouter::OnAdapterInitialized,
-        weak_ptr_factory_.GetWeakPtr(),
+        &IgnoreAdapterResultAndThen,
         base::Bind(&BluetoothEventRouter::StartDiscoverySessionImpl,
                    weak_ptr_factory_.GetWeakPtr(), make_scoped_refptr(adapter),
                    extension_id, callback, error_callback)));
@@ -193,14 +206,14 @@
 }
 
 void BluetoothEventRouter::OnAdapterInitialized(
-    const base::Closure& callback,
+    const device::BluetoothAdapterFactory::AdapterCallback& callback,
     scoped_refptr<device::BluetoothAdapter> adapter) {
   if (!adapter_.get()) {
     adapter_ = adapter;
     adapter_->AddObserver(this);
   }
 
-  callback.Run();
+  callback.Run(adapter);
 }
 
 void BluetoothEventRouter::MaybeReleaseAdapter() {
@@ -215,8 +228,7 @@
 void BluetoothEventRouter::AddPairingDelegate(const std::string& extension_id) {
   if (!adapter_.get() && IsBluetoothSupported()) {
     GetAdapter(
-        base::Bind(&BluetoothEventRouter::OnAdapterInitialized,
-                   weak_ptr_factory_.GetWeakPtr(),
+        base::Bind(&IgnoreAdapterResultAndThen,
                    base::Bind(&BluetoothEventRouter::AddPairingDelegateImpl,
                               weak_ptr_factory_.GetWeakPtr(), extension_id)));
     return;
@@ -349,11 +361,8 @@
 void BluetoothEventRouter::OnListenerAdded() {
   num_event_listeners_++;
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  if (!adapter_.get()) {
-    GetAdapter(base::Bind(&BluetoothEventRouter::OnAdapterInitialized,
-                          weak_ptr_factory_.GetWeakPtr(),
-                          base::Bind(&base::DoNothing)));
-  }
+  if (!adapter_.get())
+    GetAdapter(base::Bind(&IgnoreAdapterResult));
 }
 
 void BluetoothEventRouter::OnListenerRemoved() {
diff --git a/extensions/browser/api/bluetooth/bluetooth_event_router.h b/extensions/browser/api/bluetooth/bluetooth_event_router.h
index 7863a24..2535fa9a 100644
--- a/extensions/browser/api/bluetooth/bluetooth_event_router.h
+++ b/extensions/browser/api/bluetooth/bluetooth_event_router.h
@@ -137,8 +137,9 @@
                                  const base::Closure& error_callback);
   void AddPairingDelegateImpl(const std::string& extension_id);
 
-  void OnAdapterInitialized(const base::Closure& callback,
-                            scoped_refptr<device::BluetoothAdapter> adapter);
+  void OnAdapterInitialized(
+      const device::BluetoothAdapterFactory::AdapterCallback& callback,
+      scoped_refptr<device::BluetoothAdapter> adapter);
   void MaybeReleaseAdapter();
   void DispatchAdapterStateEvent();
   void DispatchDeviceEvent(events::HistogramValue histogram_value,
diff --git a/extensions/renderer/i18n_custom_bindings.cc b/extensions/renderer/i18n_custom_bindings.cc
index 6a743cc..386b22ee 100644
--- a/extensions/renderer/i18n_custom_bindings.cc
+++ b/extensions/renderer/i18n_custom_bindings.cc
@@ -4,6 +4,8 @@
 
 #include "extensions/renderer/i18n_custom_bindings.h"
 
+#include <vector>
+
 #include "base/bind.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_thread.h"
@@ -55,7 +57,7 @@
 
   // Array of detectedLanguage of size 1-3. The null is returned if
   // there were no languages detected
-  ScopedVector<DetectedLanguage> languages;
+  std::vector<scoped_ptr<DetectedLanguage>> languages;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(LanguageDetectionResult);
@@ -98,9 +100,10 @@
   return handle_scope.Escape(result);
 }
 
-void InitDetectedLanguages(CLD2::Language* languages,
-                           int* percents,
-                           ScopedVector<DetectedLanguage>* detected_languages) {
+void InitDetectedLanguages(
+    CLD2::Language* languages,
+    int* percents,
+    std::vector<scoped_ptr<DetectedLanguage>>* detected_languages) {
   for (int i = 0; i < kCldNumLangs; i++) {
     std::string language_code;
     // Convert LanguageCode 'zh' to 'zh-CN' and 'zh-Hant' to 'zh-TW' for
@@ -115,7 +118,7 @@
           CLD2::LanguageCode(static_cast<CLD2::Language>(languages[i]));
     }
     detected_languages->push_back(
-        new DetectedLanguage(language_code, percents[i]));
+        make_scoped_ptr(new DetectedLanguage(language_code, percents[i])));
   }
 }
 
diff --git a/extensions/renderer/script_injection_manager.cc b/extensions/renderer/script_injection_manager.cc
index 5ab712f..90622c7 100644
--- a/extensions/renderer/script_injection_manager.cc
+++ b/extensions/renderer/script_injection_manager.cc
@@ -4,8 +4,11 @@
 
 #include "extensions/renderer/script_injection_manager.h"
 
+#include <utility>
+
 #include "base/auto_reset.h"
 #include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/values.h"
 #include "content/public/renderer/render_frame.h"
@@ -223,15 +226,15 @@
 }
 
 ScriptInjectionManager::~ScriptInjectionManager() {
-  for (ScriptInjection* injection : pending_injections_)
+  for (const auto& injection : pending_injections_)
     injection->invalidate_render_frame();
-  for (ScriptInjection* injection : running_injections_)
+  for (const auto& injection : running_injections_)
     injection->invalidate_render_frame();
 }
 
 void ScriptInjectionManager::OnRenderFrameCreated(
     content::RenderFrame* render_frame) {
-  rfo_helpers_.push_back(new RFOHelper(render_frame, this));
+  rfo_helpers_.push_back(make_scoped_ptr(new RFOHelper(render_frame, this)));
 }
 
 void ScriptInjectionManager::OnExtensionUnloaded(
@@ -249,10 +252,11 @@
 
 void ScriptInjectionManager::OnInjectionFinished(
     ScriptInjection* injection) {
-  ScopedVector<ScriptInjection>::iterator iter =
-      std::find(running_injections_.begin(),
-                running_injections_.end(),
-                injection);
+  auto iter =
+      std::find_if(running_injections_.begin(), running_injections_.end(),
+                   [injection](const scoped_ptr<ScriptInjection>& mode) {
+                     return injection == mode.get();
+                   });
   if (iter != running_injections_.end())
     running_injections_.erase(iter);
 }
@@ -260,8 +264,7 @@
 void ScriptInjectionManager::OnUserScriptsUpdated(
     const std::set<HostID>& changed_hosts,
     const std::vector<UserScript*>& scripts) {
-  for (ScopedVector<ScriptInjection>::iterator iter =
-           pending_injections_.begin();
+  for (auto iter = pending_injections_.begin();
        iter != pending_injections_.end();) {
     if (changed_hosts.count((*iter)->host_id()) > 0)
       iter = pending_injections_.erase(iter);
@@ -271,10 +274,8 @@
 }
 
 void ScriptInjectionManager::RemoveObserver(RFOHelper* helper) {
-  for (ScopedVector<RFOHelper>::iterator iter = rfo_helpers_.begin();
-       iter != rfo_helpers_.end();
-       ++iter) {
-    if (*iter == helper) {
+  for (auto iter = rfo_helpers_.begin(); iter != rfo_helpers_.end(); ++iter) {
+    if (iter->get() == helper) {
       rfo_helpers_.erase(iter);
       break;
     }
@@ -286,8 +287,7 @@
   // note it.
   active_injection_frames_.erase(frame);
 
-  for (ScopedVector<ScriptInjection>::iterator iter =
-           pending_injections_.begin();
+  for (auto iter = pending_injections_.begin();
        iter != pending_injections_.end();) {
     if ((*iter)->render_frame() == frame)
       iter = pending_injections_.erase(iter);
@@ -337,13 +337,12 @@
     content::RenderFrame* frame,
     UserScript::RunLocation run_location) {
   // Find any injections that want to run on the given frame.
-  ScopedVector<ScriptInjection> frame_injections;
-  for (ScopedVector<ScriptInjection>::iterator iter =
-           pending_injections_.begin();
+  ScriptInjectionVector frame_injections;
+  for (auto iter = pending_injections_.begin();
        iter != pending_injections_.end();) {
     if ((*iter)->render_frame() == frame) {
-      frame_injections.push_back(*iter);
-      iter = pending_injections_.weak_erase(iter);
+      frame_injections.push_back(std::move(*iter));
+      iter = pending_injections_.erase(iter);
     } else {
       ++iter;
     }
@@ -351,22 +350,21 @@
 
   // Add any injections for user scripts.
   int tab_id = ExtensionFrameHelper::Get(frame)->tab_id();
-  user_script_set_manager_->GetAllInjections(
-      &frame_injections, frame, tab_id, run_location);
+  user_script_set_manager_->GetAllInjections(&frame_injections, frame, tab_id,
+                                             run_location);
 
   // Note that we are running in |frame|.
   active_injection_frames_.insert(frame);
 
   ScriptsRunInfo scripts_run_info(frame, run_location);
-  for (ScopedVector<ScriptInjection>::iterator iter = frame_injections.begin();
-       iter != frame_injections.end();) {
+  for (auto iter = frame_injections.begin(); iter != frame_injections.end();) {
     // It's possible for the frame to be invalidated in the course of injection
     // (if a script removes its own frame, for example). If this happens, abort.
     if (!active_injection_frames_.count(frame))
       break;
-    scoped_ptr<ScriptInjection> injection(*iter);
-    iter = frame_injections.weak_erase(iter);
-    TryToInject(injection.Pass(), run_location, &scripts_run_info);
+    scoped_ptr<ScriptInjection> injection(std::move(*iter));
+    iter = frame_injections.erase(iter);
+    TryToInject(std::move(injection), run_location, &scripts_run_info);
   }
 
   // We are done running in the frame.
@@ -390,10 +388,10 @@
       base::Bind(&ScriptInjectionManager::OnInjectionFinished,
                  base::Unretained(this)))) {
     case ScriptInjection::INJECTION_WAITING:
-      pending_injections_.push_back(injection.Pass());
+      pending_injections_.push_back(std::move(injection));
       break;
     case ScriptInjection::INJECTION_BLOCKED:
-      running_injections_.push_back(injection.Pass());
+      running_injections_.push_back(std::move(injection));
       break;
     case ScriptInjection::INJECTION_FINISHED:
       break;
@@ -453,8 +451,7 @@
 }
 
 void ScriptInjectionManager::HandlePermitScriptInjection(int64 request_id) {
-  ScopedVector<ScriptInjection>::iterator iter =
-      pending_injections_.begin();
+  auto iter = pending_injections_.begin();
   for (; iter != pending_injections_.end(); ++iter) {
     if ((*iter)->request_id() == request_id) {
       DCHECK((*iter)->host_id().type() == HostID::EXTENSIONS);
@@ -469,15 +466,15 @@
   // RFOHelper's DidStartProvisionalLoad callback would have caused it to be
   // cleared out).
 
-  scoped_ptr<ScriptInjection> injection(*iter);
-  pending_injections_.weak_erase(iter);
+  scoped_ptr<ScriptInjection> injection(std::move(*iter));
+  pending_injections_.erase(iter);
 
   ScriptsRunInfo scripts_run_info(injection->render_frame(),
                                   UserScript::RUN_DEFERRED);
   ScriptInjection::InjectionResult res = injection->OnPermissionGranted(
       &scripts_run_info);
   if (res == ScriptInjection::INJECTION_BLOCKED)
-    running_injections_.push_back(injection.Pass());
+    running_injections_.push_back(std::move(injection));
   scripts_run_info.LogRun();
 }
 
diff --git a/extensions/renderer/script_injection_manager.h b/extensions/renderer/script_injection_manager.h
index 7d79f1c..c85b4fe 100644
--- a/extensions/renderer/script_injection_manager.h
+++ b/extensions/renderer/script_injection_manager.h
@@ -8,9 +8,9 @@
 #include <map>
 #include <set>
 #include <string>
+#include <vector>
 
 #include "base/callback.h"
-#include "base/memory/scoped_vector.h"
 #include "base/scoped_observer.h"
 #include "extensions/common/user_script.h"
 #include "extensions/renderer/script_injection.h"
@@ -50,6 +50,8 @@
   using FrameStatusMap =
       std::map<content::RenderFrame*, UserScript::RunLocation>;
 
+  using ScriptInjectionVector = std::vector<scoped_ptr<ScriptInjection>>;
+
   // Notifies that an injection has been finished.
   void OnInjectionFinished(ScriptInjection* injection);
 
@@ -98,17 +100,17 @@
   std::set<content::RenderFrame*> active_injection_frames_;
 
   // The collection of RFOHelpers.
-  ScopedVector<RFOHelper> rfo_helpers_;
+  std::vector<scoped_ptr<RFOHelper>> rfo_helpers_;
 
   // The set of UserScripts associated with extensions. Owned by the Dispatcher.
   UserScriptSetManager* user_script_set_manager_;
 
   // Pending injections which are waiting for either the proper run location or
   // user consent.
-  ScopedVector<ScriptInjection> pending_injections_;
+  ScriptInjectionVector pending_injections_;
 
   // Running injections which are waiting for async callbacks from blink.
-  ScopedVector<ScriptInjection> running_injections_;
+  ScriptInjectionVector running_injections_;
 
   ScopedObserver<UserScriptSetManager, UserScriptSetManager::Observer>
       user_script_set_manager_observer_;
diff --git a/extensions/renderer/user_script_set.cc b/extensions/renderer/user_script_set.cc
index 23cb833f..5667f2d 100644
--- a/extensions/renderer/user_script_set.cc
+++ b/extensions/renderer/user_script_set.cc
@@ -63,7 +63,7 @@
 }
 
 void UserScriptSet::GetInjections(
-    ScopedVector<ScriptInjection>* injections,
+    std::vector<scoped_ptr<ScriptInjection>>* injections,
     content::RenderFrame* render_frame,
     int tab_id,
     UserScript::RunLocation run_location) {
@@ -77,7 +77,7 @@
         document_url,
         false /* is_declarative */);
     if (injection.get())
-      injections->push_back(injection.Pass());
+      injections->push_back(std::move(injection));
   }
 }
 
diff --git a/extensions/renderer/user_script_set.h b/extensions/renderer/user_script_set.h
index 231722e..42d3190f 100644
--- a/extensions/renderer/user_script_set.h
+++ b/extensions/renderer/user_script_set.h
@@ -7,6 +7,7 @@
 
 #include <set>
 #include <string>
+#include <vector>
 
 #include "base/basictypes.h"
 #include "base/macros.h"
@@ -52,7 +53,7 @@
   // |tab_id|, at the given |run_location|, to |injections|.
   // |extensions| is passed in to verify the corresponding extension is still
   // valid.
-  void GetInjections(ScopedVector<ScriptInjection>* injections,
+  void GetInjections(std::vector<scoped_ptr<ScriptInjection>>* injections,
                      content::RenderFrame* render_frame,
                      int tab_id,
                      UserScript::RunLocation run_location);
diff --git a/extensions/renderer/user_script_set_manager.cc b/extensions/renderer/user_script_set_manager.cc
index c131577..0404e055 100644
--- a/extensions/renderer/user_script_set_manager.cc
+++ b/extensions/renderer/user_script_set_manager.cc
@@ -61,7 +61,7 @@
 }
 
 void UserScriptSetManager::GetAllInjections(
-    ScopedVector<ScriptInjection>* injections,
+    std::vector<scoped_ptr<ScriptInjection>>* injections,
     content::RenderFrame* render_frame,
     int tab_id,
     UserScript::RunLocation run_location) {
diff --git a/extensions/renderer/user_script_set_manager.h b/extensions/renderer/user_script_set_manager.h
index 3be8fff..bf878fe 100644
--- a/extensions/renderer/user_script_set_manager.h
+++ b/extensions/renderer/user_script_set_manager.h
@@ -8,6 +8,7 @@
 #include <map>
 #include <set>
 #include <string>
+#include <vector>
 
 #include "base/memory/linked_ptr.h"
 #include "base/memory/shared_memory.h"
@@ -67,7 +68,7 @@
 
   // Append all injections from |static_scripts| and each of
   // |programmatic_scripts_| to |injections|.
-  void GetAllInjections(ScopedVector<ScriptInjection>* injections,
+  void GetAllInjections(std::vector<scoped_ptr<ScriptInjection>>* injections,
                         content::RenderFrame* render_frame,
                         int tab_id,
                         UserScript::RunLocation run_location);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index d1d4d2a..58b9a00 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -8938,6 +8938,12 @@
         GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
     return error::kNoError;
   }
+  if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV)
+      && size != 4) {
+    LOCAL_SET_GL_ERROR(
+        GL_INVALID_OPERATION, "glVertexAttribPointer", "size != 4");
+    return error::kNoError;
+  }
   if (indx >= group_->max_vertex_attribs()) {
     LOCAL_SET_GL_ERROR(
         GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
diff --git a/media/media.gyp b/media/media.gyp
index c8970d1..fb7a1595 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -13,7 +13,7 @@
     'linux_link_pulseaudio%': 0,
     'conditions': [
       # Enable ALSA and Pulse for runtime selection.
-      ['(OS=="linux" or OS=="freebsd" or OS=="solaris") and (embedded!=1 or (chromecast==1 and target_arch!="arm"))', {
+      ['(OS=="linux" or OS=="freebsd" or OS=="solaris") and (chromecast==0 or is_cast_desktop_build==1)', {
         # ALSA is always needed for Web MIDI even if the cras is enabled.
         'use_alsa%': 1,
         'conditions': [
diff --git a/media/media_options.gni b/media/media_options.gni
index 07b7fde..96582e5a 100644
--- a/media/media_options.gni
+++ b/media/media_options.gni
@@ -38,7 +38,7 @@
   # Alsa should be used on non-Android, non-Mac POSIX systems, and Chromecast
   # builds for desktop Linux.
   if (is_posix && !is_headless && !is_android && !is_mac &&
-      (!is_chromecast || target_cpu != "arm")) {
+      (!is_chromecast || is_cast_desktop_build)) {
     use_alsa = true
     if (!use_cras) {
       use_pulseaudio = true
diff --git a/media/midi/midi.gyp b/media/midi/midi.gyp
index 723a9a3..467c6e31 100644
--- a/media/midi/midi.gyp
+++ b/media/midi/midi.gyp
@@ -6,7 +6,7 @@
   'variables': {
     'chromium_code': 1,
     'conditions': [
-      ['(OS=="linux" or OS=="freebsd" or OS=="solaris") and (embedded!=1 or (chromecast==1 and target_arch!="arm"))', {
+      ['(OS=="linux" or OS=="freebsd" or OS=="solaris") and (chromecast==0 or is_cast_desktop_build==1)', {
         'use_alsa%': 1,
       }, {
         'use_alsa%': 0,
diff --git a/mojo/common/BUILD.gn b/mojo/common/BUILD.gn
index f2da1fc..0278cf3 100644
--- a/mojo/common/BUILD.gn
+++ b/mojo/common/BUILD.gn
@@ -119,4 +119,10 @@
   sources = [
     "../message_pump/handle_watcher_perftest.cc",
   ]
+
+  if (is_linux && !is_component_build) {
+    # This test dynamically loads libmojo_test_support even in non-component
+    # builds.
+    configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
+  }
 }
diff --git a/mojo/mojo_nacl.gypi b/mojo/mojo_nacl.gypi
deleted file mode 100644
index 01cfc21..0000000
--- a/mojo/mojo_nacl.gypi
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'variables': {
-     'monacl_codegen_dir': '<(SHARED_INTERMEDIATE_DIR)/<!(python <(DEPTH)/build/inverse_depth.py <(DEPTH))/nacl',
-   },
-}
diff --git a/mojo/public/c/system/tests/core_unittest.cc b/mojo/public/c/system/tests/core_unittest.cc
index de59a70f..0a878b20 100644
--- a/mojo/public/c/system/tests/core_unittest.cc
+++ b/mojo/public/c/system/tests/core_unittest.cc
@@ -167,16 +167,7 @@
   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1));
 }
 
-// TODO(ncbray): enable these tests once NaCl supports the corresponding APIs.
-#ifdef __native_client__
-#define MAYBE_BasicDataPipe DISABLED_BasicDataPipe
-#define MAYBE_BasicSharedBuffer DISABLED_BasicSharedBuffer
-#else
-#define MAYBE_BasicDataPipe BasicDataPipe
-#define MAYBE_BasicSharedBuffer BasicSharedBuffer
-#endif
-
-TEST(CoreTest, MAYBE_BasicDataPipe) {
+TEST(CoreTest, BasicDataPipe) {
   MojoHandle hp, hc;
   MojoHandleSignals sig;
   char buffer[20] = {0};
@@ -287,7 +278,7 @@
   // the producer never-writable?
 }
 
-TEST(CoreTest, MAYBE_BasicSharedBuffer) {
+TEST(CoreTest, BasicSharedBuffer) {
   MojoHandle h0, h1;
   void* pointer;
 
diff --git a/mojo/public/interfaces/bindings/tests/BUILD.gn b/mojo/public/interfaces/bindings/tests/BUILD.gn
index d5baa9d..802bd58 100644
--- a/mojo/public/interfaces/bindings/tests/BUILD.gn
+++ b/mojo/public/interfaces/bindings/tests/BUILD.gn
@@ -20,6 +20,7 @@
     "scoping.mojom",
     "serialization_test_structs.mojom",
     "test_constants.mojom",
+    "test_native_types.mojom",
     "test_structs.mojom",
     "validation_test_interfaces.mojom",
   ]
diff --git a/mojo/public/interfaces/bindings/tests/test_native_types.mojom b/mojo/public/interfaces/bindings/tests/test_native_types.mojom
new file mode 100644
index 0000000..3537703
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/test_native_types.mojom
@@ -0,0 +1,11 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module mojo.test;
+
+// Used to verify that structs can be declared with no body in mojom.
+
+[native=True]
+struct PickledStruct;
+
diff --git a/mojo/public/mojo_application.gni b/mojo/public/mojo_application.gni
index 3f068a39..c310eb6 100644
--- a/mojo/public/mojo_application.gni
+++ b/mojo/public/mojo_application.gni
@@ -39,245 +39,126 @@
     mojo_deps += [ ":$copy_step_name" ]
   }
 
-  if (!is_nacl) {
-    output = base_target_name + ".mojo"
-    library_target_name = base_target_name + "_library"
-    library_name = "${shlib_prefix}${library_target_name}${shlib_extension}"
+  output = base_target_name + ".mojo"
+  library_target_name = base_target_name + "_library"
+  library_name = "${shlib_prefix}${library_target_name}${shlib_extension}"
 
-    shared_library(library_target_name) {
-      if (defined(invoker.cflags)) {
-        cflags = invoker.cflags
-      }
-      if (defined(invoker.cflags_c)) {
-        cflags_c = invoker.cflags_c
-      }
-      if (defined(invoker.cflags_cc)) {
-        cflags_cc = invoker.cflags_cc
-      }
-      if (defined(invoker.cflags_objc)) {
-        cflags_objc = invoker.cflags_objc
-      }
-      if (defined(invoker.cflags_objcc)) {
-        cflags_objcc = invoker.cflags_objcc
-      }
-      if (defined(invoker.defines)) {
-        defines = invoker.defines
-      }
-      if (defined(invoker.include_dirs)) {
-        include_dirs = invoker.include_dirs
-      }
-      if (defined(invoker.ldflags)) {
-        ldflags = invoker.ldflags
-      }
-      if (defined(invoker.lib_dirs)) {
-        lib_dirs = invoker.lib_dirs
-      }
-      if (defined(invoker.libs)) {
-        libs = invoker.libs
-      }
-
-      data_deps = []
-      if (!defined(invoker.avoid_runner_cycle) || !invoker.avoid_runner_cycle) {
-        # Give the user an out; as some mojo services are depended on by the
-        # runner.
-        data_deps += [ "//mojo/runner:mojo_runner" ]
-      }
-      if (defined(invoker.data_deps)) {
-        data_deps += invoker.data_deps
-      }
-
-      deps = [
-        "//mojo/platform_handle:for_shared_library",
-        "//mojo/public/c/system:for_shared_library",
-        "//mojo/public/gles2:for_shared_library",
-      ]
-
-      deps += mojo_deps
-      if (defined(invoker.public_deps)) {
-        public_deps = invoker.public_deps
-      }
-      if (defined(invoker.all_dependent_configs)) {
-        all_dependent_configs = invoker.all_dependent_configs
-      }
-      if (defined(invoker.public_configs)) {
-        public_configs = invoker.public_configs
-      }
-      if (defined(invoker.check_includes)) {
-        check_includes = invoker.check_includes
-      }
-      if (defined(invoker.configs)) {
-        configs += invoker.configs
-      }
-      if (defined(invoker.data)) {
-        data = invoker.data
-      }
-      if (defined(invoker.inputs)) {
-        inputs = invoker.inputs
-      }
-      if (defined(invoker.public)) {
-        public = invoker.public
-      }
-      if (defined(invoker.sources)) {
-        sources = invoker.sources
-      }
-      if (defined(invoker.testonly)) {
-        testonly = invoker.testonly
-      }
+  shared_library(library_target_name) {
+    if (defined(invoker.cflags)) {
+      cflags = invoker.cflags
+    }
+    if (defined(invoker.cflags_c)) {
+      cflags_c = invoker.cflags_c
+    }
+    if (defined(invoker.cflags_cc)) {
+      cflags_cc = invoker.cflags_cc
+    }
+    if (defined(invoker.cflags_objc)) {
+      cflags_objc = invoker.cflags_objc
+    }
+    if (defined(invoker.cflags_objcc)) {
+      cflags_objcc = invoker.cflags_objcc
+    }
+    if (defined(invoker.defines)) {
+      defines = invoker.defines
+    }
+    if (defined(invoker.include_dirs)) {
+      include_dirs = invoker.include_dirs
+    }
+    if (defined(invoker.ldflags)) {
+      ldflags = invoker.ldflags
+    }
+    if (defined(invoker.lib_dirs)) {
+      lib_dirs = invoker.lib_dirs
+    }
+    if (defined(invoker.libs)) {
+      libs = invoker.libs
     }
 
-    copy(final_target_name) {
-      forward_variables_from(invoker,
-                             [
-                               "testonly",
-                               "visibility",
-                             ])
+    data_deps = []
+    if (!defined(invoker.avoid_runner_cycle) || !invoker.avoid_runner_cycle) {
+      # Give the user an out; as some mojo services are depended on by the
+      # runner.
+      data_deps += [ "//mojo/runner:mojo_runner" ]
+    }
+    if (defined(invoker.data_deps)) {
+      data_deps += invoker.data_deps
+    }
+
+    deps = [
+      "//mojo/platform_handle:for_shared_library",
+      "//mojo/public/c/system:for_shared_library",
+      "//mojo/public/gles2:for_shared_library",
+    ]
+
+    deps += mojo_deps
+    if (defined(invoker.public_deps)) {
+      public_deps = invoker.public_deps
+    }
+    if (defined(invoker.all_dependent_configs)) {
+      all_dependent_configs = invoker.all_dependent_configs
+    }
+    if (defined(invoker.public_configs)) {
+      public_configs = invoker.public_configs
+    }
+    if (defined(invoker.check_includes)) {
+      check_includes = invoker.check_includes
+    }
+    if (defined(invoker.configs)) {
+      configs += invoker.configs
+    }
+    if (defined(invoker.data)) {
+      data = invoker.data
+    }
+    if (defined(invoker.inputs)) {
+      inputs = invoker.inputs
+    }
+    if (defined(invoker.public)) {
+      public = invoker.public
+    }
+    if (defined(invoker.sources)) {
+      sources = invoker.sources
+    }
+    if (defined(invoker.testonly)) {
+      testonly = invoker.testonly
+    }
+  }
+
+  copy(final_target_name) {
+    forward_variables_from(invoker,
+                            [
+                              "testonly",
+                              "visibility",
+                            ])
+    deps = [
+      ":${library_target_name}",
+    ]
+
+    sources = [
+      "${root_shlib_dir}/${library_name}",
+    ]
+    outputs = [
+      "${root_out_dir}/${base_target_name}/${output}",
+    ]
+  }
+
+  if (is_android) {
+    android_assets("${final_target_name}_assets") {
+      forward_variables_from(invoker, [ "testonly" ])
       deps = [
         ":${library_target_name}",
       ]
-
-      sources = [
-        "${root_shlib_dir}/${library_name}",
-      ]
-      outputs = [
-        "${root_out_dir}/${base_target_name}/${output}",
-      ]
-    }
-
-    if (is_android) {
-      android_assets("${final_target_name}_assets") {
-        forward_variables_from(invoker, [ "testonly" ])
-        deps = [
-          ":${library_target_name}",
-        ]
-        if (defined(invoker.deps)) {
-          deps += invoker.deps
-        }
-        renaming_sources = [ "${root_shlib_dir}/${library_name}" ]
-        renaming_destinations = [ "${base_target_name}/${output}" ]
-        if (defined(invoker.resources)) {
-          renaming_sources += invoker.resources
-          renaming_destinations += process_file_template(
-                  invoker.resources,
-                  [ "$base_target_name/resources/{{source_file_part}}" ])
-        }
+      if (defined(invoker.deps)) {
+        deps += invoker.deps
       }
-    }
-  } else {
-    nexe_target_name = base_target_name + "_nexe"
-    nexe_name = base_target_name + ".nexe"
-
-    output = "${base_target_name}_${target_cpu}.nexe.mojo"
-
-    executable(nexe_target_name) {
-      output_name = base_target_name
-
-      if (defined(invoker.cflags)) {
-        cflags = invoker.cflags
+      renaming_sources = [ "${root_shlib_dir}/${library_name}" ]
+      renaming_destinations = [ "${base_target_name}/${output}" ]
+      if (defined(invoker.resources)) {
+        renaming_sources += invoker.resources
+        renaming_destinations += process_file_template(
+                invoker.resources,
+                [ "$base_target_name/resources/{{source_file_part}}" ])
       }
-      if (defined(invoker.cflags_c)) {
-        cflags_c = invoker.cflags_c
-      }
-      if (defined(invoker.cflags_cc)) {
-        cflags_cc = invoker.cflags_cc
-      }
-      if (defined(invoker.cflags_objc)) {
-        cflags_objc = invoker.cflags_objc
-      }
-      if (defined(invoker.cflags_objcc)) {
-        cflags_objcc = invoker.cflags_objcc
-      }
-      if (defined(invoker.defines)) {
-        defines = invoker.defines
-      }
-      if (defined(invoker.include_dirs)) {
-        include_dirs = invoker.include_dirs
-      }
-      if (defined(invoker.ldflags)) {
-        ldflags = invoker.ldflags
-      }
-      if (defined(invoker.lib_dirs)) {
-        lib_dirs = invoker.lib_dirs
-      }
-      if (defined(invoker.libs)) {
-        libs = invoker.libs
-      }
-
-      data_deps = []
-      if (defined(invoker.data_deps)) {
-        data_deps = invoker.data_deps
-      }
-
-      deps = [
-        "//mojo/public/c/system",
-        "//mojo/public/platform/nacl:system",
-      ]
-
-      deps += mojo_deps
-      if (defined(invoker.public_deps)) {
-        public_deps = invoker.public_deps
-      }
-      if (defined(invoker.all_dependent_configs)) {
-        all_dependent_configs = invoker.all_dependent_configs
-      }
-      if (defined(invoker.public_configs)) {
-        public_configs = invoker.public_configs
-      }
-      if (defined(invoker.check_includes)) {
-        check_includes = invoker.check_includes
-      }
-      if (defined(invoker.configs)) {
-        configs += invoker.configs
-      }
-      if (defined(invoker.data)) {
-        data = invoker.data
-      }
-      if (defined(invoker.inputs)) {
-        inputs = invoker.inputs
-      }
-      if (defined(invoker.public)) {
-        public = invoker.public
-      }
-      if (defined(invoker.sources)) {
-        sources = invoker.sources
-      }
-      if (defined(invoker.testonly)) {
-        testonly = invoker.testonly
-      }
-
-      visibility = [ ":${final_target_name}" ]
-    }
-
-    action(target_name) {
-      if (defined(invoker.testonly)) {
-        testonly = invoker.testonly
-      }
-      if (defined(invoker.visibility)) {
-        visibility = invoker.visibility
-      }
-
-      script = "//mojo/public/tools/prepend.py"
-
-      input_path = "${root_out_dir}/${nexe_name}"
-      inputs = [
-        input_path,
-      ]
-
-      output_path = "${root_build_dir}/${base_target_name}/${output}"
-      outputs = [
-        output_path,
-      ]
-
-      deps = [
-        ":${nexe_target_name}",
-      ]
-
-      rebase_input = rebase_path(input_path, root_build_dir)
-      rebase_output = rebase_path(output_path, root_build_dir)
-      args = [
-        "--input=$rebase_input",
-        "--output=$rebase_output",
-        "--line=#!mojo mojo:nacl_content_handler",
-      ]
     }
   }
 }
diff --git a/mojo/public/platform/nacl/BUILD.gn b/mojo/public/platform/nacl/BUILD.gn
deleted file mode 100644
index ba29a79..0000000
--- a/mojo/public/platform/nacl/BUILD.gn
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-assert(is_nacl)
-
-# Untrusted code
-if (is_nacl) {
-  # Thunk mapping the Mojo public API onto NaCl syscalls.
-  source_set("mojo") {
-    sources = [
-      "libmojo.cc",
-      "mojo_irt.h",
-    ]
-    deps = [
-      "//mojo/public/c/system",
-    ]
-  }
-
-  source_set("system") {
-    sources = [
-      "mojo_initial_handle.h",
-      "mojo_main_thunk.cc",
-    ]
-
-    deps = [
-      "//mojo/public/c/system",
-      "//mojo/public/platform/nacl:mojo",
-    ]
-  }
-}
diff --git a/mojo/public/platform/nacl/DEPS b/mojo/public/platform/nacl/DEPS
deleted file mode 100644
index ef97f1a..0000000
--- a/mojo/public/platform/nacl/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
-  # This code is checked into the chromium repo so it's fine to depend on this.
-  "+native_client",
-]
diff --git a/mojo/public/platform/nacl/libmojo.cc b/mojo/public/platform/nacl/libmojo.cc
deleted file mode 100644
index de0b495..0000000
--- a/mojo/public/platform/nacl/libmojo.cc
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// WARNING this file was generated by generate_nacl_bindings.py
-// Do not edit by hand.
-
-#include "mojo/public/c/system/core.h"
-#include "mojo/public/platform/nacl/mojo_irt.h"
-#include "native_client/src/public/chrome_main.h"
-#include "native_client/src/public/imc_syscalls.h"
-#include "native_client/src/public/imc_types.h"
-#include "native_client/src/untrusted/irt/irt.h"
-
-// The value for this FD must not conflict with uses inside Chromium. However,
-// mojo/nacl doesn't depend on any Chromium headers, so we can't use a #define
-// from there.
-#define NACL_MOJO_DESC (NACL_CHROME_DESC_BASE + 3)
-
-bool g_irt_mojo_valid = false;
-struct nacl_irt_mojo g_irt_mojo;
-
-struct nacl_irt_mojo* get_irt_mojo() {
-  if (!g_irt_mojo_valid) {
-    size_t rc = nacl_interface_query(NACL_IRT_MOJO_v0_1, &g_irt_mojo,
-                                     sizeof(g_irt_mojo));
-    if (rc != sizeof(g_irt_mojo))
-      return NULL;
-    else
-      g_irt_mojo_valid = true;
-  }
-  return &g_irt_mojo;
-}
-
-MojoResult MojoCreateSharedBuffer(
-    const struct MojoCreateSharedBufferOptions* options,
-    uint64_t num_bytes,
-    MojoHandle* shared_buffer_handle) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoCreateSharedBuffer(options, num_bytes,
-                                          shared_buffer_handle);
-}
-
-MojoResult MojoDuplicateBufferHandle(
-    MojoHandle buffer_handle,
-    const struct MojoDuplicateBufferHandleOptions* options,
-    MojoHandle* new_buffer_handle) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoDuplicateBufferHandle(buffer_handle, options,
-                                             new_buffer_handle);
-}
-
-MojoResult MojoMapBuffer(MojoHandle buffer_handle,
-                         uint64_t offset,
-                         uint64_t num_bytes,
-                         void** buffer,
-                         MojoMapBufferFlags flags) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoMapBuffer(buffer_handle, offset, num_bytes, buffer,
-                                 flags);
-}
-
-MojoResult MojoUnmapBuffer(void* buffer) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoUnmapBuffer(buffer);
-}
-
-MojoResult MojoCreateDataPipe(const struct MojoCreateDataPipeOptions* options,
-                              MojoHandle* data_pipe_producer_handle,
-                              MojoHandle* data_pipe_consumer_handle) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoCreateDataPipe(options, data_pipe_producer_handle,
-                                      data_pipe_consumer_handle);
-}
-
-MojoResult MojoWriteData(MojoHandle data_pipe_producer_handle,
-                         const void* elements,
-                         uint32_t* num_bytes,
-                         MojoWriteDataFlags flags) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoWriteData(data_pipe_producer_handle, elements, num_bytes,
-                                 flags);
-}
-
-MojoResult MojoBeginWriteData(MojoHandle data_pipe_producer_handle,
-                              void** buffer,
-                              uint32_t* buffer_num_bytes,
-                              MojoWriteDataFlags flags) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoBeginWriteData(data_pipe_producer_handle, buffer,
-                                      buffer_num_bytes, flags);
-}
-
-MojoResult MojoEndWriteData(MojoHandle data_pipe_producer_handle,
-                            uint32_t num_bytes_written) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoEndWriteData(data_pipe_producer_handle,
-                                    num_bytes_written);
-}
-
-MojoResult MojoReadData(MojoHandle data_pipe_consumer_handle,
-                        void* elements,
-                        uint32_t* num_bytes,
-                        MojoReadDataFlags flags) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoReadData(data_pipe_consumer_handle, elements, num_bytes,
-                                flags);
-}
-
-MojoResult MojoBeginReadData(MojoHandle data_pipe_consumer_handle,
-                             const void** buffer,
-                             uint32_t* buffer_num_bytes,
-                             MojoReadDataFlags flags) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoBeginReadData(data_pipe_consumer_handle, buffer,
-                                     buffer_num_bytes, flags);
-}
-
-MojoResult MojoEndReadData(MojoHandle data_pipe_consumer_handle,
-                           uint32_t num_bytes_read) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoEndReadData(data_pipe_consumer_handle, num_bytes_read);
-}
-
-MojoTimeTicks MojoGetTimeTicksNow() {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoGetTimeTicksNow();
-}
-
-MojoResult MojoClose(MojoHandle handle) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoClose(handle);
-}
-
-MojoResult MojoWait(MojoHandle handle,
-                    MojoHandleSignals signals,
-                    MojoDeadline deadline,
-                    struct MojoHandleSignalsState* signals_state) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoWait(handle, signals, deadline, signals_state);
-}
-
-MojoResult MojoWaitMany(const MojoHandle* handles,
-                        const MojoHandleSignals* signals,
-                        uint32_t num_handles,
-                        MojoDeadline deadline,
-                        uint32_t* result_index,
-                        struct MojoHandleSignalsState* signals_states) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoWaitMany(handles, signals, num_handles, deadline,
-                                result_index, signals_states);
-}
-
-MojoResult MojoCreateMessagePipe(
-    const struct MojoCreateMessagePipeOptions* options,
-    MojoHandle* message_pipe_handle0,
-    MojoHandle* message_pipe_handle1) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoCreateMessagePipe(options, message_pipe_handle0,
-                                         message_pipe_handle1);
-}
-
-MojoResult MojoWriteMessage(MojoHandle message_pipe_handle,
-                            const void* bytes,
-                            uint32_t num_bytes,
-                            const MojoHandle* handles,
-                            uint32_t num_handles,
-                            MojoWriteMessageFlags flags) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoWriteMessage(message_pipe_handle, bytes, num_bytes,
-                                    handles, num_handles, flags);
-}
-
-MojoResult MojoReadMessage(MojoHandle message_pipe_handle,
-                           void* bytes,
-                           uint32_t* num_bytes,
-                           MojoHandle* handles,
-                           uint32_t* num_handles,
-                           MojoReadMessageFlags flags) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->MojoReadMessage(message_pipe_handle, bytes, num_bytes,
-                                   handles, num_handles, flags);
-}
-
-MojoResult _MojoGetInitialHandle(MojoHandle* handle) {
-  struct nacl_irt_mojo* irt_mojo = get_irt_mojo();
-  if (irt_mojo == NULL)
-    return MOJO_RESULT_INTERNAL;
-  return irt_mojo->_MojoGetInitialHandle(handle);
-}
-
diff --git a/mojo/public/platform/nacl/mojo_initial_handle.h b/mojo/public/platform/nacl/mojo_initial_handle.h
deleted file mode 100644
index e02146cb..0000000
--- a/mojo/public/platform/nacl/mojo_initial_handle.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_PLATFORM_NACL_MOJO_INITIAL_HANDLE_H_
-#define MOJO_PUBLIC_PLATFORM_NACL_MOJO_INITIAL_HANDLE_H_
-
-#include "mojo/public/c/system/types.h"
-
-// Provides a MojoHandle that allows untrusted code to communicate with Mojo
-// interfaces outside the sandbox or in other processes.
-MojoResult _MojoGetInitialHandle(MojoHandle* out_handle);
-
-#endif  // MOJO_PUBLIC_PLATFORM_NACL_MOJO_INITIAL_HANDLE_H_
diff --git a/mojo/public/platform/nacl/mojo_irt.h b/mojo/public/platform/nacl/mojo_irt.h
deleted file mode 100644
index db3a180f..0000000
--- a/mojo/public/platform/nacl/mojo_irt.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// WARNING this file was generated by generate_nacl_bindings.py
-// Do not edit by hand.
-
-#ifndef MOJO_PUBLIC_PLATFORM_NACL_MOJO_IRT_H_
-#define MOJO_PUBLIC_PLATFORM_NACL_MOJO_IRT_H_
-
-#include "mojo/public/c/system/buffer.h"
-#include "mojo/public/c/system/data_pipe.h"
-#include "mojo/public/c/system/message_pipe.h"
-#include "mojo/public/c/system/types.h"
-
-#define NACL_IRT_MOJO_v0_1 "nacl-irt-mojo-0.1"
-
-struct nacl_irt_mojo {
-  MojoResult (*MojoCreateSharedBuffer)(
-      const struct MojoCreateSharedBufferOptions* options,
-      uint64_t num_bytes,
-      MojoHandle* shared_buffer_handle);
-  MojoResult (*MojoDuplicateBufferHandle)(
-      MojoHandle buffer_handle,
-      const struct MojoDuplicateBufferHandleOptions* options,
-      MojoHandle* new_buffer_handle);
-  MojoResult (*MojoMapBuffer)(MojoHandle buffer_handle,
-                              uint64_t offset,
-                              uint64_t num_bytes,
-                              void** buffer,
-                              MojoMapBufferFlags flags);
-  MojoResult (*MojoUnmapBuffer)(void* buffer);
-  MojoResult (*MojoCreateDataPipe)(
-      const struct MojoCreateDataPipeOptions* options,
-      MojoHandle* data_pipe_producer_handle,
-      MojoHandle* data_pipe_consumer_handle);
-  MojoResult (*MojoWriteData)(MojoHandle data_pipe_producer_handle,
-                              const void* elements,
-                              uint32_t* num_bytes,
-                              MojoWriteDataFlags flags);
-  MojoResult (*MojoBeginWriteData)(MojoHandle data_pipe_producer_handle,
-                                   void** buffer,
-                                   uint32_t* buffer_num_bytes,
-                                   MojoWriteDataFlags flags);
-  MojoResult (*MojoEndWriteData)(MojoHandle data_pipe_producer_handle,
-                                 uint32_t num_bytes_written);
-  MojoResult (*MojoReadData)(MojoHandle data_pipe_consumer_handle,
-                             void* elements,
-                             uint32_t* num_bytes,
-                             MojoReadDataFlags flags);
-  MojoResult (*MojoBeginReadData)(MojoHandle data_pipe_consumer_handle,
-                                  const void** buffer,
-                                  uint32_t* buffer_num_bytes,
-                                  MojoReadDataFlags flags);
-  MojoResult (*MojoEndReadData)(MojoHandle data_pipe_consumer_handle,
-                                uint32_t num_bytes_read);
-  MojoTimeTicks (*MojoGetTimeTicksNow)();
-  MojoResult (*MojoClose)(MojoHandle handle);
-  MojoResult (*MojoWait)(MojoHandle handle,
-                         MojoHandleSignals signals,
-                         MojoDeadline deadline,
-                         struct MojoHandleSignalsState* signals_state);
-  MojoResult (*MojoWaitMany)(const MojoHandle* handles,
-                             const MojoHandleSignals* signals,
-                             uint32_t num_handles,
-                             MojoDeadline deadline,
-                             uint32_t* result_index,
-                             struct MojoHandleSignalsState* signals_states);
-  MojoResult (*MojoCreateMessagePipe)(
-      const struct MojoCreateMessagePipeOptions* options,
-      MojoHandle* message_pipe_handle0,
-      MojoHandle* message_pipe_handle1);
-  MojoResult (*MojoWriteMessage)(MojoHandle message_pipe_handle,
-                                 const void* bytes,
-                                 uint32_t num_bytes,
-                                 const MojoHandle* handles,
-                                 uint32_t num_handles,
-                                 MojoWriteMessageFlags flags);
-  MojoResult (*MojoReadMessage)(MojoHandle message_pipe_handle,
-                                void* bytes,
-                                uint32_t* num_bytes,
-                                MojoHandle* handles,
-                                uint32_t* num_handles,
-                                MojoReadMessageFlags flags);
-  MojoResult (*_MojoGetInitialHandle)(MojoHandle* handle);
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-size_t mojo_irt_query(const char* interface_ident,
-                      void* table,
-                      size_t tablesize);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif  // MOJO_PUBLIC_PLATFORM_NACL_MOJO_IRT_H_
diff --git a/mojo/public/platform/nacl/mojo_main_thunk.cc b/mojo/public/platform/nacl/mojo_main_thunk.cc
deleted file mode 100644
index 7cb5b52..0000000
--- a/mojo/public/platform/nacl/mojo_main_thunk.cc
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/c/system/main.h"
-#include "mojo/public/platform/nacl/mojo_initial_handle.h"
-
-int main() {
-  MojoHandle handle;
-  _MojoGetInitialHandle(&handle);
-  return MojoMain(handle);
-}
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/data.py b/mojo/public/tools/bindings/pylib/mojom/generate/data.py
index 1109a6af..60ae1e0 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/data.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/data.py
@@ -209,15 +209,29 @@
 def StructFromData(module, data):
   struct = mojom.Struct(module=module)
   struct.name = data['name']
+  struct.native_only = data['native_only']
   struct.spec = 'x:' + module.namespace + '.' + struct.name
   module.kinds[struct.spec] = struct
-  struct.enums = map(lambda enum:
-      EnumFromData(module, enum, struct), data['enums'])
-  struct.constants = map(lambda constant:
-      ConstantFromData(module, constant, struct), data['constants'])
-  # Stash fields data here temporarily.
-  struct.fields_data = data['fields']
+  if struct.native_only:
+    struct.enums = []
+    struct.constants = []
+    struct.fields_data = []
+  else:
+    struct.enums = map(lambda enum:
+        EnumFromData(module, enum, struct), data['enums'])
+    struct.constants = map(lambda constant:
+        ConstantFromData(module, constant, struct), data['constants'])
+    # Stash fields data here temporarily.
+    struct.fields_data = data['fields']
   struct.attributes = data.get('attributes')
+
+  # Enforce that a [native=True] attribute is set to make native-only struct
+  # declarations more explicit.
+  if struct.native_only:
+    if not struct.attributes or not struct.attributes.get('native', False):
+      raise Exception("Native-only struct declarations must include a " +
+                      "native=True attribute.")
+
   return struct
 
 def UnionToData(union):
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/module.py b/mojo/public/tools/bindings/pylib/mojom/generate/module.py
index 8af874fa7..dfde609d 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/module.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/module.py
@@ -202,6 +202,7 @@
 
 class Struct(ReferenceKind):
   ReferenceKind.AddSharedProperty('name')
+  ReferenceKind.AddSharedProperty('native_only')
   ReferenceKind.AddSharedProperty('module')
   ReferenceKind.AddSharedProperty('imported_from')
   ReferenceKind.AddSharedProperty('fields')
@@ -214,6 +215,7 @@
       spec = None
     ReferenceKind.__init__(self, spec)
     self.name = name
+    self.native_only = False
     self.module = module
     self.imported_from = None
     self.fields = []
diff --git a/mojo/public/tools/bindings/pylib/mojom/parse/ast.py b/mojo/public/tools/bindings/pylib/mojom/parse/ast.py
index ffb44e0..6473b02b 100644
--- a/mojo/public/tools/bindings/pylib/mojom/parse/ast.py
+++ b/mojo/public/tools/bindings/pylib/mojom/parse/ast.py
@@ -326,7 +326,7 @@
 
   def __init__(self, name, attribute_list, body, **kwargs):
     assert attribute_list is None or isinstance(attribute_list, AttributeList)
-    assert isinstance(body, StructBody)
+    assert isinstance(body, StructBody) or body is None
     super(Struct, self).__init__(name, **kwargs)
     self.attribute_list = attribute_list
     self.body = body
diff --git a/mojo/public/tools/bindings/pylib/mojom/parse/parser.py b/mojo/public/tools/bindings/pylib/mojom/parse/parser.py
index f52f91d2..8d90cd5 100644
--- a/mojo/public/tools/bindings/pylib/mojom/parse/parser.py
+++ b/mojo/public/tools/bindings/pylib/mojom/parse/parser.py
@@ -155,10 +155,14 @@
     # 'eval' the literal to strip the quotes.
     p[0] = eval(p[1])
 
-  def p_struct(self, p):
+  def p_struct_1(self, p):
     """struct : attribute_section STRUCT NAME LBRACE struct_body RBRACE SEMI"""
     p[0] = ast.Struct(p[3], p[1], p[5])
 
+  def p_struct_2(self, p):
+    """struct : attribute_section STRUCT NAME SEMI"""
+    p[0] = ast.Struct(p[3], p[1], None)
+
   def p_struct_body_1(self, p):
     """struct_body : """
     p[0] = ast.StructBody()
diff --git a/mojo/public/tools/bindings/pylib/mojom/parse/translate.py b/mojo/public/tools/bindings/pylib/mojom/parse/translate.py
index aad245fd..e457f99 100644
--- a/mojo/public/tools/bindings/pylib/mojom/parse/translate.py
+++ b/mojo/public/tools/bindings/pylib/mojom/parse/translate.py
@@ -130,12 +130,15 @@
 
       assert isinstance(struct, ast.Struct)
       data = {'name': struct.name,
-              'fields': _MapTreeForType(StructFieldToDict, struct.body,
-                                        ast.StructField, struct.name),
-              'enums': _MapTreeForType(_EnumToDict, struct.body, ast.Enum,
-                                       struct.name),
-              'constants': _MapTreeForType(_ConstToDict, struct.body,
-                                           ast.Const, struct.name)}
+              'native_only': struct.body is None}
+      if not data['native_only']:
+        data.update({
+            'fields': _MapTreeForType(StructFieldToDict, struct.body,
+                                      ast.StructField, struct.name),
+            'enums': _MapTreeForType(_EnumToDict, struct.body, ast.Enum,
+                                     struct.name),
+            'constants': _MapTreeForType(_ConstToDict, struct.body,
+                                         ast.Const, struct.name)})
       _AddOptional(data, 'attributes',
                    _AttributeListToDict(struct.attribute_list))
       return data
diff --git a/net/base/net_util.cc b/net/base/net_util.cc
index d1ac2a5..e29fa5c5 100644
--- a/net/base/net_util.cc
+++ b/net/base/net_util.cc
@@ -21,14 +21,7 @@
 #elif defined(OS_POSIX)
 #include <fcntl.h>
 #include <netdb.h>
-#include <netinet/in.h>
 #include <unistd.h>
-#if !defined(OS_NACL)
-#include <net/if.h>
-#if !defined(OS_ANDROID)
-#include <ifaddrs.h>
-#endif  // !defined(OS_NACL)
-#endif  // !defined(OS_ANDROID)
 #endif  // defined(OS_POSIX)
 
 #include "base/basictypes.h"
@@ -53,9 +46,6 @@
 #include "url/url_canon.h"
 #include "url/url_canon_ip.h"
 
-#if defined(OS_ANDROID)
-#include "net/android/network_library.h"
-#endif
 #if defined(OS_WIN)
 #include "net/base/winsock_init.h"
 #endif
@@ -160,18 +150,6 @@
   return most_recent_component_started_alphanumeric;
 }
 
-int SetNonBlocking(int fd) {
-#if defined(OS_WIN)
-  unsigned long no_block = 1;
-  return ioctlsocket(fd, FIONBIO, &no_block);
-#elif defined(OS_POSIX)
-  int flags = fcntl(fd, F_GETFL, 0);
-  if (-1 == flags)
-    return flags;
-  return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-#endif
-}
-
 bool ParseHostAndPort(std::string::const_iterator host_and_port_begin,
                       std::string::const_iterator host_and_port_end,
                       std::string* host,
@@ -430,57 +408,6 @@
   return url.ReplaceComponents(replacements);
 }
 
-bool HaveOnlyLoopbackAddresses() {
-#if defined(OS_ANDROID)
-  return android::HaveOnlyLoopbackAddresses();
-#elif defined(OS_NACL)
-  NOTIMPLEMENTED();
-  return false;
-#elif defined(OS_POSIX)
-  struct ifaddrs* interface_addr = NULL;
-  int rv = getifaddrs(&interface_addr);
-  if (rv != 0) {
-    DVLOG(1) << "getifaddrs() failed with errno = " << errno;
-    return false;
-  }
-
-  bool result = true;
-  for (struct ifaddrs* interface = interface_addr;
-       interface != NULL;
-       interface = interface->ifa_next) {
-    if (!(IFF_UP & interface->ifa_flags))
-      continue;
-    if (IFF_LOOPBACK & interface->ifa_flags)
-      continue;
-    const struct sockaddr* addr = interface->ifa_addr;
-    if (!addr)
-      continue;
-    if (addr->sa_family == AF_INET6) {
-      // Safe cast since this is AF_INET6.
-      const struct sockaddr_in6* addr_in6 =
-          reinterpret_cast<const struct sockaddr_in6*>(addr);
-      const struct in6_addr* sin6_addr = &addr_in6->sin6_addr;
-      if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_LINKLOCAL(sin6_addr))
-        continue;
-    }
-    if (addr->sa_family != AF_INET6 && addr->sa_family != AF_INET)
-      continue;
-
-    result = false;
-    break;
-  }
-  freeifaddrs(interface_addr);
-  return result;
-#elif defined(OS_WIN)
-  // TODO(wtc): implement with the GetAdaptersAddresses function.
-  NOTIMPLEMENTED();
-  return false;
-#else
-  NOTIMPLEMENTED();
-  return false;
-#endif  // defined(various platforms)
-}
-
 const uint16_t* GetPortFieldFromSockaddr(const struct sockaddr* address,
                                          socklen_t address_len) {
   if (address->sa_family == AF_INET) {
diff --git a/net/base/net_util.h b/net/base/net_util.h
index 1e4e388..b4185417 100644
--- a/net/base/net_util.h
+++ b/net/base/net_util.h
@@ -161,19 +161,11 @@
                                                 int64_t size,
                                                 base::Time modified);
 
-// Set socket to non-blocking mode
-NET_EXPORT int SetNonBlocking(int fd);
-
 // Strip the portions of |url| that aren't core to the network request.
 //   - user name / password
 //   - reference section
 NET_EXPORT_PRIVATE GURL SimplifyUrlForRequest(const GURL& url);
 
-// Returns true if it can determine that only loopback addresses are configured.
-// i.e. if only 127.0.0.1 and ::1 are routable.
-// Also returns false if it cannot determine this.
-bool HaveOnlyLoopbackAddresses();
-
 // Retuns the port field of the |sockaddr|.
 const uint16_t* GetPortFieldFromSockaddr(const struct sockaddr* address,
                                          socklen_t address_len);
diff --git a/net/dns/dns_util.cc b/net/dns/dns_util.cc
index 7ab60c6a..a75d706 100644
--- a/net/dns/dns_util.cc
+++ b/net/dns/dns_util.cc
@@ -6,6 +6,22 @@
 
 #include <cstring>
 
+#include "build/build_config.h"
+
+#if defined(OS_POSIX)
+#include <netinet/in.h>
+#if !defined(OS_NACL)
+#include <net/if.h>
+#if !defined(OS_ANDROID)
+#include <ifaddrs.h>
+#endif  // !defined(OS_ANDROID)
+#endif  // !defined(OS_NACL)
+#endif  // defined(OS_POSIX)
+
+#if defined(OS_ANDROID)
+#include "net/android/network_library.h"
+#endif
+
 namespace net {
 
 // Based on DJB's public domain code.
@@ -82,4 +98,55 @@
   return ret;
 }
 
+bool HaveOnlyLoopbackAddresses() {
+#if defined(OS_ANDROID)
+  return android::HaveOnlyLoopbackAddresses();
+#elif defined(OS_NACL)
+  NOTIMPLEMENTED();
+  return false;
+#elif defined(OS_POSIX)
+  struct ifaddrs* interface_addr = NULL;
+  int rv = getifaddrs(&interface_addr);
+  if (rv != 0) {
+    DVLOG(1) << "getifaddrs() failed with errno = " << errno;
+    return false;
+  }
+
+  bool result = true;
+  for (struct ifaddrs* interface = interface_addr;
+       interface != NULL;
+       interface = interface->ifa_next) {
+    if (!(IFF_UP & interface->ifa_flags))
+      continue;
+    if (IFF_LOOPBACK & interface->ifa_flags)
+      continue;
+    const struct sockaddr* addr = interface->ifa_addr;
+    if (!addr)
+      continue;
+    if (addr->sa_family == AF_INET6) {
+      // Safe cast since this is AF_INET6.
+      const struct sockaddr_in6* addr_in6 =
+          reinterpret_cast<const struct sockaddr_in6*>(addr);
+      const struct in6_addr* sin6_addr = &addr_in6->sin6_addr;
+      if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_LINKLOCAL(sin6_addr))
+        continue;
+    }
+    if (addr->sa_family != AF_INET6 && addr->sa_family != AF_INET)
+      continue;
+
+    result = false;
+    break;
+  }
+  freeifaddrs(interface_addr);
+  return result;
+#elif defined(OS_WIN)
+  // TODO(wtc): implement with the GetAdaptersAddresses function.
+  NOTIMPLEMENTED();
+  return false;
+#else
+  NOTIMPLEMENTED();
+  return false;
+#endif  // defined(various platforms)
+}
+
 }  // namespace net
diff --git a/net/dns/dns_util.h b/net/dns/dns_util.h
index 3332cb84..74f17cc 100644
--- a/net/dns/dns_util.h
+++ b/net/dns/dns_util.h
@@ -25,6 +25,11 @@
 NET_EXPORT_PRIVATE std::string DNSDomainToString(
     const base::StringPiece& domain);
 
+// Returns true if it can determine that only loopback addresses are configured.
+// i.e. if only 127.0.0.1 and ::1 are routable.
+// Also returns false if it cannot determine this.
+NET_EXPORT_PRIVATE bool HaveOnlyLoopbackAddresses();
+
 }  // namespace net
 
 #endif  // NET_DNS_DNS_UTIL_H_
diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc
index 492b89b4..0038a8a3 100644
--- a/net/http/http_stream_factory.cc
+++ b/net/http/http_stream_factory.cc
@@ -153,7 +153,7 @@
   http_server_properties->SetAlternativeService(
       RewriteHost(http_host_port_pair),
       AlternativeService(protocol, "", static_cast<uint16>(port)), probability,
-      base::Time::Now() + base::TimeDelta::FromDays(1));
+      base::Time::Now() + base::TimeDelta::FromDays(30));
 }
 
 GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url,
diff --git a/net/socket/socket_posix.cc b/net/socket/socket_posix.cc
index c8098c3..cd7aff1 100644
--- a/net/socket/socket_posix.cc
+++ b/net/socket/socket_posix.cc
@@ -9,6 +9,7 @@
 #include <sys/socket.h>
 
 #include "base/callback_helpers.h"
+#include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
 #include "net/base/io_buffer.h"
@@ -79,7 +80,7 @@
     return MapSystemError(errno);
   }
 
-  if (SetNonBlocking(socket_fd_)) {
+  if (!base::SetNonBlocking(socket_fd_)) {
     int rv = MapSystemError(errno);
     Close();
     return rv;
@@ -95,7 +96,7 @@
 
   socket_fd_ = socket;
 
-  if (SetNonBlocking(socket_fd_)) {
+  if (!base::SetNonBlocking(socket_fd_)) {
     int rv = MapSystemError(errno);
     Close();
     return rv;
diff --git a/net/socket/tcp_socket_win.cc b/net/socket/tcp_socket_win.cc
index 3bd2a69..028e830 100644
--- a/net/socket/tcp_socket_win.cc
+++ b/net/socket/tcp_socket_win.cc
@@ -9,6 +9,7 @@
 #include <mstcpip.h>
 
 #include "base/callback_helpers.h"
+#include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/profiler/scoped_tracker.h"
 #include "base/win/windows_version.h"
@@ -302,7 +303,7 @@
     return MapSystemError(WSAGetLastError());
   }
 
-  if (SetNonBlocking(socket_)) {
+  if (!base::SetNonBlocking(socket_)) {
     int result = MapSystemError(WSAGetLastError());
     Close();
     return result;
@@ -319,7 +320,7 @@
 
   socket_ = socket;
 
-  if (SetNonBlocking(socket_)) {
+  if (!base::SetNonBlocking(socket_)) {
     int result = MapSystemError(WSAGetLastError());
     Close();
     return result;
@@ -337,7 +338,7 @@
 
   socket_ = socket;
 
-  if (SetNonBlocking(socket_)) {
+  if (!base::SetNonBlocking(socket_)) {
     int result = MapSystemError(WSAGetLastError());
     Close();
     return result;
diff --git a/net/udp/udp_socket_posix.cc b/net/udp/udp_socket_posix.cc
index c395b88..545d2ee8 100644
--- a/net/udp/udp_socket_posix.cc
+++ b/net/udp/udp_socket_posix.cc
@@ -14,6 +14,7 @@
 
 #include "base/callback.h"
 #include "base/debug/alias.h"
+#include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/sparse_histogram.h"
@@ -102,7 +103,7 @@
   socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0);
   if (socket_ == kInvalidSocket)
     return MapSystemError(errno);
-  if (SetNonBlocking(socket_)) {
+  if (!base::SetNonBlocking(socket_)) {
     const int err = MapSystemError(errno);
     Close();
     return err;
diff --git a/remoting/host/token_validator_base.cc b/remoting/host/token_validator_base.cc
index 751e802..f7d0136 100644
--- a/remoting/host/token_validator_base.cc
+++ b/remoting/host/token_validator_base.cc
@@ -29,6 +29,7 @@
 #include "net/ssl/ssl_cert_request_info.h"
 #include "net/ssl/ssl_platform_key.h"
 #include "net/ssl/ssl_private_key.h"
+#include "net/url_request/redirect_info.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_status.h"
@@ -68,7 +69,7 @@
   DCHECK(!on_token_validated.is_null());
 
   on_token_validated_ = on_token_validated;
-
+  token_ = token;
   StartValidateRequest(token);
 }
 
@@ -103,12 +104,29 @@
   const net::URLRequestStatus status = request_->status();
 
   if (!status.is_io_pending()) {
+    retrying_request_ = false;
     std::string shared_token = ProcessResponse();
     request_.reset();
     on_token_validated_.Run(shared_token);
   }
 }
 
+void TokenValidatorBase::OnReceivedRedirect(
+    net::URLRequest* request,
+    const net::RedirectInfo& redirect_info,
+    bool* defer_redirect) {
+  if (!retrying_request_ && redirect_info.new_method == "GET" &&
+      redirect_info.new_url == third_party_auth_config_.token_validation_url) {
+    // A sequence of redirects caused the original POST request to become a GET
+    // request for this URL. Cancel the request, and re-submit the POST request.
+    // The chain of redirects are expected to set some cookies that will
+    // ensure the new POST request succeeds.
+    retrying_request_ = true;
+    DCHECK(data_.empty());
+    StartValidateRequest(token_);
+  }
+}
+
 void TokenValidatorBase::OnCertificateRequested(
     net::URLRequest* source,
     net::SSLCertRequestInfo* cert_request_info) {
diff --git a/remoting/host/token_validator_base.h b/remoting/host/token_validator_base.h
index a10ab1a..d7fc115 100644
--- a/remoting/host/token_validator_base.h
+++ b/remoting/host/token_validator_base.h
@@ -43,6 +43,9 @@
   // URLRequest::Delegate interface.
   void OnResponseStarted(net::URLRequest* source) override;
   void OnReadCompleted(net::URLRequest* source, int bytes_read) override;
+  void OnReceivedRedirect(net::URLRequest* request,
+                          const net::RedirectInfo& redirect_info,
+                          bool* defer_redirect) override;
   void OnCertificateRequested(
       net::URLRequest* source,
       net::SSLCertRequestInfo* cert_request_info) override;
@@ -65,6 +68,18 @@
   scoped_refptr<net::IOBuffer> buffer_;
   std::string data_;
 
+  // This is set by OnReceivedRedirect() if the token validation request is
+  // being re-submitted as a POST request. This can happen if the authentication
+  // cookie has not yet been set, and a login handler redirection causes the
+  // POST request to be turned into a GET operation, losing the POST data. In
+  // this case, an immediate retry (with the same cookie jar) is expected to
+  // succeeed.
+  bool retrying_request_ = false;
+
+  // Stores the most recently requested token, in case the validation request
+  // needs to be retried.
+  std::string token_;
+
   base::Callback<void(const std::string& shared_secret)> on_token_validated_;
 
   base::WeakPtrFactory<TokenValidatorBase> weak_factory_;
diff --git a/testing/libfuzzer/BUILD.gn b/testing/libfuzzer/BUILD.gn
index e08e205..d5ec6326 100644
--- a/testing/libfuzzer/BUILD.gn
+++ b/testing/libfuzzer/BUILD.gn
@@ -34,3 +34,9 @@
     sources += [ "drfuzz_main.cc" ]
   }
 }
+
+# Noop config used to tag fuzzer tests excluded from clusterfuzz.
+# Libfuzzer build bot uses this to filter out targets while
+# building an archive for clusterfuzz.
+config("no_clusterfuzz") {
+}
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn
index 0ad4ef2..558a151 100644
--- a/testing/libfuzzer/fuzzers/BUILD.gn
+++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -11,6 +11,7 @@
   sources = [
     "empty_fuzzer.cc",
   ]
+  additional_configs = [ "//testing/libfuzzer:no_clusterfuzz" ]
 }
 
 fuzzer_test("brotli_fuzzer") {
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index e82431eb..77c0eec 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -78,12 +78,101 @@
 
 crbug.com/267206 [ Mac ] virtual/rootlayerscrolls/fast/scrolling/scrollbar-tickmarks-hittest.html [ Timeout ]
 
-crbug.com/465126 imported/gecko/variables/variable-declaration-24.html [ Failure ]
-crbug.com/465126 imported/gecko/variables/variable-declaration-25.html [ Failure ]
 crbug.com/465126 imported/gecko/variables/variable-external-font-face-01.html [ Failure ]
 
 crbug.com/280342 [ Linux Win ] http/tests/media/progress-events-generated-correctly.html [ Failure ]
 
+crbug.com/569919 compositing/color-matching/image-color-matching.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/composited-reflected.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/crash-filter-change.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-blur.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-brightness-clamping-hw.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-brightness-clamping.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-brightness-hw.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-brightness.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-combined-hw.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-combined.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-contrast-hw.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-contrast.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-drop-shadow.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-grayscale-hw.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-grayscale.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-hue-rotate-hw.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-hue-rotate.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-invert-hw.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-invert.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-opacity-hw.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-opacity.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-reference-colorspace.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-reference-composite-hw.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-reference-composite.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-reference-external.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-reference-hidpi.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-reference-ordering.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-reference-subregion-chained-hw.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-reference-subregion-chained.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-reference-subregion-colormatrix.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-reference-subregion.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-reference-zoom.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-reference.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-saturate-hw.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-saturate.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-sepia-hw.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/effect-sepia.html [ NeedsRebaseline ]
+crbug.com/569919 css3/filters/regions-expanding.html [ NeedsRebaseline ]
+crbug.com/569919 css3/images/cross-fade-background-size.html [ NeedsRebaseline ]
+crbug.com/569919 fast/canvas/canvas-toBlob-jpeg-maximum-quality.html [ NeedsRebaseline ]
+crbug.com/569919 fast/canvas/canvas-toBlob-jpeg-medium-quality.html [ NeedsRebaseline ]
+crbug.com/569919 fast/canvas/canvas-toBlob-webp-maximum-quality.html [ NeedsRebaseline ]
+crbug.com/569919 fast/canvas/canvas-toDataURL-jpeg-maximum-quality.html [ NeedsRebaseline ]
+crbug.com/569919 fast/images/color-profile-munsell-srgb-to-srgb.html [ NeedsRebaseline ]
+crbug.com/569919 fast/images/paint-subrect.html [ NeedsRebaseline ]
+crbug.com/569919 fast/images/png-color-profile-ignore-gamma.html [ NeedsRebaseline ]
+crbug.com/569919 fast/inline/inline-box-background-long-image.html [ NeedsRebaseline ]
+crbug.com/569919 ietestcenter/css3/bordersbackgrounds/background-attachment-local-scrolling.htm [ NeedsRebaseline ]
+crbug.com/569919 ietestcenter/css3/bordersbackgrounds/background-size-aspect-ratio.htm [ NeedsRebaseline ]
+crbug.com/569919 ietestcenter/css3/bordersbackgrounds/background_repeat_space_content_box.htm [ NeedsRebaseline ]
+crbug.com/569919 svg/custom/clip-mask-negative-scale.svg [ NeedsRebaseline ]
+crbug.com/569919 svg/custom/createImageElement.svg [ NeedsRebaseline ]
+crbug.com/569919 svg/custom/createImageElement2.xhtml [ NeedsRebaseline ]
+crbug.com/569919 svg/custom/focus-ring.svg [ NeedsRebaseline ]
+crbug.com/569919 svg/custom/image-parent-translation.xhtml [ NeedsRebaseline ]
+crbug.com/569919 svg/custom/image-small-width-height.svg [ NeedsRebaseline ]
+crbug.com/569919 svg/custom/js-update-image-and-display.svg [ NeedsRebaseline ]
+crbug.com/569919 svg/custom/js-update-image-and-display2.svg [ NeedsRebaseline ]
+crbug.com/569919 svg/custom/js-update-image-and-display3.svg [ NeedsRebaseline ]
+crbug.com/569919 svg/custom/js-update-image.svg [ NeedsRebaseline ]
+crbug.com/569919 svg/custom/text-image-opacity.svg [ NeedsRebaseline ]
+crbug.com/569919 svg/custom/transformed-outlines.svg [ NeedsRebaseline ]
+crbug.com/569919 svg/custom/use-on-g-containing-foreignObject-and-image.svg [ NeedsRebaseline ]
+crbug.com/569919 svg/dynamic-updates/SVGImageElement-dom-height-attr.html [ NeedsRebaseline ]
+crbug.com/569919 svg/dynamic-updates/SVGImageElement-dom-preserveAspectRatio-attr.html [ NeedsRebaseline ]
+crbug.com/569919 svg/dynamic-updates/SVGImageElement-dom-width-attr.html [ NeedsRebaseline ]
+crbug.com/569919 svg/dynamic-updates/SVGImageElement-dom-x-attr.html [ NeedsRebaseline ]
+crbug.com/569919 svg/dynamic-updates/SVGImageElement-dom-y-attr.html [ NeedsRebaseline ]
+crbug.com/569919 svg/dynamic-updates/SVGImageElement-svgdom-height-prop.html [ NeedsRebaseline ]
+crbug.com/569919 svg/dynamic-updates/SVGImageElement-svgdom-preserveAspectRatio-prop.html [ NeedsRebaseline ]
+crbug.com/569919 svg/dynamic-updates/SVGImageElement-svgdom-width-prop.html [ NeedsRebaseline ]
+crbug.com/569919 svg/dynamic-updates/SVGImageElement-svgdom-x-prop.html [ NeedsRebaseline ]
+crbug.com/569919 svg/dynamic-updates/SVGImageElement-svgdom-y-prop.html [ NeedsRebaseline ]
+crbug.com/569919 svg/filters/feImage-subregions-preseveAspectRatio-none-with-viewBox.svg [ NeedsRebaseline ]
+crbug.com/569919 svg/filters/feImage-subregions-preseveAspectRatio-none.svg [ NeedsRebaseline ]
+crbug.com/569919 svg/filters/feImage-subregions.svg [ NeedsRebaseline ]
+crbug.com/569919 svg/repaint/image-href-change.svg [ NeedsRebaseline ]
+crbug.com/569919 [ Linux Win ] svg/transforms/animated-path-inside-transformed-html.xhtml [ NeedsRebaseline ]
+crbug.com/569919 svg/zoom/page/zoom-background-images.html [ NeedsRebaseline ]
+crbug.com/569919 svg/zoom/page/zoom-svg-through-object-with-absolute-size-2.xhtml [ NeedsRebaseline ]
+crbug.com/569919 svg/zoom/page/zoom-svg-through-object-with-absolute-size.xhtml [ NeedsRebaseline ]
+crbug.com/569919 [ Win7 Mac Linux ] svg/zoom/page/zoom-svg-through-object-with-percentage-size.xhtml [ NeedsRebaseline ]
+crbug.com/569919 virtual/display_list_2d_canvas/fast/canvas/canvas-toBlob-jpeg-maximum-quality.html [ NeedsRebaseline ]
+crbug.com/569919 virtual/display_list_2d_canvas/fast/canvas/canvas-toBlob-jpeg-medium-quality.html [ NeedsRebaseline ]
+crbug.com/569919 virtual/display_list_2d_canvas/fast/canvas/canvas-toBlob-webp-maximum-quality.html [ NeedsRebaseline ]
+crbug.com/569919 virtual/display_list_2d_canvas/fast/canvas/canvas-toDataURL-jpeg-maximum-quality.html [ NeedsRebaseline ]
+crbug.com/569919 virtual/gpu/fast/canvas/canvas-toBlob-jpeg-maximum-quality.html [ NeedsRebaseline ]
+crbug.com/569919 virtual/gpu/fast/canvas/canvas-toBlob-jpeg-medium-quality.html [ NeedsRebaseline ]
+crbug.com/569919 virtual/gpu/fast/canvas/canvas-toBlob-webp-maximum-quality.html [ NeedsRebaseline ]
+crbug.com/569919 virtual/gpu/fast/canvas/canvas-toDataURL-jpeg-maximum-quality.html [ NeedsRebaseline ]
+
 crbug.com/520739 [ Mac ] http/tests/websocket/close-code-and-reason.html [ Failure Pass Timeout ]
 crbug.com/520737 [ Mac ] imported/csswg-test/css-writing-modes-3/writing-mode-vertical-rl-001.xht [ Failure Pass Timeout ]
 crbug.com/520736 [ Win7 ] media/W3C/video/networkState/networkState_during_progress.html [ Failure Pass ]
@@ -881,6 +970,8 @@
 crbug.com/498021 [ Linux ] fast/text/international/complex-character-based-fallback.html [ Failure ]
 crbug.com/498021 [ Linux ] fast/text/international/hindi-spacing.html [ Failure ]
 
+crbug.com/567998 imported/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-all.html [ NeedsManualRebaseline ]
+
 # Significant Slimming Paint failure.
 crbug.com/459305 [ Mac ] svg/custom/foreign-object-skew.svg [ Failure ]
 
@@ -1291,7 +1382,7 @@
 crbug.com/561595 [ XP ] plugins/webview-plugin-nested-iframe-scroll.html [ Failure ]
 
 crbug.com/568678 [ XP ] virtual/gpu/fast/canvas/canvas-scale-strokePath-shadow.html [ Failure ]
-crbug.com/568740 [ Mac10.8 Win7 XP ] svg/custom/repaint-shadow.svg [ Failure ]
+crbug.com/568740 [ Mac10.8 Mac10.9 Win7 XP ] svg/custom/repaint-shadow.svg [ Failure ]
 
 crbug.com/568778 [ XP ] media/video-aspect-ratio.html [ Failure ]
 crbug.com/568778 [ XP ] media/video-colorspace-yuv420.html [ Failure ]
@@ -1327,3 +1418,6 @@
 crbug.com/569514 inspector/sources/debugger/debugger-scripts.html [ NeedsManualRebaseline ]
 
 crbug.com/569811 inspector-protocol/debugger/updateCallFrameScopes.html [ Pass Failure ]
+
+crbug.com/570221 virtual/threaded/animations/svg-attribute-composition/svg-markerWidth-composition.html [ Pass Failure ]
+crbug.com/570221 virtual/threaded/animations/svg-attribute-composition/svg-markerHeight-composition.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations
index 1d911af..beab4dd 100644
--- a/third_party/WebKit/LayoutTests/W3CImportExpectations
+++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -97,7 +97,8 @@
 # imported/web-platform-tests/custom-elements [ Pass ]
 imported/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass [ Skip ]
 imported/web-platform-tests/docs [ Skip ]
-imported/web-platform-tests/dom [ Skip ]
+## Owners: philipj@opera.com
+imported/web-platform-tests/dom [ Pass ]
 imported/web-platform-tests/domparsing [ Skip ]
 imported/web-platform-tests/domxpath [ Skip ]
 imported/web-platform-tests/editing [ Skip ]
@@ -205,6 +206,11 @@
 imported/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-038.html [ Skip ]
 
 # crbug.com/490939: The following tests are too large.  They cause time out frequently.
+imported/web-platform-tests/dom/ranges/Range-compareBoundaryPoints.html [ Skip ]
+imported/web-platform-tests/dom/ranges/Range-comparePoint.html [ Skip ]
+imported/web-platform-tests/dom/ranges/Range-isPointInRange.html [ Skip ]
+imported/web-platform-tests/dom/ranges/Range-mutations.html [ Skip ]
+imported/web-platform-tests/dom/ranges/Range-set.html [ Skip ]
 imported/web-platform-tests/html/dom/interfaces.html [ Skip ]
 imported/web-platform-tests/html/dom/reflection-embedded.html [ Skip ]
 imported/web-platform-tests/html/dom/reflection-forms.html [ Skip ]
@@ -302,6 +308,19 @@
 imported/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html [ Skip ]
 
 # crbug.com/490940: Needs to load extra HTML resources.
+imported/web-platform-tests/dom/nodes/Document-createElement-namespace.html [ Skip ]
+imported/web-platform-tests/dom/nodes/Element-getElementsByTagName-change-document-HTMLNess.html [ Skip ]
+imported/web-platform-tests/dom/nodes/Node-isEqualNode.xhtml [ Skip ]
+imported/web-platform-tests/dom/nodes/Node-parentNode.html [ Skip ]
+imported/web-platform-tests/dom/nodes/ParentNode-querySelector-All.html [ Skip ]
+imported/web-platform-tests/dom/nodes/ParentNode-querySelector-All.js [ Skip ]
+imported/web-platform-tests/dom/nodes/ParentNode-querySelector-All-xht.xht [ Skip ]
+imported/web-platform-tests/dom/nodes/getElementsByClassName-31.htm [ Skip ]
+imported/web-platform-tests/dom/ranges/Range-cloneContents.html [ Skip ]
+imported/web-platform-tests/dom/ranges/Range-deleteContents.html [ Skip ]
+imported/web-platform-tests/dom/ranges/Range-extractContents.html [ Skip ]
+imported/web-platform-tests/dom/ranges/Range-insertNode.html [ Skip ]
+imported/web-platform-tests/dom/ranges/Range-surroundContents.html [ Skip ]
 imported/web-platform-tests/html/browsers/browsing-the-web/history-traversal/001.html [ Skip ]
 imported/web-platform-tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name.html [ Skip ]
 imported/web-platform-tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin.html [ Skip ]
@@ -374,6 +393,28 @@
 imported/web-platform-tests/html/webappapis/scripting/events/onerroreventhandler.html [ Skip ]
 
 # crbug.com/493537: Need to support SVG reference tests
+imported/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Element-childElement-null-svg.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add-svg.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove-svg.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Element-childElementCount-nochild-svg.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Element-childElementCount-svg.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Element-firstElementChild-entity.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Element-firstElementChild-namespace-svg.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Element-firstElementChild-svg.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Element-lastElementChild-svg.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Element-nextElementSibling-svg.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Element-previousElementSibling-svg.svg [ Skip ]
+imported/web-platform-tests/dom/nodes/Element-siblingElement-null-svg.svg [ Skip ]
 imported/web-platform-tests/html/editing/the-hidden-attribute/hidden-2.svg [ Skip ]
 
 # https://github.com/w3c/web-platform-tests/issues/1861: A function can be
@@ -421,6 +462,14 @@
 imported/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/deny.html [ Skip ]
 
 # Requires http server.
+imported/web-platform-tests/dom/nodes/Document-URL.sub.html [ Skip ]
+imported/web-platform-tests/dom/nodes/Document-characterSet-normalization.html [ Skip ]
+imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_01.html [ Skip ]
+imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_02.html [ Skip ]
+imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_xml.html [ Skip ]
+imported/web-platform-tests/dom/nodes/Document-contentType/contentType/xhr_responseType_document.html [ Skip ]
+imported/web-platform-tests/dom/nodes/Element-matches.html [ Skip ]
+imported/web-platform-tests/dom/nodes/Node-baseURI.html [ Skip ]
 imported/web-platform-tests/html/browsers/history/the-history-interface/008.html [ Skip ]
 imported/web-platform-tests/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain.html [ Skip ]
 imported/web-platform-tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html [ Skip ]
@@ -559,3 +608,6 @@
 # crbug.com/561421: Update meta refresh parsing to match the new spec
 imported/web-platform-tests/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/parsing.html [ Skip ]
 imported/web-platform-tests/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/support [ Skip ]
+
+# crbug.com/441355: MutationObserver incorrect for replaceChild (causes timeout)
+imported/web-platform-tests/dom/nodes/MutationObserver-childList.html [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/animations/interpolation/svg-d-interpolation.html b/third_party/WebKit/LayoutTests/animations/interpolation/svg-d-interpolation.html
new file mode 100644
index 0000000..1766336
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/interpolation/svg-d-interpolation.html
@@ -0,0 +1,400 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<style>
+.parent {
+  cx: 100px;
+}
+.target {
+  font-size: 16px;
+  cx: 50px;
+}
+.expected {
+  fill: green;
+}
+</style>
+<body>
+<template id="target-template">
+  <svg width="90" height="90">
+    <path class="target" />
+  </svg>
+</template>
+<script src="resources/interpolation-test.js"></script>
+<script>
+'use strict';
+
+// Distinct number of path segments
+assertNoInterpolation({
+  property: 'd',
+  from: "path('m 0 0 h 1 h 2')",
+  to: "path('m 0 0 h 3')"
+});
+
+// Distinct segment types
+assertNoInterpolation({
+  property: 'd',
+  from: "path('m 10 0 h 1')",
+  to: "path('m 20 0 v 2')"
+});
+
+assertNoInterpolation({
+  property: 'd',
+  from: "path('m 1 2 l 3 4 Z')",
+  to: "path('m 1 2 l 3 4')"
+});
+
+// Exercise each segment type
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 Z')",
+  to: "path('m 0 0 Z')"
+}, [
+  {at: -0.4, is: "path('m 0 0 Z')"},
+  {at: 0, is: "path('m 0 0 Z')"},
+  {at: 0.2, is: "path('m 0 0 Z')"},
+  {at: 0.6, is: "path('m 0 0 Z')"},
+  {at: 1, is: "path('m 0 0 Z')"},
+  {at: 1.4, is: "path('m 0 0 Z')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('M 20 50')",
+  to: "path('M 30 70')"
+}, [
+  {at: -0.4, is: "path('M 16 42')"},
+  {at: 0, is: "path('M 20 50')"},
+  {at: 0.2, is: "path('M 22 54')"},
+  {at: 0.6, is: "path('M 26 62')"},
+  {at: 1, is: "path('M 30 70')"},
+  {at: 1.4, is: "path('M 34 78')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 20 50')",
+  to: "path('m 30 70')"
+}, [
+  {at: -0.4, is: "path('m 16 42')"},
+  {at: 0, is: "path('m 20 50')"},
+  {at: 0.2, is: "path('m 22 54')"},
+  {at: 0.6, is: "path('m 26 62')"},
+  {at: 1, is: "path('m 30 70')"},
+  {at: 1.4, is: "path('m 34 78')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 L 20 50')",
+  to: "path('m 0 0 L 30 70')"
+}, [
+  {at: -0.4, is: "path('m 0 0 L 16 42')"},
+  {at: 0, is: "path('m 0 0 L 20 50')"},
+  {at: 0.2, is: "path('m 0 0 L 22 54')"},
+  {at: 0.6, is: "path('m 0 0 L 26 62')"},
+  {at: 1, is: "path('m 0 0 L 30 70')"},
+  {at: 1.4, is: "path('m 0 0 L 34 78')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 l 20 50')",
+  to: "path('m 0 0 l 30 70')"
+}, [
+  {at: -0.4, is: "path('m 0 0 l 16 42')"},
+  {at: 0, is: "path('m 0 0 l 20 50')"},
+  {at: 0.2, is: "path('m 0 0 l 22 54')"},
+  {at: 0.6, is: "path('m 0 0 l 26 62')"},
+  {at: 1, is: "path('m 0 0 l 30 70')"},
+  {at: 1.4, is: "path('m 0 0 l 34 78')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 C 32 42 52 62 12 22')",
+  to: "path('m 0 0 C 37 47 57 67 17 27')",
+}, [
+  {at: -0.4, is: "path('m 0 0 C 30 40 50 60 10 20')"},
+  {at: 0, is: "path('m 0 0 C 32 42 52 62 12 22')"},
+  {at: 0.2, is: "path('m 0 0 C 33 43 53 63 13 23')"},
+  {at: 0.6, is: "path('m 0 0 C 35 45 55 65 15 25')"},
+  {at: 1, is: "path('m 0 0 C 37 47 57 67 17 27')"},
+  {at: 1.4, is: "path('m 0 0 C 39 49 59 69 19 29')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 c 32 42 52 62 12 22')",
+  to: "path('m 0 0 c 37 47 57 67 17 27')"
+}, [
+  {at: -0.4, is: "path('m 0 0 c 30 40 50 60 10 20')"},
+  {at: 0, is: "path('m 0 0 c 32 42 52 62 12 22')"},
+  {at: 0.2, is: "path('m 0 0 c 33 43 53 63 13 23')"},
+  {at: 0.6, is: "path('m 0 0 c 35 45 55 65 15 25')"},
+  {at: 1, is: "path('m 0 0 c 37 47 57 67 17 27')"},
+  {at: 1.4, is: "path('m 0 0 c 39 49 59 69 19 29')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 Q 32 42 52 62')",
+  to: "path('m 0 0 Q 37 47 57 67')"
+}, [
+  {at: -0.4, is: "path('m 0 0 Q 30 40 50 60')"},
+  {at: 0, is: "path('m 0 0 Q 32 42 52 62')"},
+  {at: 0.2, is: "path('m 0 0 Q 33 43 53 63')"},
+  {at: 0.6, is: "path('m 0 0 Q 35 45 55 65')"},
+  {at: 1, is: "path('m 0 0 Q 37 47 57 67')"},
+  {at: 1.4, is: "path('m 0 0 Q 39 49 59 69')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 q 32 42 52 62')",
+  to: "path('m 0 0 q 37 47 57 67')"
+}, [
+  {at: -0.4, is: "path('m 0 0 q 30 40 50 60')"},
+  {at: 0, is: "path('m 0 0 q 32 42 52 62')"},
+  {at: 0.2, is: "path('m 0 0 q 33 43 53 63')"},
+  {at: 0.6, is: "path('m 0 0 q 35 45 55 65')"},
+  {at: 1, is: "path('m 0 0 q 37 47 57 67')"},
+  {at: 1.4, is: "path('m 0 0 q 39 49 59 69')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 A 10 20 30 1 0 40 50')",
+  to: "path('m 0 0 A 60 70 80 0 1 90 100')"
+}, [
+  {at: -0.4, is: "path('m 0 0 A -10 0 10 1 0 20 30')"},
+  {at: 0, is: "path('m 0 0 A 10 20 30 1 0 40 50')"},
+  {at: 0.2, is: "path('m 0 0 A 20 30 40 1 0 50 60')"},
+  {at: 0.6, is: "path('m 0 0 A 40 50 60 0 1 70 80')"},
+  {at: 1, is: "path('m 0 0 A 60 70 80 0 1 90 100')"},
+  {at: 1.4, is: "path('m 0 0 A 80 90 100 0 1 110 120')"},
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 a 10 20 30 1 0 40 50')",
+  to: "path('m 0 0 a 60 70 80 0 1 90 100')"
+}, [
+  {at: -0.4, is: "path('m 0 0 a -10 0 10 1 0 20 30')"},
+  {at: 0, is: "path('m 0 0 a 10 20 30 1 0 40 50')"},
+  {at: 0.2, is: "path('m 0 0 a 20 30 40 1 0 50 60')"},
+  {at: 0.6, is: "path('m 0 0 a 40 50 60 0 1 70 80')"},
+  {at: 1, is: "path('m 0 0 a 60 70 80 0 1 90 100')"},
+  {at: 1.4, is: "path('m 0 0 a 80 90 100 0 1 110 120')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 H 10')",
+  to: "path('m 0 0 H 60')"
+}, [
+  {at: -0.4, is: "path('m 0 0 H -10')"},
+  {at: 0, is: "path('m 0 0 H 10')"},
+  {at: 0.2, is: "path('m 0 0 H 20')"},
+  {at: 0.6, is: "path('m 0 0 H 40')"},
+  {at: 1, is: "path('m 0 0 H 60')"},
+  {at: 1.4, is: "path('m 0 0 H 80')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 h 10')",
+  to: "path('m 0 0 h 60')"
+}, [
+  {at: -0.4, is: "path('m 0 0 h -10')"},
+  {at: 0, is: "path('m 0 0 h 10')"},
+  {at: 0.2, is: "path('m 0 0 h 20')"},
+  {at: 0.6, is: "path('m 0 0 h 40')"},
+  {at: 1, is: "path('m 0 0 h 60')"},
+  {at: 1.4, is: "path('m 0 0 h 80')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 V 10')",
+  to: "path('m 0 0 V 60')"
+}, [
+  {at: -0.4, is: "path('m 0 0 V -10')"},
+  {at: 0, is: "path('m 0 0 V 10')"},
+  {at: 0.2, is: "path('m 0 0 V 20')"},
+  {at: 0.6, is: "path('m 0 0 V 40')"},
+  {at: 1, is: "path('m 0 0 V 60')"},
+  {at: 1.4, is: "path('m 0 0 V 80')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 v 10')",
+  to: "path('m 0 0 v 60')"
+}, [
+  {at: -0.4, is: "path('m 0 0 v -10')"},
+  {at: 0, is: "path('m 0 0 v 10')"},
+  {at: 0.2, is: "path('m 0 0 v 20')"},
+  {at: 0.6, is: "path('m 0 0 v 40')"},
+  {at: 1, is: "path('m 0 0 v 60')"},
+  {at: 1.4, is: "path('m 0 0 v 80')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 S 32 42 52 62')",
+  to: "path('m 0 0 S 37 47 57 67')"
+}, [
+  {at: -0.4, is: "path('m 0 0 S 30 40 50 60')"},
+  {at: 0, is: "path('m 0 0 S 32 42 52 62')"},
+  {at: 0.2, is: "path('m 0 0 S 33 43 53 63')"},
+  {at: 0.6, is: "path('m 0 0 S 35 45 55 65')"},
+  {at: 1, is: "path('m 0 0 S 37 47 57 67')"},
+  {at: 1.4, is: "path('m 0 0 S 39 49 59 69')"},
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 s 32 42 52 62')",
+  to: "path('m 0 0 s 37 47 57 67')"
+}, [
+  {at: -0.4, is: "path('m 0 0 s 30 40 50 60')"},
+  {at: 0, is: "path('m 0 0 s 32 42 52 62')"},
+  {at: 0.2, is: "path('m 0 0 s 33 43 53 63')"},
+  {at: 0.6, is: "path('m 0 0 s 35 45 55 65')"},
+  {at: 1, is: "path('m 0 0 s 37 47 57 67')"},
+  {at: 1.4, is: "path('m 0 0 s 39 49 59 69')"},
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 T 20 50')",
+  to: "path('m 0 0 T 30 70')"
+}, [
+  {at: -0.4, is: "path('m 0 0 T 16 42')"},
+  {at: 0, is: "path('m 0 0 T 20 50')"},
+  {at: 0.2, is: "path('m 0 0 T 22 54')"},
+  {at: 0.6, is: "path('m 0 0 T 26 62')"},
+  {at: 1, is: "path('m 0 0 T 30 70')"},
+  {at: 1.4, is: "path('m 0 0 T 34 78')"},
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 0 0 t 20 50')",
+  to: "path('m 0 0 t 30 70')"
+}, [
+  {at: -0.4, is: "path('m 0 0 t 16 42')"},
+  {at: 0, is: "path('m 0 0 t 20 50')"},
+  {at: 0.2, is: "path('m 0 0 t 22 54')"},
+  {at: 0.6, is: "path('m 0 0 t 26 62')"},
+  {at: 1, is: "path('m 0 0 t 30 70')"},
+  {at: 1.4, is: "path('m 0 0 t 34 78')"},
+]);
+
+// Mix relative and non-relative
+assertInterpolation({
+  property: 'd',
+  from: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')",
+  to: "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 200 100 z')"
+}, [
+  {at: -0.4, is: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 120 20 Z')"},
+  {at: 0, is: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+  {at: 0.2, is: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 240 140 Z')"},
+  {at: 0.6, is: "path('M 0 0 L 100 100 m 0 100 l 100 0 Z l 120 20 Z')"},
+  {at: 1, is: "path('M 0 0 L 100 100 m 0 100 l 100 0 Z l 200 100 Z')"},
+  {at: 1.4, is: "path('M 0 0 L 100 100 m 0 100 l 100 0 Z l 280 180 Z')"},
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')",
+  to: "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 100 -100 z')"
+}, [
+  {at: -0.4, is: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 160 100 Z')"},
+  {at: 0, is: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+  {at: 0.2, is: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 220 100 Z')"},
+  {at: 0.6, is: "path('M 0 0 L 100 100 m 0 100 l 100 0 Z l 60 -100 Z')"},
+  {at: 1, is: "path('M 0 0 L 100 100 m 0 100 l 100 0 Z l 100 -100 Z')"},
+  {at: 1.4, is: "path('M 0 0 L 100 100 m 0 100 l 100 0 Z l 140 -100 Z')"},
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 10 20 l 20 30 z l 50 60 z m 70 80 l 90 60 z t 70 120')",
+  to: "path('M 110 120 L 130 150 Z L 80 110 Z M 100 140 L 190 200 Z T 210 220')"
+}, [
+  {at: -0.4, is: "path('m -30 -20 l 20 30 Z l 90 100 Z m 90 100 l 90 60 Z t 90 160')"},
+  {at: 0, is: "path('m 10 20 l 20 30 Z l 50 60 Z m 70 80 l 90 60 Z t 70 120')"},
+  {at: 0.2, is: "path('m 30 40 l 20 30 Z l 30 40 Z m 60 70 l 90 60 Z t 60 100')"},
+  {at: 0.6, is: "path('M 70 80 L 90 110 Z L 80 110 Z M 120 160 L 210 220 Z T 250 280')"},
+  {at: 1, is: "path('M 110 120 L 130 150 Z L 80 110 Z M 100 140 L 190 200 Z T 210 220')"},
+  {at: 1.4, is: "path('M 150 160 L 170 190 Z L 80 110 Z M 80 120 L 170 180 Z T 170 160')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 10 20 c 40 50 30 60 80 70 c 90 100 140 110 120 130')",
+  to: "path('M 110 120 C 140 150 130 160 180 170 C 290 300 340 310 320 330')"
+}, [
+  {at: -0.4, is: "path('m -30 -20 c 44 58 34 68 84 78 c 82 88 132 98 112 118')"},
+  {at: 0, is: "path('m 10 20 c 40 50 30 60 80 70 c 90 100 140 110 120 130')"},
+  {at: 0.2, is: "path('m 30 40 c 38 46 28 56 78 66 c 94 106 144 116 124 136')"},
+  {at: 0.6, is: "path('M 70 80 C 104 118 94 128 144 138 C 246 256 296 266 276 286')"},
+  {at: 1, is: "path('M 110 120 C 140 150 130 160 180 170 C 290 300 340 310 320 330')"},
+  {at: 1.4, is: "path('M 150 160 C 176 182 166 192 216 202 C 334 344 384 354 364 374')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 10 20 q 30 60 40 50 q 100 70 90 80')",
+  to: "path('M 110 120 Q 130 160 140 150 Q 200 170 190 180')"
+}, [
+  {at: -0.4, is: "path('m -30 -20 q 34 68 44 58 q 116 90 106 100')"},
+  {at: 0, is: "path('m 10 20 q 30 60 40 50 q 100 70 90 80')"},
+  {at: 0.2, is: "path('m 30 40 q 28 56 38 46 q 92 60 82 70')"},
+  {at: 0.6, is: "path('M 70 80 Q 94 128 104 118 Q 180 158 170 168')"},
+  {at: 1, is: "path('M 110 120 Q 130 160 140 150 Q 200 170 190 180')"},
+  {at: 1.4, is: "path('M 150 160 Q 166 192 176 182 Q 220 182 210 192')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 10 20 s 30 60 40 50 s 100 70 90 80')",
+  to: "path('M 110 120 S 130 160 140 150 S 200 170 190 180')"
+}, [
+  {at: -0.4, is: "path('m -30 -20 s 34 68 44 58 s 116 90 106 100')"},
+  {at: 0, is: "path('m 10 20 s 30 60 40 50 s 100 70 90 80')"},
+  {at: 0.2, is: "path('m 30 40 s 28 56 38 46 s 92 60 82 70')"},
+  {at: 0.6, is: "path('M 70 80 S 94 128 104 118 S 180 158 170 168')"},
+  {at: 1, is: "path('M 110 120 S 130 160 140 150 S 200 170 190 180')"},
+  {at: 1.4, is: "path('M 150 160 S 166 192 176 182 S 220 182 210 192')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 10 20 h 30 v 40 h 50 v 60 l 70 80')",
+  to: "path('M 110 120 H 130 V 140 H 250 V 260 L 270 280')"
+}, [
+  {at: -0.4, is: "path('m -30 -20 h 34 v 48 h 22 v 36 l 90 104')"},
+  {at: 0, is: "path('m 10 20 h 30 v 40 h 50 v 60 l 70 80')"},
+  {at: 0.2, is: "path('m 30 40 h 28 v 36 h 64 v 72 l 60 68')"},
+  {at: 0.6, is: "path('M 70 80 H 94 V 108 H 186 V 204 L 226 248')"},
+  {at: 1, is: "path('M 110 120 H 130 V 140 H 250 V 260 L 270 280')"},
+  {at: 1.4, is: "path('M 150 160 H 166 V 172 H 314 V 316 L 314 312')"}
+]);
+
+assertInterpolation({
+  property: 'd',
+  from: "path('m 10 20 a 10 20 30 1 0 40 50 a 110 120 30 1 1 140 50')",
+  to: "path('M 20 30 A 60 70 80 0 1 90 100 A 160 170 80 0 1 90 100')"
+}, [
+  {at: -0.4, is: "path('m 6 16 a -10 0 10 1 0 28 42 a 90 100 10 1 1 196 70')"},
+  {at: 0, is: "path('m 10 20 a 10 20 30 1 0 40 50 a 110 120 30 1 1 140 50')"},
+  {at: 0.2, is: "path('m 12 22 a 20 30 40 1 0 46 54 a 120 130 40 1 1 112 40')"},
+  {at: 0.6, is: "path('M 16 26 A 40 50 60 0 1 74 88 A 140 150 60 0 1 130 108')"},
+  {at: 1, is: "path('M 20 30 A 60 70 80 0 1 90 100 A 160 170 80 0 1 90 100')"},
+  {at: 1.4, is: "path('M 24 34 A 80 90 100 0 1 106 112 A 180 190 100 0 1 50 92')"}
+]);
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/animations/responsive/d-responsive.html b/third_party/WebKit/LayoutTests/animations/responsive/d-responsive.html
new file mode 100644
index 0000000..af6d311
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/responsive/d-responsive.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<script src="resources/responsive-test.js"></script>
+<script>
+assertCSSResponsive({
+  targetTag: 'path',
+  property: 'd',
+  from: "inherit",
+  to: "path('M 10 20 H 30')",
+  configurations: [{
+    state: {inherited: "path('M 90 60 H 34')"},
+    expect: [
+      {at: 0.25, is: "path('M 70 50 H 33')"},
+      {at: 0.75, is: "path('M 30 30 H 31')"},
+    ],
+  }, {
+    state: {inherited: "path('M 6 0 H 70')"},
+    expect: [
+      {at: 0.25, is: "path('M 7 5 H 60')"},
+      {at: 0.75, is: "path('M 9 15 H 40')"},
+    ],
+  }],
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/animations/responsive/resources/responsive-test.js b/third_party/WebKit/LayoutTests/animations/responsive/resources/responsive-test.js
index 59dcba8..c7e63e7 100644
--- a/third_party/WebKit/LayoutTests/animations/responsive/resources/responsive-test.js
+++ b/third_party/WebKit/LayoutTests/animations/responsive/resources/responsive-test.js
@@ -54,9 +54,19 @@
         return property;
       },
       createTargetContainer(container) {
+        if (options.targetTag) {
+          var svgRoot = createElement('svg', container, 'svg-root', svgNamespace);
+          svgRoot.setAttribute('width', 0);
+          svgRoot.setAttribute('height', 0);
+          return svgRoot;
+        }
+
         return createElement('div', container);
       },
       createTarget(container) {
+        if (options.targetTag)
+          return createElement(options.targetTag, container, 'target', svgNamespace);
+
         return createElement('div', container, 'target');
       },
       setValue(target, property, value) {
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-cx-cy-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-cx-cy-composition.html
new file mode 100644
index 0000000..a296718
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-cx-cy-composition.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html>
+<body>
+<template id="target-template">
+<svg width="90" height="90">
+<ellipse class="target" cx="40" cy="30" rx="20" ry="30" />
+</svg>
+</template>
+<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script>
+<script>
+'use strict';
+
+assertAttributeInterpolation({
+  property: 'cx',
+  underlying: '3',
+  from: '-2',
+  fromComposite: 'add',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'cx',
+  underlying: '3',
+  from: '1',
+  fromComposite: 'replace',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'cx',
+  underlying: '1',
+  from: neutralKeyframe,
+  to: '6',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'cy',
+  underlying: '3',
+  from: '-2',
+  fromComposite: 'add',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'cy',
+  underlying: '3',
+  from: '1',
+  fromComposite: 'replace',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'cy',
+  underlying: '1',
+  from: neutralKeyframe,
+  to: '6',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-fx-fy-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-fx-fy-composition.html
new file mode 100644
index 0000000..c5ab10e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-fx-fy-composition.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html>
+<body>
+<template id="target-template">
+<svg width="90" height="90">
+<radialGradient class="target" />
+</svg>
+</template>
+<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script>
+<script>
+'use strict';
+
+assertAttributeInterpolation({
+  property: 'fx',
+  underlying: '3',
+  from: '-2',
+  fromComposite: 'add',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'fx',
+  underlying: '3',
+  from: '1',
+  fromComposite: 'replace',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'fx',
+  underlying: '1',
+  from: neutralKeyframe,
+  to: '6',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'fy',
+  underlying: '3',
+  from: '-2',
+  fromComposite: 'add',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'fy',
+  underlying: '3',
+  from: '1',
+  fromComposite: 'replace',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'fy',
+  underlying: '1',
+  from: neutralKeyframe,
+  to: '6',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-height-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-height-composition.html
new file mode 100644
index 0000000..65180d4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-height-composition.html
@@ -0,0 +1,341 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/ahem.js"></script>
+<style>
+:root {
+  font: 10px Ahem;
+}
+</style>
+</head>
+<body>
+<template id="target-template">
+<svg width="200px" height="300px" viewBox="0 0 1500 1000">
+  <rect class="target" x="10" y="10" width="10" height="10" />
+</svg>
+</template>
+<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script>
+<script>
+'use strict';
+
+// Same unit
+
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '20',
+  from: '-10',
+  fromComposite: 'add',
+  to: '40',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '20%',
+  from: '-10%',
+  fromComposite: 'add',
+  to: '40%',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0%'},
+  {at: 0, is: '10%'},
+  {at: 0.2, is: '20%'},
+  {at: 0.6, is: '40%'},
+  {at: 1, is: '60%'},
+  {at: 1.4, is: '80%'}
+]);
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '20em',
+  from: '-10em',
+  fromComposite: 'add',
+  to: '40em',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0em'},
+  {at: 0, is: '10em'},
+  {at: 0.2, is: '20em'},
+  {at: 0.6, is: '40em'},
+  {at: 1, is: '60em'},
+  {at: 1.4, is: '80em'}
+]);
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '20ex',
+  from: '-10ex',
+  fromComposite: 'add',
+  to: '40ex',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0ex'},
+  {at: 0, is: '10ex'},
+  {at: 0.2, is: '20ex'},
+  {at: 0.6, is: '40ex'},
+  {at: 1, is: '60ex'},
+  {at: 1.4, is: '80ex'}
+]);
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '20rem',
+  from: '-10rem',
+  fromComposite: 'add',
+  to: '40rem',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0rem'},
+  {at: 0, is: '10rem'},
+  {at: 0.2, is: '20rem'},
+  {at: 0.6, is: '40rem'},
+  {at: 1, is: '60rem'},
+  {at: 1.4, is: '80rem'}
+]);
+
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '20',
+  from: '10',
+  fromComposite: 'replace',
+  to: '40',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '20%',
+  from: '10%',
+  fromComposite: 'replace',
+  to: '40%',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0%'},
+  {at: 0, is: '10%'},
+  {at: 0.2, is: '20%'},
+  {at: 0.6, is: '40%'},
+  {at: 1, is: '60%'},
+  {at: 1.4, is: '80%'}
+]);
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '20em',
+  from: '10em',
+  fromComposite: 'replace',
+  to: '40em',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0em'},
+  {at: 0, is: '10em'},
+  {at: 0.2, is: '20em'},
+  {at: 0.6, is: '40em'},
+  {at: 1, is: '60em'},
+  {at: 1.4, is: '80em'}
+]);
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '20ex',
+  from: '10ex',
+  fromComposite: 'replace',
+  to: '40ex',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0ex'},
+  {at: 0, is: '10ex'},
+  {at: 0.2, is: '20ex'},
+  {at: 0.6, is: '40ex'},
+  {at: 1, is: '60ex'},
+  {at: 1.4, is: '80ex'}
+]);
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '20rem',
+  from: '10rem',
+  fromComposite: 'replace',
+  to: '40rem',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0rem'},
+  {at: 0, is: '10rem'},
+  {at: 0.2, is: '20rem'},
+  {at: 0.6, is: '40rem'},
+  {at: 1, is: '60rem'},
+  {at: 1.4, is: '80rem'}
+]);
+
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '10',
+  from: neutralKeyframe,
+  to: '60',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '10%',
+  from: neutralKeyframe,
+  to: '60%',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '0%'},
+  {at: 0, is: '10%'},
+  {at: 0.2, is: '20%'},
+  {at: 0.6, is: '40%'},
+  {at: 1, is: '60%'},
+  {at: 1.4, is: '80%'}
+]);
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '10em',
+  from: neutralKeyframe,
+  to: '60em',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '0em'},
+  {at: 0, is: '10em'},
+  {at: 0.2, is: '20em'},
+  {at: 0.6, is: '40em'},
+  {at: 1, is: '60em'},
+  {at: 1.4, is: '80em'}
+]);
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '10ex',
+  from: neutralKeyframe,
+  to: '60ex',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '0ex'},
+  {at: 0, is: '10ex'},
+  {at: 0.2, is: '20ex'},
+  {at: 0.6, is: '40ex'},
+  {at: 1, is: '60ex'},
+  {at: 1.4, is: '80ex'}
+]);
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '10rem',
+  from: neutralKeyframe,
+  to: '60rem',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '0rem'},
+  {at: 0, is: '10rem'},
+  {at: 0.2, is: '20rem'},
+  {at: 0.6, is: '40rem'},
+  {at: 1, is: '60rem'},
+  {at: 1.4, is: '80rem'}
+]);
+
+// Mixed units
+
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '10',
+  from: '10mm',
+  fromComposite: 'add',
+  to: '20px',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '54.913387298583984'},
+  {at: 0, is: '47.79527559055118'},
+  {at: 0.2, is: '44.23622131347656'},
+  {at: 0.6, is: '37.11811065673828'},
+  {at: 1, is: '30px'},
+  {at: 1.4, is: '22.881889343261719'}
+]);
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '10mm',
+  from: '10mm',
+  fromComposite: 'add',
+  to: '20px',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '82.70866141732283'},
+  {at: 0, is: '20mm'},
+  {at: 0.2, is: '72.03149606299212'},
+  {at: 0.6, is: '64.91338582677164'},
+  {at: 1, is: '57.79527559055118'},
+  {at: 1.4, is: '50.677165354330704'}
+]);
+
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '10',
+  from: '10mm',
+  fromComposite: 'replace',
+  to: '10px',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '44.913387298583984'},
+  {at: 0, is: '10mm'},
+  {at: 0.2, is: '34.23622131347656'},
+  {at: 0.6, is: '27.11811065673828'},
+  {at: 1, is: '20px'},
+  {at: 1.4, is: '12.881889343261719'}
+]);
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '10mm',
+  from: '20mm',
+  fromComposite: 'replace',
+  to: '20px',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '82.70866141732283'},
+  {at: 0, is: '20mm'},
+  {at: 0.2, is: '72.03149606299212'},
+  {at: 0.6, is: '64.91338582677164'},
+  {at: 1, is: '57.79527559055118'},
+  {at: 1.4, is: '50.677165354330704'}
+]);
+
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '10',
+  from: neutralKeyframe,
+  to: '60px',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'height',
+  underlying: '10mm',
+  from: neutralKeyframe,
+  to: '20px',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '44.913387298583984'},
+  {at: 0, is: '10mm'},
+  {at: 0.2, is: '34.23622131347656'},
+  {at: 0.6, is: '27.11811065673828'},
+  {at: 1, is: '20px'},
+  {at: 1.4, is: '12.881889343261719'}
+]);
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-markerHeight-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-markerHeight-composition.html
new file mode 100644
index 0000000..57e34d7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-markerHeight-composition.html
@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/ahem.js"></script>
+<style>
+:root {
+  font: 10px Ahem;
+}
+</style>
+</head>
+<body>
+<template id="target-template">
+<svg width="200px" height="300px" viewBox="0 0 1500 1000">
+  <marker class="target" />
+</svg>
+</template>
+<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script>
+<script>
+'use strict';
+assertAttributeInterpolation({
+  property: 'markerHeight',
+  underlying: '2',
+  from: '-1',
+  fromComposite: 'add',
+  to: '4',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+assertAttributeInterpolation({
+  property: 'markerHeight',
+  underlying: '1in',
+  from: '9in',
+  fromComposite: 'add',
+  to: '698pt',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '700pt'},
+  {at: 0, is: '720pt'},
+  {at: 0.2, is: '730pt'},
+  {at: 0.6, is: '750pt'},
+  {at: 1, is: '770pt'},
+  {at: 1.4, is: '790pt'}
+]);
+assertAttributeInterpolation({
+  property: 'markerHeight',
+  underlying: '5',
+  from: '5',
+  fromComposite: 'add',
+  to: '19ex',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0'},
+  {at: 0, is: '10'},
+  {at: 0.2, is: '28'},
+  {at: 0.6, is: '64'},
+  {at: 1, is: '100'},
+  {at: 1.4, is: '136'}
+]);
+
+assertAttributeInterpolation({
+  property: 'markerHeight',
+  underlying: '2',
+  from: '1',
+  fromComposite: 'replace',
+  to: '4',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+assertAttributeInterpolation({
+  property: 'markerHeight',
+  underlying: '1in',
+  from: '10in',
+  fromComposite: 'replace',
+  to: '698pt',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '700pt'},
+  {at: 0, is: '720pt'},
+  {at: 0.2, is: '730pt'},
+  {at: 0.6, is: '750pt'},
+  {at: 1, is: '770pt'},
+  {at: 1.4, is: '790pt'}
+]);
+assertAttributeInterpolation({
+  property: 'markerHeight',
+  underlying: '5ex',
+  from: '10',
+  fromComposite: 'replace',
+  to: '15ex',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0'},
+  {at: 0, is: '10'},
+  {at: 0.2, is: '28'},
+  {at: 0.6, is: '64'},
+  {at: 1, is: '100'},
+  {at: 1.4, is: '136'}
+]);
+
+assertAttributeInterpolation({
+  property: 'markerHeight',
+  underlying: '1',
+  from: neutralKeyframe,
+  to: '6',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+assertAttributeInterpolation({
+  property: 'markerHeight',
+  underlying: '10in',
+  from: neutralKeyframe,
+  to: '770pt',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '700pt'},
+  {at: 0, is: '720pt'},
+  {at: 0.2, is: '730pt'},
+  {at: 0.6, is: '750pt'},
+  {at: 1, is: '770pt'},
+  {at: 1.4, is: '790pt'}
+]);
+assertAttributeInterpolation({
+  property: 'markerHeight',
+  underlying: '10',
+  from: neutralKeyframe,
+  to: '20ex',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '0'},
+  {at: 0, is: '10'},
+  {at: 0.2, is: '28'},
+  {at: 0.6, is: '64'},
+  {at: 1, is: '100'},
+  {at: 1.4, is: '136'}
+]);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-markerWidth-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-markerWidth-composition.html
new file mode 100644
index 0000000..92f6c6f3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-markerWidth-composition.html
@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/ahem.js"></script>
+<style>
+:root {
+  font: 10px Ahem;
+}
+</style>
+</head>
+<body>
+<template id="target-template">
+<svg width="200px" height="300px" viewBox="0 0 1500 1000">
+  <marker class="target" />
+</svg>
+</template>
+<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script>
+<script>
+'use strict';
+assertAttributeInterpolation({
+  property: 'markerWidth',
+  underlying: '2',
+  from: '-1',
+  fromComposite: 'add',
+  to: '4',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+assertAttributeInterpolation({
+  property: 'markerWidth',
+  underlying: '1in',
+  from: '9in',
+  fromComposite: 'add',
+  to: '698pt',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '700pt'},
+  {at: 0, is: '720pt'},
+  {at: 0.2, is: '730pt'},
+  {at: 0.6, is: '750pt'},
+  {at: 1, is: '770pt'},
+  {at: 1.4, is: '790pt'}
+]);
+assertAttributeInterpolation({
+  property: 'markerWidth',
+  underlying: '5',
+  from: '5',
+  fromComposite: 'add',
+  to: '19ex',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0'},
+  {at: 0, is: '10'},
+  {at: 0.2, is: '28'},
+  {at: 0.6, is: '64'},
+  {at: 1, is: '100'},
+  {at: 1.4, is: '136'}
+]);
+
+assertAttributeInterpolation({
+  property: 'markerWidth',
+  underlying: '2',
+  from: '1',
+  fromComposite: 'replace',
+  to: '4',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+assertAttributeInterpolation({
+  property: 'markerWidth',
+  underlying: '1in',
+  from: '10in',
+  fromComposite: 'replace',
+  to: '698pt',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '700pt'},
+  {at: 0, is: '720pt'},
+  {at: 0.2, is: '730pt'},
+  {at: 0.6, is: '750pt'},
+  {at: 1, is: '770pt'},
+  {at: 1.4, is: '790pt'}
+]);
+assertAttributeInterpolation({
+  property: 'markerWidth',
+  underlying: '5ex',
+  from: '10',
+  fromComposite: 'replace',
+  to: '15ex',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0'},
+  {at: 0, is: '10'},
+  {at: 0.2, is: '28'},
+  {at: 0.6, is: '64'},
+  {at: 1, is: '100'},
+  {at: 1.4, is: '136'}
+]);
+
+assertAttributeInterpolation({
+  property: 'markerWidth',
+  underlying: '1',
+  from: neutralKeyframe,
+  to: '6',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+assertAttributeInterpolation({
+  property: 'markerWidth',
+  underlying: '10in',
+  from: neutralKeyframe,
+  to: '770pt',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '700pt'},
+  {at: 0, is: '720pt'},
+  {at: 0.2, is: '730pt'},
+  {at: 0.6, is: '750pt'},
+  {at: 1, is: '770pt'},
+  {at: 1.4, is: '790pt'}
+]);
+assertAttributeInterpolation({
+  property: 'markerWidth',
+  underlying: '10',
+  from: neutralKeyframe,
+  to: '20ex',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '0'},
+  {at: 0, is: '10'},
+  {at: 0.2, is: '28'},
+  {at: 0.6, is: '64'},
+  {at: 1, is: '100'},
+  {at: 1.4, is: '136'}
+]);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-r-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-r-composition.html
new file mode 100644
index 0000000..20d1c4b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-r-composition.html
@@ -0,0 +1,155 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+:root {
+  font: 10px Ahem;
+}
+</style>
+</head>
+<body>
+<template id="target-template">
+<svg width="7px" height="17px" viewBox="0 0 140 340">
+<circle class="target" cx="70" cy="70" />
+</svg>
+</template>
+<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script>
+<script>
+'use strict';
+assertAttributeInterpolation({
+  property: 'r',
+  underlying: '5ch',
+  from: '5ch',
+  fromComposite: 'add',
+  to: '55ch',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0ch'},
+  {at: 0, is: '10ch'},
+  {at: 0.2, is: '20ch'},
+  {at: 0.6, is: '40ch'},
+  {at: 1, is: '60ch'},
+  {at: 1.4, is: '80ch'}
+]);
+assertAttributeInterpolation({
+  property: 'r',
+  underlying: '5mm',
+  from: '5mm',
+  fromComposite: 'add',
+  to: '5.5cm',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0mm'},
+  {at: 0, is: '10mm'},
+  {at: 0.2, is: '20mm'},
+  {at: 0.6, is: '40mm'},
+  {at: 1, is: '60mm'},
+  {at: 1.4, is: '80mm'}
+]);
+assertAttributeInterpolation({
+  property: 'r',
+  underlying: '20',
+  from: '10pc',
+  fromComposite: 'add',
+  to: '20ch',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '164'},
+  {at: 0, is: '180'},
+  {at: 0.2, is: '188'},
+  {at: 0.6, is: '204'},
+  {at: 1, is: '220'},
+  {at: 1.4, is: '236'}
+]);
+
+assertAttributeInterpolation({
+  property: 'r',
+  underlying: '20ch',
+  from: '10ch',
+  fromComposite: 'replace',
+  to: '40ch',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0ch'},
+  {at: 0, is: '10ch'},
+  {at: 0.2, is: '20ch'},
+  {at: 0.6, is: '40ch'},
+  {at: 1, is: '60ch'},
+  {at: 1.4, is: '80ch'}
+]);
+assertAttributeInterpolation({
+  property: 'r',
+  underlying: '2cm',
+  from: '10mm',
+  fromComposite: 'replace',
+  to: '4cm',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0mm'},
+  {at: 0, is: '10mm'},
+  {at: 0.2, is: '20mm'},
+  {at: 0.6, is: '40mm'},
+  {at: 1, is: '60mm'},
+  {at: 1.4, is: '80mm'}
+]);
+assertAttributeInterpolation({
+  property: 'r',
+  underlying: '10ch',
+  from: '10pc',
+  fromComposite: 'replace',
+  to: '10ch',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '144'},
+  {at: 0, is: '10pc'},
+  {at: 0.2, is: '168'},
+  {at: 0.6, is: '184'},
+  {at: 1, is: '20ch'},
+  {at: 1.4, is: '216'}
+]);
+
+assertAttributeInterpolation({
+  property: 'r',
+  underlying: '10ch',
+  from: neutralKeyframe,
+  to: '60ch',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '0ch'},
+  {at: 0, is: '10ch'},
+  {at: 0.2, is: '20ch'},
+  {at: 0.6, is: '40ch'},
+  {at: 1, is: '60ch'},
+  {at: 1.4, is: '80ch'}
+]);
+assertAttributeInterpolation({
+  property: 'r',
+  underlying: '10mm',
+  from: neutralKeyframe,
+  to: '6cm',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '0mm'},
+  {at: 0, is: '10mm'},
+  {at: 0.2, is: '20mm'},
+  {at: 0.6, is: '40mm'},
+  {at: 1, is: '60mm'},
+  {at: 1.4, is: '80mm'}
+]);
+assertAttributeInterpolation({
+  property: 'r',
+  underlying: '10pc',
+  from: neutralKeyframe,
+  to: '20ch',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '144'},
+  {at: 0, is: '10pc'},
+  {at: 0.2, is: '168'},
+  {at: 0.6, is: '184'},
+  {at: 1, is: '20ch'},
+  {at: 1.4, is: '216'}
+]);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-refX-refY-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-refX-refY-composition.html
new file mode 100644
index 0000000..94029ca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-refX-refY-composition.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html>
+<body>
+<template id="target-template">
+<svg width="90" height="90">
+<marker class="target" />
+</svg>
+</template>
+<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script>
+<script>
+'use strict';
+
+assertAttributeInterpolation({
+  property: 'refX',
+  underlying: '3',
+  from: '-2',
+  fromComposite: 'add',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'refX',
+  underlying: '3',
+  from: '1',
+  fromComposite: 'replace',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'refX',
+  underlying: '1',
+  from: neutralKeyframe,
+  to: '6',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'refY',
+  underlying: '3',
+  from: '-2',
+  fromComposite: 'add',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'refY',
+  underlying: '3',
+  from: '1',
+  fromComposite: 'replace',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'refY',
+  underlying: '1',
+  from: neutralKeyframe,
+  to: '6',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-rx-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-rx-composition.html
new file mode 100644
index 0000000..95e63f7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-rx-composition.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html>
+<body>
+<template id="target-template">
+<svg width="90" height="90">
+<ellipse class="target" cx="20" cy="20" />
+</svg>
+</template>
+<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script>
+<script>
+'use strict';
+
+assertAttributeInterpolation({
+  property: 'rx',
+  underlying: '3',
+  from: '-2',
+  fromComposite: 'add',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'rx',
+  underlying: '3',
+  from: '1',
+  fromComposite: 'replace',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'rx',
+  underlying: '1',
+  from: neutralKeyframe,
+  to: '6',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'ry',
+  underlying: '3',
+  from: '-2',
+  fromComposite: 'add',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'ry',
+  underlying: '3',
+  from: '1',
+  fromComposite: 'replace',
+  to: '3',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+
+assertAttributeInterpolation({
+  property: 'ry',
+  underlying: '1',
+  from: neutralKeyframe,
+  to: '6',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-startOffset-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-startOffset-composition.html
new file mode 100644
index 0000000..8e159d0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-startOffset-composition.html
@@ -0,0 +1,165 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/ahem.js"></script>
+<style>
+:root {
+  font: 50px Ahem;
+}
+</style>
+</head>
+<body>
+<svg>
+  <defs>
+    <path id="path1" d="m 0 0 h 250 v 250 h -250 z"/>
+  </defs>
+</svg>
+<template id="target-template">
+<svg width="7px" height="17px" viewBox="0 0 140 340">
+  <text text-anchor="middle">
+    <textPath xlink:href="#path1" startOffset="50%" class="target">
+      Text on a path
+    </textPath>
+  </text>
+</svg>
+</template>
+<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script>
+<script>
+'use strict';
+assertAttributeInterpolation({
+  property: 'startOffset',
+  underlying: '2',
+  from: '-1',
+  fromComposite: 'add',
+  to: '4',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+assertAttributeInterpolation({
+  property: 'startOffset',
+  underlying: '1in',
+  from: '9in',
+  fromComposite: 'add',
+  to: '698pt',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '700pt'},
+  {at: 0, is: '720pt'},
+  {at: 0.2, is: '730pt'},
+  {at: 0.6, is: '750pt'},
+  {at: 1, is: '770pt'},
+  {at: 1.4, is: '790pt'}
+]);
+assertAttributeInterpolation({
+  property: 'startOffset',
+  underlying: '40',
+  from: '85',
+  fromComposite: 'add',
+  to: '24ex',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '-225'},
+  {at: 0, is: '125'},
+  {at: 0.2, is: '300'},
+  {at: 0.6, is: '650'},
+  {at: 1, is: '1000'},
+  {at: 1.4, is: '1350'}
+]);
+
+assertAttributeInterpolation({
+  property: 'startOffset',
+  underlying: '2',
+  from: '1',
+  fromComposite: 'replace',
+  to: '4',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+assertAttributeInterpolation({
+  property: 'startOffset',
+  underlying: '50pt',
+  from: '10in',
+  fromComposite: 'replace',
+  to: '720pt',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '700pt'},
+  {at: 0, is: '720pt'},
+  {at: 0.2, is: '730pt'},
+  {at: 0.6, is: '750pt'},
+  {at: 1, is: '770pt'},
+  {at: 1.4, is: '790pt'}
+]);
+assertAttributeInterpolation({
+  property: 'startOffset',
+  underlying: '10ex',
+  from: '125',
+  fromComposite: 'replace',
+  to: '15ex',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '-225'},
+  {at: 0, is: '125'},
+  {at: 0.2, is: '300'},
+  {at: 0.6, is: '650'},
+  {at: 1, is: '1000'},
+  {at: 1.4, is: '1350'}
+]);
+
+assertAttributeInterpolation({
+  property: 'startOffset',
+  underlying: '1',
+  from: neutralKeyframe,
+  to: '6',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+assertAttributeInterpolation({
+  property: 'startOffset',
+  underlying: '10in',
+  from: neutralKeyframe,
+  to: '770pt',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '700pt'},
+  {at: 0, is: '720pt'},
+  {at: 0.2, is: '730pt'},
+  {at: 0.6, is: '750pt'},
+  {at: 1, is: '770pt'},
+  {at: 1.4, is: '790pt'}
+]);
+assertAttributeInterpolation({
+  property: 'startOffset',
+  underlying: '125',
+  from: neutralKeyframe,
+  to: '25ex',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '-225'},
+  {at: 0, is: '125'},
+  {at: 0.2, is: '300'},
+  {at: 0.6, is: '650'},
+  {at: 1, is: '1000'},
+  {at: 1.4, is: '1350'}
+]);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-textLength-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-textLength-composition.html
new file mode 100644
index 0000000..456c546
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-textLength-composition.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<body>
+<template id="target-template">
+<svg width="90" height="90">
+<text class="target" />
+</svg>
+</template>
+<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script>
+<script>
+'use strict';
+assertAttributeInterpolation({
+  property: 'textLength',
+  underlying: '2',
+  from: '-1',
+  fromComposite: 'add',
+  to: '4',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+assertAttributeInterpolation({
+  property: 'textLength',
+  underlying: '2',
+  from: '1',
+  fromComposite: 'replace',
+  to: '4',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+assertAttributeInterpolation({
+  property: 'textLength',
+  underlying: '1',
+  from: neutralKeyframe,
+  to: '6',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-width-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-width-composition.html
new file mode 100644
index 0000000..8d570eb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-width-composition.html
@@ -0,0 +1,341 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/ahem.js"></script>
+<style>
+:root {
+  font: 10px Ahem;
+}
+</style>
+</head>
+<body>
+<template id="target-template">
+<svg width="200px" height="300px" viewBox="0 0 1500 1000">
+  <rect class="target" x="10" y="10" width="10" height="10" />
+</svg>
+</template>
+<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script>
+<script>
+'use strict';
+
+// Same unit
+
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '20',
+  from: '-10',
+  fromComposite: 'add',
+  to: '40',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '20%',
+  from: '-10%',
+  fromComposite: 'add',
+  to: '40%',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0%'},
+  {at: 0, is: '10%'},
+  {at: 0.2, is: '20%'},
+  {at: 0.6, is: '40%'},
+  {at: 1, is: '60%'},
+  {at: 1.4, is: '80%'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '20em',
+  from: '-10em',
+  fromComposite: 'add',
+  to: '40em',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0em'},
+  {at: 0, is: '10em'},
+  {at: 0.2, is: '20em'},
+  {at: 0.6, is: '40em'},
+  {at: 1, is: '60em'},
+  {at: 1.4, is: '80em'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '20ex',
+  from: '-10ex',
+  fromComposite: 'add',
+  to: '40ex',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0ex'},
+  {at: 0, is: '10ex'},
+  {at: 0.2, is: '20ex'},
+  {at: 0.6, is: '40ex'},
+  {at: 1, is: '60ex'},
+  {at: 1.4, is: '80ex'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '20rem',
+  from: '-10rem',
+  fromComposite: 'add',
+  to: '40rem',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0rem'},
+  {at: 0, is: '10rem'},
+  {at: 0.2, is: '20rem'},
+  {at: 0.6, is: '40rem'},
+  {at: 1, is: '60rem'},
+  {at: 1.4, is: '80rem'}
+]);
+
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '20',
+  from: '10',
+  fromComposite: 'replace',
+  to: '40',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '20%',
+  from: '10%',
+  fromComposite: 'replace',
+  to: '40%',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0%'},
+  {at: 0, is: '10%'},
+  {at: 0.2, is: '20%'},
+  {at: 0.6, is: '40%'},
+  {at: 1, is: '60%'},
+  {at: 1.4, is: '80%'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '20em',
+  from: '10em',
+  fromComposite: 'replace',
+  to: '40em',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0em'},
+  {at: 0, is: '10em'},
+  {at: 0.2, is: '20em'},
+  {at: 0.6, is: '40em'},
+  {at: 1, is: '60em'},
+  {at: 1.4, is: '80em'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '20ex',
+  from: '10ex',
+  fromComposite: 'replace',
+  to: '40ex',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0ex'},
+  {at: 0, is: '10ex'},
+  {at: 0.2, is: '20ex'},
+  {at: 0.6, is: '40ex'},
+  {at: 1, is: '60ex'},
+  {at: 1.4, is: '80ex'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '20rem',
+  from: '10rem',
+  fromComposite: 'replace',
+  to: '40rem',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '0rem'},
+  {at: 0, is: '10rem'},
+  {at: 0.2, is: '20rem'},
+  {at: 0.6, is: '40rem'},
+  {at: 1, is: '60rem'},
+  {at: 1.4, is: '80rem'}
+]);
+
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '10',
+  from: neutralKeyframe,
+  to: '60',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '10%',
+  from: neutralKeyframe,
+  to: '60%',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '0%'},
+  {at: 0, is: '10%'},
+  {at: 0.2, is: '20%'},
+  {at: 0.6, is: '40%'},
+  {at: 1, is: '60%'},
+  {at: 1.4, is: '80%'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '10em',
+  from: neutralKeyframe,
+  to: '60em',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '0em'},
+  {at: 0, is: '10em'},
+  {at: 0.2, is: '20em'},
+  {at: 0.6, is: '40em'},
+  {at: 1, is: '60em'},
+  {at: 1.4, is: '80em'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '10ex',
+  from: neutralKeyframe,
+  to: '60ex',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '0ex'},
+  {at: 0, is: '10ex'},
+  {at: 0.2, is: '20ex'},
+  {at: 0.6, is: '40ex'},
+  {at: 1, is: '60ex'},
+  {at: 1.4, is: '80ex'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '10rem',
+  from: neutralKeyframe,
+  to: '60rem',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '0rem'},
+  {at: 0, is: '10rem'},
+  {at: 0.2, is: '20rem'},
+  {at: 0.6, is: '40rem'},
+  {at: 1, is: '60rem'},
+  {at: 1.4, is: '80rem'}
+]);
+
+// Mixed units
+
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '10',
+  from: '10mm',
+  fromComposite: 'add',
+  to: '20px',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '54.913387298583984'},
+  {at: 0, is: '47.79527559055118'},
+  {at: 0.2, is: '44.23622131347656'},
+  {at: 0.6, is: '37.11811065673828'},
+  {at: 1, is: '30px'},
+  {at: 1.4, is: '22.881889343261719'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '10mm',
+  from: '10mm',
+  fromComposite: 'add',
+  to: '20px',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '82.70866141732283'},
+  {at: 0, is: '20mm'},
+  {at: 0.2, is: '72.03149606299212'},
+  {at: 0.6, is: '64.91338582677164'},
+  {at: 1, is: '57.79527559055118'},
+  {at: 1.4, is: '50.677165354330704'}
+]);
+
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '10',
+  from: '10mm',
+  fromComposite: 'replace',
+  to: '10px',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '44.913387298583984'},
+  {at: 0, is: '10mm'},
+  {at: 0.2, is: '34.23622131347656'},
+  {at: 0.6, is: '27.11811065673828'},
+  {at: 1, is: '20px'},
+  {at: 1.4, is: '12.881889343261719'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '10mm',
+  from: '20mm',
+  fromComposite: 'replace',
+  to: '20px',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: '82.70866141732283'},
+  {at: 0, is: '20mm'},
+  {at: 0.2, is: '72.03149606299212'},
+  {at: 0.6, is: '64.91338582677164'},
+  {at: 1, is: '57.79527559055118'},
+  {at: 1.4, is: '50.677165354330704'}
+]);
+
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '10',
+  from: neutralKeyframe,
+  to: '60px',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: 0},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  underlying: '10mm',
+  from: neutralKeyframe,
+  to: '20px',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: '44.913387298583984'},
+  {at: 0, is: '10mm'},
+  {at: 0.2, is: '34.23622131347656'},
+  {at: 0.6, is: '27.11811065673828'},
+  {at: 1, is: '20px'},
+  {at: 1.4, is: '12.881889343261719'}
+]);
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-x-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-x-composition.html
new file mode 100644
index 0000000..cc8fac6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-x-composition.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+<body>
+<template id="target-template">
+<svg width="90" height="90">
+<!-- In text positioning elements, x is a list.
+     See svg-y-interpolation.html for an example. -->
+<rect class="target" x="10" y="10" width="20" height="20" />
+</svg>
+</template>
+<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script>
+<script>
+'use strict';
+assertAttributeInterpolation({
+  property: 'x',
+  underlying: '2',
+  from: '-1',
+  fromComposite: 'add',
+  to: '4',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+assertAttributeInterpolation({
+  property: 'x',
+  underlying: '2',
+  from: '1',
+  fromComposite: 'replace',
+  to: '4',
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+assertAttributeInterpolation({
+  property: 'x',
+  underlying: '1',
+  from: neutralKeyframe,
+  to: '6',
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: -1},
+  {at: 0, is: 1},
+  {at: 0.2, is: 2},
+  {at: 0.6, is: 4},
+  {at: 1, is: 6},
+  {at: 1.4, is: 8}
+]);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-x1-x2-y1-y2-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-x1-x2-y1-y2-composition.html
new file mode 100644
index 0000000..f8c82695
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-x1-x2-y1-y2-composition.html
@@ -0,0 +1,192 @@
+<!DOCTYPE html>
+<html>
+<body>
+<template id="target-template">
+<svg width="90" height="90">
+<line class="target" x1="10" y1="10" x2="60" y2="60" />
+</svg>
+</template>
+<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script>
+<script>
+'use strict';
+assertAttributeInterpolation({
+  property: 'x1',
+  underlying: 20,
+  from: -10,
+  fromComposite: 'add',
+  to: 40,
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -10},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'x2',
+  underlying: 20,
+  from: -10,
+  fromComposite: 'add',
+  to: 40,
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -10},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'y1',
+  underlying: 20,
+  from: -10,
+  fromComposite: 'add',
+  to: 40,
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -10},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'y2',
+  underlying: 20,
+  from: -10,
+  fromComposite: 'add',
+  to: 40,
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -10},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+
+assertAttributeInterpolation({
+  property: 'x1',
+  underlying: 20,
+  from: 10,
+  fromComposite: 'replace',
+  to: 40,
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -10},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'x2',
+  underlying: 20,
+  from: 10,
+  fromComposite: 'replace',
+  to: 40,
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -10},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'y1',
+  underlying: 20,
+  from: 10,
+  fromComposite: 'replace',
+  to: 40,
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -10},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'y2',
+  underlying: 20,
+  from: 10,
+  fromComposite: 'replace',
+  to: 40,
+  toComposite: 'add'
+}, [
+  {at: -0.4, is: -10},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+
+assertAttributeInterpolation({
+  property: 'x1',
+  underlying: 10,
+  from: neutralKeyframe,
+  to: 60,
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: -10},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'x2',
+  underlying: 10,
+  from: neutralKeyframe,
+  to: 60,
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: -10},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'y1',
+  underlying: 10,
+  from: neutralKeyframe,
+  to: 60,
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: -10},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+assertAttributeInterpolation({
+  property: 'y2',
+  underlying: 10,
+  from: neutralKeyframe,
+  to: 60,
+  toComposite: 'replace'
+}, [
+  {at: -0.4, is: -10},
+  {at: 0, is: 10},
+  {at: 0.2, is: 20},
+  {at: 0.6, is: 40},
+  {at: 1, is: 60},
+  {at: 1.4, is: 80}
+]);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-element-css-animation-crash.html b/third_party/WebKit/LayoutTests/animations/svg-element-css-animation-crash.html
new file mode 100644
index 0000000..a66769c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/svg-element-css-animation-crash.html
@@ -0,0 +1,16 @@
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<style>
+@keyframes crash {
+  to {color: green;}
+}
+rect {
+  animation: crash 100s;
+}
+</style>
+<svg>
+  <rect></rect>
+</svg>
+<script>
+test(() => {}, 'This test passes if it does not crash.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/compositing/layer-creation/should-invoke-deferred-compositing-expected.txt b/third_party/WebKit/LayoutTests/compositing/layer-creation/should-invoke-deferred-compositing-expected.txt
index 4a81d2d..d6d864d 100644
--- a/third_party/WebKit/LayoutTests/compositing/layer-creation/should-invoke-deferred-compositing-expected.txt
+++ b/third_party/WebKit/LayoutTests/compositing/layer-creation/should-invoke-deferred-compositing-expected.txt
@@ -8,9 +8,6 @@
       "children": [
         {
           "bounds": [300, 300],
-          "paintInvalidationClients": [
-            "LayoutHTMLCanvas (positioned) CANVAS"
-          ],
           "children": [
             {
               "bounds": [200, 200],
diff --git a/third_party/WebKit/LayoutTests/compositing/repaint/clipping-should-not-repaint-composited-descendants-expected.txt b/third_party/WebKit/LayoutTests/compositing/repaint/clipping-should-not-repaint-composited-descendants-expected.txt
index 47714b5..0be25f8d 100644
--- a/third_party/WebKit/LayoutTests/compositing/repaint/clipping-should-not-repaint-composited-descendants-expected.txt
+++ b/third_party/WebKit/LayoutTests/compositing/repaint/clipping-should-not-repaint-composited-descendants-expected.txt
@@ -9,9 +9,6 @@
         {
           "position": [108, 108],
           "bounds": [100, 100],
-          "paintInvalidationClients": [
-            "LayoutBlockFlow (positioned) DIV class='clipping-container'"
-          ],
           "children": [
             {
               "bounds": [100, 100],
@@ -30,9 +27,6 @@
         {
           "position": [108, 408],
           "bounds": [100, 100],
-          "paintInvalidationClients": [
-            "LayoutBlockFlow (positioned) DIV class='clipping-container with-initial-clipping'"
-          ],
           "children": [
             {
               "bounds": [100, 100],
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-drawImage-out-of-bounds-src.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-drawImage-out-of-bounds-src.html
index e2afad9..85173363 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-drawImage-out-of-bounds-src.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-drawImage-out-of-bounds-src.html
@@ -36,17 +36,15 @@
 ctx1.drawImage(bgcanvas, 0,    0,    100, 200, 75,  175, 100, 100);
 ctx1.drawImage(bgcanvas, 0,    0,    200, 200, 175, 175, 100, 100);
 
-img.onload = function() {
-    ctx2.drawImage(img, -100, -100, 300, 300, -25, -25, 300, 300);
-    ctx2.drawImage(img, -100, -100, 200, 200, -25, -25, 100, 100);
-    ctx2.drawImage(img, 0,    -100, 100, 200, 75,  -25, 100, 100);
-    ctx2.drawImage(img, 0,    -100, 200, 200, 175, -25, 100, 100);
-    ctx2.drawImage(img, -100, 0,    200, 100, -25, 75,  100, 100);
-    ctx2.drawImage(img, 0,  0,      200, 100, 175, 75,  100, 100);
-    ctx2.drawImage(img, -100, 0,    200, 200, -25, 175, 100, 100);
-    ctx2.drawImage(img, 0,    0,    100, 200, 75,  175, 100, 100);
-    ctx2.drawImage(img, 0,    0,    200, 200, 175, 175, 100, 100);
-}
+ctx2.drawImage(img, -100, -100, 300, 300, -25, -25, 300, 300);
+ctx2.drawImage(img, -100, -100, 200, 200, -25, -25, 100, 100);
+ctx2.drawImage(img, 0,    -100, 100, 200, 75,  -25, 100, 100);
+ctx2.drawImage(img, 0,    -100, 200, 200, 175, -25, 100, 100);
+ctx2.drawImage(img, -100, 0,    200, 100, -25, 75,  100, 100);
+ctx2.drawImage(img, 0,  0,      200, 100, 175, 75,  100, 100);
+ctx2.drawImage(img, -100, 0,    200, 200, -25, 175, 100, 100);
+ctx2.drawImage(img, 0,    0,    100, 200, 75,  175, 100, 100);
+ctx2.drawImage(img, 0,    0,    200, 200, 175, 175, 100, 100);
 
 if (window.testRunner) {
     testRunner.waitUntilDone();
@@ -98,4 +96,4 @@
 }
 
 </script>
-</body></html>
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLImageElement/image-async-loading-data-uris.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLImageElement/image-async-loading-data-uris.html
deleted file mode 100644
index 458b84930b..0000000
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLImageElement/image-async-loading-data-uris.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script>
-    test(function() {
-        var img = new Image();
-        img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=";
-        assert_equals(img.width, 0);
-    }, "Test that a data URI resource doesn't get loaded synchronously");
-</script>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/shadow/labelsnodelist-in-shadow.html b/third_party/WebKit/LayoutTests/fast/dom/shadow/labelsnodelist-in-shadow.html
new file mode 100644
index 0000000..2afeffd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/shadow/labelsnodelist-in-shadow.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<body>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+    var host = document.createElement('div');
+    var root = host.attachShadow({mode: 'open'});
+    root.innerHTML = '<input id="i1"><label for="i1"></label>';
+    assert_equals(root.firstChild.labels.length, 1);
+
+    document.body.appendChild(host);
+    assert_equals(root.firstChild.labels.length, 1);
+}, 'LabelsNodeList should work in Shadow DOM.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/shadow/radionodelist-in-shadow.html b/third_party/WebKit/LayoutTests/fast/dom/shadow/radionodelist-in-shadow.html
new file mode 100644
index 0000000..64fa74b3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/shadow/radionodelist-in-shadow.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<body>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+    var host = document.createElement('div');
+    var root = host.attachShadow({mode: 'open'});
+    root.innerHTML = '<form id="f1"><input name="n"><select name="n"></select></form>';
+    assert_equals(root.firstChild.elements.n.length, 2);
+    assert_equals(root.firstChild.n.length, 2);
+
+    document.body.appendChild(host);
+    assert_equals(root.firstChild.elements.n.length, 2);
+    assert_equals(root.firstChild.n.length, 2);
+}, 'RadioNodeList should work in Shadow DOM.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/basic-buttons.html b/third_party/WebKit/LayoutTests/fast/forms/basic-buttons.html
index 47fbe97..1ff9824 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/basic-buttons.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/basic-buttons.html
@@ -48,10 +48,8 @@
     }
 }
 
-window.onload = function() {
-    printSize('button');
-    printSize('input');
-};
+printSize('button');
+printSize('input');
 </script>
 
 </body> 
diff --git a/third_party/WebKit/LayoutTests/fast/images/color-profile-munsell-srgb-to-srgb.html b/third_party/WebKit/LayoutTests/fast/images/color-profile-munsell-srgb-to-srgb.html
new file mode 100644
index 0000000..38420604
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/images/color-profile-munsell-srgb-to-srgb.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<script src="resources/color-checker-munsell-chart.js"></script>
+
+<style id="some-for-manual-tests">
+  div { position: relative; top: -556px; left: 470px }
+  a:hover { background-color: #ccc }
+  a:link { text-decoration: none }
+</style>
+
+<!-- Color accuracy test case: you should not rebaseline this test. -->
+
+<body style="overflow: hidden">
+  <img><p><canvas></canvas></p>
+  <div>
+   <pre id="log" style="font-size: 9pt"></pre>
+   <a href="http://www.brucelindbloom.com/index.html?ColorCheckerRGB.html">
+    <pre>* Munsell Cyan is outside 255 sRGB gamut<pre></a>
+  <div>
+</body>
+
+<script>
+if (window.testRunner) {
+  testRunner.dumpAsTextWithPixelResults();
+  testRunner.waitUntilDone();
+}
+
+window.onload = function() {
+  if (window.internals)
+    internals.settings.setImageColorProfilesEnabled(true);
+
+  testImageColors('resources/color-checker-srgb-color-profile.png');
+};
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/images/resources/color-checker-munsell-chart.js b/third_party/WebKit/LayoutTests/fast/images/resources/color-checker-munsell-chart.js
new file mode 100644
index 0000000..2f494b3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/images/resources/color-checker-munsell-chart.js
@@ -0,0 +1,137 @@
+function log(message) {
+  document.getElementById('log').textContent += message + '\n';
+}
+
+function testImageColors(source) {
+  var image = document.querySelector('img');
+
+  image.onload = function() {
+    runAfterLayoutAndPaint(window.testRunner ? changeColorProfile : profileChanged);
+  };
+
+  image.src = source;
+}
+
+function changeColorProfile() {
+  /* The test image contains the Munsell colors in a known color space. Convert
+   * the colors to sRGB color space and test the transformed color accuracy.
+   */
+  window.testRunner.setColorProfile('sRGB', profileChanged);
+}
+
+function profileChanged() {
+  setTimeout(drawImageToCanvas, 0);
+}
+
+function drawImageToCanvas() {
+  var image = document.querySelector('img');
+
+  var canvas = document.querySelector('canvas');
+  canvas.width = image.width;
+  canvas.height = image.height;
+
+  canvas.getContext('2d').drawImage(image, 0, 0, canvas.width, canvas.height);
+  chartColorTransform(canvas);
+}
+
+function getCanvasColor(canvas, i) {
+  var x = 40 + (i % 6) * (canvas.width / 6);
+  var y = 40 + Math.floor(i / 6) * (canvas.height / 4);
+  try {
+    var data = canvas.getContext('2d').getImageData(x, y, 1, 1).data;
+    if (data[3] == 255)
+      return { rgb: [data[0], data[1], data[2]] };
+    return { rgb: [0, 0, 0] };
+  } catch (error) {
+    console.error(error);
+    return { rgb: [255, 255, 255] };
+  }
+}
+
+function getMunsellColor(i) {
+  if (!window.munsell_srgb_colors) {
+    window.munsell_srgb_colors = new Array( // Munsell colors in sRGB space.
+      { color: 'Dark Skin',     rgb: [ 115,  80,  64 ] },
+      { color: 'Light Skin',    rgb: [ 195, 151, 130 ] },
+      { color: 'Blue Sky',      rgb: [  94, 123, 156 ] },
+      { color: 'Foliage',       rgb: [  88, 108,  65 ] },
+      { color: 'Blue Flower',   rgb: [ 130, 129, 177 ] },
+      { color: 'Bluish Green',  rgb: [ 100, 190, 171 ] },
+      { color: 'Orange',        rgb: [ 217, 122,  37 ] },
+      { color: 'Purplish Blue', rgb: [  72,  91, 165 ] },
+      { color: 'Moderate Red',  rgb: [ 194,  84,  98 ] },
+      { color: 'Purple',        rgb: [  91,  59, 107 ] },
+      { color: 'Yellow Green',  rgb: [ 160, 188,  60 ] },
+      { color: 'Orange Yellow', rgb: [ 230, 163,  42 ] },
+      { color: 'Blue',          rgb: [  46,  60, 153 ] },
+      { color: 'Green',         rgb: [  71, 150,  69 ] },
+      { color: 'Red',           rgb: [ 177,  44,  56 ] },
+      { color: 'Yellow',        rgb: [ 238, 200,  27 ] },
+      { color: 'Magenta',       rgb: [ 187,  82, 148 ] },
+      { color: 'Cyan (*)',      rgb: [ /* -49 */ 0, 135, 166 ] },
+      { color: 'White',         rgb: [ 243, 242, 237 ] },
+      { color: 'Neutral 8',     rgb: [ 201, 201, 201 ] },
+      { color: 'Neutral 6.5',   rgb: [ 161, 161, 161 ] },
+      { color: 'Neutral 5',     rgb: [ 122, 122, 121 ] },
+      { color: 'Neutral 3.5',   rgb: [  83,  83,  83 ] },
+      { color: 'Black',         rgb: [  50,  49,  50 ] }
+    );
+  }
+
+  if (i < 0 && i >= munsell_srgb_colors.length)
+    return { color: 'invalid-color', rgb: [ 0, 0, 0 ] };
+  return munsell_srgb_colors[i];
+}
+
+function getColorError(cx, cy) {
+  var dr = (cx[0] - cy[0]);
+  var dg = (cx[1] - cy[1]);
+  var db = (cx[2] - cy[2]);
+  return Math.round(Math.sqrt((dr * dr) + (dg * dg) + (db * db)));
+}
+
+function pad(string, size) {
+  size = size || 14;
+  if (string.length < size)
+    string += ' '.repeat(size - string.length);
+  return string;
+}
+
+function drawRule(size) {
+  log('-'.repeat(size || 44));
+}
+
+function chartColorTransform(canvas) {
+  /*
+   * Add header over table of color names, acutal and expected values, and the
+   * per color error (Euclidean distance).
+   */
+  log(pad('Color') + pad('Actual') + pad('Expected') + 'dE');
+  drawRule();
+
+  var totalSquaredError = 0.0;
+
+  /*
+   * Report per color error dE, by comparing with the expected Munsell colors.
+   */
+  for (var i = 0; i < 24;) {
+    var expected = getMunsellColor(i);
+    var actual = getCanvasColor(canvas, i);
+    var dE = getColorError(actual.rgb, expected.rgb);
+
+    log(pad(expected.color) + pad(actual.rgb.join(',')) + pad(expected.rgb.join(',')) + dE);
+    totalSquaredError += dE * dE;
+
+    if (++i % 6 == 0 && i < 24)
+      drawRule();
+  }
+
+  /*
+   * Report the total RMS color error neglecting out-of-srgb-gamut color Cyan.
+   */
+  drawRule();
+  log('\nResult: total RMS color error: ' + Math.sqrt(totalSquaredError / 24.0).toFixed(2));
+
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/dont-invalidate-root-layer-when-composited-layer-becomes-visible-expected.txt b/third_party/WebKit/LayoutTests/fast/repaint/dont-invalidate-root-layer-when-composited-layer-becomes-visible-expected.txt
index 7c57cae99..3120f82 100644
--- a/third_party/WebKit/LayoutTests/fast/repaint/dont-invalidate-root-layer-when-composited-layer-becomes-visible-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/repaint/dont-invalidate-root-layer-when-composited-layer-becomes-visible-expected.txt
@@ -11,10 +11,7 @@
       "children": [
         {
           "position": [200, 200],
-          "bounds": [200, 200],
-          "paintInvalidationClients": [
-            "LayoutBlockFlow (positioned) DIV id='target'"
-          ]
+          "bounds": [200, 200]
         }
       ]
     }
diff --git a/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/response-stream-construction.js b/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/response-stream-construction.js
deleted file mode 100644
index 40b4da7..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/response-stream-construction.js
+++ /dev/null
@@ -1,96 +0,0 @@
-// This file contains tests for Response construction with a readable stream.
-// Move these tests to response.js once the feature gets stable.
-
-if (self.importScripts) {
-  importScripts('../resources/fetch-test-helpers.js');
-  importScripts('/streams/resources/rs-utils.js');
-}
-
-test(() => {
-    var controller;
-    var stream = new ReadableStream({start: c => controller = c});
-
-    var response = new Response(stream);
-    // TODO(yhirano): This should be assert_equals.
-    assert_not_equals(response.body, stream);
-  }, 'Response constructed with a stream');
-
-promise_test(() => {
-    var controller;
-    var stream = new ReadableStream({start: c => controller = c});
-    controller.enqueue(new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0x6f]));
-    controller.enqueue(new Uint8Array([0x77, 0x6f, 0x72, 0x6c, 0x64]));
-    controller.close();
-    assert_false(stream.locked);
-    var response = new Response(stream);
-    var p = response.text().then(t => {
-        assert_equals(t, 'helloworld');
-      });
-    assert_true(stream.locked);
-    return p;
-  }, 'Response constructed with a stream');
-
-promise_test(() => {
-    var controller;
-    var stream = new ReadableStream({start: c => controller = c});
-    controller.enqueue(new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0x6f]));
-    controller.enqueue(new Uint8Array([0x77, 0x6f, 0x72, 0x6c, 0x64]));
-    controller.close();
-
-    var response = new Response(stream);
-    return readableStreamToArray(response.body).then(chunks => {
-        var decoder = new TextDecoder('utf-8');
-        var r = '';
-        for (var chunk of chunks) {
-          r += decoder.decode(chunk, {stream: true});
-        }
-        r += decoder.decode();
-        assert_equals(r, 'helloworld');
-      });
-  }, 'Response constructed with a stream / Read from body stream');
-
-promise_test(t => {
-    var controller;
-    var stream = new ReadableStream({start: c => controller = c});
-    setTimeout(() => {
-        controller.enqueue(new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0x6f]));
-        controller.enqueue(new Uint8Array([0x77, 0x6f, 0x72, 0x6c, 0x64]));
-        controller.error();
-    }, 1);
-    var response = new Response(stream);
-    return promise_rejects(t, TypeError(), response.text());
-  }, 'Response constructed with an errored stream');
-
-promise_test(t => {
-    var controller;
-    var stream = new ReadableStream({start: c => controller = c});
-    stream.getReader();
-    var response = new Response(stream);
-    return promise_rejects(t, TypeError(), response.text());
-  }, 'Response constructed with a locked stream');
-
-promise_test(t => {
-    var controller;
-    var stream = new ReadableStream({start: c => controller = c});
-    setTimeout(() => controller.enqueue(), 1);
-    var response = new Response(stream);
-    return promise_rejects(t, TypeError(), response.text());
-  }, 'Response constructed stream with an undefined chunk');
-
-promise_test(t => {
-    var controller;
-    var stream = new ReadableStream({start: c => controller = c});
-    setTimeout(() => controller.enqueue(null), 1);
-    var response = new Response(stream);
-    return promise_rejects(t, TypeError(), response.text());
-  }, 'Response constructed stream with a null chunk');
-
-promise_test(t => {
-    var controller;
-    var stream = new ReadableStream({start: c => controller = c});
-    setTimeout(() => controller.enqueue('hello'), 1);
-    var response = new Response(stream);
-    return promise_rejects(t, TypeError(), response.text());
-  }, 'Response constructed stream with a string chunk');
-
-done();
diff --git a/third_party/WebKit/LayoutTests/http/tests/fetch/serviceworker/response-stream-construction-base-https-other-https.html b/third_party/WebKit/LayoutTests/http/tests/fetch/serviceworker/response-stream-construction-base-https-other-https.html
deleted file mode 100644
index f5de1cff..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/fetch/serviceworker/response-stream-construction-base-https-other-https.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!doctype html>
-<head>
-<meta name="timeout" content="long"></meta>
-<script src = "/resources/testharness.js"></script>
-<script src = "/resources/testharnessreport.js"></script>
-<script src = "/serviceworker/resources/test-helpers.js"></script>
-</head>
-<body>
-<script>
-function start(t) {
-  service_worker_test(
-    '../script-tests/response-stream-construction.js?-base-https-other-https',
-    'response-stream-construction');
-  t.done();
-}
-function init() {
-  return Promise.resolve();
-}
-</script>
-<script src = "../resources/init.js"></script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/fetch/serviceworker/response-stream-construction.html b/third_party/WebKit/LayoutTests/http/tests/fetch/serviceworker/response-stream-construction.html
deleted file mode 100644
index 1297ef32..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/fetch/serviceworker/response-stream-construction.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!doctype html>
-<head>
-<meta name="timeout" content="long"></meta>
-<script src = "/resources/testharness.js"></script>
-<script src = "/resources/testharnessreport.js"></script>
-<script src = "/serviceworker/resources/test-helpers.js"></script>
-</head>
-<body>
-<script>
-function start(t) {
-  service_worker_test(
-    '../script-tests/response-stream-construction.js?',
-    'response-stream-construction');
-  t.done();
-}
-function init() {
-  return Promise.resolve();
-}
-</script>
-<script src = "../resources/init.js"></script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/fetch/window/response-stream-construction-base-https-other-https.html b/third_party/WebKit/LayoutTests/http/tests/fetch/window/response-stream-construction-base-https-other-https.html
deleted file mode 100644
index 793e160..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/fetch/window/response-stream-construction-base-https-other-https.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!doctype html>
-<head>
-<meta name="timeout" content="long"></meta>
-<script src = "/resources/testharness.js"></script>
-<script src = "/resources/testharness-helpers.js"></script>
-<script src = "/resources/testharnessreport.js"></script>
-<script src = "/serviceworker/resources/test-helpers.js"></script>
-<script src = "../resources/fetch-test-options.js"></script>
-<script src = "../resources/fetch-test-helpers.js"></script>
-<script src = "/streams/resources/rs-utils.js"></script>
-</head>
-<body>
-<script>
-function start(t) {
-  var script = document.createElement('script');
-  script.src = '../script-tests/response-stream-construction.js?-base-https-other-https';
-  script.addEventListener(
-    'error',
-    function() { unreached_rejection(t); });
-  script.addEventListener(
-    'load',
-    function() { t.done(); });
-  document.body.appendChild(script);
-}
-function init() {
-  return Promise.resolve();
-}
-</script>
-<script src = "../resources/init.js"></script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/fetch/window/response-stream-construction.html b/third_party/WebKit/LayoutTests/http/tests/fetch/window/response-stream-construction.html
deleted file mode 100644
index 9cf6bbb..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/fetch/window/response-stream-construction.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!doctype html>
-<head>
-<meta name="timeout" content="long"></meta>
-<script src = "/resources/testharness.js"></script>
-<script src = "/resources/testharness-helpers.js"></script>
-<script src = "/resources/testharnessreport.js"></script>
-<script src = "/serviceworker/resources/test-helpers.js"></script>
-<script src = "../resources/fetch-test-options.js"></script>
-<script src = "../resources/fetch-test-helpers.js"></script>
-<script src = "/streams/resources/rs-utils.js"></script>
-</head>
-<body>
-<script>
-function start(t) {
-  var script = document.createElement('script');
-  script.src = '../script-tests/response-stream-construction.js?';
-  script.addEventListener(
-    'error',
-    function() { unreached_rejection(t); });
-  script.addEventListener(
-    'load',
-    function() { t.done(); });
-  document.body.appendChild(script);
-}
-function init() {
-  return Promise.resolve();
-}
-</script>
-<script src = "../resources/init.js"></script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/fetch/workers/response-stream-construction-base-https-other-https.html b/third_party/WebKit/LayoutTests/http/tests/fetch/workers/response-stream-construction-base-https-other-https.html
deleted file mode 100644
index 930d670..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/fetch/workers/response-stream-construction-base-https-other-https.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!doctype html>
-<head>
-<meta name="timeout" content="long"></meta>
-<script src = "/resources/testharness.js"></script>
-<script src = "/resources/testharnessreport.js"></script>
-<script src = "/serviceworker/resources/test-helpers.js"></script>
-</head>
-<body>
-<script>
-function start(t) {
-  fetch_tests_from_worker(
-    new Worker('../script-tests/response-stream-construction.js?-base-https-other-https'));
-  t.done();
-}
-function init() {
-  return Promise.resolve();
-}
-</script>
-<script src = "../resources/init.js"></script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/fetch/workers/response-stream-construction.html b/third_party/WebKit/LayoutTests/http/tests/fetch/workers/response-stream-construction.html
deleted file mode 100644
index 07b7a89..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/fetch/workers/response-stream-construction.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!doctype html>
-<head>
-<meta name="timeout" content="long"></meta>
-<script src = "/resources/testharness.js"></script>
-<script src = "/resources/testharnessreport.js"></script>
-<script src = "/serviceworker/resources/test-helpers.js"></script>
-</head>
-<body>
-<script>
-function start(t) {
-  fetch_tests_from_worker(
-    new Worker('../script-tests/response-stream-construction.js?'));
-  t.done();
-}
-function init() {
-  return Promise.resolve();
-}
-</script>
-<script src = "../resources/init.js"></script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/cached-resource-destroyed-moved-to-storage.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/cached-resource-destroyed-moved-to-storage.html
index deef1bc..461151b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/cached-resource-destroyed-moved-to-storage.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/cached-resource-destroyed-moved-to-storage.html
@@ -26,11 +26,6 @@
     console.log("Done2.");
 }
 
-function forceCachedResourceLoaderGC() {
-    if (window.internals)
-        window.internals.garbageCollectDocumentResources();
-}
-
 function test()
 {
     var imageRequest;
@@ -72,9 +67,6 @@
 
     function step6()
     {
-        // Force CachedResourceLoader garbage collector run.
-        InspectorTest.evaluateInPage("forceCachedResourceLoaderGC()");
-
         // Re-request content now that CachedResource should have been destroyed.
         delete imageRequest._content;
         imageRequest.requestContent(step7);
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/from-disk-cache-timing.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/from-disk-cache-timing.html
index ff9c496..f7c9173 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/from-disk-cache-timing.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/from-disk-cache-timing.html
@@ -20,8 +20,6 @@
 
 function gc()
 {
-    if (window.internals)
-        window.internals.garbageCollectDocumentResources(document);
     // In Oilpan, Resource objects are not destructed until GC.
     if (window.GCController)
         GCController.collectAll();
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/long-script-content.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/long-script-content.html
index 4c89c9f..844a384 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/long-script-content.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/long-script-content.html
@@ -20,8 +20,6 @@
 
 function gc()
 {
-    if (window.internals)
-        window.internals.garbageCollectDocumentResources(document);
     // In Oilpan, Resource objects are not destructed until GC.
     if (window.GCController)
         GCController.collectAll();
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/timeline-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/timeline-test.js
index 36f9c9b..277f41b1 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/timeline-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/timeline-test.js
@@ -61,18 +61,6 @@
     return "{reason: " + cause.reason + ", stackTrace: " + stackTrace + "}";
 }
 
-InspectorTest.switchTimelineToWaterfallMode = function()
-{
-    if (WebInspector.panels.timeline._flameChartToggleButton.toggled())
-        WebInspector.panels.timeline._flameChartToggleButton.element.click();
-}
-
-InspectorTest.timelinePresentationModel = function()
-{
-    InspectorTest.switchTimelineToWaterfallMode();
-    return WebInspector.panels.timeline._currentViews[0]._presentationModel;
-}
-
 InspectorTest.timelineModel = function()
 {
     return WebInspector.panels.timeline._model;
@@ -184,10 +172,24 @@
     InspectorTest.timelineModel().forAllRecords(InspectorTest._printTimlineRecord.bind(InspectorTest, typeName, detailsFormatter.bind(null, typeName)));
 };
 
-InspectorTest.printTimelinePresentationRecords = function(typeName, formatter)
+InspectorTest.walkTimelineEventTree = function(callback)
 {
-    InspectorTest.innerPrintTimelinePresentationRecords(WebInspector.panels.timeline._model.records(), typeName, formatter);
-};
+    var model = InspectorTest.timelineModel();
+    var view = new WebInspector.EventsTimelineTreeView(model, null);
+    var selection = WebInspector.TimelineSelection.fromRange(model.minimumRecordTime(), model.maximumRecordTime());
+    view.updateContents(selection);
+    InspectorTest.walkTimelineEventTreeUnderNode(callback, view._currentTree, 0);
+}
+
+InspectorTest.walkTimelineEventTreeUnderNode = function(callback, root, level)
+{
+    var event = root.event;
+    if (event)
+        callback(event, level)
+    var children = root.children ? root.children.values() : [];
+    for (var child of children)
+        InspectorTest.walkTimelineEventTreeUnderNode(callback, child, (level || 0) + 1);
+}
 
 InspectorTest.printTimestampRecords = function(typeName, formatter)
 {
@@ -208,17 +210,6 @@
         formatter(record);
 };
 
-InspectorTest.innerPrintTimelinePresentationRecords = function(records, typeName, formatter)
-{
-    for (var i = 0; i < records.length; ++i) {
-        if (typeName && records[i].type() === typeName)
-            InspectorTest.printTimelineRecordProperties(records[i]);
-        if (formatter)
-            formatter(records[i]);
-        InspectorTest.innerPrintTimelinePresentationRecords(records[i].children(), typeName, formatter);
-    }
-};
-
 // Dump just the record name, indenting output on separate lines for subrecords
 InspectorTest.dumpTimelineRecord = function(record, detailsCallback, level, filterTypes)
 {
@@ -264,39 +255,6 @@
         InspectorTest.dumpTimelineModelRecord(record.children()[i], level + 1);
 }
 
-// Dump just the record name, indenting output on separate lines for subrecords
-InspectorTest.dumpPresentationRecord = function(presentationRecord, detailsCallback, level, filterTypes)
-{
-    var record = !presentationRecord.presentationParent() ? null : presentationRecord.record();
-    if (typeof level !== "number")
-        level = 0;
-    var message = "";
-    for (var i = 0; i < level ; ++i)
-        message = "----" + message;
-    if (level > 0)
-        message = message + "> ";
-    if (!record) {
-        message += "Root";
-    } else if (presentationRecord.coalesced()) {
-        message += record.type() + " x " + presentationRecord.presentationChildren().length;
-    } else if (record.type() === WebInspector.TimelineModel.RecordType.TimeStamp
-        || record.type() === WebInspector.TimelineModel.RecordType.ConsoleTime) {
-        message += WebInspector.TimelineUIUtils.eventTitle(record.traceEvent());
-    } else {
-        message += record.type();
-    }
-    if (detailsCallback)
-        message += " " + detailsCallback(presentationRecord);
-    InspectorTest.addResult(message);
-
-    var numChildren = presentationRecord.presentationChildren() ? presentationRecord.presentationChildren().length : 0;
-    for (var i = 0; i < numChildren; ++i) {
-        if (filterTypes && filterTypes.indexOf(presentationRecord.presentationChildren()[i].record().type()) == -1)
-            continue;
-        InspectorTest.dumpPresentationRecord(presentationRecord.presentationChildren()[i], detailsCallback, level + 1, filterTypes);
-    }
-}
-
 InspectorTest.dumpTimelineRecords = function(timelineRecords)
 {
     for (var i = 0; i < timelineRecords.length; ++i)
@@ -305,25 +263,32 @@
 
 InspectorTest.printTimelineRecordProperties = function(record)
 {
-    InspectorTest.addResult(record.type() + " Properties:");
-    var traceEvent = record.traceEvent();
+    InspectorTest.printTraceEventProperties(record.traceEvent());
+}
+
+InspectorTest.printTraceEventPropertiesIfNameMatches = function(set, traceEvent)
+{
+    if (set.has(traceEvent.name))
+        InspectorTest.printTraceEventProperties(traceEvent);
+}
+
+InspectorTest.printTraceEventProperties = function(traceEvent)
+{
+    InspectorTest.addResult(traceEvent.name + " Properties:");
     var data = traceEvent.args["beginData"] || traceEvent.args["data"];
     var frameId = data && data["frame"];
     var object = {
         data: traceEvent.args["data"] || traceEvent.args,
-        endTime: record.endTime(),
+        endTime: traceEvent.endTime || traceEvent.startTime,
         frameId: frameId,
         stackTrace: traceEvent.stackTrace,
-        startTime: record.startTime(),
-        thread: record.thread(),
-        type: record.type()
+        startTime: traceEvent.startTime,
+        type: traceEvent.name,
     };
     for (var field in object) {
         if (object[field] === null || object[field] === undefined)
             delete object[field];
     }
-    if (record.children().length)
-        object["children"] = [];
     InspectorTest.addObject(object, InspectorTest.timelinePropertyFormatters);
 };
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/timeline-xhr-event-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/timeline-xhr-event-expected.txt
index 18e98e8..7344afa 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/timeline-xhr-event-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/timeline-xhr-event-expected.txt
@@ -12,13 +12,11 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "XHRReadyStateChange"
 }
 Text details for XHRReadyStateChange: network/resources/resource.php
 XHRReadyStateChange Properties:
 {
-    children : <object>
     data : {
         frame : <string>
         readyState : 2
@@ -27,13 +25,11 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "XHRReadyStateChange"
 }
 Text details for XHRReadyStateChange: network/resources/resource.php
 XHRReadyStateChange Properties:
 {
-    children : <object>
     data : {
         frame : <string>
         readyState : 3
@@ -42,13 +38,11 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "XHRReadyStateChange"
 }
 Text details for XHRReadyStateChange: network/resources/resource.php
 XHRReadyStateChange Properties:
 {
-    children : <object>
     data : {
         frame : <string>
         readyState : 4
@@ -57,13 +51,11 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "XHRReadyStateChange"
 }
 Text details for XHRReadyStateChange: network/resources/resource.php
 XHRLoad Properties:
 {
-    children : <object>
     data : {
         frame : <string>
         url : .../inspector/tracing/network/resources/resource.php
@@ -71,7 +63,6 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "XHRLoad"
 }
 Text details for XHRLoad: network/resources/resource.php
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/timeline-xhr-response-type-blob-event-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/timeline-xhr-response-type-blob-event-expected.txt
index 1d99495..688554a7 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/timeline-xhr-response-type-blob-event-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/timeline-xhr-response-type-blob-event-expected.txt
@@ -12,12 +12,10 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "XHRReadyStateChange"
 }
 XHRReadyStateChange Properties:
 {
-    children : <object>
     data : {
         frame : <string>
         readyState : 2
@@ -26,12 +24,10 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "XHRReadyStateChange"
 }
 XHRReadyStateChange Properties:
 {
-    children : <object>
     data : {
         frame : <string>
         readyState : 3
@@ -40,12 +36,10 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "XHRReadyStateChange"
 }
 XHRReadyStateChange Properties:
 {
-    children : <object>
     data : {
         frame : <string>
         readyState : 4
@@ -54,12 +48,10 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "XHRReadyStateChange"
 }
 XHRLoad Properties:
 {
-    children : <object>
     data : {
         frame : <string>
         url : .../inspector/tracing/network/resources/resource.php
@@ -67,7 +59,6 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "XHRLoad"
 }
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/websocket/timeline-websocket-event-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/websocket/timeline-websocket-event-expected.txt
index 6ee76ecd..48bf3d5 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/websocket/timeline-websocket-event-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/websocket/timeline-websocket-event-expected.txt
@@ -12,7 +12,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "WebSocketCreate"
 }
 Text details for WebSocketCreate: ws://127.0.0.1:8880/simple
@@ -25,7 +24,6 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "WebSocketSendHandshakeRequest"
 }
 Text details for WebSocketSendHandshakeRequest: ws://127.0.0.1:8880/simple
@@ -38,7 +36,6 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "WebSocketReceiveHandshakeResponse"
 }
 Text details for WebSocketReceiveHandshakeResponse: ws://127.0.0.1:8880/simple
@@ -51,7 +48,6 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "WebSocketDestroy"
 }
 Text details for WebSocketDestroy: ws://127.0.0.1:8880/simple
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/report-blocked-data-uri-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/report-blocked-data-uri-expected.txt
index c13fa03..7897f99 100644
--- a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/report-blocked-data-uri-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/report-blocked-data-uri-expected.txt
@@ -1,4 +1,4 @@
-CONSOLE ERROR: line 9: Refused to load the image 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' because it violates the following Content Security Policy directive: "img-src 'none'".
+CONSOLE ERROR: line 8: Refused to load the image 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' because it violates the following Content Security Policy directive: "img-src 'none'".
 
 PingLoader dispatched to 'http://127.0.0.1:8000/security/contentSecurityPolicy/resources/save-report.php?test=report-blocked-data-uri.html'.
 CSP report received:
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/powerfulFeatureRestrictions/serviceworker-on-insecure-origin.html b/third_party/WebKit/LayoutTests/http/tests/security/powerfulFeatureRestrictions/serviceworker-on-insecure-origin.html
index 8fc6cbf..948cd3e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/security/powerfulFeatureRestrictions/serviceworker-on-insecure-origin.html
+++ b/third_party/WebKit/LayoutTests/http/tests/security/powerfulFeatureRestrictions/serviceworker-on-insecure-origin.html
@@ -18,7 +18,7 @@
                 service_worker_unregister_and_done(this, scope);
             }),
             this.step_func(function(reason) {
-                assert_equals(reason.name, "NotSupportedError");
+                assert_equals(reason.name, "SecurityError");
                 this.done();
             })
         );
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/http-to-https-redirect-and-register.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/http-to-https-redirect-and-register.html
index 50dff55..5a498c95 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/http-to-https-redirect-and-register.html
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/http-to-https-redirect-and-register.html
@@ -42,7 +42,7 @@
       '/serviceworker/resources/register.html';
 
     return redirect_and_register(target_url)
-      .then(result => {assert_equals(result, 'FAIL: NotSupportedError');});
+      .then(result => {assert_equals(result, 'FAIL: SecurityError');});
   }, 'register on a non-secure page after redirect from an non-secure url');
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/windowclient-navigate.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/windowclient-navigate.html
index 2d3e8e189..6249dad 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/windowclient-navigate.html
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/windowclient-navigate.html
@@ -7,6 +7,7 @@
 <script>
 
 var scope = 'resources/blank.html?windowclient-navigate';
+var script_url = 'resources/windowclient-navigate-worker.js';
 var client_frame;
 var worker;
 var test;
@@ -14,6 +15,7 @@
 var current_index = 0;
 var test_list = [
   { url : 'blank.html' },
+  { url : '' },
   { url : 'blank.html', init : 'uncontrolled/blank.html' },
   { url : get_host_info()['HTTP_REMOTE_ORIGIN'] +
       '/serviceworker/resources/blank.html' },
@@ -26,6 +28,7 @@
 
 var expected = [
   location.origin + '/serviceworker/resources/blank.html',
+  location.origin + '/serviceworker/' + script_url,
   'TypeError',
   null,
   'TypeError',
@@ -39,8 +42,7 @@
 
 async_test(function(t) {
   test = t;
-  return service_worker_unregister_and_register(
-      test, 'resources/windowclient-navigate-worker.js', scope)
+  return service_worker_unregister_and_register(test, script_url, scope)
     .then(function(registration) {
         worker = registration.installing;
         return wait_for_state(test, worker, 'activated');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/HTMLCollection-empty-name.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/HTMLCollection-empty-name.html
new file mode 100644
index 0000000..bfd1019
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/HTMLCollection-empty-name.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLCollection and empty names</title>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<div id=log></div>
+<div id=test>
+<div class=a id></div>
+<div class=a name></div>
+<a class=a name></a>
+</div>
+<script>
+test(function() {
+  var c = document.getElementsByTagName("*");
+  assert_false("" in c, "Empty string should not be in the collection.");
+  assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+  assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Document.getElementsByTagName");
+
+test(function() {
+  var div = document.getElementById("test");
+  var c = div.getElementsByTagName("*");
+  assert_false("" in c, "Empty string should not be in the collection.");
+  assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+  assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Element.getElementsByTagName");
+
+test(function() {
+  var c = document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "a");
+  assert_false("" in c, "Empty string should not be in the collection.");
+  assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+  assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Document.getElementsByTagNameNS");
+
+test(function() {
+  var div = document.getElementById("test");
+  var c = div.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "a");
+  assert_false("" in c, "Empty string should not be in the collection.");
+  assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+  assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Element.getElementsByTagNameNS");
+
+test(function() {
+  var c = document.getElementsByClassName("a");
+  assert_false("" in c, "Empty string should not be in the collection.");
+  assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+  assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Document.getElementsByClassName");
+
+test(function() {
+  var div = document.getElementById("test");
+  var c = div.getElementsByClassName("a");
+  assert_false("" in c, "Empty string should not be in the collection.");
+  assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+  assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Element.getElementsByClassName");
+
+test(function() {
+  var div = document.getElementById("test");
+  var c = div.children;
+  assert_false("" in c, "Empty string should not be in the collection.");
+  assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+  assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Element.children");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/HTMLCollection-supported-property-names.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/HTMLCollection-supported-property-names.html
new file mode 100644
index 0000000..3a71f58
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/HTMLCollection-supported-property-names.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<meta charset=utf-8>
+<link rel=help href=https://dom.spec.whatwg.org/#interface-htmlcollection>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+
+<div id=log></div>
+
+<!--  with no attribute  -->
+<span></span>
+
+<!--  with `id` attribute  -->
+<span id=''></span>
+<span id='some-id'></span>
+<span id='some-id'></span><!--  to ensure no duplicates  -->
+
+<!--  with `name` attribute  -->
+<span name=''></span>
+<span name='some-name'></span>
+<span name='some-name'></span><!--  to ensure no duplicates  -->
+
+<!--  with `name` and `id` attribute  -->
+<span id='another-id' name='another-name'></span>
+
+<script>
+test(function () {
+  var elements = document.getElementsByTagName("span");
+  assert_array_equals(
+    Object.getOwnPropertyNames(elements),
+    ['0', '1', '2', '3', '4', '5', '6', '7', 'some-id', 'some-name', 'another-id', 'another-name']
+  );
+}, 'Object.getOwnPropertyNames on HTMLCollection');
+
+test(function () {
+  var elem = document.createElementNS('some-random-namespace', 'foo');
+  this.add_cleanup(function () {elem.remove();});
+  elem.setAttribute("name", "some-name");
+  document.body.appendChild(elem);
+
+  var elements = document.getElementsByTagName("foo");
+  assert_array_equals(Object.getOwnPropertyNames(elements), ['0']);
+}, 'Object.getOwnPropertyNames on HTMLCollection with non-HTML namespace');
+
+test(function () {
+  var elem = document.createElement('foo');
+  this.add_cleanup(function () {elem.remove();});
+  document.body.appendChild(elem);
+
+  var elements = document.getElementsByTagName("foo");
+  elements.someProperty = "some value";
+
+  assert_array_equals(Object.getOwnPropertyNames(elements), ['0', 'someProperty']);
+}, 'Object.getOwnPropertyNames on HTMLCollection with expando object');
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/domstringmap-supported-property-names.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/domstringmap-supported-property-names.html
new file mode 100644
index 0000000..6e7e6ddb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/domstringmap-supported-property-names.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>DOMStringMap Test: Supported property names</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+
+<div id="edge1" data-="012">Simple</div>
+
+<div id="edge2" data-id-="012">Simple</div>
+
+<div id="user" data-id="1234567890" data-user="johndoe" data-date-of-birth>
+    John Doe
+</div>
+
+<div id="user2" data-unique-id="1234567890"> Jane Doe </div>
+
+<div id="user3" data-unique-id="4324324241"> Jim Doe </div>
+
+<script>
+
+test(function() {
+    var element = document.querySelector('#edge1');
+    assert_array_equals(Object.getOwnPropertyNames(element.dataset),
+        [""]);
+}, "Object.getOwnPropertyNames on DOMStringMap, empty data attribute");
+
+test(function() {
+    var element = document.querySelector('#edge2');
+    assert_array_equals(Object.getOwnPropertyNames(element.dataset),
+        ["id-"]);
+}, "Object.getOwnPropertyNames on DOMStringMap, data attribute trailing hyphen");
+
+test(function() {
+    var element = document.querySelector('#user');
+    assert_array_equals(Object.getOwnPropertyNames(element.dataset),
+        ['id', 'user', 'dateOfBirth']);
+}, "Object.getOwnPropertyNames on DOMStringMap, multiple data attributes");
+
+test(function() {
+    var element = document.querySelector('#user2');
+    element.dataset.middleName = "mark";
+    assert_array_equals(Object.getOwnPropertyNames(element.dataset),
+        ['uniqueId', 'middleName']);
+}, "Object.getOwnPropertyNames on DOMStringMap, attribute set on dataset in JS");
+
+test(function() {
+    var element = document.querySelector('#user3');
+    element.setAttribute("data-age", 30);
+    assert_array_equals(Object.getOwnPropertyNames(element.dataset),
+        ['uniqueId', 'age']);
+}, "Object.getOwnPropertyNames on DOMStringMap, attribute set on element in JS");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/namednodemap-supported-property-names-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/namednodemap-supported-property-names-expected.txt
new file mode 100644
index 0000000..9dc9a2c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/namednodemap-supported-property-names-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+FAIL Object.getOwnPropertyNames on NamedNodeMap assert_array_equals: lengths differ, expected 4 got 2
+FAIL Object.getOwnPropertyNames on NamedNodeMap of input assert_array_equals: lengths differ, expected 8 got 4
+FAIL Object.getOwnPropertyNames on NamedNodeMap after attribute removal assert_array_equals: lengths differ, expected 6 got 3
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/namednodemap-supported-property-names.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/namednodemap-supported-property-names.html
new file mode 100644
index 0000000..1ad8547
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/namednodemap-supported-property-names.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>NamedNodeMap Test: Supported property names</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="simple" class="fancy">Simple</div>
+<input id="result" type="text" value="" width="200px">
+<script>
+
+test(function() {
+    var elt = document.querySelector('#simple');
+    assert_array_equals(Object.getOwnPropertyNames(elt.attributes),
+        ['0','1','id','class']);
+}, "Object.getOwnPropertyNames on NamedNodeMap");
+
+test(function() {
+    var result = document.getElementById("result");
+    assert_array_equals(Object.getOwnPropertyNames(result.attributes),
+        ['0','1','2','3','id','type','value','width']);
+}, "Object.getOwnPropertyNames on NamedNodeMap of input");
+
+test(function() {
+    var result = document.getElementById("result");
+    result.removeAttribute("width");
+    assert_array_equals(Object.getOwnPropertyNames(result.attributes),
+        ['0','1','2','id','type','value']);
+}, "Object.getOwnPropertyNames on NamedNodeMap after attribute removal");
+
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/common.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/common.js
new file mode 100644
index 0000000..70367b2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/common.js
@@ -0,0 +1,1083 @@
+"use strict";
+// Written by Aryeh Gregor <ayg@aryeh.name>
+
+// TODO: iframes, contenteditable/designMode
+
+// Everything is done in functions in this test harness, so we have to declare
+// all the variables before use to make sure they can be reused.
+var testDiv, paras, detachedDiv, detachedPara1, detachedPara2,
+    foreignDoc, foreignPara1, foreignPara2, xmlDoc, xmlElement,
+    detachedXmlElement, detachedTextNode, foreignTextNode,
+    detachedForeignTextNode, xmlTextNode, detachedXmlTextNode,
+    processingInstruction, detachedProcessingInstruction, comment,
+    detachedComment, foreignComment, detachedForeignComment, xmlComment,
+    detachedXmlComment, docfrag, foreignDocfrag, xmlDocfrag, doctype,
+    foreignDoctype, xmlDoctype;
+var testRangesShort, testRanges, testPoints, testNodesShort, testNodes;
+
+function setupRangeTests() {
+    testDiv = document.querySelector("#test");
+    if (testDiv) {
+        testDiv.parentNode.removeChild(testDiv);
+    }
+    testDiv = document.createElement("div");
+    testDiv.id = "test";
+    document.body.insertBefore(testDiv, document.body.firstChild);
+
+    paras = [];
+    paras.push(document.createElement("p"));
+    paras[0].setAttribute("id", "a");
+    // Test some diacritics, to make sure browsers are using code units here
+    // and not something like grapheme clusters.
+    paras[0].textContent = "A\u0308b\u0308c\u0308d\u0308e\u0308f\u0308g\u0308h\u0308\n";
+    testDiv.appendChild(paras[0]);
+
+    paras.push(document.createElement("p"));
+    paras[1].setAttribute("id", "b");
+    paras[1].setAttribute("style", "display:none");
+    paras[1].textContent = "Ijklmnop\n";
+    testDiv.appendChild(paras[1]);
+
+    paras.push(document.createElement("p"));
+    paras[2].setAttribute("id", "c");
+    paras[2].textContent = "Qrstuvwx";
+    testDiv.appendChild(paras[2]);
+
+    paras.push(document.createElement("p"));
+    paras[3].setAttribute("id", "d");
+    paras[3].setAttribute("style", "display:none");
+    paras[3].textContent = "Yzabcdef";
+    testDiv.appendChild(paras[3]);
+
+    paras.push(document.createElement("p"));
+    paras[4].setAttribute("id", "e");
+    paras[4].setAttribute("style", "display:none");
+    paras[4].textContent = "Ghijklmn";
+    testDiv.appendChild(paras[4]);
+
+    detachedDiv = document.createElement("div");
+    detachedPara1 = document.createElement("p");
+    detachedPara1.appendChild(document.createTextNode("Opqrstuv"));
+    detachedPara2 = document.createElement("p");
+    detachedPara2.appendChild(document.createTextNode("Wxyzabcd"));
+    detachedDiv.appendChild(detachedPara1);
+    detachedDiv.appendChild(detachedPara2);
+
+    // Opera doesn't automatically create a doctype for a new HTML document,
+    // contrary to spec.  It also doesn't let you add doctypes to documents
+    // after the fact through any means I've tried.  So foreignDoc in Opera
+    // will have no doctype, foreignDoctype will be null, and Opera will fail
+    // some tests somewhat mysteriously as a result.
+    foreignDoc = document.implementation.createHTMLDocument("");
+    foreignPara1 = foreignDoc.createElement("p");
+    foreignPara1.appendChild(foreignDoc.createTextNode("Efghijkl"));
+    foreignPara2 = foreignDoc.createElement("p");
+    foreignPara2.appendChild(foreignDoc.createTextNode("Mnopqrst"));
+    foreignDoc.body.appendChild(foreignPara1);
+    foreignDoc.body.appendChild(foreignPara2);
+
+    // Now we get to do really silly stuff, which nobody in the universe is
+    // ever going to actually do, but the spec defines behavior, so too bad.
+    // Testing is fun!
+    xmlDoctype = document.implementation.createDocumentType("qorflesnorf", "abcde", "x\"'y");
+    xmlDoc = document.implementation.createDocument(null, null, xmlDoctype);
+    detachedXmlElement = xmlDoc.createElement("everyone-hates-hyphenated-element-names");
+    detachedTextNode = document.createTextNode("Uvwxyzab");
+    detachedForeignTextNode = foreignDoc.createTextNode("Cdefghij");
+    detachedXmlTextNode = xmlDoc.createTextNode("Klmnopqr");
+    // PIs only exist in XML documents, so don't bother with document or
+    // foreignDoc.
+    detachedProcessingInstruction = xmlDoc.createProcessingInstruction("whippoorwill", "chirp chirp chirp");
+    detachedComment = document.createComment("Stuvwxyz");
+    // Hurrah, we finally got to "z" at the end!
+    detachedForeignComment = foreignDoc.createComment("אריה יהודה");
+    detachedXmlComment = xmlDoc.createComment("בן חיים אליעזר");
+
+    // We should also test with document fragments that actually contain stuff
+    // . . . but, maybe later.
+    docfrag = document.createDocumentFragment();
+    foreignDocfrag = foreignDoc.createDocumentFragment();
+    xmlDocfrag = xmlDoc.createDocumentFragment();
+
+    xmlElement = xmlDoc.createElement("igiveuponcreativenames");
+    xmlTextNode = xmlDoc.createTextNode("do re mi fa so la ti");
+    xmlElement.appendChild(xmlTextNode);
+    processingInstruction = xmlDoc.createProcessingInstruction("somePI", 'Did you know that ":syn sync fromstart" is very useful when using vim to edit large amounts of JavaScript embedded in HTML?');
+    xmlDoc.appendChild(xmlElement);
+    xmlDoc.appendChild(processingInstruction);
+    xmlComment = xmlDoc.createComment("I maliciously created a comment that will break incautious XML serializers, but Firefox threw an exception, so all I got was this lousy T-shirt");
+    xmlDoc.appendChild(xmlComment);
+
+    comment = document.createComment("Alphabet soup?");
+    testDiv.appendChild(comment);
+
+    foreignComment = foreignDoc.createComment('"Commenter" and "commentator" mean different things.  I\'ve seen non-native speakers trip up on this.');
+    foreignDoc.appendChild(foreignComment);
+    foreignTextNode = foreignDoc.createTextNode("I admit that I harbor doubts about whether we really need so many things to test, but it's too late to stop now.");
+    foreignDoc.body.appendChild(foreignTextNode);
+
+    doctype = document.doctype;
+    foreignDoctype = foreignDoc.doctype;
+
+    testRangesShort = [
+        // Various ranges within the text node children of different
+        // paragraphs.  All should be valid.
+        "[paras[0].firstChild, 0, paras[0].firstChild, 0]",
+        "[paras[0].firstChild, 0, paras[0].firstChild, 1]",
+        "[paras[0].firstChild, 2, paras[0].firstChild, 8]",
+        "[paras[0].firstChild, 2, paras[0].firstChild, 9]",
+        "[paras[1].firstChild, 0, paras[1].firstChild, 0]",
+        "[paras[1].firstChild, 2, paras[1].firstChild, 9]",
+        "[detachedPara1.firstChild, 0, detachedPara1.firstChild, 0]",
+        "[detachedPara1.firstChild, 2, detachedPara1.firstChild, 8]",
+        "[foreignPara1.firstChild, 0, foreignPara1.firstChild, 0]",
+        "[foreignPara1.firstChild, 2, foreignPara1.firstChild, 8]",
+        // Now try testing some elements, not just text nodes.
+        "[document.documentElement, 0, document.documentElement, 1]",
+        "[document.documentElement, 0, document.documentElement, 2]",
+        "[document.documentElement, 1, document.documentElement, 2]",
+        "[document.head, 1, document.head, 1]",
+        "[document.body, 4, document.body, 5]",
+        "[foreignDoc.documentElement, 0, foreignDoc.documentElement, 1]",
+        "[paras[0], 0, paras[0], 1]",
+        "[detachedPara1, 0, detachedPara1, 1]",
+        // Now try some ranges that span elements.
+        "[paras[0].firstChild, 0, paras[1].firstChild, 0]",
+        "[paras[0].firstChild, 0, paras[1].firstChild, 8]",
+        "[paras[0].firstChild, 3, paras[3], 1]",
+        // How about something that spans a node and its descendant?
+        "[paras[0], 0, paras[0].firstChild, 7]",
+        "[testDiv, 2, paras[4], 1]",
+        // Then a few more interesting things just for good measure.
+        "[document, 0, document, 1]",
+        "[document, 0, document, 2]",
+        "[comment, 2, comment, 3]",
+        "[testDiv, 0, comment, 5]",
+        "[foreignDoc, 1, foreignComment, 2]",
+        "[foreignDoc.body, 0, foreignTextNode, 36]",
+        "[xmlDoc, 1, xmlComment, 0]",
+        "[detachedTextNode, 0, detachedTextNode, 8]",
+        "[detachedForeignTextNode, 0, detachedForeignTextNode, 8]",
+        "[detachedXmlTextNode, 0, detachedXmlTextNode, 8]",
+        "[detachedComment, 3, detachedComment, 4]",
+        "[detachedForeignComment, 0, detachedForeignComment, 1]",
+        "[detachedXmlComment, 2, detachedXmlComment, 6]",
+        "[docfrag, 0, docfrag, 0]",
+        "[processingInstruction, 0, processingInstruction, 4]",
+    ];
+
+    testRanges = testRangesShort.concat([
+        "[paras[1].firstChild, 0, paras[1].firstChild, 1]",
+        "[paras[1].firstChild, 2, paras[1].firstChild, 8]",
+        "[detachedPara1.firstChild, 0, detachedPara1.firstChild, 1]",
+        "[foreignPara1.firstChild, 0, foreignPara1.firstChild, 1]",
+        "[foreignDoc.head, 1, foreignDoc.head, 1]",
+        "[foreignDoc.body, 0, foreignDoc.body, 0]",
+        "[paras[0], 0, paras[0], 0]",
+        "[detachedPara1, 0, detachedPara1, 0]",
+        "[testDiv, 1, paras[2].firstChild, 5]",
+        "[document.documentElement, 1, document.body, 0]",
+        "[foreignDoc.documentElement, 1, foreignDoc.body, 0]",
+        "[document, 1, document, 2]",
+        "[paras[2].firstChild, 4, comment, 2]",
+        "[paras[3], 1, comment, 8]",
+        "[foreignDoc, 0, foreignDoc, 0]",
+        "[xmlDoc, 0, xmlDoc, 0]",
+        "[detachedForeignTextNode, 7, detachedForeignTextNode, 7]",
+        "[detachedXmlTextNode, 7, detachedXmlTextNode, 7]",
+        "[detachedComment, 5, detachedComment, 5]",
+        "[detachedForeignComment, 4, detachedForeignComment, 4]",
+        "[foreignDocfrag, 0, foreignDocfrag, 0]",
+        "[xmlDocfrag, 0, xmlDocfrag, 0]",
+    ]);
+
+    testPoints = [
+        // Various positions within the page, some invalid.  Remember that
+        // paras[0] is visible, and paras[1] is display: none.
+        "[paras[0].firstChild, -1]",
+        "[paras[0].firstChild, 0]",
+        "[paras[0].firstChild, 1]",
+        "[paras[0].firstChild, 2]",
+        "[paras[0].firstChild, 8]",
+        "[paras[0].firstChild, 9]",
+        "[paras[0].firstChild, 10]",
+        "[paras[0].firstChild, 65535]",
+        "[paras[1].firstChild, -1]",
+        "[paras[1].firstChild, 0]",
+        "[paras[1].firstChild, 1]",
+        "[paras[1].firstChild, 2]",
+        "[paras[1].firstChild, 8]",
+        "[paras[1].firstChild, 9]",
+        "[paras[1].firstChild, 10]",
+        "[paras[1].firstChild, 65535]",
+        "[detachedPara1.firstChild, 0]",
+        "[detachedPara1.firstChild, 1]",
+        "[detachedPara1.firstChild, 8]",
+        "[detachedPara1.firstChild, 9]",
+        "[foreignPara1.firstChild, 0]",
+        "[foreignPara1.firstChild, 1]",
+        "[foreignPara1.firstChild, 8]",
+        "[foreignPara1.firstChild, 9]",
+        // Now try testing some elements, not just text nodes.
+        "[document.documentElement, -1]",
+        "[document.documentElement, 0]",
+        "[document.documentElement, 1]",
+        "[document.documentElement, 2]",
+        "[document.documentElement, 7]",
+        "[document.head, 1]",
+        "[document.body, 3]",
+        "[foreignDoc.documentElement, 0]",
+        "[foreignDoc.documentElement, 1]",
+        "[foreignDoc.head, 0]",
+        "[foreignDoc.body, 1]",
+        "[paras[0], 0]",
+        "[paras[0], 1]",
+        "[paras[0], 2]",
+        "[paras[1], 0]",
+        "[paras[1], 1]",
+        "[paras[1], 2]",
+        "[detachedPara1, 0]",
+        "[detachedPara1, 1]",
+        "[testDiv, 0]",
+        "[testDiv, 3]",
+        // Then a few more interesting things just for good measure.
+        "[document, -1]",
+        "[document, 0]",
+        "[document, 1]",
+        "[document, 2]",
+        "[document, 3]",
+        "[comment, -1]",
+        "[comment, 0]",
+        "[comment, 4]",
+        "[comment, 96]",
+        "[foreignDoc, 0]",
+        "[foreignDoc, 1]",
+        "[foreignComment, 2]",
+        "[foreignTextNode, 0]",
+        "[foreignTextNode, 36]",
+        "[xmlDoc, -1]",
+        "[xmlDoc, 0]",
+        "[xmlDoc, 1]",
+        "[xmlDoc, 5]",
+        "[xmlComment, 0]",
+        "[xmlComment, 4]",
+        "[processingInstruction, 0]",
+        "[processingInstruction, 5]",
+        "[processingInstruction, 9]",
+        "[detachedTextNode, 0]",
+        "[detachedTextNode, 8]",
+        "[detachedForeignTextNode, 0]",
+        "[detachedForeignTextNode, 8]",
+        "[detachedXmlTextNode, 0]",
+        "[detachedXmlTextNode, 8]",
+        "[detachedProcessingInstruction, 12]",
+        "[detachedComment, 3]",
+        "[detachedComment, 5]",
+        "[detachedForeignComment, 0]",
+        "[detachedForeignComment, 4]",
+        "[detachedXmlComment, 2]",
+        "[docfrag, 0]",
+        "[foreignDocfrag, 0]",
+        "[xmlDocfrag, 0]",
+        "[doctype, 0]",
+        "[doctype, -17]",
+        "[doctype, 1]",
+        "[foreignDoctype, 0]",
+        "[xmlDoctype, 0]",
+    ];
+
+    testNodesShort = [
+        "paras[0]",
+        "paras[0].firstChild",
+        "paras[1].firstChild",
+        "foreignPara1",
+        "foreignPara1.firstChild",
+        "detachedPara1",
+        "detachedPara1.firstChild",
+        "document",
+        "detachedDiv",
+        "foreignDoc",
+        "foreignPara2",
+        "xmlDoc",
+        "xmlElement",
+        "detachedTextNode",
+        "foreignTextNode",
+        "processingInstruction",
+        "detachedProcessingInstruction",
+        "comment",
+        "detachedComment",
+        "docfrag",
+        "doctype",
+        "foreignDoctype",
+    ];
+
+    testNodes = testNodesShort.concat([
+        "paras[1]",
+        "detachedPara2",
+        "detachedPara2.firstChild",
+        "testDiv",
+        "detachedXmlElement",
+        "detachedForeignTextNode",
+        "xmlTextNode",
+        "detachedXmlTextNode",
+        "xmlComment",
+        "foreignComment",
+        "detachedForeignComment",
+        "detachedXmlComment",
+        "foreignDocfrag",
+        "xmlDocfrag",
+        "xmlDoctype",
+    ]);
+}
+if ("setup" in window) {
+    setup(setupRangeTests);
+} else {
+    // Presumably we're running from within an iframe or something
+    setupRangeTests();
+}
+
+/**
+ * The "length" of a node as defined by the Ranges section of DOM4.
+ */
+function nodeLength(node) {
+    // "The length of a node node depends on node:
+    //
+    // "DocumentType
+    //   "0."
+    if (node.nodeType == Node.DOCUMENT_TYPE_NODE) {
+        return 0;
+    }
+    // "Text
+    // "ProcessingInstruction
+    // "Comment
+    //   "Its length attribute value."
+    // Browsers don't historically support the length attribute on
+    // ProcessingInstruction, so to avoid spurious failures, do
+    // node.data.length instead of node.length.
+    if (node.nodeType == Node.TEXT_NODE || node.nodeType == Node.PROCESSING_INSTRUCTION_NODE || node.nodeType == Node.COMMENT_NODE) {
+        return node.data.length;
+    }
+    // "Any other node
+    //   "Its number of children."
+    return node.childNodes.length;
+}
+
+/**
+ * Returns the furthest ancestor of a Node as defined by the spec.
+ */
+function furthestAncestor(node) {
+    var root = node;
+    while (root.parentNode != null) {
+        root = root.parentNode;
+    }
+    return root;
+}
+
+/**
+ * "The ancestor containers of a Node are the Node itself and all its
+ * ancestors."
+ *
+ * Is node1 an ancestor container of node2?
+ */
+function isAncestorContainer(node1, node2) {
+    return node1 == node2 ||
+        (node2.compareDocumentPosition(node1) & Node.DOCUMENT_POSITION_CONTAINS);
+}
+
+/**
+ * Returns the first Node that's after node in tree order, or null if node is
+ * the last Node.
+ */
+function nextNode(node) {
+    if (node.hasChildNodes()) {
+        return node.firstChild;
+    }
+    return nextNodeDescendants(node);
+}
+
+/**
+ * Returns the last Node that's before node in tree order, or null if node is
+ * the first Node.
+ */
+function previousNode(node) {
+    if (node.previousSibling) {
+        node = node.previousSibling;
+        while (node.hasChildNodes()) {
+            node = node.lastChild;
+        }
+        return node;
+    }
+    return node.parentNode;
+}
+
+/**
+ * Returns the next Node that's after node and all its descendants in tree
+ * order, or null if node is the last Node or an ancestor of it.
+ */
+function nextNodeDescendants(node) {
+    while (node && !node.nextSibling) {
+        node = node.parentNode;
+    }
+    if (!node) {
+        return null;
+    }
+    return node.nextSibling;
+}
+
+/**
+ * Returns the ownerDocument of the Node, or the Node itself if it's a
+ * Document.
+ */
+function ownerDocument(node) {
+    return node.nodeType == Node.DOCUMENT_NODE
+        ? node
+        : node.ownerDocument;
+}
+
+/**
+ * Returns true if ancestor is an ancestor of descendant, false otherwise.
+ */
+function isAncestor(ancestor, descendant) {
+    if (!ancestor || !descendant) {
+        return false;
+    }
+    while (descendant && descendant != ancestor) {
+        descendant = descendant.parentNode;
+    }
+    return descendant == ancestor;
+}
+
+/**
+ * Returns true if ancestor is an inclusive ancestor of descendant, false
+ * otherwise.
+ */
+function isInclusiveAncestor(ancestor, descendant) {
+    return ancestor === descendant || isAncestor(ancestor, descendant);
+}
+
+/**
+ * Returns true if descendant is a descendant of ancestor, false otherwise.
+ */
+function isDescendant(descendant, ancestor) {
+    return isAncestor(ancestor, descendant);
+}
+
+/**
+ * Returns true if descendant is an inclusive descendant of ancestor, false
+ * otherwise.
+ */
+function isInclusiveDescendant(descendant, ancestor) {
+    return descendant === ancestor || isDescendant(descendant, ancestor);
+}
+
+/**
+ * The position of two boundary points relative to one another, as defined by
+ * the spec.
+ */
+function getPosition(nodeA, offsetA, nodeB, offsetB) {
+    // "If node A is the same as node B, return equal if offset A equals offset
+    // B, before if offset A is less than offset B, and after if offset A is
+    // greater than offset B."
+    if (nodeA == nodeB) {
+        if (offsetA == offsetB) {
+            return "equal";
+        }
+        if (offsetA < offsetB) {
+            return "before";
+        }
+        if (offsetA > offsetB) {
+            return "after";
+        }
+    }
+
+    // "If node A is after node B in tree order, compute the position of (node
+    // B, offset B) relative to (node A, offset A). If it is before, return
+    // after. If it is after, return before."
+    if (nodeB.compareDocumentPosition(nodeA) & Node.DOCUMENT_POSITION_FOLLOWING) {
+        var pos = getPosition(nodeB, offsetB, nodeA, offsetA);
+        if (pos == "before") {
+            return "after";
+        }
+        if (pos == "after") {
+            return "before";
+        }
+    }
+
+    // "If node A is an ancestor of node B:"
+    if (nodeB.compareDocumentPosition(nodeA) & Node.DOCUMENT_POSITION_CONTAINS) {
+        // "Let child equal node B."
+        var child = nodeB;
+
+        // "While child is not a child of node A, set child to its parent."
+        while (child.parentNode != nodeA) {
+            child = child.parentNode;
+        }
+
+        // "If the index of child is less than offset A, return after."
+        if (indexOf(child) < offsetA) {
+            return "after";
+        }
+    }
+
+    // "Return before."
+    return "before";
+}
+
+/**
+ * "contained" as defined by DOM Range: "A Node node is contained in a range
+ * range if node's furthest ancestor is the same as range's root, and (node, 0)
+ * is after range's start, and (node, length of node) is before range's end."
+ */
+function isContained(node, range) {
+    var pos1 = getPosition(node, 0, range.startContainer, range.startOffset);
+    var pos2 = getPosition(node, nodeLength(node), range.endContainer, range.endOffset);
+
+    return furthestAncestor(node) == furthestAncestor(range.startContainer)
+        && pos1 == "after"
+        && pos2 == "before";
+}
+
+/**
+ * "partially contained" as defined by DOM Range: "A Node is partially
+ * contained in a range if it is an ancestor container of the range's start but
+ * not its end, or vice versa."
+ */
+function isPartiallyContained(node, range) {
+    var cond1 = isAncestorContainer(node, range.startContainer);
+    var cond2 = isAncestorContainer(node, range.endContainer);
+    return (cond1 && !cond2) || (cond2 && !cond1);
+}
+
+/**
+ * Index of a node as defined by the spec.
+ */
+function indexOf(node) {
+    if (!node.parentNode) {
+        // No preceding sibling nodes, right?
+        return 0;
+    }
+    var i = 0;
+    while (node != node.parentNode.childNodes[i]) {
+        i++;
+    }
+    return i;
+}
+
+/**
+ * extractContents() implementation, following the spec.  If an exception is
+ * supposed to be thrown, will return a string with the name (e.g.,
+ * "HIERARCHY_REQUEST_ERR") instead of a document fragment.  It might also
+ * return an arbitrary human-readable string if a condition is hit that implies
+ * a spec bug.
+ */
+function myExtractContents(range) {
+    // "Let frag be a new DocumentFragment whose ownerDocument is the same as
+    // the ownerDocument of the context object's start node."
+    var ownerDoc = range.startContainer.nodeType == Node.DOCUMENT_NODE
+        ? range.startContainer
+        : range.startContainer.ownerDocument;
+    var frag = ownerDoc.createDocumentFragment();
+
+    // "If the context object's start and end are the same, abort this method,
+    // returning frag."
+    if (range.startContainer == range.endContainer
+    && range.startOffset == range.endOffset) {
+        return frag;
+    }
+
+    // "Let original start node, original start offset, original end node, and
+    // original end offset be the context object's start and end nodes and
+    // offsets, respectively."
+    var originalStartNode = range.startContainer;
+    var originalStartOffset = range.startOffset;
+    var originalEndNode = range.endContainer;
+    var originalEndOffset = range.endOffset;
+
+    // "If original start node is original end node, and they are a Text,
+    // ProcessingInstruction, or Comment node:"
+    if (range.startContainer == range.endContainer
+    && (range.startContainer.nodeType == Node.TEXT_NODE
+    || range.startContainer.nodeType == Node.PROCESSING_INSTRUCTION_NODE
+    || range.startContainer.nodeType == Node.COMMENT_NODE)) {
+        // "Let clone be the result of calling cloneNode(false) on original
+        // start node."
+        var clone = originalStartNode.cloneNode(false);
+
+        // "Set the data of clone to the result of calling
+        // substringData(original start offset, original end offset − original
+        // start offset) on original start node."
+        clone.data = originalStartNode.substringData(originalStartOffset,
+            originalEndOffset - originalStartOffset);
+
+        // "Append clone as the last child of frag."
+        frag.appendChild(clone);
+
+        // "Call deleteData(original start offset, original end offset −
+        // original start offset) on original start node."
+        originalStartNode.deleteData(originalStartOffset,
+            originalEndOffset - originalStartOffset);
+
+        // "Abort this method, returning frag."
+        return frag;
+    }
+
+    // "Let common ancestor equal original start node."
+    var commonAncestor = originalStartNode;
+
+    // "While common ancestor is not an ancestor container of original end
+    // node, set common ancestor to its own parent."
+    while (!isAncestorContainer(commonAncestor, originalEndNode)) {
+        commonAncestor = commonAncestor.parentNode;
+    }
+
+    // "If original start node is an ancestor container of original end node,
+    // let first partially contained child be null."
+    var firstPartiallyContainedChild;
+    if (isAncestorContainer(originalStartNode, originalEndNode)) {
+        firstPartiallyContainedChild = null;
+    // "Otherwise, let first partially contained child be the first child of
+    // common ancestor that is partially contained in the context object."
+    } else {
+        for (var i = 0; i < commonAncestor.childNodes.length; i++) {
+            if (isPartiallyContained(commonAncestor.childNodes[i], range)) {
+                firstPartiallyContainedChild = commonAncestor.childNodes[i];
+                break;
+            }
+        }
+        if (!firstPartiallyContainedChild) {
+            throw "Spec bug: no first partially contained child!";
+        }
+    }
+
+    // "If original end node is an ancestor container of original start node,
+    // let last partially contained child be null."
+    var lastPartiallyContainedChild;
+    if (isAncestorContainer(originalEndNode, originalStartNode)) {
+        lastPartiallyContainedChild = null;
+    // "Otherwise, let last partially contained child be the last child of
+    // common ancestor that is partially contained in the context object."
+    } else {
+        for (var i = commonAncestor.childNodes.length - 1; i >= 0; i--) {
+            if (isPartiallyContained(commonAncestor.childNodes[i], range)) {
+                lastPartiallyContainedChild = commonAncestor.childNodes[i];
+                break;
+            }
+        }
+        if (!lastPartiallyContainedChild) {
+            throw "Spec bug: no last partially contained child!";
+        }
+    }
+
+    // "Let contained children be a list of all children of common ancestor
+    // that are contained in the context object, in tree order."
+    //
+    // "If any member of contained children is a DocumentType, raise a
+    // HIERARCHY_REQUEST_ERR exception and abort these steps."
+    var containedChildren = [];
+    for (var i = 0; i < commonAncestor.childNodes.length; i++) {
+        if (isContained(commonAncestor.childNodes[i], range)) {
+            if (commonAncestor.childNodes[i].nodeType
+            == Node.DOCUMENT_TYPE_NODE) {
+                return "HIERARCHY_REQUEST_ERR";
+            }
+            containedChildren.push(commonAncestor.childNodes[i]);
+        }
+    }
+
+    // "If original start node is an ancestor container of original end node,
+    // set new node to original start node and new offset to original start
+    // offset."
+    var newNode, newOffset;
+    if (isAncestorContainer(originalStartNode, originalEndNode)) {
+        newNode = originalStartNode;
+        newOffset = originalStartOffset;
+    // "Otherwise:"
+    } else {
+        // "Let reference node equal original start node."
+        var referenceNode = originalStartNode;
+
+        // "While reference node's parent is not null and is not an ancestor
+        // container of original end node, set reference node to its parent."
+        while (referenceNode.parentNode
+        && !isAncestorContainer(referenceNode.parentNode, originalEndNode)) {
+            referenceNode = referenceNode.parentNode;
+        }
+
+        // "Set new node to the parent of reference node, and new offset to one
+        // plus the index of reference node."
+        newNode = referenceNode.parentNode;
+        newOffset = 1 + indexOf(referenceNode);
+    }
+
+    // "If first partially contained child is a Text, ProcessingInstruction, or
+    // Comment node:"
+    if (firstPartiallyContainedChild
+    && (firstPartiallyContainedChild.nodeType == Node.TEXT_NODE
+    || firstPartiallyContainedChild.nodeType == Node.PROCESSING_INSTRUCTION_NODE
+    || firstPartiallyContainedChild.nodeType == Node.COMMENT_NODE)) {
+        // "Let clone be the result of calling cloneNode(false) on original
+        // start node."
+        var clone = originalStartNode.cloneNode(false);
+
+        // "Set the data of clone to the result of calling substringData() on
+        // original start node, with original start offset as the first
+        // argument and (length of original start node − original start offset)
+        // as the second."
+        clone.data = originalStartNode.substringData(originalStartOffset,
+            nodeLength(originalStartNode) - originalStartOffset);
+
+        // "Append clone as the last child of frag."
+        frag.appendChild(clone);
+
+        // "Call deleteData() on original start node, with original start
+        // offset as the first argument and (length of original start node −
+        // original start offset) as the second."
+        originalStartNode.deleteData(originalStartOffset,
+            nodeLength(originalStartNode) - originalStartOffset);
+    // "Otherwise, if first partially contained child is not null:"
+    } else if (firstPartiallyContainedChild) {
+        // "Let clone be the result of calling cloneNode(false) on first
+        // partially contained child."
+        var clone = firstPartiallyContainedChild.cloneNode(false);
+
+        // "Append clone as the last child of frag."
+        frag.appendChild(clone);
+
+        // "Let subrange be a new Range whose start is (original start node,
+        // original start offset) and whose end is (first partially contained
+        // child, length of first partially contained child)."
+        var subrange = ownerDoc.createRange();
+        subrange.setStart(originalStartNode, originalStartOffset);
+        subrange.setEnd(firstPartiallyContainedChild,
+            nodeLength(firstPartiallyContainedChild));
+
+        // "Let subfrag be the result of calling extractContents() on
+        // subrange."
+        var subfrag = myExtractContents(subrange);
+
+        // "For each child of subfrag, in order, append that child to clone as
+        // its last child."
+        for (var i = 0; i < subfrag.childNodes.length; i++) {
+            clone.appendChild(subfrag.childNodes[i]);
+        }
+    }
+
+    // "For each contained child in contained children, append contained child
+    // as the last child of frag."
+    for (var i = 0; i < containedChildren.length; i++) {
+        frag.appendChild(containedChildren[i]);
+    }
+
+    // "If last partially contained child is a Text, ProcessingInstruction, or
+    // Comment node:"
+    if (lastPartiallyContainedChild
+    && (lastPartiallyContainedChild.nodeType == Node.TEXT_NODE
+    || lastPartiallyContainedChild.nodeType == Node.PROCESSING_INSTRUCTION_NODE
+    || lastPartiallyContainedChild.nodeType == Node.COMMENT_NODE)) {
+        // "Let clone be the result of calling cloneNode(false) on original
+        // end node."
+        var clone = originalEndNode.cloneNode(false);
+
+        // "Set the data of clone to the result of calling substringData(0,
+        // original end offset) on original end node."
+        clone.data = originalEndNode.substringData(0, originalEndOffset);
+
+        // "Append clone as the last child of frag."
+        frag.appendChild(clone);
+
+        // "Call deleteData(0, original end offset) on original end node."
+        originalEndNode.deleteData(0, originalEndOffset);
+    // "Otherwise, if last partially contained child is not null:"
+    } else if (lastPartiallyContainedChild) {
+        // "Let clone be the result of calling cloneNode(false) on last
+        // partially contained child."
+        var clone = lastPartiallyContainedChild.cloneNode(false);
+
+        // "Append clone as the last child of frag."
+        frag.appendChild(clone);
+
+        // "Let subrange be a new Range whose start is (last partially
+        // contained child, 0) and whose end is (original end node, original
+        // end offset)."
+        var subrange = ownerDoc.createRange();
+        subrange.setStart(lastPartiallyContainedChild, 0);
+        subrange.setEnd(originalEndNode, originalEndOffset);
+
+        // "Let subfrag be the result of calling extractContents() on
+        // subrange."
+        var subfrag = myExtractContents(subrange);
+
+        // "For each child of subfrag, in order, append that child to clone as
+        // its last child."
+        for (var i = 0; i < subfrag.childNodes.length; i++) {
+            clone.appendChild(subfrag.childNodes[i]);
+        }
+    }
+
+    // "Set the context object's start and end to (new node, new offset)."
+    range.setStart(newNode, newOffset);
+    range.setEnd(newNode, newOffset);
+
+    // "Return frag."
+    return frag;
+}
+
+/**
+ * insertNode() implementation, following the spec.  If an exception is meant
+ * to be thrown, will return a string with the expected exception name, for
+ * instance "HIERARCHY_REQUEST_ERR".
+ */
+function myInsertNode(range, node) {
+    // "If range's start node is a ProcessingInstruction or Comment node, or is
+    // a Text node whose parent is null, or is node, throw an
+    // "HierarchyRequestError" exception and terminate these steps."
+    if (range.startContainer.nodeType == Node.PROCESSING_INSTRUCTION_NODE
+            || range.startContainer.nodeType == Node.COMMENT_NODE
+            || (range.startContainer.nodeType == Node.TEXT_NODE
+                && !range.startContainer.parentNode)
+            || range.startContainer == node) {
+                    return "HIERARCHY_REQUEST_ERR";
+    }
+
+    // "Let referenceNode be null."
+    var referenceNode = null;
+
+    // "If range's start node is a Text node, set referenceNode to that Text node."
+    if (range.startContainer.nodeType == Node.TEXT_NODE) {
+        referenceNode = range.startContainer;
+
+        // "Otherwise, set referenceNode to the child of start node whose index is
+        // start offset, and null if there is no such child."
+    } else {
+        if (range.startOffset < range.startContainer.childNodes.length) {
+            referenceNode = range.startContainer.childNodes[range.startOffset];
+        } else {
+            referenceNode = null;
+        }
+    }
+
+    // "Let parent be range's start node if referenceNode is null, and
+    // referenceNode's parent otherwise."
+    var parent_ = referenceNode === null ? range.startContainer :
+        referenceNode.parentNode;
+
+    // "Ensure pre-insertion validity of node into parent before
+    // referenceNode."
+    var error = ensurePreInsertionValidity(node, parent_, referenceNode);
+    if (error) {
+        return error;
+    }
+
+    // "If range's start node is a Text node, set referenceNode to the result
+    // of splitting it with offset range's start offset."
+    if (range.startContainer.nodeType == Node.TEXT_NODE) {
+        referenceNode = range.startContainer.splitText(range.startOffset);
+    }
+
+    // "If node is referenceNode, set referenceNode to its next sibling."
+    if (node == referenceNode) {
+        referenceNode = referenceNode.nextSibling;
+    }
+
+    // "If node's parent is not null, remove node from its parent."
+    if (node.parentNode) {
+        node.parentNode.removeChild(node);
+    }
+
+    // "Let newOffset be parent's length if referenceNode is null, and
+    // referenceNode's index otherwise."
+    var newOffset = referenceNode === null ? nodeLength(parent_) :
+        indexOf(referenceNode);
+
+    // "Increase newOffset by node's length if node is a DocumentFragment node,
+    // and one otherwise."
+    newOffset += node.nodeType == Node.DOCUMENT_FRAGMENT_NODE ?
+        nodeLength(node) : 1;
+
+    // "Pre-insert node into parent before referenceNode."
+    parent_.insertBefore(node, referenceNode);
+
+    // "If range's start and end are the same, set range's end to (parent,
+    // newOffset)."
+    if (range.startContainer == range.endContainer
+    && range.startOffset == range.endOffset) {
+        range.setEnd(parent_, newOffset);
+    }
+}
+
+// To make filter() calls more readable
+function isElement(node) {
+    return node.nodeType == Node.ELEMENT_NODE;
+}
+
+function isText(node) {
+    return node.nodeType == Node.TEXT_NODE;
+}
+
+function isDoctype(node) {
+    return node.nodeType == Node.DOCUMENT_TYPE_NODE;
+}
+
+function ensurePreInsertionValidity(node, parent_, child) {
+    // "If parent is not a Document, DocumentFragment, or Element node, throw a
+    // HierarchyRequestError."
+    if (parent_.nodeType != Node.DOCUMENT_NODE
+            && parent_.nodeType != Node.DOCUMENT_FRAGMENT_NODE
+            && parent_.nodeType != Node.ELEMENT_NODE) {
+                return "HIERARCHY_REQUEST_ERR";
+    }
+
+    // "If node is a host-including inclusive ancestor of parent, throw a
+    // HierarchyRequestError."
+    //
+    // XXX Does not account for host
+    if (isInclusiveAncestor(node, parent_)) {
+        return "HIERARCHY_REQUEST_ERR";
+    }
+
+    // "If child is not null and its parent is not parent, throw a NotFoundError
+    // exception."
+    if (child && child.parentNode != parent_) {
+        return "NOT_FOUND_ERR";
+    }
+
+    // "If node is not a DocumentFragment, DocumentType, Element, Text,
+    // ProcessingInstruction, or Comment node, throw a HierarchyRequestError."
+    if (node.nodeType != Node.DOCUMENT_FRAGMENT_NODE
+            && node.nodeType != Node.DOCUMENT_TYPE_NODE
+            && node.nodeType != Node.ELEMENT_NODE
+            && node.nodeType != Node.TEXT_NODE
+            && node.nodeType != Node.PROCESSING_INSTRUCTION_NODE
+            && node.nodeType != Node.COMMENT_NODE) {
+                return "HIERARCHY_REQUEST_ERR";
+    }
+
+    // "If either node is a Text node and parent is a document, or node is a
+    // doctype and parent is not a document, throw a HierarchyRequestError."
+    if ((node.nodeType == Node.TEXT_NODE
+                && parent_.nodeType == Node.DOCUMENT_NODE)
+            || (node.nodeType == Node.DOCUMENT_TYPE_NODE
+                && parent_.nodeType != Node.DOCUMENT_NODE)) {
+                    return "HIERARCHY_REQUEST_ERR";
+    }
+
+    // "If parent is a document, and any of the statements below, switched on
+    // node, are true, throw a HierarchyRequestError."
+    if (parent_.nodeType == Node.DOCUMENT_NODE) {
+        switch (node.nodeType) {
+        case Node.DOCUMENT_FRAGMENT_NODE:
+            // "If node has more than one element child or has a Text node
+            // child.  Otherwise, if node has one element child and either
+            // parent has an element child, child is a doctype, or child is not
+            // null and a doctype is following child."
+            if ([].filter.call(node.childNodes, isElement).length > 1) {
+                return "HIERARCHY_REQUEST_ERR";
+            }
+
+            if ([].some.call(node.childNodes, isText)) {
+                return "HIERARCHY_REQUEST_ERR";
+            }
+
+            if ([].filter.call(node.childNodes, isElement).length == 1) {
+                if ([].some.call(parent_.childNodes, isElement)) {
+                    return "HIERARCHY_REQUEST_ERR";
+                }
+
+                if (child && child.nodeType == Node.DOCUMENT_TYPE_NODE) {
+                    return "HIERARCHY_REQUEST_ERR";
+                }
+
+                if (child && [].slice.call(parent_.childNodes, indexOf(child) + 1)
+                               .filter(isDoctype)) {
+                    return "HIERARCHY_REQUEST_ERR";
+                }
+            }
+            break;
+
+        case Node.ELEMENT_NODE:
+            // "parent has an element child, child is a doctype, or child is
+            // not null and a doctype is following child."
+            if ([].some.call(parent_.childNodes, isElement)) {
+                return "HIERARCHY_REQUEST_ERR";
+            }
+
+            if (child.nodeType == Node.DOCUMENT_TYPE_NODE) {
+                return "HIERARCHY_REQUEST_ERR";
+            }
+
+            if (child && [].slice.call(parent_.childNodes, indexOf(child) + 1)
+                           .filter(isDoctype)) {
+                return "HIERARCHY_REQUEST_ERR";
+            }
+            break;
+
+        case Node.DOCUMENT_TYPE_NODE:
+            // "parent has a doctype child, an element is preceding child, or
+            // child is null and parent has an element child."
+            if ([].some.call(parent_.childNodes, isDoctype)) {
+                return "HIERARCHY_REQUEST_ERR";
+            }
+
+            if (child && [].slice.call(parent_.childNodes, 0, indexOf(child))
+                           .some(isElement)) {
+                return "HIERARCHY_REQUEST_ERR";
+            }
+
+            if (!child && [].some.call(parent_.childNodes, isElement)) {
+                return "HIERARCHY_REQUEST_ERR";
+            }
+            break;
+        }
+    }
+}
+
+/**
+ * Asserts that two nodes are equal, in the sense of isEqualNode().  If they
+ * aren't, tries to print a relatively informative reason why not.  TODO: Move
+ * this to testharness.js?
+ */
+function assertNodesEqual(actual, expected, msg) {
+    if (!actual.isEqualNode(expected)) {
+        msg = "Actual and expected mismatch for " + msg + ".  ";
+
+        while (actual && expected) {
+            assert_true(actual.nodeType === expected.nodeType
+                && actual.nodeName === expected.nodeName
+                && actual.nodeValue === expected.nodeValue,
+                "First differing node: expected " + format_value(expected)
+                + ", got " + format_value(actual) + " [" + msg + "]");
+            actual = nextNode(actual);
+            expected = nextNode(expected);
+        }
+
+        assert_unreached("DOMs were not equal but we couldn't figure out why");
+    }
+}
+
+/**
+ * Given a DOMException, return the name (e.g., "HIERARCHY_REQUEST_ERR").
+ */
+function getDomExceptionName(e) {
+    var ret = null;
+    for (var prop in e) {
+        if (/^[A-Z_]+_ERR$/.test(prop) && e[prop] == e.code) {
+            return prop;
+        }
+    }
+
+    throw "Exception seems to not be a DOMException?  " + e;
+}
+
+/**
+ * Given an array of endpoint data [start container, start offset, end
+ * container, end offset], returns a Range with those endpoints.
+ */
+function rangeFromEndpoints(endpoints) {
+    // If we just use document instead of the ownerDocument of endpoints[0],
+    // WebKit will throw on setStart/setEnd.  This is a WebKit bug, but it's in
+    // range, not selection, so we don't want to fail anything for it.
+    var range = ownerDocument(endpoints[0]).createRange();
+    range.setStart(endpoints[0], endpoints[1]);
+    range.setEnd(endpoints[2], endpoints[3]);
+    return range;
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/constants.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/constants.js
new file mode 100644
index 0000000..397df96f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/constants.js
@@ -0,0 +1,11 @@
+function testConstants(objects, constants, msg) {
+  objects.forEach(function(arr) {
+    var o = arr[0], desc = arr[1];
+    test(function() {
+      constants.forEach(function(d) {
+        assert_true(d[0] in o, "Object " + o + " doesn't have " + d[0])
+        assert_equals(o[d[0]], d[1], "Object " + o + " value for " + d[0] + " is wrong")
+      })
+    }, "Constants for " + msg + " on " + desc + ".")
+  })
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constants.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constants.html
new file mode 100644
index 0000000..2311ef60
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constants.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>Event constants</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="../constants.js"></script>
+<div id="log"></div>
+<script>
+var objects;
+setup(function() {
+  objects = [
+    [Event, "Event interface object"],
+    [Event.prototype, "Event prototype object"],
+    [document.createEvent("Event"), "Event object"],
+    [document.createEvent("CustomEvent"), "CustomEvent object"]
+  ]
+})
+testConstants(objects, [
+  ["NONE", 0],
+  ["CAPTURING_PHASE", 1],
+  ["AT_TARGET", 2],
+  ["BUBBLING_PHASE", 3]
+], "eventPhase")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constructors-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constructors-expected.txt
new file mode 100644
index 0000000..a3966081
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constructors-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+PASS Event constructors 
+PASS Event constructors 1 
+PASS Event constructors 2 
+PASS Event constructors 3 
+FAIL Event constructors 4 Failed to construct 'Event': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
+PASS Event constructors 5 
+PASS Event constructors 6 
+PASS Event constructors 7 
+PASS Event constructors 8 
+PASS Event constructors 9 
+PASS Event constructors 10 
+PASS Event constructors 11 
+PASS Event constructors 12 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constructors.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constructors.html
new file mode 100644
index 0000000..a3247af
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constructors.html
@@ -0,0 +1,124 @@
+<!doctype html>
+<title>Event constructors</title>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+  assert_throws(new TypeError(), function() {
+    new Event()
+  })
+})
+test(function() {
+  var test_error = { name: "test" }
+  assert_throws(test_error, function() {
+    new Event({ toString: function() { throw test_error; } })
+  })
+})
+test(function() {
+  var ev = new Event("")
+  assert_equals(ev.type, "")
+  assert_equals(ev.target, null)
+  assert_equals(ev.currentTarget, null)
+  assert_equals(ev.eventPhase, Event.NONE)
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, false)
+  assert_equals(ev.defaultPrevented, false)
+  assert_equals(ev.isTrusted, false)
+  assert_true(ev.timeStamp > 0)
+  assert_true("initEvent" in ev)
+})
+test(function() {
+  var ev = new Event("test")
+  assert_equals(ev.type, "test")
+  assert_equals(ev.target, null)
+  assert_equals(ev.currentTarget, null)
+  assert_equals(ev.eventPhase, Event.NONE)
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, false)
+  assert_equals(ev.defaultPrevented, false)
+  assert_equals(ev.isTrusted, false)
+  assert_true(ev.timeStamp > 0)
+  assert_true("initEvent" in ev)
+})
+test(function() {
+  var ev = Event("test")
+  assert_equals(ev.type, "test")
+  assert_equals(ev.target, null)
+  assert_equals(ev.currentTarget, null)
+  assert_equals(ev.eventPhase, Event.NONE)
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, false)
+  assert_equals(ev.defaultPrevented, false)
+  assert_equals(ev.isTrusted, false)
+  assert_true(ev.timeStamp > 0)
+  assert_true("initEvent" in ev)
+})
+test(function() {
+  var ev = new Event("I am an event", { bubbles: true, cancelable: false})
+  assert_equals(ev.type, "I am an event")
+  assert_equals(ev.bubbles, true)
+  assert_equals(ev.cancelable, false)
+})
+test(function() {
+  var ev = new Event("@", { bubblesIGNORED: true, cancelable: true})
+  assert_equals(ev.type, "@")
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, true)
+})
+test(function() {
+  var ev = new Event("@", { "bubbles\0IGNORED": true, cancelable: true})
+  assert_equals(ev.type, "@")
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, true)
+})
+test(function() {
+  var ev = new Event("Xx", { cancelable: true})
+  assert_equals(ev.type, "Xx")
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, true)
+})
+test(function() {
+  var ev = new Event("Xx", {})
+  assert_equals(ev.type, "Xx")
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, false)
+})
+test(function() {
+  var ev = new Event("Xx", {bubbles: true, cancelable: false, sweet: "x"})
+  assert_equals(ev.type, "Xx")
+  assert_equals(ev.bubbles, true)
+  assert_equals(ev.cancelable, false)
+  assert_equals(ev.sweet, undefined)
+})
+test(function() {
+  var called = []
+  var ev = new Event("Xx", {
+    get cancelable() {
+      called.push("cancelable")
+      return false
+    },
+    get bubbles() {
+      called.push("bubbles")
+      return true;
+    },
+    get sweet() {
+      called.push("sweet")
+      return "x"
+    }
+  })
+  assert_array_equals(called, ["bubbles", "cancelable"])
+  assert_equals(ev.type, "Xx")
+  assert_equals(ev.bubbles, true)
+  assert_equals(ev.cancelable, false)
+  assert_equals(ev.sweet, undefined)
+})
+test(function() {
+  var ev = new CustomEvent("$", {detail: 54, sweet: "x", sweet2: "x", cancelable:true})
+  assert_equals(ev.type, "$")
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, true)
+  assert_equals(ev.sweet, undefined)
+  assert_equals(ev.detail, 54)
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-defaultPrevented.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-defaultPrevented.html
new file mode 100644
index 0000000..fc6bd281
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-defaultPrevented.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<title>Event.defaultPrevented</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var ev;
+test(function() {
+  ev = document.createEvent("Event");
+  assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "When an event is created, defaultPrevented should be initialized to false.");
+test(function() {
+  ev.initEvent("foo", true, false);
+  assert_equals(ev.bubbles, true, "bubbles");
+  assert_equals(ev.cancelable, false, "cancelable");
+  assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "initEvent should work correctly (not cancelable).");
+test(function() {
+  assert_equals(ev.cancelable, false, "cancelable (before)");
+  ev.preventDefault();
+  assert_equals(ev.cancelable, false, "cancelable (after)");
+  assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "preventDefault() should not change defaultPrevented if cancelable is false.");
+test(function() {
+  ev.initEvent("foo", true, true);
+  assert_equals(ev.bubbles, true, "bubbles");
+  assert_equals(ev.cancelable, true, "cancelable");
+  assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "initEvent should work correctly (cancelable).");
+test(function() {
+  assert_equals(ev.cancelable, true, "cancelable (before)");
+  ev.preventDefault();
+  assert_equals(ev.cancelable, true, "cancelable (after)");
+  assert_equals(ev.defaultPrevented, true, "defaultPrevented");
+}, "preventDefault() should change defaultPrevented if cancelable is false.");
+test(function() {
+  ev.initEvent("foo", true, true);
+  assert_equals(ev.bubbles, true, "bubbles");
+  assert_equals(ev.cancelable, true, "cancelable");
+  assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "initEvent should unset defaultPrevented.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-bubbles-false.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-bubbles-false.html
new file mode 100644
index 0000000..43a6331
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-bubbles-false.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title> Event.bubbles attribute is set to false </title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-initevent">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+<script>
+test(function() {
+    var event_type = "click";
+    var target = document.getElementById("target");
+    var targets = [
+        window,
+        document,
+        document.documentElement,
+        document.body,
+        document.getElementById("table"),
+        document.getElementById("table-body"),
+        document.getElementById("parent"),
+        target,
+    ];
+    var expected_targets = targets.concat(target);
+    var phases = [
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.AT_TARGET,
+        Event.AT_TARGET,
+    ];
+
+
+    var actual_targets = [], actual_phases = [];
+    var test_event = function(evt) {
+        actual_targets.push(evt.currentTarget);
+        actual_phases.push(evt.eventPhase);
+    }
+
+    for (var i = 0; i < targets.length; i++) {
+        targets[i].addEventListener(event_type, test_event, true);
+        targets[i].addEventListener(event_type, test_event, false);
+    }
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event_type, false, true);
+
+    target.dispatchEvent(evt);
+
+    assert_array_equals(actual_targets, expected_targets, "targets");
+    assert_array_equals(actual_phases, phases, "phases");
+}, "Event.dispatchEvent with Event.bubbles set to false.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-handlers-changed.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-handlers-changed.html
new file mode 100644
index 0000000..4695bad
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-handlers-changed.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title> Dispatch additional events inside an event listener </title>
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+
+<script>
+async_test(function() {
+  var event_type = "bar";
+  var target = document.getElementById("target");
+  var parent = document.getElementById("parent");
+  var tbody = document.getElementById("table-body");
+  var table = document.getElementById("table");
+  var body = document.body;
+  var html = document.documentElement;
+  var targets = [window, document, html, body, table, tbody, parent, target];
+  var expected_targets = [
+    window,
+    document,
+    html,
+    body,
+    table,
+    tbody,
+    parent,
+    target,
+    target,
+    parent,
+    tbody,
+    table,
+    body,
+    html,
+    document,
+    window
+  ];
+  var expected_listeners = [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1];
+
+  var actual_targets = [], actual_listeners = [];
+  var test_event_function = function(i) {
+    return this.step_func(function(evt) {
+      actual_targets.push(evt.currentTarget);
+      actual_listeners.push(i);
+
+      if (evt.eventPhase != evt.BUBBLING_PHASE && evt.currentTarget.foo != 1) {
+        evt.currentTarget.removeEventListener(event_type, event_handlers[0], true);
+        evt.currentTarget.addEventListener(event_type, event_handlers[2], true);
+        evt.currentTarget.foo = 1;
+      }
+
+      if (evt.eventPhase != evt.CAPTURING_PHASE && evt.currentTarget.foo != 3) {
+        evt.currentTarget.removeEventListener(event_type, event_handlers[0], false);
+        evt.currentTarget.addEventListener(event_type, event_handlers[3], false);
+        evt.currentTarget.foo = 3;
+      }
+    });
+  }.bind(this);
+  var event_handlers = [
+    test_event_function(0),
+    test_event_function(1),
+    test_event_function(2),
+    test_event_function(3),
+  ];
+
+  for (var i = 0; i < targets.length; ++i) {
+    targets[i].addEventListener(event_type, event_handlers[0], true);
+    targets[i].addEventListener(event_type, event_handlers[1], false);
+  }
+
+  var evt = document.createEvent("Event");
+  evt.initEvent(event_type, true, true);
+  target.dispatchEvent(evt);
+
+  assert_array_equals(actual_targets, expected_targets, "actual_targets");
+  assert_array_equals(actual_listeners, expected_listeners, "actual_listeners");
+
+  this.done();
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-omitted-capture.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-omitted-capture.html
new file mode 100644
index 0000000..abcdd3f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-omitted-capture.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>EventTarget.addEventListener: capture argument omitted</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+<script>
+test(function() {
+    var event_type = "foo";
+    var target = document.getElementById("target");
+    var targets = [
+        target,
+        document.getElementById("parent"),
+        document.getElementById("table-body"),
+        document.getElementById("table"),
+        document.body,
+        document.documentElement,
+        document,
+        window
+    ];
+    var phases = [
+        Event.AT_TARGET,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE
+    ];
+
+    var actual_targets = [], actual_phases = [];
+    var test_event = function(evt) {
+        actual_targets.push(evt.currentTarget);
+        actual_phases.push(evt.eventPhase);
+    }
+
+    for (var i = 0; i < targets.length; i++) {
+        targets[i].addEventListener(event_type, test_event);
+    }
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event_type, true, true);
+
+    target.dispatchEvent(evt);
+
+    for (var i = 0; i < targets.length; i++) {
+        targets[i].removeEventListener(event_type, test_event);
+    }
+
+    target.dispatchEvent(evt);
+
+    assert_array_equals(actual_targets, targets, "targets");
+    assert_array_equals(actual_phases, phases, "phases");
+}, "EventTarget.addEventListener with the capture argument omitted");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-propagation-stopped.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-propagation-stopped.html
new file mode 100644
index 0000000..d303759b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-propagation-stopped.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Calling stopPropagation() prior to dispatchEvent() </title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+
+<script>
+test(function() {
+    var event = "foo";
+    var target = document.getElementById("target");
+    var parent = document.getElementById("parent");
+    var tbody = document.getElementById("table-body");
+    var table = document.getElementById("table");
+    var body = document.body;
+    var html = document.documentElement;
+    var current_targets = [window, document, html, body, table, tbody, parent, target];
+    var expected_targets = [];
+    var actual_targets = [];
+    var expected_phases = [];
+    var actual_phases = [];
+
+    var test_event = function(evt) {
+        actual_targets.push(evt.currentTarget);
+        actual_phases.push(evt.eventPhase);
+    };
+
+    for (var i = 0; i < current_targets.length; ++i) {
+        current_targets[i].addEventListener(event, test_event, true);
+        current_targets[i].addEventListener(event, test_event, false);
+    }
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event, true, true);
+    evt.stopPropagation();
+    target.dispatchEvent(evt);
+
+    assert_array_equals(actual_targets, expected_targets, "actual_targets");
+    assert_array_equals(actual_phases, expected_phases, "actual_phases");
+});
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-redispatch.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-redispatch.html
new file mode 100644
index 0000000..c46efdf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-redispatch.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset=urf-8>
+<title>EventTarget#dispatchEvent(): redispatching a native event</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var event;
+  document.addEventListener("DOMContentLoaded", this.step_func(function(e) {
+    assert_true(e.isTrusted, "Should be trusted when first handled");
+    event = e;
+  }), true);
+
+  window.onload = this.step_func_done(function() {
+    var received = 0;
+    var target = document.createElement("span");
+    target.addEventListener("DOMContentLoaded", this.step_func(function(e) {
+      assert_false(e.isTrusted, "Should not be trusted during redispatching");
+      ++received;
+    }), true);
+    assert_true(event.isTrusted, "Should be trusted before redispatching");
+    target.dispatchEvent(event);
+    assert_false(event.isTrusted, "Should not be trusted after redispatching");
+    assert_equals(received, 1);
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-reenter.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-reenter.html
new file mode 100644
index 0000000..f63a065c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-reenter.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title> Dispatch additional events inside an event listener </title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+<script>
+test(function() {
+    var event_type = "foo";
+    var target = document.getElementById("target");
+    var parent = document.getElementById("parent");
+    var tbody = document.getElementById("table-body");
+    var table = document.getElementById("table");
+    var body = document.body;
+    var html = document.documentElement;
+    var targets = [window, document, html, body, table, tbody, parent, target];
+    var expected_targets = [
+        window, document, html, body, table,
+        target, parent, tbody,
+        table, body, html, document, window,
+        tbody, parent, target];
+    var actual_targets = [];
+    var expected_types = [
+        "foo", "foo", "foo", "foo", "foo",
+        "bar", "bar", "bar",
+        "bar", "bar", "bar", "bar", "bar",
+        "foo", "foo", "foo"
+    ];
+
+    var actual_targets = [], actual_types = [];
+    var test_event = this.step_func(function(evt) {
+        actual_targets.push(evt.currentTarget);
+        actual_types.push(evt.type);
+
+        if (table == evt.currentTarget && event_type == evt.type) {
+            var e = document.createEvent("Event");
+            e.initEvent("bar", true, true);
+            target.dispatchEvent(e);
+        }
+    });
+
+    for (var i = 0; i < targets.length; ++i) {
+        targets[i].addEventListener(event_type, test_event, true);
+        targets[i].addEventListener("bar", test_event, false);
+    }
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event_type, false, true);
+    target.dispatchEvent(evt);
+
+    assert_array_equals(actual_targets, expected_targets, "actual_targets");
+    assert_array_equals(actual_types, expected_types, "actual_types");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-target-moved.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-target-moved.html
new file mode 100644
index 0000000..0f30483
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-target-moved.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title> Determined event propagation path - target moved </title>
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+<script>
+test(function() {
+    var event_type = "foo";
+    var target = document.getElementById("target");
+    var parent = document.getElementById("parent");
+    var tbody = document.getElementById("table-body");
+    var table = document.getElementById("table");
+    var body = document.body;
+    var html = document.documentElement;
+    var targets = [window, document, html, body, table, tbody, parent, target];
+    var expected_targets = targets.concat([target, parent, tbody, table, body, html, document, window]);
+    var phases = [
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.AT_TARGET,
+        Event.AT_TARGET,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+    ];
+
+    var actual_targets = [], actual_phases = [];
+    var test_event = this.step_func(function(evt) {
+        if (parent === target.parentNode) {
+            var table_row = document.getElementById("table-row");
+            table_row.appendChild(parent.removeChild(target));
+        }
+
+        actual_targets.push(evt.currentTarget);
+        actual_phases.push(evt.eventPhase);
+    });
+
+    for (var i = 0; i < targets.length; i++) {
+        targets[i].addEventListener(event_type, test_event, true);
+        targets[i].addEventListener(event_type, test_event, false);
+    }
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event_type, true, true);
+    target.dispatchEvent(evt);
+
+    assert_array_equals(actual_targets, expected_targets, "targets");
+    assert_array_equals(actual_phases, phases, "phases");
+}, "Event propagation path when an element in it is moved within the DOM");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-target-removed.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-target-removed.html
new file mode 100644
index 0000000..fbb8198
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-dispatch-target-removed.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Determined event propagation path - target removed</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+<script>
+test(function() {
+    var event_type = "foo";
+    var target = document.getElementById("target");
+    var parent = document.getElementById("parent");
+    var tbody = document.getElementById("table-body");
+    var table = document.getElementById("table");
+    var body = document.body;
+    var html = document.documentElement;
+    var targets = [window, document, html, body, table, tbody, parent, target];
+    var expected_targets = targets.concat([target, parent, tbody, table, body, html, document, window]);
+    var phases = [
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.AT_TARGET,
+        Event.AT_TARGET,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+    ];
+
+    var actual_targets = [], actual_phases = [];
+    var test_event = this.step_func(function(evt) {
+        if (parent === target.parentNode) {
+            parent.removeChild(target);
+        }
+
+        actual_targets.push(evt.currentTarget);
+        actual_phases.push(evt.eventPhase);
+    });
+
+    for (var i = 0; i < targets.length; i++) {
+        targets[i].addEventListener(event_type, test_event, true);
+        targets[i].addEventListener(event_type, test_event, false);
+    }
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event_type, true, true);
+    target.dispatchEvent(evt);
+
+    assert_array_equals(actual_targets, expected_targets, "targets");
+    assert_array_equals(actual_phases, phases, "phases");
+}, "Event propagation path when an element in it is removed from the DOM");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-initEvent.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-initEvent.html
new file mode 100644
index 0000000..20b2f870
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-initEvent.html
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<title>Event.initEvent</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var booleans = [true, false];
+booleans.forEach(function(bubbles) {
+  booleans.forEach(function(cancelable) {
+    test(function() {
+      var e = document.createEvent("Event")
+      e.initEvent("type", bubbles, cancelable)
+
+      // Step 3.
+      // Can't test the stop propagation flag and stop immediate propagation flag.
+      assert_equals(e.defaultPrevented, false, "defaultPrevented")
+      // Step 4.
+      assert_equals(e.isTrusted, false, "isTrusted")
+      // Step 5.
+      assert_equals(e.target, null, "target")
+      // Step 6.
+      assert_equals(e.type, "type", "type")
+      // Step 7.
+      assert_equals(e.bubbles, bubbles, "bubbles")
+      // Step 8.
+      assert_equals(e.cancelable, cancelable, "cancelable")
+    }, "Properties of initEvent(type, " + bubbles + ", " + cancelable + ")")
+  })
+})
+
+test(function() {
+  var e = document.createEvent("Event")
+  e.initEvent("type 1", true, false)
+  assert_equals(e.type, "type 1", "type (first init)")
+  assert_equals(e.bubbles, true, "bubbles (first init)")
+  assert_equals(e.cancelable, false, "cancelable (first init)")
+
+  e.initEvent("type 2", false, true)
+  assert_equals(e.type, "type 2", "type (second init)")
+  assert_equals(e.bubbles, false, "bubbles (second init)")
+  assert_equals(e.cancelable, true, "cancelable (second init)")
+}, "Calling initEvent multiple times (getting type).")
+
+test(function() {
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=998809
+  var e = document.createEvent("Event")
+  e.initEvent("type 1", true, false)
+  assert_equals(e.bubbles, true, "bubbles (first init)")
+  assert_equals(e.cancelable, false, "cancelable (first init)")
+
+  e.initEvent("type 2", false, true)
+  assert_equals(e.type, "type 2", "type (second init)")
+  assert_equals(e.bubbles, false, "bubbles (second init)")
+  assert_equals(e.cancelable, true, "cancelable (second init)")
+}, "Calling initEvent multiple times (not getting type).")
+
+// Step 2.
+async_test(function() {
+  // https://www.w3.org/Bugs/Public/show_bug.cgi?id=17715
+
+  var e = document.createEvent("Event")
+  e.initEvent("type", false, false)
+  assert_equals(e.type, "type", "type (first init)")
+  assert_equals(e.bubbles, false, "bubbles (first init)")
+  assert_equals(e.cancelable, false, "cancelable (first init)")
+
+  var target = document.createElement("div")
+  target.addEventListener("type", this.step_func(function() {
+    e.initEvent("fail", true, true)
+    assert_equals(e.type, "type", "type (second init)")
+    assert_equals(e.bubbles, false, "bubbles (second init)")
+    assert_equals(e.cancelable, false, "cancelable (second init)")
+  }), false)
+
+  assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+
+  this.done()
+}, "Calling initEvent must not have an effect during dispatching.")
+
+async_test(function() {
+  var e = document.createEvent("Event")
+  e.initEvent("type", false, false)
+  e.stopPropagation()
+
+  var target = document.createElement("div")
+  target.addEventListener("type", this.step_func(function() {
+    assert_unreached("")
+  }), false)
+  assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+  assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+
+  e.initEvent("type", false, false)
+  var called = false
+  var target = document.createElement("div")
+  target.addEventListener("type", this.step_func(function() {
+    called = true
+  }), false)
+  assert_false(called)
+  assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+  assert_true(called)
+
+  this.done()
+}, "Calling initEvent must unset the stop propagation flag.")
+
+async_test(function() {
+  var e = document.createEvent("Event")
+  e.initEvent("type", false, false)
+
+  var target = document.createElement("div")
+  target.addEventListener("type", this.step_func(function() {
+    e.initEvent("type2", true, true);
+    assert_equals(e.type, "type", "initEvent type setter should short-circuit");
+    assert_false(e.bubbles, "initEvent bubbles setter should short-circuit");
+    assert_false(e.cancelable, "initEvent cancelable setter should short-circuit");
+  }), false)
+  assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+
+  this.done()
+}, "Calling initEvent during propagation.")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-propagation-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-propagation-expected.txt
new file mode 100644
index 0000000..991c91f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-propagation-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+PASS Newly-created Event 
+PASS After stopPropagation() 
+FAIL Reinitialized after stopPropagation() assert_equals: Propagation flag expected true but got false
+PASS After stopImmediatePropagation() 
+FAIL Reinitialized after stopImmediatePropagation() assert_equals: Propagation flag expected true but got false
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-propagation.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-propagation.html
new file mode 100644
index 0000000..15882ed
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-propagation.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<title>Event propagation tests</title>
+<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
+<div id=log></div>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<script>
+"use strict";
+
+function testPropagationFlag(ev, expected, desc) {
+  test(function() {
+    var called = false;
+    var callback = function() { called = true };
+    document.head.addEventListener("foo", callback);
+    document.head.dispatchEvent(ev);
+    // Gecko resets the flags after dispatching; it will happily dispatch
+    // the event the second time around.
+    document.head.dispatchEvent(ev);
+    assert_equals(called, expected, "Propagation flag");
+    document.head.removeEventListener("foo", callback);
+  }, desc);
+}
+
+var ev = document.createEvent("Event");
+ev.initEvent("foo", true, false);
+testPropagationFlag(ev, true, "Newly-created Event");
+ev.stopPropagation();
+testPropagationFlag(ev, false, "After stopPropagation()");
+ev.initEvent("foo", true, false);
+testPropagationFlag(ev, true, "Reinitialized after stopPropagation()");
+
+var ev = document.createEvent("Event");
+ev.initEvent("foo", true, false);
+ev.stopImmediatePropagation();
+testPropagationFlag(ev, false, "After stopImmediatePropagation()");
+ev.initEvent("foo", true, false);
+testPropagationFlag(ev, true, "Reinitialized after stopImmediatePropagation()");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-type-empty-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-type-empty-expected.txt
new file mode 100644
index 0000000..60b5540a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-type-empty-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL initEvent Failed to execute 'dispatchEvent' on 'EventTarget': The event provided is uninitialized.
+FAIL Constructor Failed to execute 'dispatchEvent' on 'EventTarget': The event provided is uninitialized.
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-type-empty.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-type-empty.html
new file mode 100644
index 0000000..d043f04
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-type-empty.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Event.type set to the empty string</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-type">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function do_test(t, e) {
+  assert_equals(e.type, "", "type");
+  assert_equals(e.bubbles, false, "bubbles");
+  assert_equals(e.cancelable, false, "cancelable");
+
+  var target = document.createElement("div");
+  var handled = false;
+  target.addEventListener("", t.step_func(function(e) {
+    handled = true;
+  }));
+  assert_true(target.dispatchEvent(e));
+  assert_true(handled);
+}
+
+async_test(function() {
+  var e = document.createEvent("Event");
+  e.initEvent("", false, false);
+  do_test(this, e);
+  this.done();
+}, "initEvent");
+
+async_test(function() {
+  var e = new Event("");
+  do_test(this, e);
+  this.done();
+}, "Constructor");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-type.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-type.html
new file mode 100644
index 0000000..7605386
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-type.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>Event.type</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-type">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var e = document.createEvent("Event")
+  assert_equals(e.type, "");
+}, "Event.type should initially be the empty string");
+test(function() {
+  var e = document.createEvent("Event")
+  e.initEvent("foo", false, false)
+  assert_equals(e.type, "foo")
+}, "Event.type should be initialized by initEvent");
+test(function() {
+  var e = new Event("bar")
+  assert_equals(e.type, "bar")
+}, "Event.type should be initialized by the constructor");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/EventTarget-addEventListener.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/EventTarget-addEventListener.html
new file mode 100644
index 0000000..99e4b47
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/EventTarget-addEventListener.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>EventTarget.addEventListener</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// Step 1.
+test(function() {
+  assert_equals(document.addEventListener("x", null, false), undefined);
+  assert_equals(document.addEventListener("x", null, true), undefined);
+  assert_equals(document.addEventListener("x", null), undefined);
+}, "Adding a null event listener should succeed");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/EventTarget-dispatchEvent-returnvalue.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/EventTarget-dispatchEvent-returnvalue.html
new file mode 100644
index 0000000..b8d5eb3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/EventTarget-dispatchEvent-returnvalue.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>EventTarget.dispatchEvent: return value</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-preventdefault">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-defaultprevented">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+<script>
+test(function() {
+    var event_type = "foo";
+    var target = document.getElementById("target");
+    var parent = document.getElementById("parent");
+    var default_prevented;
+
+    parent.addEventListener(event_type, function(e) {}, true);
+    target.addEventListener(event_type, function(e) {
+        evt.preventDefault();
+        default_prevented = evt.defaultPrevented;
+    }, true);
+    target.addEventListener(event_type, function(e) {}, true);
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event_type, true, true);
+
+    assert_true(parent.dispatchEvent(evt));
+    assert_false(target.dispatchEvent(evt));
+    assert_true(default_prevented);
+}, "Return value of EventTarget.dispatchEvent.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/EventTarget-dispatchEvent.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/EventTarget-dispatchEvent.html
new file mode 100644
index 0000000..d677c0b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/EventTarget-dispatchEvent.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>EventTarget.dispatchEvent</title>
+<link rel="author" title="Olli Pettay" href="mailto:Olli.Pettay@gmail.com">
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-eventtarget-dispatchevent">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="/dom/nodes/Document-createEvent.js"></script>
+<div id="log"></div>
+<script>
+setup({
+  "allow_uncaught_exception": true,
+})
+
+test(function() {
+  assert_throws(new TypeError(), function() { document.dispatchEvent(null) })
+}, "Calling dispatchEvent(null).")
+
+aliases.forEach(function(alias) {
+  test(function() {
+    var e = document.createEvent(alias[0])
+    assert_equals(e.type, "", "Event type should be empty string before initialization")
+    assert_throws("InvalidStateError", function() { document.dispatchEvent(e) })
+  }, "If the event's initialized flag is not set, an InvalidStateError must be thrown (" + alias [0] + ").")
+})
+
+var dispatch_dispatch = async_test("If the event's dispatch flag is set, an InvalidStateError must be thrown.")
+dispatch_dispatch.step(function() {
+  var e = document.createEvent("Event")
+  e.initEvent("type", false, false)
+
+  var target = document.createElement("div")
+  target.addEventListener("type", dispatch_dispatch.step_func(function() {
+    assert_throws("InvalidStateError", function() {
+      target.dispatchEvent(e)
+    })
+    assert_throws("InvalidStateError", function() {
+      document.dispatchEvent(e)
+    })
+  }), false)
+
+  assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+
+  dispatch_dispatch.done()
+})
+
+test(function() {
+  // https://www.w3.org/Bugs/Public/show_bug.cgi?id=17713
+  // https://www.w3.org/Bugs/Public/show_bug.cgi?id=17714
+
+  var e = document.createEvent("Event")
+  e.initEvent("type", false, false)
+
+  var called = []
+
+  var target = document.createElement("div")
+  target.addEventListener("type", function() {
+    called.push("First")
+    throw new Error()
+  }, false)
+
+  target.addEventListener("type", function() {
+    called.push("Second")
+  }, false)
+
+  assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+  assert_array_equals(called, ["First", "Second"],
+                      "Should have continued to call other event listeners")
+}, "Exceptions from event listeners must not be propagated.")
+
+async_test(function() {
+  var results = []
+  var outerb = document.createElement("b")
+  var middleb = outerb.appendChild(document.createElement("b"))
+  var innerb = middleb.appendChild(document.createElement("b"))
+  outerb.addEventListener("x", this.step_func(function() {
+    middleb.addEventListener("x", this.step_func(function() {
+      results.push("middle")
+    }), true)
+    results.push("outer")
+  }), true)
+  innerb.dispatchEvent(new Event("x"))
+  assert_array_equals(results, ["outer", "middle"])
+  this.done()
+}, "Event listeners added during dispatch should be called");
+
+async_test(function() {
+  var results = []
+  var b = document.createElement("b")
+  b.addEventListener("x", this.step_func(function() {
+    results.push(1)
+  }), true)
+  b.addEventListener("x", this.step_func(function() {
+    results.push(2)
+  }), false)
+  b.addEventListener("x", this.step_func(function() {
+    results.push(3)
+  }), true)
+  b.dispatchEvent(new Event("x"))
+  assert_array_equals(results, [1, 2, 3])
+  this.done()
+}, "Event listeners should be called in order of addition")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/EventTarget-removeEventListener.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/EventTarget-removeEventListener.html
new file mode 100644
index 0000000..1395361b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/EventTarget-removeEventListener.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>EventTarget.removeEventListener</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// Step 1.
+test(function() {
+  assert_equals(document.removeEventListener("x", null, false), undefined);
+  assert_equals(document.removeEventListener("x", null, true), undefined);
+  assert_equals(document.removeEventListener("x", null), undefined);
+}, "removing a null event listener should succeed");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/ProgressEvent-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/ProgressEvent-expected.txt
new file mode 100644
index 0000000..7b5f376
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/ProgressEvent-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+PASS Default event values. 
+FAIL document.createEvent() should not work with ProgressEvent. assert_throws: function "function () {
+    document.createEvent("ProgressEvent")
+  }" did not throw
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/ProgressEvent.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/ProgressEvent.html
new file mode 100644
index 0000000..5a4e076
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/ProgressEvent.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>ProgressEvent constructor</title>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+  var ev = new ProgressEvent("test")
+  assert_equals(ev.type, "test")
+  assert_equals(ev.target, null)
+  assert_equals(ev.currentTarget, null)
+  assert_equals(ev.eventPhase, Event.NONE)
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, false)
+  assert_equals(ev.defaultPrevented, false)
+  assert_equals(ev.isTrusted, false)
+  assert_true(ev.timeStamp > 0)
+  assert_true("initEvent" in ev)
+}, "Default event values.")
+test(function() {
+  assert_throws("NotSupportedError", function() {
+    document.createEvent("ProgressEvent")
+  })
+}, "document.createEvent() should not work with ProgressEvent.")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/historical-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/historical-expected.txt
new file mode 100644
index 0000000..91bb4b4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/historical-expected.txt
@@ -0,0 +1,52 @@
+This is a testharness.js-based test.
+FAIL Historical DOM features must be removed: CDATASection assert_equals: expected (undefined) undefined but got (function) function "function CDATASection() { [native code] }"
+PASS Historical DOM features must be removed: DOMConfiguration 
+FAIL Historical DOM features must be removed: DOMError assert_equals: expected (undefined) undefined but got (function) function "function DOMError() { [native code] }"
+PASS Historical DOM features must be removed: DOMErrorHandler 
+PASS Historical DOM features must be removed: DOMImplementationList 
+PASS Historical DOM features must be removed: DOMImplementationSource 
+PASS Historical DOM features must be removed: DOMLocator 
+PASS Historical DOM features must be removed: DOMObject 
+PASS Historical DOM features must be removed: DOMUserData 
+PASS Historical DOM features must be removed: Entity 
+PASS Historical DOM features must be removed: EntityReference 
+PASS Historical DOM features must be removed: EventException 
+PASS Historical DOM features must be removed: NameList 
+PASS Historical DOM features must be removed: Notation 
+PASS Historical DOM features must be removed: TypeInfo 
+PASS Historical DOM features must be removed: UserDataHandler 
+PASS Historical DOM features must be removed: RangeException 
+FAIL Historical DOM features must be removed: createCDATASection assert_equals: expected (undefined) undefined but got (function) function "function createCDATASection() { [native code] }"
+PASS Historical DOM features must be removed: createEntityReference 
+FAIL Historical DOM features must be removed: xmlEncoding assert_equals: expected (undefined) undefined but got (object) null
+FAIL Historical DOM features must be removed: xmlStandalone assert_equals: expected (undefined) undefined but got (boolean) false
+FAIL Historical DOM features must be removed: xmlVersion assert_equals: expected (undefined) undefined but got (object) null
+PASS Historical DOM features must be removed: strictErrorChecking 
+PASS Historical DOM features must be removed: domConfig 
+PASS Historical DOM features must be removed: normalizeDocument 
+PASS Historical DOM features must be removed: renameNode 
+FAIL Historical DOM features must be removed: defaultCharset assert_equals: expected (undefined) undefined but got (string) "ISO-8859-1"
+PASS Historical DOM features must be removed: height 
+PASS Historical DOM features must be removed: width 
+PASS DOMImplementation.getFeature() must be nuked. 
+PASS Historical DOM features must be removed: schemaTypeInfo 
+PASS Historical DOM features must be removed: setIdAttribute 
+PASS Historical DOM features must be removed: setIdAttributeNS 
+PASS Historical DOM features must be removed: setIdAttributeNode 
+PASS DocumentType member must be nuked: entities 
+PASS DocumentType member must be nuked: notations 
+PASS DocumentType member must be nuked: internalSubset 
+PASS Text member must be nuked: isElementContentWhitespace 
+PASS Text member must be nuked: replaceWholeText 
+PASS Node member must be nuked: hasAttributes 
+PASS Node member must be nuked: attributes 
+PASS Node member must be nuked: namespaceURI 
+PASS Node member must be nuked: prefix 
+PASS Node member must be nuked: localName 
+PASS Node member must be nuked: isSupported 
+PASS Node member must be nuked: getFeature 
+PASS Node member must be nuked: getUserData 
+PASS Node member must be nuked: setUserData 
+PASS Window member must be nuked: attachEvent 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/historical.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/historical.html
new file mode 100644
index 0000000..93e46b1b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/historical.html
@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+<title>Historical DOM features must be removed</title>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function isInterfaceNuked(name) {
+  test(function() {
+    assert_equals(window[name], undefined)
+  }, "Historical DOM features must be removed: " + name)
+}
+var nukedInterfaces = [
+  "CDATASection",
+  "DOMConfiguration",
+  "DOMError",
+  "DOMErrorHandler",
+  "DOMImplementationList",
+  "DOMImplementationSource",
+  "DOMLocator",
+  "DOMObject",
+  "DOMUserData",
+  "Entity",
+  "EntityReference",
+  "EventException", // DOM Events
+  "NameList",
+  "Notation",
+  "TypeInfo",
+  "UserDataHandler",
+  "RangeException" // DOM Range
+]
+nukedInterfaces.forEach(isInterfaceNuked)
+
+function isNukedFromDocument(name) {
+  test(function() {
+    var doc = document.implementation.createDocument(null,null,null)
+    assert_equals(document[name], undefined)
+    assert_equals(doc[name], undefined)
+  }, "Historical DOM features must be removed: " + name)
+}
+var documentNuked = [
+  "createCDATASection",
+  "createEntityReference",
+  "xmlEncoding",
+  "xmlStandalone",
+  "xmlVersion",
+  "strictErrorChecking",
+  "domConfig",
+  "normalizeDocument",
+  "renameNode",
+  "defaultCharset",
+  "height",
+  "width"
+]
+documentNuked.forEach(isNukedFromDocument)
+
+test(function() {
+  assert_equals(document.implementation["getFeature"], undefined)
+}, "DOMImplementation.getFeature() must be nuked.")
+
+function isNukedFromElement(name) {
+  test(function() {
+    var ele = document.createElementNS("test", "test")
+    assert_equals(document.body[name], undefined)
+    assert_equals(ele[name], undefined)
+  }, "Historical DOM features must be removed: " + name)
+}
+var elementNuked = [
+  "schemaTypeInfo",
+  "setIdAttribute",
+  "setIdAttributeNS",
+  "setIdAttributeNode"
+]
+elementNuked.forEach(isNukedFromElement)
+
+function isNukedFromDoctype(name) {
+  test(function() {
+    var doctype = document.implementation.createDocumentType("test", "", "")
+    assert_equals(doctype[name], undefined)
+  }, "DocumentType member must be nuked: " + name)
+}
+var doctypeNuked = [
+  "entities",
+  "notations",
+  "internalSubset"
+]
+doctypeNuked.forEach(isNukedFromDoctype)
+
+function isNukedFromText(name) {
+  test(function() {
+    var text = document.createTextNode("test")
+    assert_equals(text[name], undefined)
+  }, "Text member must be nuked: " + name)
+}
+var textNuked = [
+  "isElementContentWhitespace",
+  "replaceWholeText"
+]
+textNuked.forEach(isNukedFromText)
+
+function isNukedFromNode(name) {
+  test(function() {
+    var doc = document.implementation.createDocument(null,null,null)
+    var doctype = document.implementation.createDocumentType("test", "", "")
+    var text = document.createTextNode("test")
+    assert_equals(doc[name], undefined)
+    assert_equals(doctype[name], undefined)
+    assert_equals(text[name], undefined)
+  }, "Node member must be nuked: " + name)
+}
+var nodeNuked = [
+  "hasAttributes",
+  "attributes",
+  "namespaceURI",
+  "prefix",
+  "localName",
+  "isSupported",
+  "getFeature",
+  "getUserData",
+  "setUserData"
+]
+nodeNuked.forEach(isNukedFromNode)
+
+function isNukedFromWindow(name) {
+  test(function() {
+    assert_equals(window[name], undefined)
+  }, "Window member must be nuked: " + name)
+}
+var windowNuked = [
+  "attachEvent"
+]
+windowNuked.forEach(isNukedFromWindow)
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interface-objects.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interface-objects.html
new file mode 100644
index 0000000..ac06b71
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interface-objects.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<title>Interfaces</title>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testInterfaceDeletable(iface) {
+  test(function() {
+    assert_true(!!window[iface], "Interface should exist.")
+    assert_true(delete window[iface], "The delete operator should return true.")
+    assert_equals(window[iface], undefined, "Interface should be gone.")
+  }, "Should be able to delete " + iface + ".")
+}
+var interfaces = [
+  "Event",
+  "CustomEvent",
+  "EventTarget",
+  "Node",
+  "Document",
+  "DOMImplementation",
+  "DocumentFragment",
+  "ProcessingInstruction",
+  "DocumentType",
+  "Element",
+  "Attr",
+  "CharacterData",
+  "Text",
+  "Comment",
+  "NodeIterator",
+  "TreeWalker",
+  "NodeFilter",
+  "NodeList",
+  "HTMLCollection",
+  "DOMStringList",
+  "DOMTokenList",
+  "DOMSettableTokenList"
+];
+test(function() {
+  for (var p in window) {
+    interfaces.forEach(function(i) {
+      assert_not_equals(p, i)
+    })
+  }
+}, "Interface objects properties should not be Enumerable")
+interfaces.forEach(testInterfaceDeletable);
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interfaces-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interfaces-expected.txt
new file mode 100644
index 0000000..e71121ae
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interfaces-expected.txt
@@ -0,0 +1,1365 @@
+CONSOLE MESSAGE: line 198: callback not yet supported
+This is a testharness.js-based test.
+PASS Event interface: existence and properties of interface object 
+PASS Event interface object length 
+PASS Event interface object name 
+FAIL Event interface: existence and properties of interface prototype object assert_equals: class string of Event.prototype expected "[object EventPrototype]" but got "[object Object]"
+PASS Event interface: existence and properties of interface prototype object's "constructor" property 
+PASS Event interface: attribute type 
+PASS Event interface: attribute target 
+PASS Event interface: attribute currentTarget 
+PASS Event interface: constant NONE on interface object 
+PASS Event interface: constant NONE on interface prototype object 
+PASS Event interface: constant CAPTURING_PHASE on interface object 
+PASS Event interface: constant CAPTURING_PHASE on interface prototype object 
+PASS Event interface: constant AT_TARGET on interface object 
+PASS Event interface: constant AT_TARGET on interface prototype object 
+PASS Event interface: constant BUBBLING_PHASE on interface object 
+PASS Event interface: constant BUBBLING_PHASE on interface prototype object 
+PASS Event interface: attribute eventPhase 
+PASS Event interface: operation stopPropagation() 
+PASS Event interface: operation stopImmediatePropagation() 
+PASS Event interface: attribute bubbles 
+PASS Event interface: attribute cancelable 
+PASS Event interface: operation preventDefault() 
+PASS Event interface: attribute defaultPrevented 
+PASS Event interface: attribute timeStamp 
+FAIL Event interface: operation initEvent(DOMString,boolean,boolean) assert_equals: property has wrong .length expected 3 but got 0
+PASS Event must be primary interface of document.createEvent("Event") 
+PASS Stringification of document.createEvent("Event") 
+PASS Event interface: document.createEvent("Event") must inherit property "type" with the proper type (0) 
+PASS Event interface: document.createEvent("Event") must inherit property "target" with the proper type (1) 
+PASS Event interface: document.createEvent("Event") must inherit property "currentTarget" with the proper type (2) 
+PASS Event interface: document.createEvent("Event") must inherit property "NONE" with the proper type (3) 
+PASS Event interface: document.createEvent("Event") must inherit property "CAPTURING_PHASE" with the proper type (4) 
+PASS Event interface: document.createEvent("Event") must inherit property "AT_TARGET" with the proper type (5) 
+PASS Event interface: document.createEvent("Event") must inherit property "BUBBLING_PHASE" with the proper type (6) 
+PASS Event interface: document.createEvent("Event") must inherit property "eventPhase" with the proper type (7) 
+PASS Event interface: document.createEvent("Event") must inherit property "stopPropagation" with the proper type (8) 
+PASS Event interface: document.createEvent("Event") must inherit property "stopImmediatePropagation" with the proper type (9) 
+PASS Event interface: document.createEvent("Event") must inherit property "bubbles" with the proper type (10) 
+PASS Event interface: document.createEvent("Event") must inherit property "cancelable" with the proper type (11) 
+PASS Event interface: document.createEvent("Event") must inherit property "preventDefault" with the proper type (12) 
+PASS Event interface: document.createEvent("Event") must inherit property "defaultPrevented" with the proper type (13) 
+PASS Event interface: document.createEvent("Event") must have own property "isTrusted" 
+PASS Event interface: document.createEvent("Event") must inherit property "timeStamp" with the proper type (15) 
+PASS Event interface: document.createEvent("Event") must inherit property "initEvent" with the proper type (16) 
+FAIL Event interface: calling initEvent(DOMString,boolean,boolean) on document.createEvent("Event") with too few arguments must throw TypeError assert_throws: Called with 0 arguments function "function () { [native code] }" did not throw
+PASS Event must be primary interface of new Event("foo") 
+PASS Stringification of new Event("foo") 
+PASS Event interface: new Event("foo") must inherit property "type" with the proper type (0) 
+PASS Event interface: new Event("foo") must inherit property "target" with the proper type (1) 
+PASS Event interface: new Event("foo") must inherit property "currentTarget" with the proper type (2) 
+PASS Event interface: new Event("foo") must inherit property "NONE" with the proper type (3) 
+PASS Event interface: new Event("foo") must inherit property "CAPTURING_PHASE" with the proper type (4) 
+PASS Event interface: new Event("foo") must inherit property "AT_TARGET" with the proper type (5) 
+PASS Event interface: new Event("foo") must inherit property "BUBBLING_PHASE" with the proper type (6) 
+PASS Event interface: new Event("foo") must inherit property "eventPhase" with the proper type (7) 
+PASS Event interface: new Event("foo") must inherit property "stopPropagation" with the proper type (8) 
+PASS Event interface: new Event("foo") must inherit property "stopImmediatePropagation" with the proper type (9) 
+PASS Event interface: new Event("foo") must inherit property "bubbles" with the proper type (10) 
+PASS Event interface: new Event("foo") must inherit property "cancelable" with the proper type (11) 
+PASS Event interface: new Event("foo") must inherit property "preventDefault" with the proper type (12) 
+PASS Event interface: new Event("foo") must inherit property "defaultPrevented" with the proper type (13) 
+PASS Event interface: new Event("foo") must have own property "isTrusted" 
+PASS Event interface: new Event("foo") must inherit property "timeStamp" with the proper type (15) 
+PASS Event interface: new Event("foo") must inherit property "initEvent" with the proper type (16) 
+FAIL Event interface: calling initEvent(DOMString,boolean,boolean) on new Event("foo") with too few arguments must throw TypeError assert_throws: Called with 0 arguments function "function () { [native code] }" did not throw
+PASS CustomEvent interface: existence and properties of interface object 
+FAIL CustomEvent interface object length assert_equals: wrong value for CustomEvent.length expected 1 but got 0
+PASS CustomEvent interface object name 
+FAIL CustomEvent interface: existence and properties of interface prototype object assert_equals: class string of CustomEvent.prototype expected "[object CustomEventPrototype]" but got "[object Object]"
+PASS CustomEvent interface: existence and properties of interface prototype object's "constructor" property 
+PASS CustomEvent interface: attribute detail 
+PASS CustomEvent interface: operation initCustomEvent(DOMString,boolean,boolean,any) 
+PASS CustomEvent must be primary interface of new CustomEvent("foo") 
+PASS Stringification of new CustomEvent("foo") 
+PASS CustomEvent interface: new CustomEvent("foo") must inherit property "detail" with the proper type (0) 
+PASS CustomEvent interface: new CustomEvent("foo") must inherit property "initCustomEvent" with the proper type (1) 
+PASS CustomEvent interface: calling initCustomEvent(DOMString,boolean,boolean,any) on new CustomEvent("foo") with too few arguments must throw TypeError 
+PASS Event interface: new CustomEvent("foo") must inherit property "type" with the proper type (0) 
+PASS Event interface: new CustomEvent("foo") must inherit property "target" with the proper type (1) 
+PASS Event interface: new CustomEvent("foo") must inherit property "currentTarget" with the proper type (2) 
+PASS Event interface: new CustomEvent("foo") must inherit property "NONE" with the proper type (3) 
+PASS Event interface: new CustomEvent("foo") must inherit property "CAPTURING_PHASE" with the proper type (4) 
+PASS Event interface: new CustomEvent("foo") must inherit property "AT_TARGET" with the proper type (5) 
+PASS Event interface: new CustomEvent("foo") must inherit property "BUBBLING_PHASE" with the proper type (6) 
+PASS Event interface: new CustomEvent("foo") must inherit property "eventPhase" with the proper type (7) 
+PASS Event interface: new CustomEvent("foo") must inherit property "stopPropagation" with the proper type (8) 
+PASS Event interface: new CustomEvent("foo") must inherit property "stopImmediatePropagation" with the proper type (9) 
+PASS Event interface: new CustomEvent("foo") must inherit property "bubbles" with the proper type (10) 
+PASS Event interface: new CustomEvent("foo") must inherit property "cancelable" with the proper type (11) 
+PASS Event interface: new CustomEvent("foo") must inherit property "preventDefault" with the proper type (12) 
+PASS Event interface: new CustomEvent("foo") must inherit property "defaultPrevented" with the proper type (13) 
+PASS Event interface: new CustomEvent("foo") must have own property "isTrusted" 
+PASS Event interface: new CustomEvent("foo") must inherit property "timeStamp" with the proper type (15) 
+PASS Event interface: new CustomEvent("foo") must inherit property "initEvent" with the proper type (16) 
+FAIL Event interface: calling initEvent(DOMString,boolean,boolean) on new CustomEvent("foo") with too few arguments must throw TypeError assert_throws: Called with 0 arguments function "function () { [native code] }" did not throw
+PASS EventTarget interface: existence and properties of interface object 
+PASS EventTarget interface object length 
+PASS EventTarget interface object name 
+FAIL EventTarget interface: existence and properties of interface prototype object assert_equals: class string of EventTarget.prototype expected "[object EventTargetPrototype]" but got "[object Object]"
+PASS EventTarget interface: existence and properties of interface prototype object's "constructor" property 
+PASS EventTarget interface: operation addEventListener(DOMString,EventListener,boolean) 
+PASS EventTarget interface: operation removeEventListener(DOMString,EventListener,boolean) 
+PASS EventTarget interface: operation dispatchEvent(Event) 
+PASS EventListener interface: existence and properties of interface object 
+PASS EventListener interface: existence and properties of interface prototype object 
+PASS EventListener interface: existence and properties of interface prototype object's "constructor" property 
+PASS EventListener interface: operation handleEvent(Event) 
+PASS NodeList interface: existence and properties of interface object 
+PASS NodeList interface object length 
+PASS NodeList interface object name 
+FAIL NodeList interface: existence and properties of interface prototype object assert_equals: class string of NodeList.prototype expected "[object NodeListPrototype]" but got "[object Object]"
+PASS NodeList interface: existence and properties of interface prototype object's "constructor" property 
+PASS NodeList interface: operation item(unsigned long) 
+PASS NodeList interface: attribute length 
+PASS NodeList must be primary interface of document.querySelectorAll("script") 
+PASS Stringification of document.querySelectorAll("script") 
+PASS NodeList interface: document.querySelectorAll("script") must inherit property "item" with the proper type (0) 
+PASS NodeList interface: calling item(unsigned long) on document.querySelectorAll("script") with too few arguments must throw TypeError 
+PASS NodeList interface: document.querySelectorAll("script") must inherit property "length" with the proper type (1) 
+PASS HTMLCollection interface: existence and properties of interface object 
+PASS HTMLCollection interface object length 
+PASS HTMLCollection interface object name 
+FAIL HTMLCollection interface: existence and properties of interface prototype object assert_equals: class string of HTMLCollection.prototype expected "[object HTMLCollectionPrototype]" but got "[object Object]"
+PASS HTMLCollection interface: existence and properties of interface prototype object's "constructor" property 
+PASS HTMLCollection interface: attribute length 
+PASS HTMLCollection interface: operation item(unsigned long) 
+PASS HTMLCollection interface: operation namedItem(DOMString) 
+PASS HTMLCollection must be primary interface of document.body.children 
+PASS Stringification of document.body.children 
+PASS HTMLCollection interface: document.body.children must inherit property "length" with the proper type (0) 
+PASS HTMLCollection interface: document.body.children must inherit property "item" with the proper type (1) 
+PASS HTMLCollection interface: calling item(unsigned long) on document.body.children with too few arguments must throw TypeError 
+PASS HTMLCollection interface: document.body.children must inherit property "namedItem" with the proper type (2) 
+PASS HTMLCollection interface: calling namedItem(DOMString) on document.body.children with too few arguments must throw TypeError 
+PASS MutationObserver interface: existence and properties of interface object 
+PASS MutationObserver interface object length 
+PASS MutationObserver interface object name 
+FAIL MutationObserver interface: existence and properties of interface prototype object assert_equals: class string of MutationObserver.prototype expected "[object MutationObserverPrototype]" but got "[object Object]"
+PASS MutationObserver interface: existence and properties of interface prototype object's "constructor" property 
+PASS MutationObserver interface: operation observe(Node,MutationObserverInit) 
+PASS MutationObserver interface: operation disconnect() 
+PASS MutationObserver interface: operation takeRecords() 
+PASS MutationRecord interface: existence and properties of interface object 
+PASS MutationRecord interface object length 
+PASS MutationRecord interface object name 
+FAIL MutationRecord interface: existence and properties of interface prototype object assert_equals: class string of MutationRecord.prototype expected "[object MutationRecordPrototype]" but got "[object Object]"
+PASS MutationRecord interface: existence and properties of interface prototype object's "constructor" property 
+PASS MutationRecord interface: attribute type 
+PASS MutationRecord interface: attribute target 
+PASS MutationRecord interface: attribute addedNodes 
+PASS MutationRecord interface: attribute removedNodes 
+PASS MutationRecord interface: attribute previousSibling 
+PASS MutationRecord interface: attribute nextSibling 
+PASS MutationRecord interface: attribute attributeName 
+PASS MutationRecord interface: attribute attributeNamespace 
+PASS MutationRecord interface: attribute oldValue 
+PASS Node interface: existence and properties of interface object 
+PASS Node interface object length 
+PASS Node interface object name 
+FAIL Node interface: existence and properties of interface prototype object assert_equals: class string of Node.prototype expected "[object NodePrototype]" but got "[object Object]"
+PASS Node interface: existence and properties of interface prototype object's "constructor" property 
+PASS Node interface: constant ELEMENT_NODE on interface object 
+PASS Node interface: constant ELEMENT_NODE on interface prototype object 
+PASS Node interface: constant ATTRIBUTE_NODE on interface object 
+PASS Node interface: constant ATTRIBUTE_NODE on interface prototype object 
+PASS Node interface: constant TEXT_NODE on interface object 
+PASS Node interface: constant TEXT_NODE on interface prototype object 
+PASS Node interface: constant CDATA_SECTION_NODE on interface object 
+PASS Node interface: constant CDATA_SECTION_NODE on interface prototype object 
+PASS Node interface: constant ENTITY_REFERENCE_NODE on interface object 
+PASS Node interface: constant ENTITY_REFERENCE_NODE on interface prototype object 
+PASS Node interface: constant ENTITY_NODE on interface object 
+PASS Node interface: constant ENTITY_NODE on interface prototype object 
+PASS Node interface: constant PROCESSING_INSTRUCTION_NODE on interface object 
+PASS Node interface: constant PROCESSING_INSTRUCTION_NODE on interface prototype object 
+PASS Node interface: constant COMMENT_NODE on interface object 
+PASS Node interface: constant COMMENT_NODE on interface prototype object 
+PASS Node interface: constant DOCUMENT_NODE on interface object 
+PASS Node interface: constant DOCUMENT_NODE on interface prototype object 
+PASS Node interface: constant DOCUMENT_TYPE_NODE on interface object 
+PASS Node interface: constant DOCUMENT_TYPE_NODE on interface prototype object 
+PASS Node interface: constant DOCUMENT_FRAGMENT_NODE on interface object 
+PASS Node interface: constant DOCUMENT_FRAGMENT_NODE on interface prototype object 
+PASS Node interface: constant NOTATION_NODE on interface object 
+PASS Node interface: constant NOTATION_NODE on interface prototype object 
+PASS Node interface: attribute nodeType 
+PASS Node interface: attribute nodeName 
+PASS Node interface: attribute baseURI 
+PASS Node interface: attribute ownerDocument 
+PASS Node interface: attribute parentNode 
+PASS Node interface: attribute parentElement 
+PASS Node interface: operation hasChildNodes() 
+PASS Node interface: attribute childNodes 
+PASS Node interface: attribute firstChild 
+PASS Node interface: attribute lastChild 
+PASS Node interface: attribute previousSibling 
+PASS Node interface: attribute nextSibling 
+PASS Node interface: attribute nodeValue 
+PASS Node interface: attribute textContent 
+PASS Node interface: operation normalize() 
+PASS Node interface: operation cloneNode(boolean) 
+PASS Node interface: operation isEqualNode(Node) 
+PASS Node interface: constant DOCUMENT_POSITION_DISCONNECTED on interface object 
+PASS Node interface: constant DOCUMENT_POSITION_DISCONNECTED on interface prototype object 
+PASS Node interface: constant DOCUMENT_POSITION_PRECEDING on interface object 
+PASS Node interface: constant DOCUMENT_POSITION_PRECEDING on interface prototype object 
+PASS Node interface: constant DOCUMENT_POSITION_FOLLOWING on interface object 
+PASS Node interface: constant DOCUMENT_POSITION_FOLLOWING on interface prototype object 
+PASS Node interface: constant DOCUMENT_POSITION_CONTAINS on interface object 
+PASS Node interface: constant DOCUMENT_POSITION_CONTAINS on interface prototype object 
+PASS Node interface: constant DOCUMENT_POSITION_CONTAINED_BY on interface object 
+PASS Node interface: constant DOCUMENT_POSITION_CONTAINED_BY on interface prototype object 
+PASS Node interface: constant DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC on interface object 
+PASS Node interface: constant DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC on interface prototype object 
+PASS Node interface: operation compareDocumentPosition(Node) 
+PASS Node interface: operation contains(Node) 
+PASS Node interface: operation lookupPrefix(DOMString) 
+PASS Node interface: operation lookupNamespaceURI(DOMString) 
+PASS Node interface: operation isDefaultNamespace(DOMString) 
+PASS Node interface: operation insertBefore(Node,Node) 
+PASS Node interface: operation appendChild(Node) 
+PASS Node interface: operation replaceChild(Node,Node) 
+PASS Node interface: operation removeChild(Node) 
+PASS Document interface: existence and properties of interface object 
+PASS Document interface object length 
+PASS Document interface object name 
+FAIL Document interface: existence and properties of interface prototype object assert_equals: class string of Document.prototype expected "[object DocumentPrototype]" but got "[object Object]"
+PASS Document interface: existence and properties of interface prototype object's "constructor" property 
+PASS Document interface: attribute implementation 
+PASS Document interface: attribute URL 
+PASS Document interface: attribute documentURI 
+PASS Document interface: attribute origin 
+PASS Document interface: attribute compatMode 
+PASS Document interface: attribute characterSet 
+PASS Document interface: attribute charset 
+PASS Document interface: attribute inputEncoding 
+PASS Document interface: attribute contentType 
+PASS Document interface: attribute doctype 
+PASS Document interface: attribute documentElement 
+PASS Document interface: operation getElementsByTagName(DOMString) 
+PASS Document interface: operation getElementsByTagNameNS(DOMString,DOMString) 
+PASS Document interface: operation getElementsByClassName(DOMString) 
+PASS Document interface: operation createElement(DOMString) 
+PASS Document interface: operation createElementNS(DOMString,DOMString) 
+PASS Document interface: operation createDocumentFragment() 
+PASS Document interface: operation createTextNode(DOMString) 
+PASS Document interface: operation createComment(DOMString) 
+PASS Document interface: operation createProcessingInstruction(DOMString,DOMString) 
+PASS Document interface: operation importNode(Node,boolean) 
+PASS Document interface: operation adoptNode(Node) 
+PASS Document interface: operation createAttribute(DOMString) 
+PASS Document interface: operation createAttributeNS(DOMString,DOMString) 
+PASS Document interface: operation createEvent(DOMString) 
+PASS Document interface: operation createRange() 
+PASS Document interface: operation createNodeIterator(Node,unsigned long,NodeFilter) 
+PASS Document interface: operation createTreeWalker(Node,unsigned long,NodeFilter) 
+PASS Document interface: operation getElementById(DOMString) 
+PASS Document interface: attribute children 
+PASS Document interface: attribute firstElementChild 
+PASS Document interface: attribute lastElementChild 
+PASS Document interface: attribute childElementCount 
+FAIL Document interface: operation prepend([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "prepend" missing
+FAIL Document interface: operation append([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "append" missing
+FAIL Document interface: operation query(DOMString) assert_own_property: interface prototype object missing non-static operation expected property "query" missing
+FAIL Document interface: operation queryAll(DOMString) assert_own_property: interface prototype object missing non-static operation expected property "queryAll" missing
+PASS Document interface: operation querySelector(DOMString) 
+PASS Document interface: operation querySelectorAll(DOMString) 
+PASS XMLDocument interface: existence and properties of interface object 
+PASS XMLDocument interface object length 
+PASS XMLDocument interface object name 
+FAIL XMLDocument interface: existence and properties of interface prototype object assert_equals: class string of XMLDocument.prototype expected "[object XMLDocumentPrototype]" but got "[object Object]"
+PASS XMLDocument interface: existence and properties of interface prototype object's "constructor" property 
+PASS XMLDocument must be primary interface of xmlDoc 
+PASS Stringification of xmlDoc 
+PASS Document interface: xmlDoc must inherit property "implementation" with the proper type (0) 
+PASS Document interface: xmlDoc must inherit property "URL" with the proper type (1) 
+FAIL Document interface: xmlDoc must inherit property "documentURI" with the proper type (2) assert_equals: expected "string" but got "object"
+PASS Document interface: xmlDoc must inherit property "origin" with the proper type (3) 
+PASS Document interface: xmlDoc must inherit property "compatMode" with the proper type (4) 
+PASS Document interface: xmlDoc must inherit property "characterSet" with the proper type (5) 
+PASS Document interface: xmlDoc must inherit property "charset" with the proper type (6) 
+PASS Document interface: xmlDoc must inherit property "inputEncoding" with the proper type (7) 
+PASS Document interface: xmlDoc must inherit property "contentType" with the proper type (8) 
+PASS Document interface: xmlDoc must inherit property "doctype" with the proper type (9) 
+PASS Document interface: xmlDoc must inherit property "documentElement" with the proper type (10) 
+PASS Document interface: xmlDoc must inherit property "getElementsByTagName" with the proper type (11) 
+PASS Document interface: calling getElementsByTagName(DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "getElementsByTagNameNS" with the proper type (12) 
+PASS Document interface: calling getElementsByTagNameNS(DOMString,DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "getElementsByClassName" with the proper type (13) 
+PASS Document interface: calling getElementsByClassName(DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "createElement" with the proper type (14) 
+PASS Document interface: calling createElement(DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "createElementNS" with the proper type (15) 
+PASS Document interface: calling createElementNS(DOMString,DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "createDocumentFragment" with the proper type (16) 
+PASS Document interface: xmlDoc must inherit property "createTextNode" with the proper type (17) 
+PASS Document interface: calling createTextNode(DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "createComment" with the proper type (18) 
+PASS Document interface: calling createComment(DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "createProcessingInstruction" with the proper type (19) 
+PASS Document interface: calling createProcessingInstruction(DOMString,DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "importNode" with the proper type (20) 
+PASS Document interface: calling importNode(Node,boolean) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "adoptNode" with the proper type (21) 
+PASS Document interface: calling adoptNode(Node) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "createAttribute" with the proper type (22) 
+PASS Document interface: calling createAttribute(DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "createAttributeNS" with the proper type (23) 
+PASS Document interface: calling createAttributeNS(DOMString,DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "createEvent" with the proper type (24) 
+PASS Document interface: calling createEvent(DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "createRange" with the proper type (25) 
+PASS Document interface: xmlDoc must inherit property "createNodeIterator" with the proper type (26) 
+PASS Document interface: calling createNodeIterator(Node,unsigned long,NodeFilter) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "createTreeWalker" with the proper type (27) 
+PASS Document interface: calling createTreeWalker(Node,unsigned long,NodeFilter) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "getElementById" with the proper type (28) 
+PASS Document interface: calling getElementById(DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "children" with the proper type (29) 
+PASS Document interface: xmlDoc must inherit property "firstElementChild" with the proper type (30) 
+PASS Document interface: xmlDoc must inherit property "lastElementChild" with the proper type (31) 
+PASS Document interface: xmlDoc must inherit property "childElementCount" with the proper type (32) 
+FAIL Document interface: xmlDoc must inherit property "prepend" with the proper type (33) assert_inherits: property "prepend" not found in prototype chain
+FAIL Document interface: calling prepend([object Object],[object Object]) on xmlDoc with too few arguments must throw TypeError assert_inherits: property "prepend" not found in prototype chain
+FAIL Document interface: xmlDoc must inherit property "append" with the proper type (34) assert_inherits: property "append" not found in prototype chain
+FAIL Document interface: calling append([object Object],[object Object]) on xmlDoc with too few arguments must throw TypeError assert_inherits: property "append" not found in prototype chain
+FAIL Document interface: xmlDoc must inherit property "query" with the proper type (35) assert_inherits: property "query" not found in prototype chain
+FAIL Document interface: calling query(DOMString) on xmlDoc with too few arguments must throw TypeError assert_inherits: property "query" not found in prototype chain
+FAIL Document interface: xmlDoc must inherit property "queryAll" with the proper type (36) assert_inherits: property "queryAll" not found in prototype chain
+FAIL Document interface: calling queryAll(DOMString) on xmlDoc with too few arguments must throw TypeError assert_inherits: property "queryAll" not found in prototype chain
+PASS Document interface: xmlDoc must inherit property "querySelector" with the proper type (37) 
+PASS Document interface: calling querySelector(DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: xmlDoc must inherit property "querySelectorAll" with the proper type (38) 
+PASS Document interface: calling querySelectorAll(DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc must inherit property "ELEMENT_NODE" with the proper type (0) 
+PASS Node interface: xmlDoc must inherit property "ATTRIBUTE_NODE" with the proper type (1) 
+PASS Node interface: xmlDoc must inherit property "TEXT_NODE" with the proper type (2) 
+PASS Node interface: xmlDoc must inherit property "CDATA_SECTION_NODE" with the proper type (3) 
+PASS Node interface: xmlDoc must inherit property "ENTITY_REFERENCE_NODE" with the proper type (4) 
+PASS Node interface: xmlDoc must inherit property "ENTITY_NODE" with the proper type (5) 
+PASS Node interface: xmlDoc must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type (6) 
+PASS Node interface: xmlDoc must inherit property "COMMENT_NODE" with the proper type (7) 
+PASS Node interface: xmlDoc must inherit property "DOCUMENT_NODE" with the proper type (8) 
+PASS Node interface: xmlDoc must inherit property "DOCUMENT_TYPE_NODE" with the proper type (9) 
+PASS Node interface: xmlDoc must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type (10) 
+PASS Node interface: xmlDoc must inherit property "NOTATION_NODE" with the proper type (11) 
+PASS Node interface: xmlDoc must inherit property "nodeType" with the proper type (12) 
+PASS Node interface: xmlDoc must inherit property "nodeName" with the proper type (13) 
+PASS Node interface: xmlDoc must inherit property "baseURI" with the proper type (14) 
+PASS Node interface: xmlDoc must inherit property "ownerDocument" with the proper type (15) 
+PASS Node interface: xmlDoc must inherit property "parentNode" with the proper type (16) 
+PASS Node interface: xmlDoc must inherit property "parentElement" with the proper type (17) 
+PASS Node interface: xmlDoc must inherit property "hasChildNodes" with the proper type (18) 
+PASS Node interface: xmlDoc must inherit property "childNodes" with the proper type (19) 
+PASS Node interface: xmlDoc must inherit property "firstChild" with the proper type (20) 
+PASS Node interface: xmlDoc must inherit property "lastChild" with the proper type (21) 
+PASS Node interface: xmlDoc must inherit property "previousSibling" with the proper type (22) 
+PASS Node interface: xmlDoc must inherit property "nextSibling" with the proper type (23) 
+PASS Node interface: xmlDoc must inherit property "nodeValue" with the proper type (24) 
+PASS Node interface: xmlDoc must inherit property "textContent" with the proper type (25) 
+PASS Node interface: xmlDoc must inherit property "normalize" with the proper type (26) 
+PASS Node interface: xmlDoc must inherit property "cloneNode" with the proper type (27) 
+PASS Node interface: calling cloneNode(boolean) on xmlDoc with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc must inherit property "isEqualNode" with the proper type (28) 
+PASS Node interface: calling isEqualNode(Node) on xmlDoc with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (29) 
+PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (30) 
+PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (31) 
+PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (32) 
+PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (33) 
+PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (34) 
+PASS Node interface: xmlDoc must inherit property "compareDocumentPosition" with the proper type (35) 
+PASS Node interface: calling compareDocumentPosition(Node) on xmlDoc with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc must inherit property "contains" with the proper type (36) 
+PASS Node interface: calling contains(Node) on xmlDoc with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc must inherit property "lookupPrefix" with the proper type (37) 
+PASS Node interface: calling lookupPrefix(DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc must inherit property "lookupNamespaceURI" with the proper type (38) 
+PASS Node interface: calling lookupNamespaceURI(DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc must inherit property "isDefaultNamespace" with the proper type (39) 
+PASS Node interface: calling isDefaultNamespace(DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc must inherit property "insertBefore" with the proper type (40) 
+PASS Node interface: calling insertBefore(Node,Node) on xmlDoc with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc must inherit property "appendChild" with the proper type (41) 
+PASS Node interface: calling appendChild(Node) on xmlDoc with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc must inherit property "replaceChild" with the proper type (42) 
+PASS Node interface: calling replaceChild(Node,Node) on xmlDoc with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc must inherit property "removeChild" with the proper type (43) 
+PASS Node interface: calling removeChild(Node) on xmlDoc with too few arguments must throw TypeError 
+PASS EventTarget interface: xmlDoc must inherit property "addEventListener" with the proper type (0) 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on xmlDoc with too few arguments must throw TypeError 
+PASS EventTarget interface: xmlDoc must inherit property "removeEventListener" with the proper type (1) 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on xmlDoc with too few arguments must throw TypeError 
+PASS EventTarget interface: xmlDoc must inherit property "dispatchEvent" with the proper type (2) 
+PASS EventTarget interface: calling dispatchEvent(Event) on xmlDoc with too few arguments must throw TypeError 
+PASS DOMImplementation interface: existence and properties of interface object 
+PASS DOMImplementation interface object length 
+PASS DOMImplementation interface object name 
+FAIL DOMImplementation interface: existence and properties of interface prototype object assert_equals: class string of DOMImplementation.prototype expected "[object DOMImplementationPrototype]" but got "[object Object]"
+PASS DOMImplementation interface: existence and properties of interface prototype object's "constructor" property 
+PASS DOMImplementation interface: operation createDocumentType(DOMString,DOMString,DOMString) 
+PASS DOMImplementation interface: operation createDocument(DOMString,DOMString,DocumentType) 
+PASS DOMImplementation interface: operation createHTMLDocument(DOMString) 
+PASS DOMImplementation interface: operation hasFeature() 
+PASS DOMImplementation must be primary interface of document.implementation 
+PASS Stringification of document.implementation 
+PASS DOMImplementation interface: document.implementation must inherit property "createDocumentType" with the proper type (0) 
+PASS DOMImplementation interface: calling createDocumentType(DOMString,DOMString,DOMString) on document.implementation with too few arguments must throw TypeError 
+PASS DOMImplementation interface: document.implementation must inherit property "createDocument" with the proper type (1) 
+PASS DOMImplementation interface: calling createDocument(DOMString,DOMString,DocumentType) on document.implementation with too few arguments must throw TypeError 
+PASS DOMImplementation interface: document.implementation must inherit property "createHTMLDocument" with the proper type (2) 
+PASS DOMImplementation interface: calling createHTMLDocument(DOMString) on document.implementation with too few arguments must throw TypeError 
+PASS DOMImplementation interface: document.implementation must inherit property "hasFeature" with the proper type (3) 
+PASS DocumentFragment interface: existence and properties of interface object 
+PASS DocumentFragment interface object length 
+PASS DocumentFragment interface object name 
+FAIL DocumentFragment interface: existence and properties of interface prototype object assert_equals: class string of DocumentFragment.prototype expected "[object DocumentFragmentPrototype]" but got "[object Object]"
+PASS DocumentFragment interface: existence and properties of interface prototype object's "constructor" property 
+PASS DocumentFragment interface: operation getElementById(DOMString) 
+PASS DocumentFragment interface: attribute children 
+PASS DocumentFragment interface: attribute firstElementChild 
+PASS DocumentFragment interface: attribute lastElementChild 
+PASS DocumentFragment interface: attribute childElementCount 
+FAIL DocumentFragment interface: operation prepend([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "prepend" missing
+FAIL DocumentFragment interface: operation append([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "append" missing
+FAIL DocumentFragment interface: operation query(DOMString) assert_own_property: interface prototype object missing non-static operation expected property "query" missing
+FAIL DocumentFragment interface: operation queryAll(DOMString) assert_own_property: interface prototype object missing non-static operation expected property "queryAll" missing
+PASS DocumentFragment interface: operation querySelector(DOMString) 
+PASS DocumentFragment interface: operation querySelectorAll(DOMString) 
+PASS DocumentFragment must be primary interface of document.createDocumentFragment() 
+PASS Stringification of document.createDocumentFragment() 
+PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "getElementById" with the proper type (0) 
+PASS DocumentFragment interface: calling getElementById(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "children" with the proper type (1) 
+PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "firstElementChild" with the proper type (2) 
+PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "lastElementChild" with the proper type (3) 
+PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "childElementCount" with the proper type (4) 
+FAIL DocumentFragment interface: document.createDocumentFragment() must inherit property "prepend" with the proper type (5) assert_inherits: property "prepend" not found in prototype chain
+FAIL DocumentFragment interface: calling prepend([object Object],[object Object]) on document.createDocumentFragment() with too few arguments must throw TypeError assert_inherits: property "prepend" not found in prototype chain
+FAIL DocumentFragment interface: document.createDocumentFragment() must inherit property "append" with the proper type (6) assert_inherits: property "append" not found in prototype chain
+FAIL DocumentFragment interface: calling append([object Object],[object Object]) on document.createDocumentFragment() with too few arguments must throw TypeError assert_inherits: property "append" not found in prototype chain
+FAIL DocumentFragment interface: document.createDocumentFragment() must inherit property "query" with the proper type (7) assert_inherits: property "query" not found in prototype chain
+FAIL DocumentFragment interface: calling query(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError assert_inherits: property "query" not found in prototype chain
+FAIL DocumentFragment interface: document.createDocumentFragment() must inherit property "queryAll" with the proper type (8) assert_inherits: property "queryAll" not found in prototype chain
+FAIL DocumentFragment interface: calling queryAll(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError assert_inherits: property "queryAll" not found in prototype chain
+PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "querySelector" with the proper type (9) 
+PASS DocumentFragment interface: calling querySelector(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "querySelectorAll" with the proper type (10) 
+PASS DocumentFragment interface: calling querySelectorAll(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "ELEMENT_NODE" with the proper type (0) 
+PASS Node interface: document.createDocumentFragment() must inherit property "ATTRIBUTE_NODE" with the proper type (1) 
+PASS Node interface: document.createDocumentFragment() must inherit property "TEXT_NODE" with the proper type (2) 
+PASS Node interface: document.createDocumentFragment() must inherit property "CDATA_SECTION_NODE" with the proper type (3) 
+PASS Node interface: document.createDocumentFragment() must inherit property "ENTITY_REFERENCE_NODE" with the proper type (4) 
+PASS Node interface: document.createDocumentFragment() must inherit property "ENTITY_NODE" with the proper type (5) 
+PASS Node interface: document.createDocumentFragment() must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type (6) 
+PASS Node interface: document.createDocumentFragment() must inherit property "COMMENT_NODE" with the proper type (7) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_NODE" with the proper type (8) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_TYPE_NODE" with the proper type (9) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type (10) 
+PASS Node interface: document.createDocumentFragment() must inherit property "NOTATION_NODE" with the proper type (11) 
+PASS Node interface: document.createDocumentFragment() must inherit property "nodeType" with the proper type (12) 
+PASS Node interface: document.createDocumentFragment() must inherit property "nodeName" with the proper type (13) 
+PASS Node interface: document.createDocumentFragment() must inherit property "baseURI" with the proper type (14) 
+PASS Node interface: document.createDocumentFragment() must inherit property "ownerDocument" with the proper type (15) 
+PASS Node interface: document.createDocumentFragment() must inherit property "parentNode" with the proper type (16) 
+PASS Node interface: document.createDocumentFragment() must inherit property "parentElement" with the proper type (17) 
+PASS Node interface: document.createDocumentFragment() must inherit property "hasChildNodes" with the proper type (18) 
+PASS Node interface: document.createDocumentFragment() must inherit property "childNodes" with the proper type (19) 
+PASS Node interface: document.createDocumentFragment() must inherit property "firstChild" with the proper type (20) 
+PASS Node interface: document.createDocumentFragment() must inherit property "lastChild" with the proper type (21) 
+PASS Node interface: document.createDocumentFragment() must inherit property "previousSibling" with the proper type (22) 
+PASS Node interface: document.createDocumentFragment() must inherit property "nextSibling" with the proper type (23) 
+PASS Node interface: document.createDocumentFragment() must inherit property "nodeValue" with the proper type (24) 
+PASS Node interface: document.createDocumentFragment() must inherit property "textContent" with the proper type (25) 
+PASS Node interface: document.createDocumentFragment() must inherit property "normalize" with the proper type (26) 
+PASS Node interface: document.createDocumentFragment() must inherit property "cloneNode" with the proper type (27) 
+PASS Node interface: calling cloneNode(boolean) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "isEqualNode" with the proper type (28) 
+PASS Node interface: calling isEqualNode(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (29) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (30) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (31) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (32) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (33) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (34) 
+PASS Node interface: document.createDocumentFragment() must inherit property "compareDocumentPosition" with the proper type (35) 
+PASS Node interface: calling compareDocumentPosition(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "contains" with the proper type (36) 
+PASS Node interface: calling contains(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "lookupPrefix" with the proper type (37) 
+PASS Node interface: calling lookupPrefix(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "lookupNamespaceURI" with the proper type (38) 
+PASS Node interface: calling lookupNamespaceURI(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "isDefaultNamespace" with the proper type (39) 
+PASS Node interface: calling isDefaultNamespace(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "insertBefore" with the proper type (40) 
+PASS Node interface: calling insertBefore(Node,Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "appendChild" with the proper type (41) 
+PASS Node interface: calling appendChild(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "replaceChild" with the proper type (42) 
+PASS Node interface: calling replaceChild(Node,Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "removeChild" with the proper type (43) 
+PASS Node interface: calling removeChild(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS EventTarget interface: document.createDocumentFragment() must inherit property "addEventListener" with the proper type (0) 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS EventTarget interface: document.createDocumentFragment() must inherit property "removeEventListener" with the proper type (1) 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS EventTarget interface: document.createDocumentFragment() must inherit property "dispatchEvent" with the proper type (2) 
+PASS EventTarget interface: calling dispatchEvent(Event) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS DocumentType interface: existence and properties of interface object 
+PASS DocumentType interface object length 
+PASS DocumentType interface object name 
+FAIL DocumentType interface: existence and properties of interface prototype object assert_equals: class string of DocumentType.prototype expected "[object DocumentTypePrototype]" but got "[object Object]"
+PASS DocumentType interface: existence and properties of interface prototype object's "constructor" property 
+PASS DocumentType interface: attribute name 
+PASS DocumentType interface: attribute publicId 
+PASS DocumentType interface: attribute systemId 
+FAIL DocumentType interface: operation before([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "before" missing
+FAIL DocumentType interface: operation after([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "after" missing
+FAIL DocumentType interface: operation replaceWith([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "replaceWith" missing
+PASS DocumentType interface: operation remove() 
+PASS DocumentType must be primary interface of document.doctype 
+PASS Stringification of document.doctype 
+PASS DocumentType interface: document.doctype must inherit property "name" with the proper type (0) 
+PASS DocumentType interface: document.doctype must inherit property "publicId" with the proper type (1) 
+PASS DocumentType interface: document.doctype must inherit property "systemId" with the proper type (2) 
+FAIL DocumentType interface: document.doctype must inherit property "before" with the proper type (3) assert_inherits: property "before" not found in prototype chain
+FAIL DocumentType interface: calling before([object Object],[object Object]) on document.doctype with too few arguments must throw TypeError assert_inherits: property "before" not found in prototype chain
+FAIL DocumentType interface: document.doctype must inherit property "after" with the proper type (4) assert_inherits: property "after" not found in prototype chain
+FAIL DocumentType interface: calling after([object Object],[object Object]) on document.doctype with too few arguments must throw TypeError assert_inherits: property "after" not found in prototype chain
+FAIL DocumentType interface: document.doctype must inherit property "replaceWith" with the proper type (5) assert_inherits: property "replaceWith" not found in prototype chain
+FAIL DocumentType interface: calling replaceWith([object Object],[object Object]) on document.doctype with too few arguments must throw TypeError assert_inherits: property "replaceWith" not found in prototype chain
+PASS DocumentType interface: document.doctype must inherit property "remove" with the proper type (6) 
+PASS Node interface: document.doctype must inherit property "ELEMENT_NODE" with the proper type (0) 
+PASS Node interface: document.doctype must inherit property "ATTRIBUTE_NODE" with the proper type (1) 
+PASS Node interface: document.doctype must inherit property "TEXT_NODE" with the proper type (2) 
+PASS Node interface: document.doctype must inherit property "CDATA_SECTION_NODE" with the proper type (3) 
+PASS Node interface: document.doctype must inherit property "ENTITY_REFERENCE_NODE" with the proper type (4) 
+PASS Node interface: document.doctype must inherit property "ENTITY_NODE" with the proper type (5) 
+PASS Node interface: document.doctype must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type (6) 
+PASS Node interface: document.doctype must inherit property "COMMENT_NODE" with the proper type (7) 
+PASS Node interface: document.doctype must inherit property "DOCUMENT_NODE" with the proper type (8) 
+PASS Node interface: document.doctype must inherit property "DOCUMENT_TYPE_NODE" with the proper type (9) 
+PASS Node interface: document.doctype must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type (10) 
+PASS Node interface: document.doctype must inherit property "NOTATION_NODE" with the proper type (11) 
+PASS Node interface: document.doctype must inherit property "nodeType" with the proper type (12) 
+PASS Node interface: document.doctype must inherit property "nodeName" with the proper type (13) 
+PASS Node interface: document.doctype must inherit property "baseURI" with the proper type (14) 
+PASS Node interface: document.doctype must inherit property "ownerDocument" with the proper type (15) 
+PASS Node interface: document.doctype must inherit property "parentNode" with the proper type (16) 
+PASS Node interface: document.doctype must inherit property "parentElement" with the proper type (17) 
+PASS Node interface: document.doctype must inherit property "hasChildNodes" with the proper type (18) 
+PASS Node interface: document.doctype must inherit property "childNodes" with the proper type (19) 
+PASS Node interface: document.doctype must inherit property "firstChild" with the proper type (20) 
+PASS Node interface: document.doctype must inherit property "lastChild" with the proper type (21) 
+PASS Node interface: document.doctype must inherit property "previousSibling" with the proper type (22) 
+PASS Node interface: document.doctype must inherit property "nextSibling" with the proper type (23) 
+PASS Node interface: document.doctype must inherit property "nodeValue" with the proper type (24) 
+PASS Node interface: document.doctype must inherit property "textContent" with the proper type (25) 
+PASS Node interface: document.doctype must inherit property "normalize" with the proper type (26) 
+PASS Node interface: document.doctype must inherit property "cloneNode" with the proper type (27) 
+PASS Node interface: calling cloneNode(boolean) on document.doctype with too few arguments must throw TypeError 
+PASS Node interface: document.doctype must inherit property "isEqualNode" with the proper type (28) 
+PASS Node interface: calling isEqualNode(Node) on document.doctype with too few arguments must throw TypeError 
+PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (29) 
+PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (30) 
+PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (31) 
+PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (32) 
+PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (33) 
+PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (34) 
+PASS Node interface: document.doctype must inherit property "compareDocumentPosition" with the proper type (35) 
+PASS Node interface: calling compareDocumentPosition(Node) on document.doctype with too few arguments must throw TypeError 
+PASS Node interface: document.doctype must inherit property "contains" with the proper type (36) 
+PASS Node interface: calling contains(Node) on document.doctype with too few arguments must throw TypeError 
+PASS Node interface: document.doctype must inherit property "lookupPrefix" with the proper type (37) 
+PASS Node interface: calling lookupPrefix(DOMString) on document.doctype with too few arguments must throw TypeError 
+PASS Node interface: document.doctype must inherit property "lookupNamespaceURI" with the proper type (38) 
+PASS Node interface: calling lookupNamespaceURI(DOMString) on document.doctype with too few arguments must throw TypeError 
+PASS Node interface: document.doctype must inherit property "isDefaultNamespace" with the proper type (39) 
+PASS Node interface: calling isDefaultNamespace(DOMString) on document.doctype with too few arguments must throw TypeError 
+PASS Node interface: document.doctype must inherit property "insertBefore" with the proper type (40) 
+PASS Node interface: calling insertBefore(Node,Node) on document.doctype with too few arguments must throw TypeError 
+PASS Node interface: document.doctype must inherit property "appendChild" with the proper type (41) 
+PASS Node interface: calling appendChild(Node) on document.doctype with too few arguments must throw TypeError 
+PASS Node interface: document.doctype must inherit property "replaceChild" with the proper type (42) 
+PASS Node interface: calling replaceChild(Node,Node) on document.doctype with too few arguments must throw TypeError 
+PASS Node interface: document.doctype must inherit property "removeChild" with the proper type (43) 
+PASS Node interface: calling removeChild(Node) on document.doctype with too few arguments must throw TypeError 
+PASS EventTarget interface: document.doctype must inherit property "addEventListener" with the proper type (0) 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on document.doctype with too few arguments must throw TypeError 
+PASS EventTarget interface: document.doctype must inherit property "removeEventListener" with the proper type (1) 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on document.doctype with too few arguments must throw TypeError 
+PASS EventTarget interface: document.doctype must inherit property "dispatchEvent" with the proper type (2) 
+PASS EventTarget interface: calling dispatchEvent(Event) on document.doctype with too few arguments must throw TypeError 
+PASS Element interface: existence and properties of interface object 
+PASS Element interface object length 
+PASS Element interface object name 
+FAIL Element interface: existence and properties of interface prototype object assert_equals: class string of Element.prototype expected "[object ElementPrototype]" but got "[object Object]"
+PASS Element interface: existence and properties of interface prototype object's "constructor" property 
+PASS Element interface: attribute namespaceURI 
+PASS Element interface: attribute prefix 
+PASS Element interface: attribute localName 
+PASS Element interface: attribute tagName 
+PASS Element interface: attribute id 
+PASS Element interface: attribute className 
+PASS Element interface: attribute classList 
+PASS Element interface: operation hasAttributes() 
+PASS Element interface: attribute attributes 
+PASS Element interface: operation getAttribute(DOMString) 
+PASS Element interface: operation getAttributeNS(DOMString,DOMString) 
+PASS Element interface: operation setAttribute(DOMString,DOMString) 
+PASS Element interface: operation setAttributeNS(DOMString,DOMString,DOMString) 
+PASS Element interface: operation removeAttribute(DOMString) 
+PASS Element interface: operation removeAttributeNS(DOMString,DOMString) 
+PASS Element interface: operation hasAttribute(DOMString) 
+PASS Element interface: operation hasAttributeNS(DOMString,DOMString) 
+PASS Element interface: operation getAttributeNode(DOMString) 
+PASS Element interface: operation getAttributeNodeNS(DOMString,DOMString) 
+PASS Element interface: operation setAttributeNode(Attr) 
+PASS Element interface: operation setAttributeNodeNS(Attr) 
+PASS Element interface: operation removeAttributeNode(Attr) 
+PASS Element interface: operation closest(DOMString) 
+PASS Element interface: operation matches(DOMString) 
+PASS Element interface: operation getElementsByTagName(DOMString) 
+PASS Element interface: operation getElementsByTagNameNS(DOMString,DOMString) 
+PASS Element interface: operation getElementsByClassName(DOMString) 
+PASS Element interface: attribute children 
+PASS Element interface: attribute firstElementChild 
+PASS Element interface: attribute lastElementChild 
+PASS Element interface: attribute childElementCount 
+FAIL Element interface: operation prepend([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "prepend" missing
+FAIL Element interface: operation append([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "append" missing
+FAIL Element interface: operation query(DOMString) assert_own_property: interface prototype object missing non-static operation expected property "query" missing
+FAIL Element interface: operation queryAll(DOMString) assert_own_property: interface prototype object missing non-static operation expected property "queryAll" missing
+PASS Element interface: operation querySelector(DOMString) 
+PASS Element interface: operation querySelectorAll(DOMString) 
+PASS Element interface: attribute previousElementSibling 
+PASS Element interface: attribute nextElementSibling 
+FAIL Element interface: operation before([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "before" missing
+FAIL Element interface: operation after([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "after" missing
+FAIL Element interface: operation replaceWith([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "replaceWith" missing
+PASS Element interface: operation remove() 
+PASS Element must be primary interface of element 
+PASS Stringification of element 
+PASS Element interface: element must inherit property "namespaceURI" with the proper type (0) 
+PASS Element interface: element must inherit property "prefix" with the proper type (1) 
+PASS Element interface: element must inherit property "localName" with the proper type (2) 
+PASS Element interface: element must inherit property "tagName" with the proper type (3) 
+PASS Element interface: element must inherit property "id" with the proper type (4) 
+PASS Element interface: element must inherit property "className" with the proper type (5) 
+PASS Element interface: element must inherit property "classList" with the proper type (6) 
+PASS Element interface: element must inherit property "hasAttributes" with the proper type (7) 
+PASS Element interface: element must inherit property "attributes" with the proper type (8) 
+PASS Element interface: element must inherit property "getAttribute" with the proper type (9) 
+PASS Element interface: calling getAttribute(DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "getAttributeNS" with the proper type (10) 
+PASS Element interface: calling getAttributeNS(DOMString,DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "setAttribute" with the proper type (11) 
+PASS Element interface: calling setAttribute(DOMString,DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "setAttributeNS" with the proper type (12) 
+PASS Element interface: calling setAttributeNS(DOMString,DOMString,DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "removeAttribute" with the proper type (13) 
+PASS Element interface: calling removeAttribute(DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "removeAttributeNS" with the proper type (14) 
+PASS Element interface: calling removeAttributeNS(DOMString,DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "hasAttribute" with the proper type (15) 
+PASS Element interface: calling hasAttribute(DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "hasAttributeNS" with the proper type (16) 
+PASS Element interface: calling hasAttributeNS(DOMString,DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "getAttributeNode" with the proper type (17) 
+PASS Element interface: calling getAttributeNode(DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "getAttributeNodeNS" with the proper type (18) 
+PASS Element interface: calling getAttributeNodeNS(DOMString,DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "setAttributeNode" with the proper type (19) 
+PASS Element interface: calling setAttributeNode(Attr) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "setAttributeNodeNS" with the proper type (20) 
+PASS Element interface: calling setAttributeNodeNS(Attr) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "removeAttributeNode" with the proper type (21) 
+PASS Element interface: calling removeAttributeNode(Attr) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "closest" with the proper type (22) 
+PASS Element interface: calling closest(DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "matches" with the proper type (23) 
+PASS Element interface: calling matches(DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "getElementsByTagName" with the proper type (24) 
+PASS Element interface: calling getElementsByTagName(DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "getElementsByTagNameNS" with the proper type (25) 
+PASS Element interface: calling getElementsByTagNameNS(DOMString,DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "getElementsByClassName" with the proper type (26) 
+PASS Element interface: calling getElementsByClassName(DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "children" with the proper type (27) 
+PASS Element interface: element must inherit property "firstElementChild" with the proper type (28) 
+PASS Element interface: element must inherit property "lastElementChild" with the proper type (29) 
+PASS Element interface: element must inherit property "childElementCount" with the proper type (30) 
+FAIL Element interface: element must inherit property "prepend" with the proper type (31) assert_inherits: property "prepend" not found in prototype chain
+FAIL Element interface: calling prepend([object Object],[object Object]) on element with too few arguments must throw TypeError assert_inherits: property "prepend" not found in prototype chain
+FAIL Element interface: element must inherit property "append" with the proper type (32) assert_inherits: property "append" not found in prototype chain
+FAIL Element interface: calling append([object Object],[object Object]) on element with too few arguments must throw TypeError assert_inherits: property "append" not found in prototype chain
+FAIL Element interface: element must inherit property "query" with the proper type (33) assert_inherits: property "query" not found in prototype chain
+FAIL Element interface: calling query(DOMString) on element with too few arguments must throw TypeError assert_inherits: property "query" not found in prototype chain
+FAIL Element interface: element must inherit property "queryAll" with the proper type (34) assert_inherits: property "queryAll" not found in prototype chain
+FAIL Element interface: calling queryAll(DOMString) on element with too few arguments must throw TypeError assert_inherits: property "queryAll" not found in prototype chain
+PASS Element interface: element must inherit property "querySelector" with the proper type (35) 
+PASS Element interface: calling querySelector(DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "querySelectorAll" with the proper type (36) 
+PASS Element interface: calling querySelectorAll(DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "previousElementSibling" with the proper type (37) 
+PASS Element interface: element must inherit property "nextElementSibling" with the proper type (38) 
+FAIL Element interface: element must inherit property "before" with the proper type (39) assert_inherits: property "before" not found in prototype chain
+FAIL Element interface: calling before([object Object],[object Object]) on element with too few arguments must throw TypeError assert_inherits: property "before" not found in prototype chain
+FAIL Element interface: element must inherit property "after" with the proper type (40) assert_inherits: property "after" not found in prototype chain
+FAIL Element interface: calling after([object Object],[object Object]) on element with too few arguments must throw TypeError assert_inherits: property "after" not found in prototype chain
+FAIL Element interface: element must inherit property "replaceWith" with the proper type (41) assert_inherits: property "replaceWith" not found in prototype chain
+FAIL Element interface: calling replaceWith([object Object],[object Object]) on element with too few arguments must throw TypeError assert_inherits: property "replaceWith" not found in prototype chain
+PASS Element interface: element must inherit property "remove" with the proper type (42) 
+PASS Node interface: element must inherit property "ELEMENT_NODE" with the proper type (0) 
+PASS Node interface: element must inherit property "ATTRIBUTE_NODE" with the proper type (1) 
+PASS Node interface: element must inherit property "TEXT_NODE" with the proper type (2) 
+PASS Node interface: element must inherit property "CDATA_SECTION_NODE" with the proper type (3) 
+PASS Node interface: element must inherit property "ENTITY_REFERENCE_NODE" with the proper type (4) 
+PASS Node interface: element must inherit property "ENTITY_NODE" with the proper type (5) 
+PASS Node interface: element must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type (6) 
+PASS Node interface: element must inherit property "COMMENT_NODE" with the proper type (7) 
+PASS Node interface: element must inherit property "DOCUMENT_NODE" with the proper type (8) 
+PASS Node interface: element must inherit property "DOCUMENT_TYPE_NODE" with the proper type (9) 
+PASS Node interface: element must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type (10) 
+PASS Node interface: element must inherit property "NOTATION_NODE" with the proper type (11) 
+PASS Node interface: element must inherit property "nodeType" with the proper type (12) 
+PASS Node interface: element must inherit property "nodeName" with the proper type (13) 
+PASS Node interface: element must inherit property "baseURI" with the proper type (14) 
+PASS Node interface: element must inherit property "ownerDocument" with the proper type (15) 
+PASS Node interface: element must inherit property "parentNode" with the proper type (16) 
+PASS Node interface: element must inherit property "parentElement" with the proper type (17) 
+PASS Node interface: element must inherit property "hasChildNodes" with the proper type (18) 
+PASS Node interface: element must inherit property "childNodes" with the proper type (19) 
+PASS Node interface: element must inherit property "firstChild" with the proper type (20) 
+PASS Node interface: element must inherit property "lastChild" with the proper type (21) 
+PASS Node interface: element must inherit property "previousSibling" with the proper type (22) 
+PASS Node interface: element must inherit property "nextSibling" with the proper type (23) 
+PASS Node interface: element must inherit property "nodeValue" with the proper type (24) 
+PASS Node interface: element must inherit property "textContent" with the proper type (25) 
+PASS Node interface: element must inherit property "normalize" with the proper type (26) 
+PASS Node interface: element must inherit property "cloneNode" with the proper type (27) 
+PASS Node interface: calling cloneNode(boolean) on element with too few arguments must throw TypeError 
+PASS Node interface: element must inherit property "isEqualNode" with the proper type (28) 
+PASS Node interface: calling isEqualNode(Node) on element with too few arguments must throw TypeError 
+PASS Node interface: element must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (29) 
+PASS Node interface: element must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (30) 
+PASS Node interface: element must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (31) 
+PASS Node interface: element must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (32) 
+PASS Node interface: element must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (33) 
+PASS Node interface: element must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (34) 
+PASS Node interface: element must inherit property "compareDocumentPosition" with the proper type (35) 
+PASS Node interface: calling compareDocumentPosition(Node) on element with too few arguments must throw TypeError 
+PASS Node interface: element must inherit property "contains" with the proper type (36) 
+PASS Node interface: calling contains(Node) on element with too few arguments must throw TypeError 
+PASS Node interface: element must inherit property "lookupPrefix" with the proper type (37) 
+PASS Node interface: calling lookupPrefix(DOMString) on element with too few arguments must throw TypeError 
+PASS Node interface: element must inherit property "lookupNamespaceURI" with the proper type (38) 
+PASS Node interface: calling lookupNamespaceURI(DOMString) on element with too few arguments must throw TypeError 
+PASS Node interface: element must inherit property "isDefaultNamespace" with the proper type (39) 
+PASS Node interface: calling isDefaultNamespace(DOMString) on element with too few arguments must throw TypeError 
+PASS Node interface: element must inherit property "insertBefore" with the proper type (40) 
+PASS Node interface: calling insertBefore(Node,Node) on element with too few arguments must throw TypeError 
+PASS Node interface: element must inherit property "appendChild" with the proper type (41) 
+PASS Node interface: calling appendChild(Node) on element with too few arguments must throw TypeError 
+PASS Node interface: element must inherit property "replaceChild" with the proper type (42) 
+PASS Node interface: calling replaceChild(Node,Node) on element with too few arguments must throw TypeError 
+PASS Node interface: element must inherit property "removeChild" with the proper type (43) 
+PASS Node interface: calling removeChild(Node) on element with too few arguments must throw TypeError 
+PASS EventTarget interface: element must inherit property "addEventListener" with the proper type (0) 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on element with too few arguments must throw TypeError 
+PASS EventTarget interface: element must inherit property "removeEventListener" with the proper type (1) 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on element with too few arguments must throw TypeError 
+PASS EventTarget interface: element must inherit property "dispatchEvent" with the proper type (2) 
+PASS EventTarget interface: calling dispatchEvent(Event) on element with too few arguments must throw TypeError 
+PASS NamedNodeMap interface: existence and properties of interface object 
+PASS NamedNodeMap interface object length 
+PASS NamedNodeMap interface object name 
+FAIL NamedNodeMap interface: existence and properties of interface prototype object assert_equals: class string of NamedNodeMap.prototype expected "[object NamedNodeMapPrototype]" but got "[object Object]"
+PASS NamedNodeMap interface: existence and properties of interface prototype object's "constructor" property 
+PASS NamedNodeMap interface: attribute length 
+PASS NamedNodeMap interface: operation item(unsigned long) 
+PASS NamedNodeMap interface: operation getNamedItem(DOMString) 
+PASS NamedNodeMap interface: operation getNamedItemNS(DOMString,DOMString) 
+PASS NamedNodeMap interface: operation setNamedItem(Attr) 
+PASS NamedNodeMap interface: operation setNamedItemNS(Attr) 
+PASS NamedNodeMap interface: operation removeNamedItem(DOMString) 
+PASS NamedNodeMap interface: operation removeNamedItemNS(DOMString,DOMString) 
+FAIL Attr interface: existence and properties of interface object assert_equals: prototype of self's property "Attr" is not Function.prototype expected function "function () {}" but got function "function Node() { [native code] }"
+PASS Attr interface object length 
+PASS Attr interface object name 
+FAIL Attr interface: existence and properties of interface prototype object assert_equals: prototype of Attr.prototype is not Object.prototype expected object "[object Object]" but got object "[object Object]"
+PASS Attr interface: existence and properties of interface prototype object's "constructor" property 
+PASS Attr interface: attribute namespaceURI 
+PASS Attr interface: attribute prefix 
+PASS Attr interface: attribute localName 
+PASS Attr interface: attribute name 
+PASS Attr interface: attribute value 
+PASS Attr interface: attribute nodeValue 
+PASS Attr interface: attribute textContent 
+PASS Attr interface: attribute ownerElement 
+PASS Attr interface: attribute specified 
+PASS Attr must be primary interface of document.querySelector("[id]").attributes[0] 
+PASS Stringification of document.querySelector("[id]").attributes[0] 
+PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "namespaceURI" with the proper type (0) 
+PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "prefix" with the proper type (1) 
+PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "localName" with the proper type (2) 
+PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "name" with the proper type (3) 
+PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "value" with the proper type (4) 
+PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "nodeValue" with the proper type (5) 
+PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "textContent" with the proper type (6) 
+PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "ownerElement" with the proper type (7) 
+PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "specified" with the proper type (8) 
+PASS CharacterData interface: existence and properties of interface object 
+PASS CharacterData interface object length 
+PASS CharacterData interface object name 
+FAIL CharacterData interface: existence and properties of interface prototype object assert_equals: class string of CharacterData.prototype expected "[object CharacterDataPrototype]" but got "[object Object]"
+PASS CharacterData interface: existence and properties of interface prototype object's "constructor" property 
+PASS CharacterData interface: attribute data 
+PASS CharacterData interface: attribute length 
+PASS CharacterData interface: operation substringData(unsigned long,unsigned long) 
+PASS CharacterData interface: operation appendData(DOMString) 
+PASS CharacterData interface: operation insertData(unsigned long,DOMString) 
+PASS CharacterData interface: operation deleteData(unsigned long,unsigned long) 
+PASS CharacterData interface: operation replaceData(unsigned long,unsigned long,DOMString) 
+PASS CharacterData interface: attribute previousElementSibling 
+PASS CharacterData interface: attribute nextElementSibling 
+FAIL CharacterData interface: operation before([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "before" missing
+FAIL CharacterData interface: operation after([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "after" missing
+FAIL CharacterData interface: operation replaceWith([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "replaceWith" missing
+PASS CharacterData interface: operation remove() 
+PASS Text interface: existence and properties of interface object 
+PASS Text interface object length 
+PASS Text interface object name 
+FAIL Text interface: existence and properties of interface prototype object assert_equals: class string of Text.prototype expected "[object TextPrototype]" but got "[object Object]"
+PASS Text interface: existence and properties of interface prototype object's "constructor" property 
+PASS Text interface: operation splitText(unsigned long) 
+PASS Text interface: attribute wholeText 
+PASS Text must be primary interface of document.createTextNode("abc") 
+PASS Stringification of document.createTextNode("abc") 
+PASS Text interface: document.createTextNode("abc") must inherit property "splitText" with the proper type (0) 
+PASS Text interface: calling splitText(unsigned long) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS Text interface: document.createTextNode("abc") must inherit property "wholeText" with the proper type (1) 
+PASS CharacterData interface: document.createTextNode("abc") must inherit property "data" with the proper type (0) 
+PASS CharacterData interface: document.createTextNode("abc") must inherit property "length" with the proper type (1) 
+PASS CharacterData interface: document.createTextNode("abc") must inherit property "substringData" with the proper type (2) 
+PASS CharacterData interface: calling substringData(unsigned long,unsigned long) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS CharacterData interface: document.createTextNode("abc") must inherit property "appendData" with the proper type (3) 
+PASS CharacterData interface: calling appendData(DOMString) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS CharacterData interface: document.createTextNode("abc") must inherit property "insertData" with the proper type (4) 
+PASS CharacterData interface: calling insertData(unsigned long,DOMString) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS CharacterData interface: document.createTextNode("abc") must inherit property "deleteData" with the proper type (5) 
+PASS CharacterData interface: calling deleteData(unsigned long,unsigned long) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS CharacterData interface: document.createTextNode("abc") must inherit property "replaceData" with the proper type (6) 
+PASS CharacterData interface: calling replaceData(unsigned long,unsigned long,DOMString) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS CharacterData interface: document.createTextNode("abc") must inherit property "previousElementSibling" with the proper type (7) 
+PASS CharacterData interface: document.createTextNode("abc") must inherit property "nextElementSibling" with the proper type (8) 
+FAIL CharacterData interface: document.createTextNode("abc") must inherit property "before" with the proper type (9) assert_inherits: property "before" not found in prototype chain
+FAIL CharacterData interface: calling before([object Object],[object Object]) on document.createTextNode("abc") with too few arguments must throw TypeError assert_inherits: property "before" not found in prototype chain
+FAIL CharacterData interface: document.createTextNode("abc") must inherit property "after" with the proper type (10) assert_inherits: property "after" not found in prototype chain
+FAIL CharacterData interface: calling after([object Object],[object Object]) on document.createTextNode("abc") with too few arguments must throw TypeError assert_inherits: property "after" not found in prototype chain
+FAIL CharacterData interface: document.createTextNode("abc") must inherit property "replaceWith" with the proper type (11) assert_inherits: property "replaceWith" not found in prototype chain
+FAIL CharacterData interface: calling replaceWith([object Object],[object Object]) on document.createTextNode("abc") with too few arguments must throw TypeError assert_inherits: property "replaceWith" not found in prototype chain
+PASS CharacterData interface: document.createTextNode("abc") must inherit property "remove" with the proper type (12) 
+PASS Node interface: document.createTextNode("abc") must inherit property "ELEMENT_NODE" with the proper type (0) 
+PASS Node interface: document.createTextNode("abc") must inherit property "ATTRIBUTE_NODE" with the proper type (1) 
+PASS Node interface: document.createTextNode("abc") must inherit property "TEXT_NODE" with the proper type (2) 
+PASS Node interface: document.createTextNode("abc") must inherit property "CDATA_SECTION_NODE" with the proper type (3) 
+PASS Node interface: document.createTextNode("abc") must inherit property "ENTITY_REFERENCE_NODE" with the proper type (4) 
+PASS Node interface: document.createTextNode("abc") must inherit property "ENTITY_NODE" with the proper type (5) 
+PASS Node interface: document.createTextNode("abc") must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type (6) 
+PASS Node interface: document.createTextNode("abc") must inherit property "COMMENT_NODE" with the proper type (7) 
+PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_NODE" with the proper type (8) 
+PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_TYPE_NODE" with the proper type (9) 
+PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type (10) 
+PASS Node interface: document.createTextNode("abc") must inherit property "NOTATION_NODE" with the proper type (11) 
+PASS Node interface: document.createTextNode("abc") must inherit property "nodeType" with the proper type (12) 
+PASS Node interface: document.createTextNode("abc") must inherit property "nodeName" with the proper type (13) 
+PASS Node interface: document.createTextNode("abc") must inherit property "baseURI" with the proper type (14) 
+PASS Node interface: document.createTextNode("abc") must inherit property "ownerDocument" with the proper type (15) 
+PASS Node interface: document.createTextNode("abc") must inherit property "parentNode" with the proper type (16) 
+PASS Node interface: document.createTextNode("abc") must inherit property "parentElement" with the proper type (17) 
+PASS Node interface: document.createTextNode("abc") must inherit property "hasChildNodes" with the proper type (18) 
+PASS Node interface: document.createTextNode("abc") must inherit property "childNodes" with the proper type (19) 
+PASS Node interface: document.createTextNode("abc") must inherit property "firstChild" with the proper type (20) 
+PASS Node interface: document.createTextNode("abc") must inherit property "lastChild" with the proper type (21) 
+PASS Node interface: document.createTextNode("abc") must inherit property "previousSibling" with the proper type (22) 
+PASS Node interface: document.createTextNode("abc") must inherit property "nextSibling" with the proper type (23) 
+PASS Node interface: document.createTextNode("abc") must inherit property "nodeValue" with the proper type (24) 
+PASS Node interface: document.createTextNode("abc") must inherit property "textContent" with the proper type (25) 
+PASS Node interface: document.createTextNode("abc") must inherit property "normalize" with the proper type (26) 
+PASS Node interface: document.createTextNode("abc") must inherit property "cloneNode" with the proper type (27) 
+PASS Node interface: calling cloneNode(boolean) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createTextNode("abc") must inherit property "isEqualNode" with the proper type (28) 
+PASS Node interface: calling isEqualNode(Node) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (29) 
+PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (30) 
+PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (31) 
+PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (32) 
+PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (33) 
+PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (34) 
+PASS Node interface: document.createTextNode("abc") must inherit property "compareDocumentPosition" with the proper type (35) 
+PASS Node interface: calling compareDocumentPosition(Node) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createTextNode("abc") must inherit property "contains" with the proper type (36) 
+PASS Node interface: calling contains(Node) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createTextNode("abc") must inherit property "lookupPrefix" with the proper type (37) 
+PASS Node interface: calling lookupPrefix(DOMString) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createTextNode("abc") must inherit property "lookupNamespaceURI" with the proper type (38) 
+PASS Node interface: calling lookupNamespaceURI(DOMString) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createTextNode("abc") must inherit property "isDefaultNamespace" with the proper type (39) 
+PASS Node interface: calling isDefaultNamespace(DOMString) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createTextNode("abc") must inherit property "insertBefore" with the proper type (40) 
+PASS Node interface: calling insertBefore(Node,Node) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createTextNode("abc") must inherit property "appendChild" with the proper type (41) 
+PASS Node interface: calling appendChild(Node) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createTextNode("abc") must inherit property "replaceChild" with the proper type (42) 
+PASS Node interface: calling replaceChild(Node,Node) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createTextNode("abc") must inherit property "removeChild" with the proper type (43) 
+PASS Node interface: calling removeChild(Node) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS EventTarget interface: document.createTextNode("abc") must inherit property "addEventListener" with the proper type (0) 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS EventTarget interface: document.createTextNode("abc") must inherit property "removeEventListener" with the proper type (1) 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS EventTarget interface: document.createTextNode("abc") must inherit property "dispatchEvent" with the proper type (2) 
+PASS EventTarget interface: calling dispatchEvent(Event) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS ProcessingInstruction interface: existence and properties of interface object 
+PASS ProcessingInstruction interface object length 
+PASS ProcessingInstruction interface object name 
+FAIL ProcessingInstruction interface: existence and properties of interface prototype object assert_equals: class string of ProcessingInstruction.prototype expected "[object ProcessingInstructionPrototype]" but got "[object Object]"
+PASS ProcessingInstruction interface: existence and properties of interface prototype object's "constructor" property 
+PASS ProcessingInstruction interface: attribute target 
+PASS ProcessingInstruction must be primary interface of xmlDoc.createProcessingInstruction("abc", "def") 
+PASS Stringification of xmlDoc.createProcessingInstruction("abc", "def") 
+PASS ProcessingInstruction interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "target" with the proper type (0) 
+PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "data" with the proper type (0) 
+PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "length" with the proper type (1) 
+PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "substringData" with the proper type (2) 
+PASS CharacterData interface: calling substringData(unsigned long,unsigned long) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "appendData" with the proper type (3) 
+PASS CharacterData interface: calling appendData(DOMString) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "insertData" with the proper type (4) 
+PASS CharacterData interface: calling insertData(unsigned long,DOMString) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "deleteData" with the proper type (5) 
+PASS CharacterData interface: calling deleteData(unsigned long,unsigned long) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "replaceData" with the proper type (6) 
+PASS CharacterData interface: calling replaceData(unsigned long,unsigned long,DOMString) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "previousElementSibling" with the proper type (7) 
+PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nextElementSibling" with the proper type (8) 
+FAIL CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "before" with the proper type (9) assert_inherits: property "before" not found in prototype chain
+FAIL CharacterData interface: calling before([object Object],[object Object]) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError assert_inherits: property "before" not found in prototype chain
+FAIL CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "after" with the proper type (10) assert_inherits: property "after" not found in prototype chain
+FAIL CharacterData interface: calling after([object Object],[object Object]) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError assert_inherits: property "after" not found in prototype chain
+FAIL CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "replaceWith" with the proper type (11) assert_inherits: property "replaceWith" not found in prototype chain
+FAIL CharacterData interface: calling replaceWith([object Object],[object Object]) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError assert_inherits: property "replaceWith" not found in prototype chain
+PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "remove" with the proper type (12) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "ELEMENT_NODE" with the proper type (0) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "ATTRIBUTE_NODE" with the proper type (1) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "TEXT_NODE" with the proper type (2) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "CDATA_SECTION_NODE" with the proper type (3) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "ENTITY_REFERENCE_NODE" with the proper type (4) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "ENTITY_NODE" with the proper type (5) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type (6) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "COMMENT_NODE" with the proper type (7) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_NODE" with the proper type (8) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_TYPE_NODE" with the proper type (9) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type (10) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "NOTATION_NODE" with the proper type (11) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nodeType" with the proper type (12) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nodeName" with the proper type (13) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "baseURI" with the proper type (14) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "ownerDocument" with the proper type (15) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "parentNode" with the proper type (16) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "parentElement" with the proper type (17) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "hasChildNodes" with the proper type (18) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "childNodes" with the proper type (19) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "firstChild" with the proper type (20) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "lastChild" with the proper type (21) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "previousSibling" with the proper type (22) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nextSibling" with the proper type (23) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nodeValue" with the proper type (24) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "textContent" with the proper type (25) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "normalize" with the proper type (26) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "cloneNode" with the proper type (27) 
+PASS Node interface: calling cloneNode(boolean) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "isEqualNode" with the proper type (28) 
+PASS Node interface: calling isEqualNode(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (29) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (30) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (31) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (32) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (33) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (34) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "compareDocumentPosition" with the proper type (35) 
+PASS Node interface: calling compareDocumentPosition(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "contains" with the proper type (36) 
+PASS Node interface: calling contains(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "lookupPrefix" with the proper type (37) 
+PASS Node interface: calling lookupPrefix(DOMString) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "lookupNamespaceURI" with the proper type (38) 
+PASS Node interface: calling lookupNamespaceURI(DOMString) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "isDefaultNamespace" with the proper type (39) 
+PASS Node interface: calling isDefaultNamespace(DOMString) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "insertBefore" with the proper type (40) 
+PASS Node interface: calling insertBefore(Node,Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "appendChild" with the proper type (41) 
+PASS Node interface: calling appendChild(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "replaceChild" with the proper type (42) 
+PASS Node interface: calling replaceChild(Node,Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "removeChild" with the proper type (43) 
+PASS Node interface: calling removeChild(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS EventTarget interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "addEventListener" with the proper type (0) 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS EventTarget interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "removeEventListener" with the proper type (1) 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS EventTarget interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "dispatchEvent" with the proper type (2) 
+PASS EventTarget interface: calling dispatchEvent(Event) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS Comment interface: existence and properties of interface object 
+PASS Comment interface object length 
+PASS Comment interface object name 
+FAIL Comment interface: existence and properties of interface prototype object assert_equals: class string of Comment.prototype expected "[object CommentPrototype]" but got "[object Object]"
+PASS Comment interface: existence and properties of interface prototype object's "constructor" property 
+PASS Comment must be primary interface of document.createComment("abc") 
+PASS Stringification of document.createComment("abc") 
+PASS CharacterData interface: document.createComment("abc") must inherit property "data" with the proper type (0) 
+PASS CharacterData interface: document.createComment("abc") must inherit property "length" with the proper type (1) 
+PASS CharacterData interface: document.createComment("abc") must inherit property "substringData" with the proper type (2) 
+PASS CharacterData interface: calling substringData(unsigned long,unsigned long) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS CharacterData interface: document.createComment("abc") must inherit property "appendData" with the proper type (3) 
+PASS CharacterData interface: calling appendData(DOMString) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS CharacterData interface: document.createComment("abc") must inherit property "insertData" with the proper type (4) 
+PASS CharacterData interface: calling insertData(unsigned long,DOMString) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS CharacterData interface: document.createComment("abc") must inherit property "deleteData" with the proper type (5) 
+PASS CharacterData interface: calling deleteData(unsigned long,unsigned long) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS CharacterData interface: document.createComment("abc") must inherit property "replaceData" with the proper type (6) 
+PASS CharacterData interface: calling replaceData(unsigned long,unsigned long,DOMString) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS CharacterData interface: document.createComment("abc") must inherit property "previousElementSibling" with the proper type (7) 
+PASS CharacterData interface: document.createComment("abc") must inherit property "nextElementSibling" with the proper type (8) 
+FAIL CharacterData interface: document.createComment("abc") must inherit property "before" with the proper type (9) assert_inherits: property "before" not found in prototype chain
+FAIL CharacterData interface: calling before([object Object],[object Object]) on document.createComment("abc") with too few arguments must throw TypeError assert_inherits: property "before" not found in prototype chain
+FAIL CharacterData interface: document.createComment("abc") must inherit property "after" with the proper type (10) assert_inherits: property "after" not found in prototype chain
+FAIL CharacterData interface: calling after([object Object],[object Object]) on document.createComment("abc") with too few arguments must throw TypeError assert_inherits: property "after" not found in prototype chain
+FAIL CharacterData interface: document.createComment("abc") must inherit property "replaceWith" with the proper type (11) assert_inherits: property "replaceWith" not found in prototype chain
+FAIL CharacterData interface: calling replaceWith([object Object],[object Object]) on document.createComment("abc") with too few arguments must throw TypeError assert_inherits: property "replaceWith" not found in prototype chain
+PASS CharacterData interface: document.createComment("abc") must inherit property "remove" with the proper type (12) 
+PASS Node interface: document.createComment("abc") must inherit property "ELEMENT_NODE" with the proper type (0) 
+PASS Node interface: document.createComment("abc") must inherit property "ATTRIBUTE_NODE" with the proper type (1) 
+PASS Node interface: document.createComment("abc") must inherit property "TEXT_NODE" with the proper type (2) 
+PASS Node interface: document.createComment("abc") must inherit property "CDATA_SECTION_NODE" with the proper type (3) 
+PASS Node interface: document.createComment("abc") must inherit property "ENTITY_REFERENCE_NODE" with the proper type (4) 
+PASS Node interface: document.createComment("abc") must inherit property "ENTITY_NODE" with the proper type (5) 
+PASS Node interface: document.createComment("abc") must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type (6) 
+PASS Node interface: document.createComment("abc") must inherit property "COMMENT_NODE" with the proper type (7) 
+PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_NODE" with the proper type (8) 
+PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_TYPE_NODE" with the proper type (9) 
+PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type (10) 
+PASS Node interface: document.createComment("abc") must inherit property "NOTATION_NODE" with the proper type (11) 
+PASS Node interface: document.createComment("abc") must inherit property "nodeType" with the proper type (12) 
+PASS Node interface: document.createComment("abc") must inherit property "nodeName" with the proper type (13) 
+PASS Node interface: document.createComment("abc") must inherit property "baseURI" with the proper type (14) 
+PASS Node interface: document.createComment("abc") must inherit property "ownerDocument" with the proper type (15) 
+PASS Node interface: document.createComment("abc") must inherit property "parentNode" with the proper type (16) 
+PASS Node interface: document.createComment("abc") must inherit property "parentElement" with the proper type (17) 
+PASS Node interface: document.createComment("abc") must inherit property "hasChildNodes" with the proper type (18) 
+PASS Node interface: document.createComment("abc") must inherit property "childNodes" with the proper type (19) 
+PASS Node interface: document.createComment("abc") must inherit property "firstChild" with the proper type (20) 
+PASS Node interface: document.createComment("abc") must inherit property "lastChild" with the proper type (21) 
+PASS Node interface: document.createComment("abc") must inherit property "previousSibling" with the proper type (22) 
+PASS Node interface: document.createComment("abc") must inherit property "nextSibling" with the proper type (23) 
+PASS Node interface: document.createComment("abc") must inherit property "nodeValue" with the proper type (24) 
+PASS Node interface: document.createComment("abc") must inherit property "textContent" with the proper type (25) 
+PASS Node interface: document.createComment("abc") must inherit property "normalize" with the proper type (26) 
+PASS Node interface: document.createComment("abc") must inherit property "cloneNode" with the proper type (27) 
+PASS Node interface: calling cloneNode(boolean) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createComment("abc") must inherit property "isEqualNode" with the proper type (28) 
+PASS Node interface: calling isEqualNode(Node) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (29) 
+PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (30) 
+PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (31) 
+PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (32) 
+PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (33) 
+PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (34) 
+PASS Node interface: document.createComment("abc") must inherit property "compareDocumentPosition" with the proper type (35) 
+PASS Node interface: calling compareDocumentPosition(Node) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createComment("abc") must inherit property "contains" with the proper type (36) 
+PASS Node interface: calling contains(Node) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createComment("abc") must inherit property "lookupPrefix" with the proper type (37) 
+PASS Node interface: calling lookupPrefix(DOMString) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createComment("abc") must inherit property "lookupNamespaceURI" with the proper type (38) 
+PASS Node interface: calling lookupNamespaceURI(DOMString) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createComment("abc") must inherit property "isDefaultNamespace" with the proper type (39) 
+PASS Node interface: calling isDefaultNamespace(DOMString) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createComment("abc") must inherit property "insertBefore" with the proper type (40) 
+PASS Node interface: calling insertBefore(Node,Node) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createComment("abc") must inherit property "appendChild" with the proper type (41) 
+PASS Node interface: calling appendChild(Node) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createComment("abc") must inherit property "replaceChild" with the proper type (42) 
+PASS Node interface: calling replaceChild(Node,Node) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createComment("abc") must inherit property "removeChild" with the proper type (43) 
+PASS Node interface: calling removeChild(Node) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS EventTarget interface: document.createComment("abc") must inherit property "addEventListener" with the proper type (0) 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS EventTarget interface: document.createComment("abc") must inherit property "removeEventListener" with the proper type (1) 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS EventTarget interface: document.createComment("abc") must inherit property "dispatchEvent" with the proper type (2) 
+PASS EventTarget interface: calling dispatchEvent(Event) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS Range interface: existence and properties of interface object 
+PASS Range interface object length 
+PASS Range interface object name 
+FAIL Range interface: existence and properties of interface prototype object assert_equals: class string of Range.prototype expected "[object RangePrototype]" but got "[object Object]"
+PASS Range interface: existence and properties of interface prototype object's "constructor" property 
+PASS Range interface: attribute startContainer 
+PASS Range interface: attribute startOffset 
+PASS Range interface: attribute endContainer 
+PASS Range interface: attribute endOffset 
+PASS Range interface: attribute collapsed 
+PASS Range interface: attribute commonAncestorContainer 
+PASS Range interface: operation setStart(Node,unsigned long) 
+PASS Range interface: operation setEnd(Node,unsigned long) 
+PASS Range interface: operation setStartBefore(Node) 
+PASS Range interface: operation setStartAfter(Node) 
+PASS Range interface: operation setEndBefore(Node) 
+PASS Range interface: operation setEndAfter(Node) 
+PASS Range interface: operation collapse(boolean) 
+PASS Range interface: operation selectNode(Node) 
+PASS Range interface: operation selectNodeContents(Node) 
+PASS Range interface: constant START_TO_START on interface object 
+PASS Range interface: constant START_TO_START on interface prototype object 
+PASS Range interface: constant START_TO_END on interface object 
+PASS Range interface: constant START_TO_END on interface prototype object 
+PASS Range interface: constant END_TO_END on interface object 
+PASS Range interface: constant END_TO_END on interface prototype object 
+PASS Range interface: constant END_TO_START on interface object 
+PASS Range interface: constant END_TO_START on interface prototype object 
+PASS Range interface: operation compareBoundaryPoints(unsigned short,Range) 
+PASS Range interface: operation deleteContents() 
+PASS Range interface: operation extractContents() 
+PASS Range interface: operation cloneContents() 
+PASS Range interface: operation insertNode(Node) 
+PASS Range interface: operation surroundContents(Node) 
+PASS Range interface: operation cloneRange() 
+PASS Range interface: operation detach() 
+PASS Range interface: operation isPointInRange(Node,unsigned long) 
+PASS Range interface: operation comparePoint(Node,unsigned long) 
+PASS Range interface: operation intersectsNode(Node) 
+PASS Range interface: stringifier 
+PASS Range must be primary interface of document.createRange() 
+PASS Stringification of document.createRange() 
+PASS Range interface: document.createRange() must inherit property "startContainer" with the proper type (0) 
+PASS Range interface: document.createRange() must inherit property "startOffset" with the proper type (1) 
+PASS Range interface: document.createRange() must inherit property "endContainer" with the proper type (2) 
+PASS Range interface: document.createRange() must inherit property "endOffset" with the proper type (3) 
+PASS Range interface: document.createRange() must inherit property "collapsed" with the proper type (4) 
+PASS Range interface: document.createRange() must inherit property "commonAncestorContainer" with the proper type (5) 
+PASS Range interface: document.createRange() must inherit property "setStart" with the proper type (6) 
+PASS Range interface: calling setStart(Node,unsigned long) on document.createRange() with too few arguments must throw TypeError 
+PASS Range interface: document.createRange() must inherit property "setEnd" with the proper type (7) 
+PASS Range interface: calling setEnd(Node,unsigned long) on document.createRange() with too few arguments must throw TypeError 
+PASS Range interface: document.createRange() must inherit property "setStartBefore" with the proper type (8) 
+PASS Range interface: calling setStartBefore(Node) on document.createRange() with too few arguments must throw TypeError 
+PASS Range interface: document.createRange() must inherit property "setStartAfter" with the proper type (9) 
+PASS Range interface: calling setStartAfter(Node) on document.createRange() with too few arguments must throw TypeError 
+PASS Range interface: document.createRange() must inherit property "setEndBefore" with the proper type (10) 
+PASS Range interface: calling setEndBefore(Node) on document.createRange() with too few arguments must throw TypeError 
+PASS Range interface: document.createRange() must inherit property "setEndAfter" with the proper type (11) 
+PASS Range interface: calling setEndAfter(Node) on document.createRange() with too few arguments must throw TypeError 
+PASS Range interface: document.createRange() must inherit property "collapse" with the proper type (12) 
+PASS Range interface: calling collapse(boolean) on document.createRange() with too few arguments must throw TypeError 
+PASS Range interface: document.createRange() must inherit property "selectNode" with the proper type (13) 
+PASS Range interface: calling selectNode(Node) on document.createRange() with too few arguments must throw TypeError 
+PASS Range interface: document.createRange() must inherit property "selectNodeContents" with the proper type (14) 
+PASS Range interface: calling selectNodeContents(Node) on document.createRange() with too few arguments must throw TypeError 
+PASS Range interface: document.createRange() must inherit property "START_TO_START" with the proper type (15) 
+PASS Range interface: document.createRange() must inherit property "START_TO_END" with the proper type (16) 
+PASS Range interface: document.createRange() must inherit property "END_TO_END" with the proper type (17) 
+PASS Range interface: document.createRange() must inherit property "END_TO_START" with the proper type (18) 
+PASS Range interface: document.createRange() must inherit property "compareBoundaryPoints" with the proper type (19) 
+PASS Range interface: calling compareBoundaryPoints(unsigned short,Range) on document.createRange() with too few arguments must throw TypeError 
+PASS Range interface: document.createRange() must inherit property "deleteContents" with the proper type (20) 
+PASS Range interface: document.createRange() must inherit property "extractContents" with the proper type (21) 
+PASS Range interface: document.createRange() must inherit property "cloneContents" with the proper type (22) 
+PASS Range interface: document.createRange() must inherit property "insertNode" with the proper type (23) 
+PASS Range interface: calling insertNode(Node) on document.createRange() with too few arguments must throw TypeError 
+PASS Range interface: document.createRange() must inherit property "surroundContents" with the proper type (24) 
+PASS Range interface: calling surroundContents(Node) on document.createRange() with too few arguments must throw TypeError 
+PASS Range interface: document.createRange() must inherit property "cloneRange" with the proper type (25) 
+PASS Range interface: document.createRange() must inherit property "detach" with the proper type (26) 
+PASS Range interface: document.createRange() must inherit property "isPointInRange" with the proper type (27) 
+PASS Range interface: calling isPointInRange(Node,unsigned long) on document.createRange() with too few arguments must throw TypeError 
+PASS Range interface: document.createRange() must inherit property "comparePoint" with the proper type (28) 
+PASS Range interface: calling comparePoint(Node,unsigned long) on document.createRange() with too few arguments must throw TypeError 
+PASS Range interface: document.createRange() must inherit property "intersectsNode" with the proper type (29) 
+PASS Range interface: calling intersectsNode(Node) on document.createRange() with too few arguments must throw TypeError 
+PASS Range must be primary interface of detachedRange 
+PASS Stringification of detachedRange 
+PASS Range interface: detachedRange must inherit property "startContainer" with the proper type (0) 
+PASS Range interface: detachedRange must inherit property "startOffset" with the proper type (1) 
+PASS Range interface: detachedRange must inherit property "endContainer" with the proper type (2) 
+PASS Range interface: detachedRange must inherit property "endOffset" with the proper type (3) 
+PASS Range interface: detachedRange must inherit property "collapsed" with the proper type (4) 
+PASS Range interface: detachedRange must inherit property "commonAncestorContainer" with the proper type (5) 
+PASS Range interface: detachedRange must inherit property "setStart" with the proper type (6) 
+PASS Range interface: calling setStart(Node,unsigned long) on detachedRange with too few arguments must throw TypeError 
+PASS Range interface: detachedRange must inherit property "setEnd" with the proper type (7) 
+PASS Range interface: calling setEnd(Node,unsigned long) on detachedRange with too few arguments must throw TypeError 
+PASS Range interface: detachedRange must inherit property "setStartBefore" with the proper type (8) 
+PASS Range interface: calling setStartBefore(Node) on detachedRange with too few arguments must throw TypeError 
+PASS Range interface: detachedRange must inherit property "setStartAfter" with the proper type (9) 
+PASS Range interface: calling setStartAfter(Node) on detachedRange with too few arguments must throw TypeError 
+PASS Range interface: detachedRange must inherit property "setEndBefore" with the proper type (10) 
+PASS Range interface: calling setEndBefore(Node) on detachedRange with too few arguments must throw TypeError 
+PASS Range interface: detachedRange must inherit property "setEndAfter" with the proper type (11) 
+PASS Range interface: calling setEndAfter(Node) on detachedRange with too few arguments must throw TypeError 
+PASS Range interface: detachedRange must inherit property "collapse" with the proper type (12) 
+PASS Range interface: calling collapse(boolean) on detachedRange with too few arguments must throw TypeError 
+PASS Range interface: detachedRange must inherit property "selectNode" with the proper type (13) 
+PASS Range interface: calling selectNode(Node) on detachedRange with too few arguments must throw TypeError 
+PASS Range interface: detachedRange must inherit property "selectNodeContents" with the proper type (14) 
+PASS Range interface: calling selectNodeContents(Node) on detachedRange with too few arguments must throw TypeError 
+PASS Range interface: detachedRange must inherit property "START_TO_START" with the proper type (15) 
+PASS Range interface: detachedRange must inherit property "START_TO_END" with the proper type (16) 
+PASS Range interface: detachedRange must inherit property "END_TO_END" with the proper type (17) 
+PASS Range interface: detachedRange must inherit property "END_TO_START" with the proper type (18) 
+PASS Range interface: detachedRange must inherit property "compareBoundaryPoints" with the proper type (19) 
+PASS Range interface: calling compareBoundaryPoints(unsigned short,Range) on detachedRange with too few arguments must throw TypeError 
+PASS Range interface: detachedRange must inherit property "deleteContents" with the proper type (20) 
+PASS Range interface: detachedRange must inherit property "extractContents" with the proper type (21) 
+PASS Range interface: detachedRange must inherit property "cloneContents" with the proper type (22) 
+PASS Range interface: detachedRange must inherit property "insertNode" with the proper type (23) 
+PASS Range interface: calling insertNode(Node) on detachedRange with too few arguments must throw TypeError 
+PASS Range interface: detachedRange must inherit property "surroundContents" with the proper type (24) 
+PASS Range interface: calling surroundContents(Node) on detachedRange with too few arguments must throw TypeError 
+PASS Range interface: detachedRange must inherit property "cloneRange" with the proper type (25) 
+PASS Range interface: detachedRange must inherit property "detach" with the proper type (26) 
+PASS Range interface: detachedRange must inherit property "isPointInRange" with the proper type (27) 
+PASS Range interface: calling isPointInRange(Node,unsigned long) on detachedRange with too few arguments must throw TypeError 
+PASS Range interface: detachedRange must inherit property "comparePoint" with the proper type (28) 
+PASS Range interface: calling comparePoint(Node,unsigned long) on detachedRange with too few arguments must throw TypeError 
+PASS Range interface: detachedRange must inherit property "intersectsNode" with the proper type (29) 
+PASS Range interface: calling intersectsNode(Node) on detachedRange with too few arguments must throw TypeError 
+PASS NodeIterator interface: existence and properties of interface object 
+PASS NodeIterator interface object length 
+PASS NodeIterator interface object name 
+FAIL NodeIterator interface: existence and properties of interface prototype object assert_equals: class string of NodeIterator.prototype expected "[object NodeIteratorPrototype]" but got "[object Object]"
+PASS NodeIterator interface: existence and properties of interface prototype object's "constructor" property 
+PASS NodeIterator interface: attribute root 
+PASS NodeIterator interface: attribute referenceNode 
+PASS NodeIterator interface: attribute pointerBeforeReferenceNode 
+PASS NodeIterator interface: attribute whatToShow 
+PASS NodeIterator interface: attribute filter 
+PASS NodeIterator interface: operation nextNode() 
+PASS NodeIterator interface: operation previousNode() 
+PASS NodeIterator interface: operation detach() 
+PASS NodeIterator must be primary interface of document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) 
+PASS Stringification of document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) 
+PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "root" with the proper type (0) 
+PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "referenceNode" with the proper type (1) 
+PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "pointerBeforeReferenceNode" with the proper type (2) 
+PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "whatToShow" with the proper type (3) 
+PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "filter" with the proper type (4) 
+PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "nextNode" with the proper type (5) 
+PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "previousNode" with the proper type (6) 
+PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "detach" with the proper type (7) 
+PASS TreeWalker interface: existence and properties of interface object 
+PASS TreeWalker interface object length 
+PASS TreeWalker interface object name 
+FAIL TreeWalker interface: existence and properties of interface prototype object assert_equals: class string of TreeWalker.prototype expected "[object TreeWalkerPrototype]" but got "[object Object]"
+PASS TreeWalker interface: existence and properties of interface prototype object's "constructor" property 
+PASS TreeWalker interface: attribute root 
+PASS TreeWalker interface: attribute whatToShow 
+PASS TreeWalker interface: attribute filter 
+PASS TreeWalker interface: attribute currentNode 
+PASS TreeWalker interface: operation parentNode() 
+PASS TreeWalker interface: operation firstChild() 
+PASS TreeWalker interface: operation lastChild() 
+PASS TreeWalker interface: operation previousSibling() 
+PASS TreeWalker interface: operation nextSibling() 
+PASS TreeWalker interface: operation previousNode() 
+PASS TreeWalker interface: operation nextNode() 
+PASS TreeWalker must be primary interface of document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) 
+PASS Stringification of document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) 
+PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "root" with the proper type (0) 
+PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "whatToShow" with the proper type (1) 
+PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "filter" with the proper type (2) 
+PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "currentNode" with the proper type (3) 
+PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "parentNode" with the proper type (4) 
+PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "firstChild" with the proper type (5) 
+PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "lastChild" with the proper type (6) 
+PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "previousSibling" with the proper type (7) 
+PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "nextSibling" with the proper type (8) 
+PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "previousNode" with the proper type (9) 
+PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "nextNode" with the proper type (10) 
+FAIL NodeFilter interface: existence and properties of interface object assert_equals: prototype of self's property "NodeFilter" is not Object.prototype expected (object) object "[object Object]" but got (function) function "function () {}"
+PASS NodeFilter interface object name 
+FAIL NodeFilter interface: existence and properties of interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+FAIL NodeFilter interface: existence and properties of interface prototype object's "constructor" property assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant FILTER_ACCEPT on interface object 
+FAIL NodeFilter interface: constant FILTER_ACCEPT on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant FILTER_REJECT on interface object 
+FAIL NodeFilter interface: constant FILTER_REJECT on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant FILTER_SKIP on interface object 
+FAIL NodeFilter interface: constant FILTER_SKIP on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant SHOW_ALL on interface object 
+FAIL NodeFilter interface: constant SHOW_ALL on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant SHOW_ELEMENT on interface object 
+FAIL NodeFilter interface: constant SHOW_ELEMENT on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant SHOW_ATTRIBUTE on interface object 
+FAIL NodeFilter interface: constant SHOW_ATTRIBUTE on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant SHOW_TEXT on interface object 
+FAIL NodeFilter interface: constant SHOW_TEXT on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant SHOW_CDATA_SECTION on interface object 
+FAIL NodeFilter interface: constant SHOW_CDATA_SECTION on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant SHOW_ENTITY_REFERENCE on interface object 
+FAIL NodeFilter interface: constant SHOW_ENTITY_REFERENCE on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant SHOW_ENTITY on interface object 
+FAIL NodeFilter interface: constant SHOW_ENTITY on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant SHOW_PROCESSING_INSTRUCTION on interface object 
+FAIL NodeFilter interface: constant SHOW_PROCESSING_INSTRUCTION on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant SHOW_COMMENT on interface object 
+FAIL NodeFilter interface: constant SHOW_COMMENT on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant SHOW_DOCUMENT on interface object 
+FAIL NodeFilter interface: constant SHOW_DOCUMENT on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant SHOW_DOCUMENT_TYPE on interface object 
+FAIL NodeFilter interface: constant SHOW_DOCUMENT_TYPE on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant SHOW_DOCUMENT_FRAGMENT on interface object 
+FAIL NodeFilter interface: constant SHOW_DOCUMENT_FRAGMENT on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS NodeFilter interface: constant SHOW_NOTATION on interface object 
+FAIL NodeFilter interface: constant SHOW_NOTATION on interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true
+FAIL NodeFilter interface: operation acceptNode(Node) assert_false: NodeFilter should not have a "prototype" property expected false got true
+PASS DOMTokenList interface: existence and properties of interface object 
+PASS DOMTokenList interface object length 
+PASS DOMTokenList interface object name 
+FAIL DOMTokenList interface: existence and properties of interface prototype object assert_equals: class string of DOMTokenList.prototype expected "[object DOMTokenListPrototype]" but got "[object Object]"
+PASS DOMTokenList interface: existence and properties of interface prototype object's "constructor" property 
+PASS DOMTokenList interface: attribute length 
+PASS DOMTokenList interface: operation item(unsigned long) 
+PASS DOMTokenList interface: operation contains(DOMString) 
+PASS DOMTokenList interface: operation add(DOMString) 
+PASS DOMTokenList interface: operation remove(DOMString) 
+PASS DOMTokenList interface: operation toggle(DOMString,boolean) 
+FAIL DOMTokenList interface: stringifier assert_true: property is not enumerable expected true got false
+PASS DOMTokenList must be primary interface of document.body.classList 
+PASS Stringification of document.body.classList 
+PASS DOMTokenList interface: document.body.classList must inherit property "length" with the proper type (0) 
+PASS DOMTokenList interface: document.body.classList must inherit property "item" with the proper type (1) 
+PASS DOMTokenList interface: calling item(unsigned long) on document.body.classList with too few arguments must throw TypeError 
+PASS DOMTokenList interface: document.body.classList must inherit property "contains" with the proper type (2) 
+PASS DOMTokenList interface: calling contains(DOMString) on document.body.classList with too few arguments must throw TypeError 
+PASS DOMTokenList interface: document.body.classList must inherit property "add" with the proper type (3) 
+PASS DOMTokenList interface: calling add(DOMString) on document.body.classList with too few arguments must throw TypeError 
+PASS DOMTokenList interface: document.body.classList must inherit property "remove" with the proper type (4) 
+PASS DOMTokenList interface: calling remove(DOMString) on document.body.classList with too few arguments must throw TypeError 
+PASS DOMTokenList interface: document.body.classList must inherit property "toggle" with the proper type (5) 
+PASS DOMTokenList interface: calling toggle(DOMString,boolean) on document.body.classList with too few arguments must throw TypeError 
+PASS DOMSettableTokenList interface: existence and properties of interface object 
+PASS DOMSettableTokenList interface object length 
+PASS DOMSettableTokenList interface object name 
+FAIL DOMSettableTokenList interface: existence and properties of interface prototype object assert_equals: class string of DOMSettableTokenList.prototype expected "[object DOMSettableTokenListPrototype]" but got "[object Object]"
+PASS DOMSettableTokenList interface: existence and properties of interface prototype object's "constructor" property 
+PASS DOMSettableTokenList interface: attribute value 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interfaces.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interfaces.html
new file mode 100644
index 0000000..8065a98
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interfaces.html
@@ -0,0 +1,505 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>DOM IDL tests</title>
+<script src=../../../resources/testharness.js></script>
+<script src=../../../resources/testharnessreport.js></script>
+<script src=../../../resources/WebIDLParser.js></script>
+<script src=../../../resources/idlharness.js></script>
+
+<h1>DOM IDL tests</h1>
+<div id=log></div>
+
+<script type=text/plain>
+[Constructor(DOMString type, optional EventInit eventInitDict)/*,
+ Exposed=(Window,Worker)*/]
+interface Event {
+  readonly attribute DOMString type;
+  readonly attribute EventTarget? target;
+  readonly attribute EventTarget? currentTarget;
+
+  const unsigned short NONE = 0;
+  const unsigned short CAPTURING_PHASE = 1;
+  const unsigned short AT_TARGET = 2;
+  const unsigned short BUBBLING_PHASE = 3;
+  readonly attribute unsigned short eventPhase;
+
+  void stopPropagation();
+  void stopImmediatePropagation();
+
+  readonly attribute boolean bubbles;
+  readonly attribute boolean cancelable;
+  void preventDefault();
+  readonly attribute boolean defaultPrevented;
+
+  [Unforgeable] readonly attribute boolean isTrusted;
+  readonly attribute DOMTimeStamp timeStamp;
+
+  void initEvent(DOMString type, boolean bubbles, boolean cancelable);
+};
+
+dictionary EventInit {
+  boolean bubbles = false;
+  boolean cancelable = false;
+};
+
+[Constructor(DOMString type, optional CustomEventInit eventInitDict)/*,
+ Exposed=(Window,Worker)*/]
+interface CustomEvent : Event {
+  readonly attribute any detail;
+
+  void initCustomEvent(DOMString type, boolean bubbles, boolean cancelable, any detail);
+};
+
+dictionary CustomEventInit : EventInit {
+  any detail = null;
+};
+
+//[Exposed=(Window,Worker)]
+interface EventTarget {
+  void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+  void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+  boolean dispatchEvent(Event event);
+};
+
+callback interface EventListener {
+  void handleEvent(Event event);
+};
+
+[NoInterfaceObject]
+interface NonElementParentNode {
+  Element? getElementById(DOMString elementId);
+};
+Document implements NonElementParentNode;
+DocumentFragment implements NonElementParentNode;
+
+[NoInterfaceObject]
+interface ParentNode {
+  [SameObject] readonly attribute HTMLCollection children;
+  readonly attribute Element? firstElementChild;
+  readonly attribute Element? lastElementChild;
+  readonly attribute unsigned long childElementCount;
+
+  [Unscopeable] void prepend((Node or DOMString)... nodes);
+  [Unscopeable] void append((Node or DOMString)... nodes);
+
+  [Unscopeable] Element? query(DOMString relativeSelectors);
+  [NewObject, Unscopeable] Elements queryAll(DOMString relativeSelectors);
+  Element? querySelector(DOMString selectors);
+  [NewObject] NodeList querySelectorAll(DOMString selectors);
+};
+Document implements ParentNode;
+DocumentFragment implements ParentNode;
+Element implements ParentNode;
+
+[NoInterfaceObject]
+interface NonDocumentTypeChildNode {
+  readonly attribute Element? previousElementSibling;
+  readonly attribute Element? nextElementSibling;
+};
+Element implements NonDocumentTypeChildNode;
+CharacterData implements NonDocumentTypeChildNode;
+
+[NoInterfaceObject]
+interface ChildNode {
+  [Unscopeable] void before((Node or DOMString)... nodes);
+  [Unscopeable] void after((Node or DOMString)... nodes);
+  [Unscopeable] void replaceWith((Node or DOMString)... nodes);
+  [Unscopeable] void remove();
+};
+DocumentType implements ChildNode;
+Element implements ChildNode;
+CharacterData implements ChildNode;
+
+// XXX unrecognized tokens "class", "extends"
+// https://www.w3.org/Bugs/Public/show_bug.cgi?id=20020
+// https://www.w3.org/Bugs/Public/show_bug.cgi?id=23225
+//class Elements extends Array {
+//  Element? query(DOMString relativeSelectors);
+//  Elements queryAll(DOMString relativeSelectors);
+//};
+
+interface NodeList {
+  getter Node? item(unsigned long index);
+  readonly attribute unsigned long length;
+//  iterable<Node>;
+};
+
+interface HTMLCollection {
+  readonly attribute unsigned long length;
+  getter Element? item(unsigned long index);
+  getter Element? namedItem(DOMString name);
+};
+
+[Constructor(MutationCallback callback)]
+interface MutationObserver {
+  void observe(Node target, MutationObserverInit options);
+  void disconnect();
+  sequence<MutationRecord> takeRecords();
+};
+
+callback MutationCallback = void (sequence<MutationRecord> mutations, MutationObserver observer);
+
+dictionary MutationObserverInit {
+  boolean childList = false;
+  boolean attributes;
+  boolean characterData;
+  boolean subtree = false;
+  boolean attributeOldValue;
+  boolean characterDataOldValue;
+  sequence<DOMString> attributeFilter;
+};
+
+interface MutationRecord {
+  readonly attribute DOMString type;
+  readonly attribute Node target;
+  [SameObject] readonly attribute NodeList addedNodes;
+  [SameObject] readonly attribute NodeList removedNodes;
+  readonly attribute Node? previousSibling;
+  readonly attribute Node? nextSibling;
+  readonly attribute DOMString? attributeName;
+  readonly attribute DOMString? attributeNamespace;
+  readonly attribute DOMString? oldValue;
+};
+
+interface Node : EventTarget {
+  const unsigned short ELEMENT_NODE = 1;
+  const unsigned short ATTRIBUTE_NODE = 2; // historical
+  const unsigned short TEXT_NODE = 3;
+  const unsigned short CDATA_SECTION_NODE = 4; // historical
+  const unsigned short ENTITY_REFERENCE_NODE = 5; // historical
+  const unsigned short ENTITY_NODE = 6; // historical
+  const unsigned short PROCESSING_INSTRUCTION_NODE = 7;
+  const unsigned short COMMENT_NODE = 8;
+  const unsigned short DOCUMENT_NODE = 9;
+  const unsigned short DOCUMENT_TYPE_NODE = 10;
+  const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
+  const unsigned short NOTATION_NODE = 12; // historical
+  readonly attribute unsigned short nodeType;
+  readonly attribute DOMString nodeName;
+
+  readonly attribute DOMString? baseURI;
+
+  readonly attribute Document? ownerDocument;
+  readonly attribute Node? parentNode;
+  readonly attribute Element? parentElement;
+  boolean hasChildNodes();
+  [SameObject] readonly attribute NodeList childNodes;
+  readonly attribute Node? firstChild;
+  readonly attribute Node? lastChild;
+  readonly attribute Node? previousSibling;
+  readonly attribute Node? nextSibling;
+
+           attribute DOMString? nodeValue;
+           attribute DOMString? textContent;
+  void normalize();
+
+  [NewObject] Node cloneNode(optional boolean deep = false);
+  boolean isEqualNode(Node? node);
+
+  const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01;
+  const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02;
+  const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x04;
+  const unsigned short DOCUMENT_POSITION_CONTAINS = 0x08;
+  const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10;
+  const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
+  unsigned short compareDocumentPosition(Node other);
+  boolean contains(Node? other);
+
+  DOMString? lookupPrefix(DOMString? namespace);
+  DOMString? lookupNamespaceURI(DOMString? prefix);
+  boolean isDefaultNamespace(DOMString? namespace);
+
+  Node insertBefore(Node node, Node? child);
+  Node appendChild(Node node);
+  Node replaceChild(Node node, Node child);
+  Node removeChild(Node child);
+};
+
+[Constructor]
+interface Document : Node {
+  [SameObject] readonly attribute DOMImplementation implementation;
+  readonly attribute DOMString URL;
+  readonly attribute DOMString documentURI;
+  readonly attribute DOMString origin;
+  readonly attribute DOMString compatMode;
+  readonly attribute DOMString characterSet;
+  readonly attribute DOMString charset; // legacy alias of .characterSet
+  readonly attribute DOMString inputEncoding; // legacy alias of .characterSet
+  readonly attribute DOMString contentType;
+
+  readonly attribute DocumentType? doctype;
+  readonly attribute Element? documentElement;
+  HTMLCollection getElementsByTagName(DOMString localName);
+  HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
+  HTMLCollection getElementsByClassName(DOMString classNames);
+
+  [NewObject] Element createElement(DOMString localName);
+  [NewObject] Element createElementNS(DOMString? namespace, DOMString qualifiedName);
+  [NewObject] DocumentFragment createDocumentFragment();
+  [NewObject] Text createTextNode(DOMString data);
+  [NewObject] Comment createComment(DOMString data);
+  [NewObject] ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data);
+
+  [NewObject] Node importNode(Node node, optional boolean deep = false);
+  Node adoptNode(Node node);
+
+  [NewObject] Attr createAttribute(DOMString localName);
+  [NewObject] Attr createAttributeNS(DOMString? namespace, DOMString name);
+
+  [NewObject] Event createEvent(DOMString interface);
+
+  [NewObject] Range createRange();
+
+  // NodeFilter.SHOW_ALL = 0xFFFFFFFF
+  [NewObject] NodeIterator createNodeIterator(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
+  [NewObject] TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
+};
+
+interface XMLDocument : Document {};
+
+interface DOMImplementation {
+  [NewObject] DocumentType createDocumentType(DOMString qualifiedName, DOMString publicId, DOMString systemId);
+  [NewObject] XMLDocument createDocument(DOMString? namespace, [TreatNullAs=EmptyString] DOMString qualifiedName, optional DocumentType? doctype = null);
+  [NewObject] Document createHTMLDocument(optional DOMString title);
+
+  boolean hasFeature(); // useless; always returns true
+};
+
+[Constructor]
+interface DocumentFragment : Node {
+};
+
+interface DocumentType : Node {
+  readonly attribute DOMString name;
+  readonly attribute DOMString publicId;
+  readonly attribute DOMString systemId;
+};
+
+interface Element : Node {
+  readonly attribute DOMString? namespaceURI;
+  readonly attribute DOMString? prefix;
+  readonly attribute DOMString localName;
+  readonly attribute DOMString tagName;
+
+           attribute DOMString id;
+           attribute DOMString className;
+  [SameObject] readonly attribute DOMTokenList classList;
+
+  boolean hasAttributes();
+  [SameObject] readonly attribute NamedNodeMap attributes;
+  DOMString? getAttribute(DOMString name);
+  DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
+  void setAttribute(DOMString name, DOMString value);
+  void setAttributeNS(DOMString? namespace, DOMString name, DOMString value);
+  void removeAttribute(DOMString name);
+  void removeAttributeNS(DOMString? namespace, DOMString localName);
+  boolean hasAttribute(DOMString name);
+  boolean hasAttributeNS(DOMString? namespace, DOMString localName);
+
+  Attr? getAttributeNode(DOMString name);
+  Attr? getAttributeNodeNS(DOMString? namespace, DOMString localName);
+  Attr? setAttributeNode(Attr attr);
+  Attr? setAttributeNodeNS(Attr attr);
+  Attr removeAttributeNode(Attr attr);
+
+  Element? closest(DOMString selectors);
+  boolean matches(DOMString selectors);
+
+  HTMLCollection getElementsByTagName(DOMString localName);
+  HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
+  HTMLCollection getElementsByClassName(DOMString classNames);
+};
+
+interface NamedNodeMap {
+  readonly attribute unsigned long length;
+  getter Attr? item(unsigned long index);
+  getter Attr? getNamedItem(DOMString name);
+  Attr? getNamedItemNS(DOMString? namespace, DOMString localName);
+  Attr? setNamedItem(Attr attr);
+  Attr? setNamedItemNS(Attr attr);
+  Attr removeNamedItem(DOMString name);
+  Attr removeNamedItemNS(DOMString? namespace, DOMString localName);
+};
+
+interface Attr {
+  readonly attribute DOMString? namespaceURI;
+  readonly attribute DOMString? prefix;
+  readonly attribute DOMString localName;
+  readonly attribute DOMString name;
+           attribute DOMString value;
+           attribute DOMString nodeValue; // legacy alias of .value
+           attribute DOMString textContent; // legacy alias of .value
+
+  readonly attribute Element? ownerElement;
+
+  readonly attribute boolean specified; // useless; always returns true
+};
+
+interface CharacterData : Node {
+  [TreatNullAs=EmptyString] attribute DOMString data;
+  readonly attribute unsigned long length;
+  DOMString substringData(unsigned long offset, unsigned long count);
+  void appendData(DOMString data);
+  void insertData(unsigned long offset, DOMString data);
+  void deleteData(unsigned long offset, unsigned long count);
+  void replaceData(unsigned long offset, unsigned long count, DOMString data);
+};
+
+[Constructor(optional DOMString data = "")]
+interface Text : CharacterData {
+  [NewObject] Text splitText(unsigned long offset);
+  readonly attribute DOMString wholeText;
+};
+
+interface ProcessingInstruction : CharacterData {
+  readonly attribute DOMString target;
+};
+
+[Constructor(optional DOMString data = "")]
+interface Comment : CharacterData {
+};
+
+[Constructor]
+interface Range {
+  readonly attribute Node startContainer;
+  readonly attribute unsigned long startOffset;
+  readonly attribute Node endContainer;
+  readonly attribute unsigned long endOffset;
+  readonly attribute boolean collapsed;
+  readonly attribute Node commonAncestorContainer;
+
+  void setStart(Node node, unsigned long offset);
+  void setEnd(Node node, unsigned long offset);
+  void setStartBefore(Node node);
+  void setStartAfter(Node node);
+  void setEndBefore(Node node);
+  void setEndAfter(Node node);
+  void collapse(optional boolean toStart = false);
+  void selectNode(Node node);
+  void selectNodeContents(Node node);
+
+  const unsigned short START_TO_START = 0;
+  const unsigned short START_TO_END = 1;
+  const unsigned short END_TO_END = 2;
+  const unsigned short END_TO_START = 3;
+  short compareBoundaryPoints(unsigned short how, Range sourceRange);
+
+  void deleteContents();
+  [NewObject] DocumentFragment extractContents();
+  [NewObject] DocumentFragment cloneContents();
+  void insertNode(Node node);
+  void surroundContents(Node newParent);
+
+  [NewObject] Range cloneRange();
+  void detach();
+
+  boolean isPointInRange(Node node, unsigned long offset);
+  short comparePoint(Node node, unsigned long offset);
+
+  boolean intersectsNode(Node node);
+
+  stringifier;
+};
+
+interface NodeIterator {
+  [SameObject] readonly attribute Node root;
+  readonly attribute Node referenceNode;
+  readonly attribute boolean pointerBeforeReferenceNode;
+  readonly attribute unsigned long whatToShow;
+  readonly attribute NodeFilter? filter;
+
+  Node? nextNode();
+  Node? previousNode();
+
+  void detach();
+};
+
+interface TreeWalker {
+  [SameObject] readonly attribute Node root;
+  readonly attribute unsigned long whatToShow;
+  readonly attribute NodeFilter? filter;
+           attribute Node currentNode;
+
+  Node? parentNode();
+  Node? firstChild();
+  Node? lastChild();
+  Node? previousSibling();
+  Node? nextSibling();
+  Node? previousNode();
+  Node? nextNode();
+};
+
+callback interface NodeFilter {
+  // Constants for acceptNode()
+  const unsigned short FILTER_ACCEPT = 1;
+  const unsigned short FILTER_REJECT = 2;
+  const unsigned short FILTER_SKIP = 3;
+
+  // Constants for whatToShow
+  const unsigned long SHOW_ALL = 0xFFFFFFFF;
+  const unsigned long SHOW_ELEMENT = 0x1;
+  const unsigned long SHOW_ATTRIBUTE = 0x2; // historical
+  const unsigned long SHOW_TEXT = 0x4;
+  const unsigned long SHOW_CDATA_SECTION = 0x8; // historical
+  const unsigned long SHOW_ENTITY_REFERENCE = 0x10; // historical
+  const unsigned long SHOW_ENTITY = 0x20; // historical
+  const unsigned long SHOW_PROCESSING_INSTRUCTION = 0x40;
+  const unsigned long SHOW_COMMENT = 0x80;
+  const unsigned long SHOW_DOCUMENT = 0x100;
+  const unsigned long SHOW_DOCUMENT_TYPE = 0x200;
+  const unsigned long SHOW_DOCUMENT_FRAGMENT = 0x400;
+  const unsigned long SHOW_NOTATION = 0x800; // historical
+
+  unsigned short acceptNode(Node node);
+};
+
+interface DOMTokenList {
+  readonly attribute unsigned long length;
+  getter DOMString? item(unsigned long index);
+  boolean contains(DOMString token);
+  void add(DOMString... tokens);
+  void remove(DOMString... tokens);
+  boolean toggle(DOMString token, optional boolean force);
+  stringifier;
+//  iterable<DOMString>;
+};
+
+interface DOMSettableTokenList : DOMTokenList {
+            attribute DOMString value;
+};
+</script>
+<script>
+"use strict";
+var xmlDoc, detachedRange, element;
+var idlArray;
+setup(function() {
+  xmlDoc = document.implementation.createDocument(null, "", null);
+  detachedRange = document.createRange();
+  detachedRange.detach();
+  element = xmlDoc.createElementNS(null, "test");
+  element.setAttribute("bar", "baz");
+
+  idlArray = new IdlArray();
+  idlArray.add_idls(document.querySelector("script[type=text\\/plain]").textContent);
+  idlArray.add_objects({
+    Event: ['document.createEvent("Event")', 'new Event("foo")'],
+    CustomEvent: ['new CustomEvent("foo")'],
+    XMLDocument: ['xmlDoc'],
+    DOMImplementation: ['document.implementation'],
+    DocumentFragment: ['document.createDocumentFragment()'],
+    DocumentType: ['document.doctype'],
+    Element: ['element'],
+    Attr: ['document.querySelector("[id]").attributes[0]'],
+    Text: ['document.createTextNode("abc")'],
+    ProcessingInstruction: ['xmlDoc.createProcessingInstruction("abc", "def")'],
+    Comment: ['document.createComment("abc")'],
+    Range: ['document.createRange()', 'detachedRange'],
+    NodeIterator: ['document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false)'],
+    TreeWalker: ['document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false)'],
+    NodeList: ['document.querySelectorAll("script")'],
+    HTMLCollection: ['document.body.children'],
+    DOMTokenList: ['document.body.classList'],
+  });
+});
+idlArray.test();
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/lists/DOMTokenList-stringifier-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/lists/DOMTokenList-stringifier-expected.txt
new file mode 100644
index 0000000..1b6c3abf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/lists/DOMTokenList-stringifier-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL DOMTokenList stringifier assert_equals: String(classList) should compress whitespace expected "a b" but got "   a  a b"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/lists/DOMTokenList-stringifier.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/lists/DOMTokenList-stringifier.html
new file mode 100644
index 0000000..d81c576
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/lists/DOMTokenList-stringifier.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>DOMTokenList stringifier</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-domtokenlist-stringifier">
+<link rel=author title=Ms2ger href="mailto:Ms2ger@gmail.com">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<span class="   a  a b"></span>
+<script>
+test(function() {
+  var span = document.querySelector("span");
+  assert_equals(span.getAttribute("class"), "   a  a b",
+                "getAttribute should return the literal value");
+  assert_equals(span.className, "   a  a b",
+                "className should return the literal value");
+  assert_equals(String(span.classList), "a b",
+                "String(classList) should compress whitespace");
+  assert_equals(span.classList.toString(), "a b",
+                "classList.toString() should compress whitespace");
+  assert_class_string(span.classList, "DOMTokenList");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-appendData.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-appendData.html
new file mode 100644
index 0000000..3456245
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-appendData.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CharacterData.appendData</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-appenddata">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testNode(create, type) {
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.appendData("bar")
+    assert_equals(node.data, "testbar")
+  }, type + ".appendData('bar')")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.appendData("")
+    assert_equals(node.data, "test")
+  }, type + ".appendData('')")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+    node.appendData(", append more 資料,測試資料");
+    assert_equals(node.data, "test, append more 資料,測試資料");
+    assert_equals(node.length, 25);
+  }, type + ".appendData(non-ASCII)")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.appendData(null)
+    assert_equals(node.data, "testnull")
+  }, type + ".appendData(null)")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.appendData(undefined)
+    assert_equals(node.data, "testundefined")
+  }, type + ".appendData(undefined)")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.appendData("", "bar")
+    assert_equals(node.data, "test")
+  }, type + ".appendData('', 'bar')")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_throws(new TypeError(), function() { node.appendData() });
+    assert_equals(node.data, "test")
+  }, type + ".appendData()")
+}
+
+testNode(function() { return document.createTextNode("test") }, "Text")
+testNode(function() { return document.createComment("test") }, "Comment")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-data.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-data.html
new file mode 100644
index 0000000..7f2d69f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-data.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CharacterData.data</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testNode(create, type) {
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+    assert_equals(node.length, 4)
+  }, type + ".data initial value")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = null;
+    assert_equals(node.data, "")
+    assert_equals(node.length, 0)
+  }, type + ".data = null")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = undefined;
+    assert_equals(node.data, "undefined")
+    assert_equals(node.length, 9)
+  }, type + ".data = undefined")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = 0;
+    assert_equals(node.data, "0")
+    assert_equals(node.length, 1)
+  }, type + ".data = 0")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = "";
+    assert_equals(node.data, "")
+    assert_equals(node.length, 0)
+  }, type + ".data = ''")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = "--";
+    assert_equals(node.data, "--")
+    assert_equals(node.length, 2)
+  }, type + ".data = '--'")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = "資料";
+    assert_equals(node.data, "資料")
+    assert_equals(node.length, 2)
+  }, type + ".data = '資料'")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = "🌠 test 🌠 TEST";
+    assert_equals(node.data, "🌠 test 🌠 TEST")
+    assert_equals(node.length, 15)  // Counting UTF-16 code units
+  }, type + ".data = '🌠 test 🌠 TEST'")
+}
+
+testNode(function() { return document.createTextNode("test") }, "Text")
+testNode(function() { return document.createComment("test") }, "Comment")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-deleteData.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-deleteData.html
new file mode 100644
index 0000000..43a2ea9b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-deleteData.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CharacterData.deleteData</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-deletedata">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testNode(create, type) {
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_throws("INDEX_SIZE_ERR", function() { node.deleteData(5, 10) })
+    assert_throws("INDEX_SIZE_ERR", function() { node.deleteData(5, 0) })
+    assert_throws("INDEX_SIZE_ERR", function() { node.deleteData(-1, 10) })
+    assert_throws("INDEX_SIZE_ERR", function() { node.deleteData(-1, 0) })
+  }, type + ".deleteData() out of bounds")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.deleteData(0, 2)
+    assert_equals(node.data, "st")
+  }, type + ".deleteData() at the start")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.deleteData(2, 10)
+    assert_equals(node.data, "te")
+  }, type + ".deleteData() at the end")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.deleteData(1, 1)
+    assert_equals(node.data, "tst")
+  }, type + ".deleteData() in the middle")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.deleteData(2, 0)
+    assert_equals(node.data, "test")
+
+    node.deleteData(0, 0)
+    assert_equals(node.data, "test")
+  }, type + ".deleteData() with zero count")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.deleteData(2, -1)
+    assert_equals(node.data, "te")
+  }, type + ".deleteData() with small negative count")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.deleteData(1, -0x100000000 + 2)
+    assert_equals(node.data, "tt")
+  }, type + ".deleteData() with large negative count")
+
+  test(function() {
+    var node = create()
+    node.data = "This is the character data test, append more 資料,更多測試資料";
+
+    node.deleteData(40, 5);
+    assert_equals(node.data, "This is the character data test, append 資料,更多測試資料");
+    node.deleteData(45, 2);
+    assert_equals(node.data, "This is the character data test, append 資料,更多資料");
+  }, type + ".deleteData() with non-ascii data")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = "🌠 test 🌠 TEST"
+
+    node.deleteData(5, 8);  // Counting UTF-16 code units
+    assert_equals(node.data, "🌠 teST");
+  }, type + ".deleteData() with non-BMP data")
+}
+
+testNode(function() { return document.createTextNode("test") }, "Text")
+testNode(function() { return document.createComment("test") }, "Comment")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-insertData.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-insertData.html
new file mode 100644
index 0000000..dde04f6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-insertData.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CharacterData.insertData</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-insertdata">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testNode(create, type) {
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_throws("INDEX_SIZE_ERR", function() { node.insertData(5, "x") })
+    assert_throws("INDEX_SIZE_ERR", function() { node.insertData(5, "") })
+  }, type + ".insertData() out of bounds")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_throws("INDEX_SIZE_ERR", function() { node.insertData(-1, "x") })
+    assert_throws("INDEX_SIZE_ERR", function() { node.insertData(-0x100000000 + 5, "x") })
+  }, type + ".insertData() negative out of bounds")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.insertData(-0x100000000 + 2, "X")
+    assert_equals(node.data, "teXst")
+  }, type + ".insertData() negative in bounds")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.insertData(0, "")
+    assert_equals(node.data, "test")
+  }, type + ".insertData('')")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.insertData(0, "X")
+    assert_equals(node.data, "Xtest")
+  }, type + ".insertData() at the start")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.insertData(2, "X")
+    assert_equals(node.data, "teXst")
+  }, type + ".insertData() in the middle")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.insertData(4, "ing")
+    assert_equals(node.data, "testing")
+  }, type + ".insertData() at the end")
+
+  test(function() {
+    var node = create()
+    node.data = "This is the character data, append more 資料,測試資料";
+
+    node.insertData(26, " test");
+    assert_equals(node.data, "This is the character data test, append more 資料,測試資料");
+    node.insertData(48, "更多");
+    assert_equals(node.data, "This is the character data test, append more 資料,更多測試資料");
+  }, type + ".insertData() with non-ascii data")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = "🌠 test 🌠 TEST"
+
+    node.insertData(5, "--");  // Counting UTF-16 code units
+    assert_equals(node.data, "🌠 te--st 🌠 TEST");
+  }, type + ".insertData() with non-BMP data")
+}
+
+testNode(function() { return document.createTextNode("test") }, "Text")
+testNode(function() { return document.createComment("test") }, "Comment")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-remove.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-remove.html
new file mode 100644
index 0000000..57ea69a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-remove.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CharacterData.remove</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-childnode-remove">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="ChildNode-remove.js"></script>
+<div id=log></div>
+<script>
+var text, text_parent,
+    comment, comment_parent,
+    pi, pi_parent;
+setup(function() {
+  text = document.createTextNode("text");
+  text_parent = document.createElement("div");
+  comment = document.createComment("comment");
+  comment_parent = document.createElement("div");
+  pi = document.createProcessingInstruction("foo", "bar");
+  pi_parent = document.createElement("div");
+});
+testRemove(text, text_parent, "text");
+testRemove(comment, comment_parent, "comment");
+testRemove(pi, pi_parent, "PI");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-replaceData.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-replaceData.html
new file mode 100644
index 0000000..346809c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-replaceData.html
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CharacterData.replaceData</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-replacedata">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testNode(create, type) {
+  // Step 2.
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_throws("IndexSizeError", function() { node.replaceData(5, 1, "x") })
+    assert_throws("IndexSizeError", function() { node.replaceData(5, 0, "") })
+    assert_throws("IndexSizeError", function() { node.replaceData(-1, 1, "x") })
+    assert_throws("IndexSizeError", function() { node.replaceData(-1, 0, "") })
+    assert_equals(node.data, "test")
+  }, type + ".replaceData() with invalid offset")
+
+  // Step 3.
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.replaceData(2, 10, "yo")
+    assert_equals(node.data, "teyo")
+  }, type + ".replaceData() with clamped count")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.replaceData(2, -1, "yo")
+    assert_equals(node.data, "teyo")
+  }, type + ".replaceData() with negative clamped count")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.replaceData(0, 0, "yo")
+    assert_equals(node.data, "yotest")
+  }, type + ".replaceData() before the start")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.replaceData(0, 2, "y")
+    assert_equals(node.data, "yst")
+  }, type + ".replaceData() at the start (shorter)")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.replaceData(0, 2, "yo")
+    assert_equals(node.data, "yost")
+  }, type + ".replaceData() at the start (equal length)")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.replaceData(0, 2, "yoa")
+    assert_equals(node.data, "yoast")
+  }, type + ".replaceData() at the start (longer)")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.replaceData(1, 2, "o")
+    assert_equals(node.data, "tot")
+  }, type + ".replaceData() in the middle (shorter)")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.replaceData(1, 2, "yo")
+    assert_equals(node.data, "tyot")
+  }, type + ".replaceData() in the middle (equal length)")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.replaceData(1, 1, "waddup")
+    assert_equals(node.data, "twaddupst")
+    node.replaceData(1, 1, "yup")
+    assert_equals(node.data, "tyupaddupst")
+  }, type + ".replaceData() in the middle (longer)")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.replaceData(1, 20, "yo")
+    assert_equals(node.data, "tyo")
+  }, type + ".replaceData() at the end (shorter)")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.replaceData(2, 20, "yo")
+    assert_equals(node.data, "teyo")
+  }, type + ".replaceData() at the end (same length)")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.replaceData(4, 20, "yo")
+    assert_equals(node.data, "testyo")
+  }, type + ".replaceData() at the end (longer)")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.replaceData(0, 4, "quux")
+    assert_equals(node.data, "quux")
+  }, type + ".replaceData() the whole string")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.replaceData(0, 4, "")
+    assert_equals(node.data, "")
+  }, type + ".replaceData() with the empty string")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = "This is the character data test, append 資料,更多資料";
+
+    node.replaceData(33, 6, "other");
+    assert_equals(node.data, "This is the character data test, other 資料,更多資料");
+    node.replaceData(44, 2, "文字");
+    assert_equals(node.data, "This is the character data test, other 資料,更多文字");
+  }, type + ".replaceData() with non-ASCII data")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = "🌠 test 🌠 TEST"
+
+    node.replaceData(5, 8, "--");  // Counting UTF-16 code units
+    assert_equals(node.data, "🌠 te--ST");
+  }, type + ".replaceData() with non-BMP data")
+}
+
+testNode(function() { return document.createTextNode("test") }, "Text")
+testNode(function() { return document.createComment("test") }, "Comment")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-substringData.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-substringData.html
new file mode 100644
index 0000000..05884c2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-substringData.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CharacterData.substringData</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-substringdata">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testNode(create, type) {
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_throws(new TypeError(), function() { node.substringData() })
+    assert_throws(new TypeError(), function() { node.substringData(0) })
+  }, type + ".substringData() with too few arguments")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_equals(node.substringData(0, 1, "test"), "t")
+  }, type + ".substringData() with too many arguments")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_throws("IndexSizeError", function() { node.substringData(5, 0) })
+    assert_throws("IndexSizeError", function() { node.substringData(6, 0) })
+    assert_throws("IndexSizeError", function() { node.substringData(-1, 0) })
+  }, type + ".substringData() with invalid offset")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_equals(node.substringData(0, 1), "t")
+    assert_equals(node.substringData(1, 1), "e")
+    assert_equals(node.substringData(2, 1), "s")
+    assert_equals(node.substringData(3, 1), "t")
+    assert_equals(node.substringData(4, 1), "")
+  }, type + ".substringData() with in-bounds offset")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_equals(node.substringData(0, 0), "")
+    assert_equals(node.substringData(1, 0), "")
+    assert_equals(node.substringData(2, 0), "")
+    assert_equals(node.substringData(3, 0), "")
+    assert_equals(node.substringData(4, 0), "")
+  }, type + ".substringData() with zero count")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_equals(node.substringData(0x100000000 + 0, 1), "t")
+    assert_equals(node.substringData(0x100000000 + 1, 1), "e")
+    assert_equals(node.substringData(0x100000000 + 2, 1), "s")
+    assert_equals(node.substringData(0x100000000 + 3, 1), "t")
+    assert_equals(node.substringData(0x100000000 + 4, 1), "")
+  }, type + ".substringData() with very large offset")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_equals(node.substringData(-0x100000000 + 2, 1), "s")
+  }, type + ".substringData() with negative offset")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_equals(node.substringData("test", 3), "tes")
+  }, type + ".substringData() with string offset")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_equals(node.substringData(0, 1), "t")
+    assert_equals(node.substringData(0, 2), "te")
+    assert_equals(node.substringData(0, 3), "tes")
+    assert_equals(node.substringData(0, 4), "test")
+  }, type + ".substringData() with in-bounds count")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_equals(node.substringData(0, 5), "test")
+    assert_equals(node.substringData(2, 20), "st")
+  }, type + ".substringData() with large count")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_equals(node.substringData(2, 0x100000000 + 1), "s")
+  }, type + ".substringData() with very large count")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    assert_equals(node.substringData(0, -1), "test")
+    assert_equals(node.substringData(0, -0x100000000 + 2), "te")
+  }, type + ".substringData() with negative count")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = "This is the character data test, other 資料,更多文字"
+
+    assert_equals(node.substringData(12, 4), "char")
+    assert_equals(node.substringData(39, 2), "資料")
+  }, type + ".substringData() with non-ASCII data")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = "🌠 test 🌠 TEST"
+
+    assert_equals(node.substringData(5, 8), "st 🌠 TE")  // Counting UTF-16 code units
+  }, type + ".substringData() with non-BMP data")
+}
+
+testNode(function() { return document.createTextNode("test") }, "Text")
+testNode(function() { return document.createComment("test") }, "Comment")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-surrogates.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-surrogates.html
new file mode 100644
index 0000000..0655d1e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/CharacterData-surrogates.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Splitting and joining surrogate pairs in CharacterData methods</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-substringdata">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-replacedata">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-insertdata">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-deletedata">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testNode(create, type) {
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = "🌠 test 🌠 TEST"
+
+    assert_equals(node.substringData(1, 8), "\uDF20 test \uD83C")
+  }, type + ".substringData() splitting surrogate pairs")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = "🌠 test 🌠 TEST"
+
+    node.replaceData(1, 4, "--");
+    assert_equals(node.data, "\uD83C--st 🌠 TEST");
+
+    node.replaceData(1, 2, "\uDF1F ");
+    assert_equals(node.data, "🌟 st 🌠 TEST");
+
+    node.replaceData(5, 2, "---");
+    assert_equals(node.data, "🌟 st---\uDF20 TEST");
+
+    node.replaceData(6, 2, " \uD83D");
+    assert_equals(node.data, "🌟 st- 🜠 TEST");
+  }, type + ".replaceData() splitting and creating surrogate pairs")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = "🌠 test 🌠 TEST"
+
+    node.deleteData(1, 4);
+    assert_equals(node.data, "\uD83Cst 🌠 TEST");
+
+    node.deleteData(1, 4);
+    assert_equals(node.data, "🌠 TEST");
+  }, type + ".deleteData() splitting and creating surrogate pairs")
+
+  test(function() {
+    var node = create()
+    assert_equals(node.data, "test")
+
+    node.data = "🌠 test 🌠 TEST"
+
+    node.insertData(1, "--");
+    assert_equals(node.data, "\uD83C--\uDF20 test 🌠 TEST");
+
+    node.insertData(1, "\uDF1F ");
+    assert_equals(node.data, "🌟 --\uDF20 test 🌠 TEST");
+
+    node.insertData(5, " \uD83D");
+    assert_equals(node.data, "🌟 -- 🜠 test 🌠 TEST");
+  }, type + ".insertData() splitting and creating surrogate pairs")
+}
+
+testNode(function() { return document.createTextNode("test") }, "Text")
+testNode(function() { return document.createComment("test") }, "Comment")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-after-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-after-expected.txt
new file mode 100644
index 0000000..7920cd8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-after-expected.txt
@@ -0,0 +1,48 @@
+This is a testharness.js-based test.
+FAIL Comment.after() without any argument. child.after is not a function
+FAIL Comment.after() with null as an argument. child.after is not a function
+FAIL Comment.after() with undefined as an argument. child.after is not a function
+FAIL Comment.after() with the empty string as an argument. child.after is not a function
+FAIL Comment.after() with only text as an argument. child.after is not a function
+FAIL Comment.after() with only one element as an argument. child.after is not a function
+FAIL Comment.after() with one element and text as arguments. child.after is not a function
+FAIL Comment.after() with context object itself as the argument. child.after is not a function
+FAIL Comment.after() with context object itself and node as the arguments, switching positions. child.after is not a function
+FAIL Comment.after() with all siblings of child as arguments. child.after is not a function
+FAIL Comment.before() with some siblings of child as arguments; no changes in tree; viable sibling is first child. child.after is not a function
+FAIL Comment.after() with some siblings of child as arguments; no changes in tree. child.after is not a function
+FAIL Comment.after() when pre-insert behaves like append. child.after is not a function
+FAIL Comment.after() with one sibling of child and text as arguments. child.after is not a function
+FAIL Comment.after() on a child without any parent. x.after is not a function
+FAIL Element.after() without any argument. child.after is not a function
+FAIL Element.after() with null as an argument. child.after is not a function
+FAIL Element.after() with undefined as an argument. child.after is not a function
+FAIL Element.after() with the empty string as an argument. child.after is not a function
+FAIL Element.after() with only text as an argument. child.after is not a function
+FAIL Element.after() with only one element as an argument. child.after is not a function
+FAIL Element.after() with one element and text as arguments. child.after is not a function
+FAIL Element.after() with context object itself as the argument. child.after is not a function
+FAIL Element.after() with context object itself and node as the arguments, switching positions. child.after is not a function
+FAIL Element.after() with all siblings of child as arguments. child.after is not a function
+FAIL Element.before() with some siblings of child as arguments; no changes in tree; viable sibling is first child. child.after is not a function
+FAIL Element.after() with some siblings of child as arguments; no changes in tree. child.after is not a function
+FAIL Element.after() when pre-insert behaves like append. child.after is not a function
+FAIL Element.after() with one sibling of child and text as arguments. child.after is not a function
+FAIL Element.after() on a child without any parent. x.after is not a function
+FAIL Text.after() without any argument. child.after is not a function
+FAIL Text.after() with null as an argument. child.after is not a function
+FAIL Text.after() with undefined as an argument. child.after is not a function
+FAIL Text.after() with the empty string as an argument. child.after is not a function
+FAIL Text.after() with only text as an argument. child.after is not a function
+FAIL Text.after() with only one element as an argument. child.after is not a function
+FAIL Text.after() with one element and text as arguments. child.after is not a function
+FAIL Text.after() with context object itself as the argument. child.after is not a function
+FAIL Text.after() with context object itself and node as the arguments, switching positions. child.after is not a function
+FAIL Text.after() with all siblings of child as arguments. child.after is not a function
+FAIL Text.before() with some siblings of child as arguments; no changes in tree; viable sibling is first child. child.after is not a function
+FAIL Text.after() with some siblings of child as arguments; no changes in tree. child.after is not a function
+FAIL Text.after() when pre-insert behaves like append. child.after is not a function
+FAIL Text.after() with one sibling of child and text as arguments. child.after is not a function
+FAIL Text.after() on a child without any parent. x.after is not a function
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-after.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-after.html
new file mode 100644
index 0000000..6f3cf32
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-after.html
@@ -0,0 +1,166 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>ChildNode.after</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-childnode-after">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script>
+
+function test_after(child, nodeName, innerHTML) {
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.after();
+        assert_equals(parent.innerHTML, innerHTML);
+    }, nodeName + '.after() without any argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.after(null);
+        var expected = innerHTML + 'null';
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.after() with null as an argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.after(undefined);
+        var expected = innerHTML + 'undefined';
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.after() with undefined as an argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.after('');
+        assert_equals(parent.lastChild.data, '');
+    }, nodeName + '.after() with the empty string as an argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.after('text');
+        var expected = innerHTML + 'text';
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.after() with only text as an argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        parent.appendChild(child);
+        child.after(x);
+        var expected = innerHTML + '<x></x>';
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.after() with only one element as an argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        parent.appendChild(child);
+        child.after(x, 'text');
+        var expected = innerHTML + '<x></x>text';
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.after() with one element and text as arguments.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.after('text', child);
+        var expected = 'text' + innerHTML;
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.after() with context object itself as the argument.');
+
+    test(function() {
+        var parent = document.createElement('div')
+        var x = document.createElement('x');
+        parent.appendChild(x);
+        parent.appendChild(child);
+        child.after(child, x);
+        var expected = innerHTML + '<x></x>';
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.after() with context object itself and node as the arguments, switching positions.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        var z = document.createElement('z');
+        parent.appendChild(y);
+        parent.appendChild(child);
+        parent.appendChild(x);
+        child.after(x, y, z);
+        var expected = innerHTML + '<x></x><y></y><z></z>';
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.after() with all siblings of child as arguments.');
+
+    test(function() {
+        var parent = document.createElement('div')
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        var z = document.createElement('z');
+        parent.appendChild(child);
+        parent.appendChild(x);
+        parent.appendChild(y);
+        parent.appendChild(z);
+        child.after(x, y);
+        var expected = innerHTML + '<x></x><y></y><z></z>';
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.before() with some siblings of child as arguments; no changes in tree; viable sibling is first child.');
+
+    test(function() {
+        var parent = document.createElement('div')
+        var v = document.createElement('v');
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        var z = document.createElement('z');
+        parent.appendChild(child);
+        parent.appendChild(v);
+        parent.appendChild(x);
+        parent.appendChild(y);
+        parent.appendChild(z);
+        child.after(v, x);
+        var expected = innerHTML + '<v></v><x></x><y></y><z></z>';
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.after() with some siblings of child as arguments; no changes in tree.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        parent.appendChild(child);
+        parent.appendChild(x);
+        parent.appendChild(y);
+        child.after(y, x);
+        var expected = innerHTML + '<y></y><x></x>';
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.after() when pre-insert behaves like append.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        parent.appendChild(child);
+        parent.appendChild(x);
+        parent.appendChild(document.createTextNode('1'));
+        parent.appendChild(y);
+        child.after(x, '2');
+        var expected = innerHTML + '<x></x>21<y></y>';
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.after() with one sibling of child and text as arguments.');
+
+    test(function() {
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        x.after(y);
+        assert_equals(x.nextSibling, null);
+    }, nodeName + '.after() on a child without any parent.');
+}
+
+test_after(document.createComment('test'), 'Comment', '<!--test-->');
+test_after(document.createElement('test'), 'Element', '<test></test>');
+test_after(document.createTextNode('test'), 'Text', 'test');
+
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-before-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-before-expected.txt
new file mode 100644
index 0000000..b806250
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-before-expected.txt
@@ -0,0 +1,48 @@
+This is a testharness.js-based test.
+FAIL Comment.before() without any argument. child.before is not a function
+FAIL Comment.before() with null as an argument. child.before is not a function
+FAIL Comment.before() with undefined as an argument. child.before is not a function
+FAIL Comment.before() with the empty string as an argument. child.before is not a function
+FAIL Comment.before() with only text as an argument. child.before is not a function
+FAIL Comment.before() with only one element as an argument. child.before is not a function
+FAIL Comment.before() with one element and text as arguments. child.before is not a function
+FAIL Comment.before() with context object itself as the argument. child.before is not a function
+FAIL Comment.before() with context object itself and node as the arguments, switching positions. child.before is not a function
+FAIL Comment.before() with all siblings of child as arguments. child.before is not a function
+FAIL Comment.before() with some siblings of child as arguments; no changes in tree; viable sibling is first child. child.before is not a function
+FAIL Comment.before() with some siblings of child as arguments; no changes in tree. child.before is not a function
+FAIL Comment.before() when pre-insert behaves like prepend. child.before is not a function
+FAIL Comment.before() with one sibling of child and text as arguments. child.before is not a function
+FAIL Comment.before() on a child without any parent. x.before is not a function
+FAIL Element.before() without any argument. child.before is not a function
+FAIL Element.before() with null as an argument. child.before is not a function
+FAIL Element.before() with undefined as an argument. child.before is not a function
+FAIL Element.before() with the empty string as an argument. child.before is not a function
+FAIL Element.before() with only text as an argument. child.before is not a function
+FAIL Element.before() with only one element as an argument. child.before is not a function
+FAIL Element.before() with one element and text as arguments. child.before is not a function
+FAIL Element.before() with context object itself as the argument. child.before is not a function
+FAIL Element.before() with context object itself and node as the arguments, switching positions. child.before is not a function
+FAIL Element.before() with all siblings of child as arguments. child.before is not a function
+FAIL Element.before() with some siblings of child as arguments; no changes in tree; viable sibling is first child. child.before is not a function
+FAIL Element.before() with some siblings of child as arguments; no changes in tree. child.before is not a function
+FAIL Element.before() when pre-insert behaves like prepend. child.before is not a function
+FAIL Element.before() with one sibling of child and text as arguments. child.before is not a function
+FAIL Element.before() on a child without any parent. x.before is not a function
+FAIL Text.before() without any argument. child.before is not a function
+FAIL Text.before() with null as an argument. child.before is not a function
+FAIL Text.before() with undefined as an argument. child.before is not a function
+FAIL Text.before() with the empty string as an argument. child.before is not a function
+FAIL Text.before() with only text as an argument. child.before is not a function
+FAIL Text.before() with only one element as an argument. child.before is not a function
+FAIL Text.before() with one element and text as arguments. child.before is not a function
+FAIL Text.before() with context object itself as the argument. child.before is not a function
+FAIL Text.before() with context object itself and node as the arguments, switching positions. child.before is not a function
+FAIL Text.before() with all siblings of child as arguments. child.before is not a function
+FAIL Text.before() with some siblings of child as arguments; no changes in tree; viable sibling is first child. child.before is not a function
+FAIL Text.before() with some siblings of child as arguments; no changes in tree. child.before is not a function
+FAIL Text.before() when pre-insert behaves like prepend. child.before is not a function
+FAIL Text.before() with one sibling of child and text as arguments. child.before is not a function
+FAIL Text.before() on a child without any parent. x.before is not a function
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-before.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-before.html
new file mode 100644
index 0000000..0e5f45e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-before.html
@@ -0,0 +1,166 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>ChildNode.before</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-childnode-before">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script>
+
+function test_before(child, nodeName, innerHTML) {
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.before();
+        assert_equals(parent.innerHTML, innerHTML);
+    }, nodeName + '.before() without any argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.before(null);
+        var expected = 'null' + innerHTML;
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.before() with null as an argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.before(undefined);
+        var expected = 'undefined' + innerHTML;
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.before() with undefined as an argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.before('');
+        assert_equals(parent.firstChild.data, '');
+    }, nodeName + '.before() with the empty string as an argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.before('text');
+        var expected = 'text' + innerHTML;
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.before() with only text as an argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        parent.appendChild(child);
+        child.before(x);
+        var expected = '<x></x>' + innerHTML;
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.before() with only one element as an argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        parent.appendChild(child);
+        child.before(x, 'text');
+        var expected = '<x></x>text' + innerHTML;
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.before() with one element and text as arguments.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.before('text', child);
+        var expected = 'text' + innerHTML;
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.before() with context object itself as the argument.');
+
+    test(function() {
+        var parent = document.createElement('div')
+        var x = document.createElement('x');
+        parent.appendChild(child);
+        parent.appendChild(x);
+        child.before(x, child);
+        var expected = '<x></x>' + innerHTML;
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.before() with context object itself and node as the arguments, switching positions.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        var z = document.createElement('z');
+        parent.appendChild(y);
+        parent.appendChild(child);
+        parent.appendChild(x);
+        child.before(x, y, z);
+        var expected = '<x></x><y></y><z></z>' + innerHTML;
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.before() with all siblings of child as arguments.');
+
+    test(function() {
+        var parent = document.createElement('div')
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        var z = document.createElement('z');
+        parent.appendChild(x);
+        parent.appendChild(y);
+        parent.appendChild(z);
+        parent.appendChild(child);
+        child.before(y, z);
+        var expected = '<x></x><y></y><z></z>' + innerHTML;
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.before() with some siblings of child as arguments; no changes in tree; viable sibling is first child.');
+
+    test(function() {
+        var parent = document.createElement('div')
+        var v = document.createElement('v');
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        var z = document.createElement('z');
+        parent.appendChild(v);
+        parent.appendChild(x);
+        parent.appendChild(y);
+        parent.appendChild(z);
+        parent.appendChild(child);
+        child.before(y, z);
+        var expected = '<v></v><x></x><y></y><z></z>' + innerHTML;
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.before() with some siblings of child as arguments; no changes in tree.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        parent.appendChild(x);
+        parent.appendChild(y);
+        parent.appendChild(child);
+        child.before(y, x);
+        var expected = '<y></y><x></x>' + innerHTML;
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.before() when pre-insert behaves like prepend.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        parent.appendChild(x);
+        parent.appendChild(document.createTextNode('1'));
+        var y = document.createElement('y');
+        parent.appendChild(y);
+        parent.appendChild(child);
+        child.before(x, '2');
+        var expected = '1<y></y><x></x>2' + innerHTML;
+        assert_equals(parent.innerHTML, expected);
+    }, nodeName + '.before() with one sibling of child and text as arguments.');
+
+    test(function() {
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        x.before(y);
+        assert_equals(x.previousSibling, null);
+    }, nodeName + '.before() on a child without any parent.');
+}
+
+test_before(document.createComment('test'), 'Comment', '<!--test-->');
+test_before(document.createElement('test'), 'Element', '<test></test>');
+test_before(document.createTextNode('test'), 'Text', 'test');
+
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-remove.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-remove.js
new file mode 100644
index 0000000..c36ba0d1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-remove.js
@@ -0,0 +1,30 @@
+function testRemove(node, parent, type) {
+  test(function() {
+    assert_true("remove" in node);
+    assert_equals(typeof node.remove, "function");
+    assert_equals(node.remove.length, 0);
+  }, type + " should support remove()");
+  test(function() {
+    assert_equals(node.parentNode, null, "Node should not have a parent");
+    assert_equals(node.remove(), undefined);
+    assert_equals(node.parentNode, null, "Removed new node should not have a parent");
+  }, "remove() should work if " + type + " doesn't have a parent");
+  test(function() {
+    assert_equals(node.parentNode, null, "Node should not have a parent");
+    parent.appendChild(node);
+    assert_equals(node.parentNode, parent, "Appended node should have a parent");
+    assert_equals(node.remove(), undefined);
+    assert_equals(node.parentNode, null, "Removed node should not have a parent");
+    assert_array_equals(parent.childNodes, [], "Parent should not have children");
+  }, "remove() should work if " + type + " does have a parent");
+  test(function() {
+    assert_equals(node.parentNode, null, "Node should not have a parent");
+    var before = parent.appendChild(document.createComment("before"));
+    parent.appendChild(node);
+    var after = parent.appendChild(document.createComment("after"));
+    assert_equals(node.parentNode, parent, "Appended node should have a parent");
+    assert_equals(node.remove(), undefined);
+    assert_equals(node.parentNode, null, "Removed node should not have a parent");
+    assert_array_equals(parent.childNodes, [before, after], "Parent should have two children left");
+  }, "remove() should work if " + type + " does have a parent and siblings");
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-replaceWith-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-replaceWith-expected.txt
new file mode 100644
index 0000000..47ec75e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-replaceWith-expected.txt
@@ -0,0 +1,36 @@
+This is a testharness.js-based test.
+FAIL Comment.replaceWith() without any argument. child.replaceWith is not a function
+FAIL Comment.replaceWith() with null as an argument. child.replaceWith is not a function
+FAIL Comment.replaceWith() with undefined as an argument. child.replaceWith is not a function
+FAIL Comment.replaceWith() with empty string as an argument. child.replaceWith is not a function
+FAIL Comment.replaceWith() with only text as an argument. child.replaceWith is not a function
+FAIL Comment.replaceWith() with only one element as an argument. child.replaceWith is not a function
+FAIL Comment.replaceWith() with sibling of child as arguments. child.replaceWith is not a function
+FAIL Comment.replaceWith() with one sibling of child and text as arguments. child.replaceWith is not a function
+FAIL Comment.replaceWith() with one sibling of child and child itself as arguments. child.replaceWith is not a function
+FAIL Comment.replaceWith() with one element and text as arguments. child.replaceWith is not a function
+FAIL Comment.replaceWith() on a parentless child with two elements as arguments. child.replaceWith is not a function
+FAIL Element.replaceWith() without any argument. child.replaceWith is not a function
+FAIL Element.replaceWith() with null as an argument. child.replaceWith is not a function
+FAIL Element.replaceWith() with undefined as an argument. child.replaceWith is not a function
+FAIL Element.replaceWith() with empty string as an argument. child.replaceWith is not a function
+FAIL Element.replaceWith() with only text as an argument. child.replaceWith is not a function
+FAIL Element.replaceWith() with only one element as an argument. child.replaceWith is not a function
+FAIL Element.replaceWith() with sibling of child as arguments. child.replaceWith is not a function
+FAIL Element.replaceWith() with one sibling of child and text as arguments. child.replaceWith is not a function
+FAIL Element.replaceWith() with one sibling of child and child itself as arguments. child.replaceWith is not a function
+FAIL Element.replaceWith() with one element and text as arguments. child.replaceWith is not a function
+FAIL Element.replaceWith() on a parentless child with two elements as arguments. child.replaceWith is not a function
+FAIL Text.replaceWith() without any argument. child.replaceWith is not a function
+FAIL Text.replaceWith() with null as an argument. child.replaceWith is not a function
+FAIL Text.replaceWith() with undefined as an argument. child.replaceWith is not a function
+FAIL Text.replaceWith() with empty string as an argument. child.replaceWith is not a function
+FAIL Text.replaceWith() with only text as an argument. child.replaceWith is not a function
+FAIL Text.replaceWith() with only one element as an argument. child.replaceWith is not a function
+FAIL Text.replaceWith() with sibling of child as arguments. child.replaceWith is not a function
+FAIL Text.replaceWith() with one sibling of child and text as arguments. child.replaceWith is not a function
+FAIL Text.replaceWith() with one sibling of child and child itself as arguments. child.replaceWith is not a function
+FAIL Text.replaceWith() with one element and text as arguments. child.replaceWith is not a function
+FAIL Text.replaceWith() on a parentless child with two elements as arguments. child.replaceWith is not a function
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-replaceWith.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-replaceWith.html
new file mode 100644
index 0000000..b05a907
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ChildNode-replaceWith.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>ChildNode.replaceWith</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-childnode-replaceWith">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script>
+
+function test_replaceWith(child, nodeName, innerHTML) {
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.replaceWith();
+        assert_equals(parent.innerHTML, '');
+    }, nodeName + '.replaceWith() without any argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.replaceWith(null);
+        assert_equals(parent.innerHTML, 'null');
+    }, nodeName + '.replaceWith() with null as an argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.replaceWith(undefined);
+        assert_equals(parent.innerHTML, 'undefined');
+    }, nodeName + '.replaceWith() with undefined as an argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.replaceWith('');
+        assert_equals(parent.innerHTML, '');
+    }, nodeName + '.replaceWith() with empty string as an argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        parent.appendChild(child);
+        child.replaceWith('text');
+        assert_equals(parent.innerHTML, 'text');
+    }, nodeName + '.replaceWith() with only text as an argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        parent.appendChild(child);
+        child.replaceWith(x);
+        assert_equals(parent.innerHTML, '<x></x>');
+    }, nodeName + '.replaceWith() with only one element as an argument.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        var z = document.createElement('z');
+        parent.appendChild(y);
+        parent.appendChild(child);
+        parent.appendChild(x);
+        child.replaceWith(x, y, z);
+        assert_equals(parent.innerHTML, '<x></x><y></y><z></z>');
+    }, nodeName + '.replaceWith() with sibling of child as arguments.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        parent.appendChild(child);
+        parent.appendChild(x);
+        parent.appendChild(document.createTextNode('1'));
+        child.replaceWith(x, '2');
+        assert_equals(parent.innerHTML, '<x></x>21');
+    }, nodeName + '.replaceWith() with one sibling of child and text as arguments.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        parent.appendChild(child);
+        parent.appendChild(x);
+        parent.appendChild(document.createTextNode('text'));
+        child.replaceWith(x, child);
+        assert_equals(parent.innerHTML, '<x></x>' + innerHTML + 'text');
+    }, nodeName + '.replaceWith() with one sibling of child and child itself as arguments.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        parent.appendChild(child);
+        child.replaceWith(x, 'text');
+        assert_equals(parent.innerHTML, '<x></x>text');
+    }, nodeName + '.replaceWith() with one element and text as arguments.');
+
+    test(function() {
+        var parent = document.createElement('div');
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        parent.appendChild(x);
+        parent.appendChild(y);
+        child.replaceWith(x, y);
+        assert_equals(parent.innerHTML, '<x></x><y></y>');
+    }, nodeName + '.replaceWith() on a parentless child with two elements as arguments.');
+}
+
+test_replaceWith(document.createComment('test'), 'Comment', '<!--test-->');
+test_replaceWith(document.createElement('test'), 'Element', '<test></test>');
+test_replaceWith(document.createTextNode('test'), 'Text', 'test');
+
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Comment-Text-constructor.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Comment-Text-constructor.js
new file mode 100644
index 0000000..360b976
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Comment-Text-constructor.js
@@ -0,0 +1,77 @@
+function test_constructor(ctor) {
+  test(function() {
+    var object = new window[ctor]();
+    assert_equals(Object.getPrototypeOf(object),
+                  window[ctor].prototype, "Prototype chain: " + ctor);
+    assert_equals(Object.getPrototypeOf(Object.getPrototypeOf(object)),
+                  CharacterData.prototype, "Prototype chain: CharacterData");
+    assert_equals(Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(object))),
+                  Node.prototype, "Prototype chain: Node");
+  }, "new " + ctor + "(): prototype chain");
+
+  test(function() {
+    var object = new window[ctor]();
+    assert_true(object instanceof Node, "Should be a Node");
+    assert_true(object instanceof CharacterData, "Should be a CharacterData");
+    assert_true(object instanceof window[ctor], "Should be a " + ctor);
+  }, "new " + ctor + "(): instanceof");
+
+  test(function() {
+    var object = new window[ctor]();
+    assert_equals(object.data, "");
+    assert_equals(object.nodeValue, "");
+    assert_equals(object.ownerDocument, document);
+  }, "new " + ctor + "(): no arguments");
+
+  var arguments = [
+    [undefined, ""],
+    [null, "null"],
+    [42, "42"],
+    ["", ""],
+    ["-", "-"],
+    ["--", "--"],
+    ["-->", "-->"],
+    ["<!--", "<!--"],
+    ["\u0000", "\u0000"],
+    ["\u0000test", "\u0000test"],
+    ["&amp;", "&amp;"],
+  ];
+
+  arguments.forEach(function(a) {
+    var argument = a[0], expected = a[1];
+    test(function() {
+      var object = new window[ctor](argument);
+      assert_equals(object.data, expected);
+      assert_equals(object.nodeValue, expected);
+      assert_equals(object.ownerDocument, document);
+    }, "new " + ctor + "(): " + format_value(argument));
+  });
+
+  test(function() {
+    var called = [];
+    var object = new window[ctor]({
+      toString: function() {
+        called.push("first");
+        return "text";
+      }
+    }, {
+      toString: function() {
+        called.push("second");
+        assert_unreached("Should not look at the second argument.");
+      }
+    });
+    assert_equals(object.data, "text");
+    assert_equals(object.nodeValue, "text");
+    assert_equals(object.ownerDocument, document);
+    assert_array_equals(called, ["first"]);
+  }, "new " + ctor + "(): two arguments")
+
+  async_test("new " + ctor + "() should get the correct ownerDocument across globals").step(function() {
+    var iframe = document.createElement("iframe");
+    iframe.onload = this.step_func_done(function() {
+      var object = new iframe.contentWindow[ctor]();
+      assert_equals(object.ownerDocument, iframe.contentDocument);
+    });
+    document.body.appendChild(iframe);
+  });
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Comment-constructor.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Comment-constructor.html
new file mode 100644
index 0000000..dbef4010
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Comment-constructor.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Comment constructor</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-comment">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="Comment-Text-constructor.js"></script>
+<div id="log"></div>
+<script>
+test_constructor("Comment");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createDocument-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createDocument-expected.txt
new file mode 100644
index 0000000..107599c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createDocument-expected.txt
@@ -0,0 +1,341 @@
+This is a testharness.js-based test.
+PASS DOMImplementation.createDocument(namespace, qualifiedName, doctype) 
+PASS createDocument test 0: null,undefined,null,null 
+FAIL createDocument test 0: metadata for null,undefined,null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 0: characterSet aliases for null,undefined,null 
+PASS createDocument test 1: null,"foo",null,null 
+FAIL createDocument test 1: metadata for null,"foo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 1: characterSet aliases for null,"foo",null 
+PASS createDocument test 2: null,"1foo",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 3: null,"f1oo",null,null 
+FAIL createDocument test 3: metadata for null,"f1oo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 3: characterSet aliases for null,"f1oo",null 
+PASS createDocument test 4: null,"foo1",null,null 
+FAIL createDocument test 4: metadata for null,"foo1",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 4: characterSet aliases for null,"foo1",null 
+PASS createDocument test 5: null,"1foo",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 6: null,"̀foo",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 7: null,"}foo",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 8: null,"f}oo",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 9: null,"foo}",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 10: null,"￿foo",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 11: null,"f￿oo",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 12: null,"foo￿",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 13: null,"<foo",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 14: null,"foo>",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 15: null,"<foo>",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 16: null,"f<oo",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 17: null,"^^",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 18: null,":foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 19: null,"f:oo",null,"NAMESPACE_ERR" 
+PASS createDocument test 20: null,"foo:",null,"NAMESPACE_ERR" 
+PASS createDocument test 21: null,":",null,"NAMESPACE_ERR" 
+PASS createDocument test 22: null,"xml",null,null 
+FAIL createDocument test 22: metadata for null,"xml",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 22: characterSet aliases for null,"xml",null 
+PASS createDocument test 23: null,"xmlns",null,"NAMESPACE_ERR" 
+PASS createDocument test 24: null,"xmlfoo",null,null 
+FAIL createDocument test 24: metadata for null,"xmlfoo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 24: characterSet aliases for null,"xmlfoo",null 
+PASS createDocument test 25: null,"xml:foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 26: null,"xmlns:foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 27: null,"xmlfoo:bar",null,"NAMESPACE_ERR" 
+PASS createDocument test 28: null,"null:xml",null,"NAMESPACE_ERR" 
+PASS createDocument test 29: "",":foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 30: "","f:oo",null,"NAMESPACE_ERR" 
+PASS createDocument test 31: "","foo:",null,"NAMESPACE_ERR" 
+FAIL createDocument test 32: undefined,undefined,null,null assert_equals: expected (object) null but got (string) "undefined"
+FAIL createDocument test 32: metadata for undefined,undefined,null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 32: characterSet aliases for undefined,undefined,null 
+FAIL createDocument test 33: undefined,"foo",null,null assert_equals: expected (object) null but got (string) "undefined"
+FAIL createDocument test 33: metadata for undefined,"foo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 33: characterSet aliases for undefined,"foo",null 
+PASS createDocument test 34: undefined,"1foo",null,"INVALID_CHARACTER_ERR" 
+FAIL createDocument test 35: undefined,"f1oo",null,null assert_equals: expected (object) null but got (string) "undefined"
+FAIL createDocument test 35: metadata for undefined,"f1oo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 35: characterSet aliases for undefined,"f1oo",null 
+FAIL createDocument test 36: undefined,"foo1",null,null assert_equals: expected (object) null but got (string) "undefined"
+FAIL createDocument test 36: metadata for undefined,"foo1",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 36: characterSet aliases for undefined,"foo1",null 
+PASS createDocument test 37: undefined,":foo",null,"NAMESPACE_ERR" 
+FAIL createDocument test 38: undefined,"f:oo",null,"NAMESPACE_ERR" assert_throws: function "function () { document.implementation.createDocument(name..." did not throw
+PASS createDocument test 39: undefined,"foo:",null,"NAMESPACE_ERR" 
+FAIL createDocument test 40: undefined,"xml",null,null assert_equals: expected (object) null but got (string) "undefined"
+FAIL createDocument test 40: metadata for undefined,"xml",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 40: characterSet aliases for undefined,"xml",null 
+PASS createDocument test 41: undefined,"xmlns",null,"NAMESPACE_ERR" 
+FAIL createDocument test 42: undefined,"xmlfoo",null,null assert_equals: expected (object) null but got (string) "undefined"
+FAIL createDocument test 42: metadata for undefined,"xmlfoo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 42: characterSet aliases for undefined,"xmlfoo",null 
+PASS createDocument test 43: undefined,"xml:foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 44: undefined,"xmlns:foo",null,"NAMESPACE_ERR" 
+FAIL createDocument test 45: undefined,"xmlfoo:bar",null,"NAMESPACE_ERR" assert_throws: function "function () { document.implementation.createDocument(name..." did not throw
+PASS createDocument test 46: "http://example.com/","foo",null,null 
+FAIL createDocument test 46: metadata for "http://example.com/","foo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 46: characterSet aliases for "http://example.com/","foo",null 
+PASS createDocument test 47: "http://example.com/","1foo",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 48: "http://example.com/","f1oo",null,null 
+FAIL createDocument test 48: metadata for "http://example.com/","f1oo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 48: characterSet aliases for "http://example.com/","f1oo",null 
+PASS createDocument test 49: "http://example.com/","foo1",null,null 
+FAIL createDocument test 49: metadata for "http://example.com/","foo1",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 49: characterSet aliases for "http://example.com/","foo1",null 
+PASS createDocument test 50: "http://example.com/",":foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 51: "http://example.com/","f:oo",null,null 
+FAIL createDocument test 51: metadata for "http://example.com/","f:oo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 51: characterSet aliases for "http://example.com/","f:oo",null 
+PASS createDocument test 52: "http://example.com/","foo:",null,"NAMESPACE_ERR" 
+PASS createDocument test 53: "http://example.com/","_:_",null,null 
+FAIL createDocument test 53: metadata for "http://example.com/","_:_",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 53: characterSet aliases for "http://example.com/","_:_",null 
+PASS createDocument test 54: "http://example.com/","_:h0",null,null 
+FAIL createDocument test 54: metadata for "http://example.com/","_:h0",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 54: characterSet aliases for "http://example.com/","_:h0",null 
+PASS createDocument test 55: "http://example.com/","_:test",null,null 
+FAIL createDocument test 55: metadata for "http://example.com/","_:test",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 55: characterSet aliases for "http://example.com/","_:test",null 
+PASS createDocument test 56: "http://example.com/","l_:_",null,null 
+FAIL createDocument test 56: metadata for "http://example.com/","l_:_",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 56: characterSet aliases for "http://example.com/","l_:_",null 
+PASS createDocument test 57: "http://example.com/","ns:_0",null,null 
+FAIL createDocument test 57: metadata for "http://example.com/","ns:_0",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 57: characterSet aliases for "http://example.com/","ns:_0",null 
+PASS createDocument test 58: "http://example.com/","ns:a0",null,null 
+FAIL createDocument test 58: metadata for "http://example.com/","ns:a0",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 58: characterSet aliases for "http://example.com/","ns:a0",null 
+PASS createDocument test 59: "http://example.com/","ns0:test",null,null 
+FAIL createDocument test 59: metadata for "http://example.com/","ns0:test",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 59: characterSet aliases for "http://example.com/","ns0:test",null 
+PASS createDocument test 60: "http://example.com/","a.b:c",null,null 
+FAIL createDocument test 60: metadata for "http://example.com/","a.b:c",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 60: characterSet aliases for "http://example.com/","a.b:c",null 
+PASS createDocument test 61: "http://example.com/","a-b:c",null,null 
+FAIL createDocument test 61: metadata for "http://example.com/","a-b:c",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 61: characterSet aliases for "http://example.com/","a-b:c",null 
+PASS createDocument test 62: "http://example.com/","a-b:c",null,null 
+FAIL createDocument test 62: metadata for "http://example.com/","a-b:c",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 62: characterSet aliases for "http://example.com/","a-b:c",null 
+PASS createDocument test 63: "http://example.com/","xml",null,null 
+FAIL createDocument test 63: metadata for "http://example.com/","xml",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 63: characterSet aliases for "http://example.com/","xml",null 
+PASS createDocument test 64: "http://example.com/","xmlns",null,"NAMESPACE_ERR" 
+PASS createDocument test 65: "http://example.com/","XMLNS",null,null 
+FAIL createDocument test 65: metadata for "http://example.com/","XMLNS",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 65: characterSet aliases for "http://example.com/","XMLNS",null 
+PASS createDocument test 66: "http://example.com/","xmlfoo",null,null 
+FAIL createDocument test 66: metadata for "http://example.com/","xmlfoo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 66: characterSet aliases for "http://example.com/","xmlfoo",null 
+PASS createDocument test 67: "http://example.com/","xml:foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 68: "http://example.com/","XML:foo",null,null 
+FAIL createDocument test 68: metadata for "http://example.com/","XML:foo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 68: characterSet aliases for "http://example.com/","XML:foo",null 
+PASS createDocument test 69: "http://example.com/","xmlns:foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 70: "http://example.com/","XMLNS:foo",null,null 
+FAIL createDocument test 70: metadata for "http://example.com/","XMLNS:foo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 70: characterSet aliases for "http://example.com/","XMLNS:foo",null 
+PASS createDocument test 71: "http://example.com/","xmlfoo:bar",null,null 
+FAIL createDocument test 71: metadata for "http://example.com/","xmlfoo:bar",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 71: characterSet aliases for "http://example.com/","xmlfoo:bar",null 
+PASS createDocument test 72: "http://example.com/","prefix::local",null,"NAMESPACE_ERR" 
+PASS createDocument test 73: "http://example.com/","namespaceURI:{",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 74: "http://example.com/","namespaceURI:}",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 75: "http://example.com/","namespaceURI:~",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 76: "http://example.com/","namespaceURI:'",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 77: "http://example.com/","namespaceURI:!",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 78: "http://example.com/","namespaceURI:@",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 79: "http://example.com/","namespaceURI:#",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 80: "http://example.com/","namespaceURI:$",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 81: "http://example.com/","namespaceURI:%",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 82: "http://example.com/","namespaceURI:^",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 83: "http://example.com/","namespaceURI:&",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 84: "http://example.com/","namespaceURI:*",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 85: "http://example.com/","namespaceURI:(",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 86: "http://example.com/","namespaceURI:)",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 87: "http://example.com/","namespaceURI:+",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 88: "http://example.com/","namespaceURI:=",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 89: "http://example.com/","namespaceURI:[",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 90: "http://example.com/","namespaceURI:]",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 91: "http://example.com/","namespaceURI:\\",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 92: "http://example.com/","namespaceURI:/",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 93: "http://example.com/","namespaceURI:;",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 94: "http://example.com/","namespaceURI:`",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 95: "http://example.com/","namespaceURI:<",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 96: "http://example.com/","namespaceURI:>",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 97: "http://example.com/","namespaceURI:,",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 98: "http://example.com/","namespaceURI:a ",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 99: "http://example.com/","namespaceURI:\"",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 100: "/","foo",null,null 
+FAIL createDocument test 100: metadata for "/","foo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 100: characterSet aliases for "/","foo",null 
+PASS createDocument test 101: "/","1foo",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 102: "/","f1oo",null,null 
+FAIL createDocument test 102: metadata for "/","f1oo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 102: characterSet aliases for "/","f1oo",null 
+PASS createDocument test 103: "/","foo1",null,null 
+FAIL createDocument test 103: metadata for "/","foo1",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 103: characterSet aliases for "/","foo1",null 
+PASS createDocument test 104: "/",":foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 105: "/","f:oo",null,null 
+FAIL createDocument test 105: metadata for "/","f:oo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 105: characterSet aliases for "/","f:oo",null 
+PASS createDocument test 106: "/","foo:",null,"NAMESPACE_ERR" 
+PASS createDocument test 107: "/","xml",null,null 
+FAIL createDocument test 107: metadata for "/","xml",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 107: characterSet aliases for "/","xml",null 
+PASS createDocument test 108: "/","xmlns",null,"NAMESPACE_ERR" 
+PASS createDocument test 109: "/","xmlfoo",null,null 
+FAIL createDocument test 109: metadata for "/","xmlfoo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 109: characterSet aliases for "/","xmlfoo",null 
+PASS createDocument test 110: "/","xml:foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 111: "/","xmlns:foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 112: "/","xmlfoo:bar",null,null 
+FAIL createDocument test 112: metadata for "/","xmlfoo:bar",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 112: characterSet aliases for "/","xmlfoo:bar",null 
+PASS createDocument test 113: "http://www.w3.org/XML/1998/namespace","foo",null,null 
+FAIL createDocument test 113: metadata for "http://www.w3.org/XML/1998/namespace","foo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 113: characterSet aliases for "http://www.w3.org/XML/1998/namespace","foo",null 
+PASS createDocument test 114: "http://www.w3.org/XML/1998/namespace","1foo",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 115: "http://www.w3.org/XML/1998/namespace","f1oo",null,null 
+FAIL createDocument test 115: metadata for "http://www.w3.org/XML/1998/namespace","f1oo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 115: characterSet aliases for "http://www.w3.org/XML/1998/namespace","f1oo",null 
+PASS createDocument test 116: "http://www.w3.org/XML/1998/namespace","foo1",null,null 
+FAIL createDocument test 116: metadata for "http://www.w3.org/XML/1998/namespace","foo1",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 116: characterSet aliases for "http://www.w3.org/XML/1998/namespace","foo1",null 
+PASS createDocument test 117: "http://www.w3.org/XML/1998/namespace",":foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 118: "http://www.w3.org/XML/1998/namespace","f:oo",null,null 
+FAIL createDocument test 118: metadata for "http://www.w3.org/XML/1998/namespace","f:oo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 118: characterSet aliases for "http://www.w3.org/XML/1998/namespace","f:oo",null 
+PASS createDocument test 119: "http://www.w3.org/XML/1998/namespace","foo:",null,"NAMESPACE_ERR" 
+PASS createDocument test 120: "http://www.w3.org/XML/1998/namespace","xml",null,null 
+FAIL createDocument test 120: metadata for "http://www.w3.org/XML/1998/namespace","xml",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 120: characterSet aliases for "http://www.w3.org/XML/1998/namespace","xml",null 
+PASS createDocument test 121: "http://www.w3.org/XML/1998/namespace","xmlns",null,"NAMESPACE_ERR" 
+PASS createDocument test 122: "http://www.w3.org/XML/1998/namespace","xmlfoo",null,null 
+FAIL createDocument test 122: metadata for "http://www.w3.org/XML/1998/namespace","xmlfoo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 122: characterSet aliases for "http://www.w3.org/XML/1998/namespace","xmlfoo",null 
+PASS createDocument test 123: "http://www.w3.org/XML/1998/namespace","xml:foo",null,null 
+FAIL createDocument test 123: metadata for "http://www.w3.org/XML/1998/namespace","xml:foo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 123: characterSet aliases for "http://www.w3.org/XML/1998/namespace","xml:foo",null 
+PASS createDocument test 124: "http://www.w3.org/XML/1998/namespace","xmlns:foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 125: "http://www.w3.org/XML/1998/namespace","xmlfoo:bar",null,null 
+FAIL createDocument test 125: metadata for "http://www.w3.org/XML/1998/namespace","xmlfoo:bar",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 125: characterSet aliases for "http://www.w3.org/XML/1998/namespace","xmlfoo:bar",null 
+PASS createDocument test 126: "http://www.w3.org/XML/1998/namespaces","xml:foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 127: "http://www.w3.org/xml/1998/namespace","xml:foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 128: "http://www.w3.org/2000/xmlns/","foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 129: "http://www.w3.org/2000/xmlns/","1foo",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 130: "http://www.w3.org/2000/xmlns/","f1oo",null,"NAMESPACE_ERR" 
+PASS createDocument test 131: "http://www.w3.org/2000/xmlns/","foo1",null,"NAMESPACE_ERR" 
+PASS createDocument test 132: "http://www.w3.org/2000/xmlns/",":foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 133: "http://www.w3.org/2000/xmlns/","f:oo",null,"NAMESPACE_ERR" 
+PASS createDocument test 134: "http://www.w3.org/2000/xmlns/","foo:",null,"NAMESPACE_ERR" 
+PASS createDocument test 135: "http://www.w3.org/2000/xmlns/","xml",null,"NAMESPACE_ERR" 
+PASS createDocument test 136: "http://www.w3.org/2000/xmlns/","xmlns",null,null 
+FAIL createDocument test 136: metadata for "http://www.w3.org/2000/xmlns/","xmlns",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 136: characterSet aliases for "http://www.w3.org/2000/xmlns/","xmlns",null 
+PASS createDocument test 137: "http://www.w3.org/2000/xmlns/","xmlfoo",null,"NAMESPACE_ERR" 
+PASS createDocument test 138: "http://www.w3.org/2000/xmlns/","xml:foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 139: "http://www.w3.org/2000/xmlns/","xmlns:foo",null,null 
+FAIL createDocument test 139: metadata for "http://www.w3.org/2000/xmlns/","xmlns:foo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 139: characterSet aliases for "http://www.w3.org/2000/xmlns/","xmlns:foo",null 
+PASS createDocument test 140: "http://www.w3.org/2000/xmlns/","xmlfoo:bar",null,"NAMESPACE_ERR" 
+PASS createDocument test 141: "http://www.w3.org/2000/xmlns/","foo:xmlns",null,"NAMESPACE_ERR" 
+PASS createDocument test 142: "foo:","foo",null,null 
+FAIL createDocument test 142: metadata for "foo:","foo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 142: characterSet aliases for "foo:","foo",null 
+PASS createDocument test 143: "foo:","1foo",null,"INVALID_CHARACTER_ERR" 
+PASS createDocument test 144: "foo:","f1oo",null,null 
+FAIL createDocument test 144: metadata for "foo:","f1oo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 144: characterSet aliases for "foo:","f1oo",null 
+PASS createDocument test 145: "foo:","foo1",null,null 
+FAIL createDocument test 145: metadata for "foo:","foo1",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 145: characterSet aliases for "foo:","foo1",null 
+PASS createDocument test 146: "foo:",":foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 147: "foo:","f:oo",null,null 
+FAIL createDocument test 147: metadata for "foo:","f:oo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 147: characterSet aliases for "foo:","f:oo",null 
+PASS createDocument test 148: "foo:","foo:",null,"NAMESPACE_ERR" 
+PASS createDocument test 149: "foo:","xml",null,null 
+FAIL createDocument test 149: metadata for "foo:","xml",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 149: characterSet aliases for "foo:","xml",null 
+PASS createDocument test 150: "foo:","xmlns",null,"NAMESPACE_ERR" 
+PASS createDocument test 151: "foo:","xmlfoo",null,null 
+FAIL createDocument test 151: metadata for "foo:","xmlfoo",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 151: characterSet aliases for "foo:","xmlfoo",null 
+PASS createDocument test 152: "foo:","xml:foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 153: "foo:","xmlns:foo",null,"NAMESPACE_ERR" 
+PASS createDocument test 154: "foo:","xmlfoo:bar",null,null 
+FAIL createDocument test 154: metadata for "foo:","xmlfoo:bar",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 154: characterSet aliases for "foo:","xmlfoo:bar",null 
+PASS createDocument test 155: null,null,false,object "TypeError" 
+PASS createDocument test 156: null,null,null,null 
+FAIL createDocument test 156: metadata for null,null,null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 156: characterSet aliases for null,null,null 
+PASS createDocument test 157: null,"",null,null 
+FAIL createDocument test 157: metadata for null,"",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 157: characterSet aliases for null,"",null 
+PASS createDocument test 158: undefined,null,undefined,null 
+FAIL createDocument test 158: metadata for undefined,null,undefined assert_equals: expected "about:blank" but got ""
+PASS createDocument test 158: characterSet aliases for undefined,null,undefined 
+FAIL createDocument test 159: undefined,undefined,undefined,null assert_equals: expected (object) null but got (string) "undefined"
+FAIL createDocument test 159: metadata for undefined,undefined,undefined assert_equals: expected "about:blank" but got ""
+PASS createDocument test 159: characterSet aliases for undefined,undefined,undefined 
+PASS createDocument test 160: undefined,"",undefined,null 
+FAIL createDocument test 160: metadata for undefined,"",undefined assert_equals: expected "about:blank" but got ""
+PASS createDocument test 160: characterSet aliases for undefined,"",undefined 
+PASS createDocument test 161: "http://example.com/",null,null,null 
+FAIL createDocument test 161: metadata for "http://example.com/",null,null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 161: characterSet aliases for "http://example.com/",null,null 
+PASS createDocument test 162: "http://example.com/","",null,null 
+FAIL createDocument test 162: metadata for "http://example.com/","",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 162: characterSet aliases for "http://example.com/","",null 
+PASS createDocument test 163: "/",null,null,null 
+FAIL createDocument test 163: metadata for "/",null,null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 163: characterSet aliases for "/",null,null 
+PASS createDocument test 164: "/","",null,null 
+FAIL createDocument test 164: metadata for "/","",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 164: characterSet aliases for "/","",null 
+PASS createDocument test 165: "http://www.w3.org/XML/1998/namespace",null,null,null 
+FAIL createDocument test 165: metadata for "http://www.w3.org/XML/1998/namespace",null,null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 165: characterSet aliases for "http://www.w3.org/XML/1998/namespace",null,null 
+PASS createDocument test 166: "http://www.w3.org/XML/1998/namespace","",null,null 
+FAIL createDocument test 166: metadata for "http://www.w3.org/XML/1998/namespace","",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 166: characterSet aliases for "http://www.w3.org/XML/1998/namespace","",null 
+PASS createDocument test 167: "http://www.w3.org/2000/xmlns/",null,null,null 
+FAIL createDocument test 167: metadata for "http://www.w3.org/2000/xmlns/",null,null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 167: characterSet aliases for "http://www.w3.org/2000/xmlns/",null,null 
+PASS createDocument test 168: "http://www.w3.org/2000/xmlns/","",null,null 
+FAIL createDocument test 168: metadata for "http://www.w3.org/2000/xmlns/","",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 168: characterSet aliases for "http://www.w3.org/2000/xmlns/","",null 
+PASS createDocument test 169: "foo:",null,null,null 
+FAIL createDocument test 169: metadata for "foo:",null,null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 169: characterSet aliases for "foo:",null,null 
+PASS createDocument test 170: "foo:","",null,null 
+FAIL createDocument test 170: metadata for "foo:","",null assert_equals: expected "about:blank" but got ""
+PASS createDocument test 170: characterSet aliases for "foo:","",null 
+PASS createDocument test 171: null,null,DocumentType node,null 
+FAIL createDocument test 171: metadata for null,null,DocumentType node assert_equals: expected "about:blank" but got ""
+PASS createDocument test 171: characterSet aliases for null,null,DocumentType node 
+PASS createDocument test 172: null,null,DocumentType node,null 
+FAIL createDocument test 172: metadata for null,null,DocumentType node assert_equals: expected "about:blank" but got ""
+PASS createDocument test 172: characterSet aliases for null,null,DocumentType node 
+PASS createDocument test 173: null,null,DocumentType node,null 
+FAIL createDocument test 173: metadata for null,null,DocumentType node assert_equals: expected "about:blank" but got ""
+PASS createDocument test 173: characterSet aliases for null,null,DocumentType node 
+PASS createDocument test 174: null,null,DocumentType node,null 
+FAIL createDocument test 174: metadata for null,null,DocumentType node assert_equals: expected "about:blank" but got ""
+PASS createDocument test 174: characterSet aliases for null,null,DocumentType node 
+PASS createDocument test 175: null,null,DocumentType node,null 
+FAIL createDocument test 175: metadata for null,null,DocumentType node assert_equals: expected "about:blank" but got ""
+PASS createDocument test 175: characterSet aliases for null,null,DocumentType node 
+PASS createDocument test 176: null,"foo",DocumentType node,null 
+FAIL createDocument test 176: metadata for null,"foo",DocumentType node assert_equals: expected "about:blank" but got ""
+PASS createDocument test 176: characterSet aliases for null,"foo",DocumentType node 
+PASS createDocument test 177: "foo",null,DocumentType node,null 
+FAIL createDocument test 177: metadata for "foo",null,DocumentType node assert_equals: expected "about:blank" but got ""
+PASS createDocument test 177: characterSet aliases for "foo",null,DocumentType node 
+PASS createDocument test 178: "foo","bar",DocumentType node,null 
+FAIL createDocument test 178: metadata for "foo","bar",DocumentType node assert_equals: expected "about:blank" but got ""
+PASS createDocument test 178: characterSet aliases for "foo","bar",DocumentType node 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createDocument.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createDocument.html
new file mode 100644
index 0000000..3a888882
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createDocument.html
@@ -0,0 +1,123 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>DOMImplementation.createDocument(namespace, qualifiedName, doctype)</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-domimplementation-createdocument">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelementns">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodetype">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-documentelement">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-doctype">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="Document-createElementNS.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var tests = createElementNS_tests.map(function(t) {
+    return [t[0], t[1], null, t[2]]
+  }).concat([
+    /* Arrays with four elements:
+     *   the namespace argument
+     *   the qualifiedName argument
+     *   the doctype argument
+     *   the expected exception, or null if none
+     */
+    [null, null, false, new TypeError()],
+    [null, null, null, null],
+    [null, "", null, null],
+    [undefined, null, undefined, null],
+    [undefined, undefined, undefined, null],
+    [undefined, "", undefined, null],
+    ["http://example.com/", null, null, null],
+    ["http://example.com/", "", null, null],
+    ["/", null, null, null],
+    ["/", "", null, null],
+    ["http://www.w3.org/XML/1998/namespace", null, null, null],
+    ["http://www.w3.org/XML/1998/namespace", "", null, null],
+    ["http://www.w3.org/2000/xmlns/", null, null, null],
+    ["http://www.w3.org/2000/xmlns/", "", null, null],
+    ["foo:", null, null, null],
+    ["foo:", "", null, null],
+    [null, null, document.implementation.createDocumentType("foo", "", ""), null],
+    [null, null, document.doctype, null], // This causes a horrible WebKit bug (now fixed in trunk).
+    [null, null, function() {
+        var foo = document.implementation.createDocumentType("foo", "", "");
+        document.implementation.createDocument(null, null, foo);
+        return foo;
+     }(), null], // DOCTYPE already associated with a document.
+    [null, null, function() {
+        var bar = document.implementation.createDocument(null, null, null);
+        return bar.implementation.createDocumentType("bar", "", "");
+     }(), null], // DOCTYPE created by a different implementation.
+    [null, null, function() {
+        var bar = document.implementation.createDocument(null, null, null);
+        var magic = bar.implementation.createDocumentType("bar", "", "");
+        bar.implementation.createDocument(null, null, magic);
+        return magic;
+     }(), null], // DOCTYPE created by a different implementation and already associated with a document.
+    [null, "foo", document.implementation.createDocumentType("foo", "", ""), null],
+    ["foo", null, document.implementation.createDocumentType("foo", "", ""), null],
+    ["foo", "bar", document.implementation.createDocumentType("foo", "", ""), null],
+  ])
+
+  tests.forEach(function(t, i) {
+    var namespace = t[0], qualifiedName = t[1], doctype = t[2], expected = t[3]
+    test(function() {
+      if (expected != null) {
+        assert_throws(expected, function() { document.implementation.createDocument(namespace, qualifiedName, doctype) })
+      } else {
+        var doc = document.implementation.createDocument(namespace, qualifiedName, doctype)
+        assert_equals(doc.nodeType, Node.DOCUMENT_NODE)
+        assert_equals(doc.nodeType, doc.DOCUMENT_NODE)
+        assert_equals(doc.nodeName, "#document")
+        assert_equals(doc.nodeValue, null)
+        var omitRootElement = qualifiedName === null || String(qualifiedName) === ""
+        if (omitRootElement) {
+          assert_equals(doc.documentElement, null)
+        } else {
+          var element = doc.documentElement
+          assert_not_equals(element, null)
+          assert_equals(element.nodeType, Node.ELEMENT_NODE)
+          assert_equals(element.ownerDocument, doc)
+          var qualified = String(qualifiedName), names = []
+          if (qualified.indexOf(":") >= 0) {
+            names = qualified.split(":", 2)
+          } else {
+            names = [null, qualified]
+          }
+          assert_equals(element.prefix, names[0])
+          assert_equals(element.localName, names[1])
+          assert_equals(element.namespaceURI, namespace === undefined ? null : namespace)
+        }
+        if (!doctype) {
+          assert_equals(doc.doctype, null)
+        } else {
+          assert_equals(doc.doctype, doctype)
+          assert_equals(doc.doctype.ownerDocument, doc)
+        }
+        assert_equals(doc.childNodes.length, !omitRootElement + !!doctype)
+      }
+    }, "createDocument test " + i + ": " + t.map(function(el) { return format_value(el) }))
+
+    if (expected === null) {
+      test(function() {
+        var doc = document.implementation.createDocument(namespace, qualifiedName, doctype)
+        assert_equals(doc.compatMode, "CSS1Compat")
+        assert_equals(doc.characterSet, "UTF-8")
+        assert_equals(doc.contentType, "application/xml")
+        assert_equals(doc.URL, "about:blank")
+        assert_equals(doc.documentURI, "about:blank")
+        assert_equals(doc.createElement("DIV").localName, "DIV");
+      }, "createDocument test " + i + ": metadata for " +
+      [namespace, qualifiedName, doctype].map(function(el) { return format_value(el) }))
+
+      test(function() {
+        var doc = document.implementation.createDocument(namespace, qualifiedName, doctype)
+        assert_equals(doc.characterSet, "UTF-8", "characterSet");
+        assert_equals(doc.charset, "UTF-8", "charset");
+        assert_equals(doc.inputEncoding, "UTF-8", "inputEncoding");
+      }, "createDocument test " + i + ": characterSet aliases for " +
+      [namespace, qualifiedName, doctype].map(function(el) { return format_value(el) }))
+    }
+  })
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createDocumentType.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createDocumentType.html
new file mode 100644
index 0000000..4d5a6fc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createDocumentType.html
@@ -0,0 +1,123 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>DOMImplementation.createDocumentType(qualifiedName, publicId, systemId)</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-name">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-publicid">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-systemid">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-ownerdocument">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var tests = [
+    ["", "", "", "INVALID_CHARACTER_ERR"],
+    ["test:root", "1234", "", null],
+    ["test:root", "1234", "test", null],
+    ["test:root", "test", "", null],
+    ["test:root", "test", "test", null],
+    ["_:_", "", "", null],
+    ["_:h0", "", "", null],
+    ["_:test", "", "", null],
+    ["_:_.", "", "", null],
+    ["_:a-", "", "", null],
+    ["l_:_", "", "", null],
+    ["ns:_0", "", "", null],
+    ["ns:a0", "", "", null],
+    ["ns0:test", "", "", null],
+    ["ns:EEE.", "", "", null],
+    ["ns:_-", "", "", null],
+    ["a.b:c", "", "", null],
+    ["a-b:c.j", "", "", null],
+    ["a-b:c", "", "", null],
+    ["foo", "", "", null],
+    ["1foo", "", "", "INVALID_CHARACTER_ERR"],
+    ["foo1", "", "", null],
+    ["f1oo", "", "", null],
+    ["@foo", "", "", "INVALID_CHARACTER_ERR"],
+    ["foo@", "", "", "INVALID_CHARACTER_ERR"],
+    ["f@oo", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:{", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:}", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:~", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:'", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:!", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:@", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:#", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:$", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:%", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:^", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:&", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:*", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:(", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:)", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:+", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:=", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:[", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:]", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:\\", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:/", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:;", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:`", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:<", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:>", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:,", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:a ", "", "", "INVALID_CHARACTER_ERR"],
+    ["edi:\"", "", "", "INVALID_CHARACTER_ERR"],
+    ["{", "", "", "INVALID_CHARACTER_ERR"],
+    ["}", "", "", "INVALID_CHARACTER_ERR"],
+    ["'", "", "", "INVALID_CHARACTER_ERR"],
+    ["~", "", "", "INVALID_CHARACTER_ERR"],
+    ["`", "", "", "INVALID_CHARACTER_ERR"],
+    ["@", "", "", "INVALID_CHARACTER_ERR"],
+    ["#", "", "", "INVALID_CHARACTER_ERR"],
+    ["$", "", "", "INVALID_CHARACTER_ERR"],
+    ["%", "", "", "INVALID_CHARACTER_ERR"],
+    ["^", "", "", "INVALID_CHARACTER_ERR"],
+    ["&", "", "", "INVALID_CHARACTER_ERR"],
+    ["*", "", "", "INVALID_CHARACTER_ERR"],
+    ["(", "", "", "INVALID_CHARACTER_ERR"],
+    [")", "", "", "INVALID_CHARACTER_ERR"],
+    ["f:oo", "", "", null],
+    [":foo", "", "", "NAMESPACE_ERR"],
+    ["foo:", "", "", "NAMESPACE_ERR"],
+    ["prefix::local", "", "", "NAMESPACE_ERR"],
+    ["foo", "foo", "", null],
+    ["foo", "", "foo", null],
+    ["foo", "f'oo", "", null],
+    ["foo", "", "f'oo", null],
+    ["foo", 'f"oo', "", null],
+    ["foo", "", 'f"oo', null],
+    ["foo", "f'o\"o", "", null],
+    ["foo", "", "f'o\"o", null],
+    ["foo", "foo>", "", null],
+    ["foo", "", "foo>", null]
+  ]
+
+  var doc = document.implementation.createHTMLDocument("title");
+  var doTest = function(aDocument, aQualifiedName, aPublicId, aSystemId) {
+    var doctype = aDocument.implementation.createDocumentType(aQualifiedName, aPublicId, aSystemId);
+    assert_equals(doctype.name, aQualifiedName, "name")
+    assert_equals(doctype.nodeName, aQualifiedName, "nodeName")
+    assert_equals(doctype.publicId, aPublicId, "publicId")
+    assert_equals(doctype.systemId, aSystemId, "systemId")
+    assert_equals(doctype.ownerDocument, aDocument, "ownerDocument")
+    assert_equals(doctype.nodeValue, null, "nodeValue")
+  }
+  tests.forEach(function(t) {
+    var qualifiedName = t[0], publicId = t[1], systemId = t[2], expected = t[3]
+    test(function() {
+      if (expected) {
+        assert_throws(expected, function() {
+          document.implementation.createDocumentType(qualifiedName, publicId, systemId)
+        })
+      } else {
+        doTest(document, qualifiedName, publicId, systemId);
+        doTest(doc, qualifiedName, publicId, systemId);
+      }
+    }, "createDocumentType(" + format_value(qualifiedName) + ", " + format_value(publicId) + ", " + format_value(systemId) + ") should " +
+       (expected ? "throw " + expected : "work"));
+  });
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument-expected.txt
new file mode 100644
index 0000000..fb7b8e501c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument-expected.txt
@@ -0,0 +1,15 @@
+This is a testharness.js-based test.
+PASS createHTMLDocument test 0: "","","" 
+PASS createHTMLDocument test 1: null,"null","null" 
+PASS createHTMLDocument test 2: undefined,undefined,"" 
+PASS createHTMLDocument test 3: "foo  bar baz","foo  bar baz","foo bar baz" 
+PASS createHTMLDocument test 4: "foo\t\tbar baz","foo\t\tbar baz","foo bar baz" 
+PASS createHTMLDocument test 5: "foo\n\nbar baz","foo\n\nbar baz","foo bar baz" 
+PASS createHTMLDocument test 6: "foo\f\fbar baz","foo\f\fbar baz","foo bar baz" 
+PASS createHTMLDocument test 7: "foo\r\rbar baz","foo\r\rbar baz","foo bar baz" 
+PASS Missing title argument 
+FAIL createHTMLDocument(): metadata assert_equals: expected "about:blank" but got ""
+PASS createHTMLDocument(): characterSet aliases 
+PASS createHTMLDocument(): URL parsing 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument.html
new file mode 100644
index 0000000..ae0a44e4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<meta charset=windows-1252>
+<!--  Using windows-1252 to ensure that DOMImplementation.createHTMLDocument()
+     doesn't inherit utf-8 from the parent document.  -->
+<title>DOMImplementation.createHTMLDocument</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-name">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-publicid">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-systemid">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-documentelement">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="DOMImplementation-createHTMLDocument.js"></script>
+<div id="log"></div>
+<script>
+createHTMLDocuments(function(doc, expectedtitle, normalizedtitle) {
+  assert_true(doc instanceof Document, "Should be a Document")
+  assert_true(doc instanceof Node, "Should be a Node")
+  assert_equals(doc.childNodes.length, 2,
+                "Document should have two child nodes")
+
+  var doctype = doc.doctype
+  assert_true(doctype instanceof DocumentType,
+              "Doctype should be a DocumentType")
+  assert_true(doctype instanceof Node, "Doctype should be a Node")
+  assert_equals(doctype.name, "html")
+  assert_equals(doctype.publicId, "")
+  assert_equals(doctype.systemId, "")
+
+  var documentElement = doc.documentElement
+  assert_true(documentElement instanceof HTMLHtmlElement,
+              "Document element should be a HTMLHtmlElement")
+  assert_equals(documentElement.childNodes.length, 2,
+                "Document element should have two child nodes")
+  assert_equals(documentElement.localName, "html")
+  assert_equals(documentElement.tagName, "HTML")
+
+  var head = documentElement.firstChild
+  assert_true(head instanceof HTMLHeadElement,
+              "Head should be a HTMLHeadElement")
+  assert_equals(head.localName, "head")
+  assert_equals(head.tagName, "HEAD")
+
+  if (expectedtitle !== undefined) {
+    assert_equals(head.childNodes.length, 1)
+
+    var title = head.firstChild
+    assert_true(title instanceof HTMLTitleElement,
+                "Title should be a HTMLTitleElement")
+    assert_equals(title.localName, "title")
+    assert_equals(title.tagName, "TITLE")
+    assert_equals(title.childNodes.length, 1)
+    assert_equals(title.firstChild.data, expectedtitle)
+  } else {
+    assert_equals(head.childNodes.length, 0)
+  }
+
+  var body = documentElement.lastChild
+  assert_true(body instanceof HTMLBodyElement,
+              "Body should be a HTMLBodyElement")
+  assert_equals(body.localName, "body")
+  assert_equals(body.tagName, "BODY")
+  assert_equals(body.childNodes.length, 0)
+})
+
+test(function() {
+  var doc = document.implementation.createHTMLDocument("test");
+  assert_equals(doc.URL, "about:blank");
+  assert_equals(doc.documentURI, "about:blank");
+  assert_equals(doc.compatMode, "CSS1Compat");
+  assert_equals(doc.characterSet, "UTF-8");
+  assert_equals(doc.contentType, "text/html");
+  assert_equals(doc.createElement("DIV").localName, "div");
+}, "createHTMLDocument(): metadata")
+
+test(function() {
+  var doc = document.implementation.createHTMLDocument("test");
+  assert_equals(doc.characterSet, "UTF-8", "characterSet");
+  assert_equals(doc.charset, "UTF-8", "charset");
+  assert_equals(doc.inputEncoding, "UTF-8", "inputEncoding");
+}, "createHTMLDocument(): characterSet aliases")
+
+test(function() {
+  var doc = document.implementation.createHTMLDocument("test");
+  var a = doc.createElement("a");
+  // In UTF-8: 0xC3 0xA4
+  a.href = "http://example.org/?\u00E4";
+  assert_equals(a.href, "http://example.org/?%C3%A4");
+}, "createHTMLDocument(): URL parsing")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument.js
new file mode 100644
index 0000000..3e7e9aa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument.js
@@ -0,0 +1,25 @@
+function createHTMLDocuments(checkDoc) {
+  var tests = [
+    ["", "", ""],
+    [null, "null", "null"],
+    [undefined, undefined, ""],
+    ["foo  bar baz", "foo  bar baz", "foo bar baz"],
+    ["foo\t\tbar baz", "foo\t\tbar baz", "foo bar baz"],
+    ["foo\n\nbar baz", "foo\n\nbar baz", "foo bar baz"],
+    ["foo\f\fbar baz", "foo\f\fbar baz", "foo bar baz"],
+    ["foo\r\rbar baz", "foo\r\rbar baz", "foo bar baz"],
+  ]
+
+  tests.forEach(function(t, i) {
+    var title = t[0], expectedtitle = t[1], normalizedtitle = t[2]
+    test(function() {
+      var doc = document.implementation.createHTMLDocument(title);
+      checkDoc(doc, expectedtitle, normalizedtitle)
+    }, "createHTMLDocument test " + i + ": " + t.map(function(el) { return format_value(el) }))
+  })
+
+  test(function() {
+    var doc = document.implementation.createHTMLDocument();
+    checkDoc(doc, undefined, "")
+  }, "Missing title argument");
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-hasFeature.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-hasFeature.html
new file mode 100644
index 0000000..ca28b02
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DOMImplementation-hasFeature.html
@@ -0,0 +1,141 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>DOMImplementation.hasFeature(feature, version)</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var tests = [
+        ["Core", "1.0"],
+        ["Core", "2.0"],
+        ["Core", "3.0"],
+        ["Core", "100.0"],
+        ["XML", "1.0"],
+        ["XML", "2.0"],
+        ["XML", "3.0"],
+        ["XML", "100.0"],
+        ["Core", "1"],
+        ["Core", "2"],
+        ["Core", "3"],
+        ["Core", "100"],
+        ["XML", "1"],
+        ["XML", "2"],
+        ["XML", "3"],
+        ["XML", "100"],
+        ["Core", "1.1"],
+        ["Core", "2.1"],
+        ["Core", "3.1"],
+        ["Core", "100.1"],
+        ["XML", "1.1"],
+        ["XML", "2.1"],
+        ["XML", "3.1"],
+        ["XML", "100.1"],
+        ["Core", ""],
+        ["XML", ""],
+        ["core", ""],
+        ["xml", ""],
+        ["CoRe", ""],
+        ["XmL", ""],
+        [" Core", ""],
+        [" XML", ""],
+        ["Core ", ""],
+        ["XML ", ""],
+        ["Co re", ""],
+        ["XM L", ""],
+        ["aCore", ""],
+        ["aXML", ""],
+        ["Corea", ""],
+        ["XMLa", ""],
+        ["Coare", ""],
+        ["XMaL", ""],
+        ["Core", " "],
+        ["XML", " "],
+        ["Core", " 1.0"],
+        ["Core", " 2.0"],
+        ["Core", " 3.0"],
+        ["Core", " 100.0"],
+        ["XML", " 1.0"],
+        ["XML", " 2.0"],
+        ["XML", " 3.0"],
+        ["XML", " 100.0"],
+        ["Core", "1.0 "],
+        ["Core", "2.0 "],
+        ["Core", "3.0 "],
+        ["Core", "100.0 "],
+        ["XML", "1.0 "],
+        ["XML", "2.0 "],
+        ["XML", "3.0 "],
+        ["XML", "100.0 "],
+        ["Core", "1. 0"],
+        ["Core", "2. 0"],
+        ["Core", "3. 0"],
+        ["Core", "100. 0"],
+        ["XML", "1. 0"],
+        ["XML", "2. 0"],
+        ["XML", "3. 0"],
+        ["XML", "100. 0"],
+        ["Core", "a1.0"],
+        ["Core", "a2.0"],
+        ["Core", "a3.0"],
+        ["Core", "a100.0"],
+        ["XML", "a1.0"],
+        ["XML", "a2.0"],
+        ["XML", "a3.0"],
+        ["XML", "a100.0"],
+        ["Core", "1.0a"],
+        ["Core", "2.0a"],
+        ["Core", "3.0a"],
+        ["Core", "100.0a"],
+        ["XML", "1.0a"],
+        ["XML", "2.0a"],
+        ["XML", "3.0a"],
+        ["XML", "100.0a"],
+        ["Core", "1.a0"],
+        ["Core", "2.a0"],
+        ["Core", "3.a0"],
+        ["Core", "100.a0"],
+        ["XML", "1.a0"],
+        ["XML", "2.a0"],
+        ["XML", "3.a0"],
+        ["XML", "100.a0"],
+        ["Core", 1],
+        ["Core", 2],
+        ["Core", 3],
+        ["Core", 100],
+        ["XML", 1],
+        ["XML", 2],
+        ["XML", 3],
+        ["XML", 100],
+        ["Core", null],
+        ["XML", null],
+        ["core", null],
+        ["xml", null],
+        ["CoRe", null],
+        ["XmL", null],
+        [" Core", null],
+        [" XML", null],
+        ["Core ", null],
+        ["XML ", null],
+        ["Co re", null],
+        ["XM L", null],
+        ["aCore", null],
+        ["aXML", null],
+        ["Corea", null],
+        ["XMLa", null],
+        ["Coare", null],
+        ["XMaL", null],
+        ["Core", undefined],
+        ["XML", undefined],
+        ["This is filler text.", ""],
+        [null, ""],
+        [undefined, ""],
+      ];
+  tests.forEach(function(data) {
+    test(function() {
+      assert_equals(document.implementation.hasFeature(data[0], data[1]), true)
+    }, "hasFeature(" + format_value(data[0]) + ", " + format_value(data[1]) + ")")
+  })
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-Element-getElementsByTagName.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-Element-getElementsByTagName.js
new file mode 100644
index 0000000..cc2b736
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-Element-getElementsByTagName.js
@@ -0,0 +1,191 @@
+function test_getElementsByTagName(context, element) {
+  // TODO: getElementsByTagName("*")
+  test(function() {
+    assert_false(context.getElementsByTagName("html") instanceof NodeList,
+                 "Should not return a NodeList")
+    assert_true(context.getElementsByTagName("html") instanceof HTMLCollection,
+                "Should return an HTMLCollection")
+  }, "Interfaces")
+
+  test(function() {
+    var firstCollection = context.getElementsByTagName("html"),
+        secondCollection = context.getElementsByTagName("html")
+    assert_true(firstCollection !== secondCollection ||
+                firstCollection === secondCollection)
+  }, "Caching is allowed")
+
+  test(function() {
+    var l = context.getElementsByTagName("nosuchtag")
+    l[5] = "foopy"
+    assert_equals(l[5], undefined)
+    assert_equals(l.item(5), null)
+  }, "Shouldn't be able to set unsigned properties on a HTMLCollection (non-strict mode)")
+
+  test(function() {
+    var l = context.getElementsByTagName("nosuchtag")
+    assert_throws(new TypeError(), function() {
+      "use strict";
+      l[5] = "foopy"
+    })
+    assert_equals(l[5], undefined)
+    assert_equals(l.item(5), null)
+  }, "Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode)")
+
+  test(function() {
+    var l = context.getElementsByTagName("nosuchtag")
+    var fn = l.item;
+    assert_equals(fn, HTMLCollection.prototype.item);
+    l.item = "pass"
+    assert_equals(l.item, "pass")
+    assert_equals(HTMLCollection.prototype.item, fn);
+  }, "Should be able to set expando shadowing a proto prop (item)")
+
+  test(function() {
+    var l = context.getElementsByTagName("nosuchtag")
+    var fn = l.namedItem;
+    assert_equals(fn, HTMLCollection.prototype.namedItem);
+    l.namedItem = "pass"
+    assert_equals(l.namedItem, "pass")
+    assert_equals(HTMLCollection.prototype.namedItem, fn);
+  }, "Should be able to set expando shadowing a proto prop (namedItem)")
+
+  test(function() {
+    var t1 = element.appendChild(document.createElement("pre"));
+    t1.id = "x";
+    var t2 = element.appendChild(document.createElement("pre"));
+    t2.setAttribute("name", "y");
+    var t3 = element.appendChild(document.createElementNS("", "pre"));
+    t3.setAttribute("id", "z");
+    var t4 = element.appendChild(document.createElementNS("", "pre"));
+    t4.setAttribute("name", "w");
+    this.add_cleanup(function() {
+      element.removeChild(t1)
+      element.removeChild(t2)
+      element.removeChild(t3)
+      element.removeChild(t4)
+    });
+
+    var list = context.getElementsByTagName('pre');
+    var pre = list[0];
+    assert_equals(pre.id, "x");
+
+    var exposedNames = { 'x': 0, 'y': 1, 'z': 2 };
+    for (var exposedName in exposedNames) {
+      assert_equals(list[exposedName], list[exposedNames[exposedName]]);
+      assert_equals(list[exposedName], list.namedItem(exposedName));
+      assert_true(exposedName in list, "'" + exposedName + "' in list");
+      assert_true(list.hasOwnProperty(exposedName),
+                  "list.hasOwnProperty('" + exposedName + "')");
+    }
+
+    var unexposedNames = ["w"];
+    for (var unexposedName of unexposedNames) {
+      assert_false(unexposedName in list);
+      assert_false(list.hasOwnProperty(unexposedName));
+      assert_equals(list[unexposedName], undefined);
+      assert_equals(list.namedItem(unexposedName), null);
+    }
+
+    assert_array_equals(Object.getOwnPropertyNames(list).sort(),
+                        ["0", "1", "2", "3", "x", "y", "z"]);
+
+    var desc = Object.getOwnPropertyDescriptor(list, '0');
+    assert_equals(typeof desc, "object", "descriptor should be an object");
+    assert_true(desc.enumerable, "desc.enumerable");
+    assert_true(desc.configurable, "desc.configurable");
+
+    desc = Object.getOwnPropertyDescriptor(list, 'x');
+    assert_equals(typeof desc, "object", "descriptor should be an object");
+    assert_false(desc.enumerable, "desc.enumerable");
+    assert_true(desc.configurable, "desc.configurable");
+  }, "hasOwnProperty, getOwnPropertyDescriptor, getOwnPropertyNames")
+
+  test(function() {
+    assert_equals(document.createElementNS("http://www.w3.org/1999/xhtml", "i").localName, "i") // Sanity
+    var t = element.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "I"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_equals(t.localName, "I")
+    assert_equals(t.tagName, "I")
+    assert_equals(context.getElementsByTagName("I").length, 0)
+    assert_equals(context.getElementsByTagName("i").length, 0)
+  }, "HTML element with uppercase tagName never matches in HTML Documents")
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("test", "st"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_array_equals(context.getElementsByTagName("st"), [t])
+    assert_array_equals(context.getElementsByTagName("ST"), [])
+  }, "Element in non-HTML namespace, no prefix, lowercase name")
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("test", "ST"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_array_equals(context.getElementsByTagName("ST"), [t])
+    assert_array_equals(context.getElementsByTagName("st"), [])
+  }, "Element in non-HTML namespace, no prefix, uppercase name")
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("test", "te:st"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_array_equals(context.getElementsByTagName("st"), [t])
+    assert_array_equals(context.getElementsByTagName("ST"), [])
+  }, "Element in non-HTML namespace, prefix, lowercase name")
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("test", "te:ST"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_array_equals(context.getElementsByTagName("ST"), [t])
+    assert_array_equals(context.getElementsByTagName("st"), [])
+    assert_array_equals(context.getElementsByTagName("te:st"), [])
+    assert_array_equals(context.getElementsByTagName("te:ST"), [])
+  }, "Element in non-HTML namespace, prefix, uppercase name")
+
+  test(function() {
+    var t = element.appendChild(document.createElement("aÇ"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_equals(t.localName, "aÇ")
+    assert_array_equals(context.getElementsByTagName("AÇ"), [t], "All uppercase input")
+    assert_array_equals(context.getElementsByTagName("aÇ"), [t], "Ascii lowercase input")
+    assert_array_equals(context.getElementsByTagName("aç"), [], "All lowercase input")
+  }, "Element in HTML namespace, no prefix, non-ascii characters in name")
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("test", "AÇ"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_array_equals(context.getElementsByTagName("AÇ"), [t])
+    assert_array_equals(context.getElementsByTagName("aÇ"), [])
+    assert_array_equals(context.getElementsByTagName("aç"), [])
+  }, "Element in non-HTML namespace, non-ascii characters in name")
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "test:aÇ"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_array_equals(context.getElementsByTagName("AÇ"), [t], "All uppercase input")
+    assert_array_equals(context.getElementsByTagName("aÇ"), [t], "Ascii lowercase input")
+    assert_array_equals(context.getElementsByTagName("aç"), [], "All lowercase input")
+  }, "Element in HTML namespace, prefix, non-ascii characters in name")
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("test", "test:AÇ"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_array_equals(context.getElementsByTagName("AÇ"), [t], "All uppercase input")
+    assert_array_equals(context.getElementsByTagName("aÇ"), [], "Ascii lowercase input")
+    assert_array_equals(context.getElementsByTagName("aç"), [], "All lowercase input")
+  }, "Element in non-HTML namespace, prefix, non-ascii characters in name")
+
+  test(function() {
+    var actual = context.getElementsByTagName("*");
+    var expected = [];
+    var get_elements = function(node) {
+      for (var i = 0; i < node.childNodes.length; i++) {
+        var child = node.childNodes[i];
+        if (child.nodeType === child.ELEMENT_NODE) {
+          expected.push(child);
+          get_elements(child);
+        }
+      }
+    }
+    get_elements(context);
+    assert_array_equals(actual, expected);
+  }, "getElementsByTagName('*')")
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-Element-getElementsByTagNameNS.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-Element-getElementsByTagNameNS.js
new file mode 100644
index 0000000..a1bb315
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-Element-getElementsByTagNameNS.js
@@ -0,0 +1,128 @@
+function test_getElementsByTagNameNS(context, element) {
+  test(function() {
+    assert_false(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "html") instanceof NodeList, "NodeList")
+    assert_true(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "html") instanceof HTMLCollection, "HTMLCollection")
+    var firstCollection = context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "html"),
+        secondCollection = context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "html")
+    assert_true(firstCollection !== secondCollection || firstCollection === secondCollection,
+                "Caching is allowed.")
+  })
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("test", "body"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    var actual = context.getElementsByTagNameNS("*", "body");
+    var expected = [];
+    var get_elements = function(node) {
+      for (var i = 0; i < node.childNodes.length; i++) {
+        var child = node.childNodes[i];
+        if (child.nodeType === child.ELEMENT_NODE) {
+          if (child.localName == "body") {
+            expected.push(child);
+          }
+          get_elements(child);
+        }
+      }
+    }
+    get_elements(context);
+    assert_array_equals(actual, expected);
+  }, "getElementsByTagNameNS('*', 'body')")
+
+  test(function() {
+    assert_array_equals(context.getElementsByTagNameNS("", "*"), []);
+    var t = element.appendChild(document.createElementNS("", "body"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_array_equals(context.getElementsByTagNameNS("", "*"), [t]);
+  }, "Empty string namespace")
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("test", "body"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_array_equals(context.getElementsByTagNameNS("test", "body"), [t]);
+  }, "body element in test namespace, no prefix")
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("test", "test:body"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_array_equals(context.getElementsByTagNameNS("test", "body"), [t]);
+  }, "body element in test namespace, prefix")
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("test", "BODY"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_array_equals(context.getElementsByTagNameNS("test", "BODY"), [t]);
+    assert_array_equals(context.getElementsByTagNameNS("test", "body"), []);
+  }, "BODY element in test namespace, no prefix")
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "abc"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_array_equals(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "abc"), [t]);
+    assert_array_equals(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "ABC"), []);
+    assert_array_equals(context.getElementsByTagNameNS("test", "ABC"), []);
+  }, "abc element in html namespace")
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "ABC"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_array_equals(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "abc"), []);
+    assert_array_equals(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "ABC"), [t]);
+  }, "ABC element in html namespace")
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "AÇ"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_array_equals(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "AÇ"), [t]);
+    assert_array_equals(context.getElementsByTagNameNS("test", "aÇ"), []);
+    assert_array_equals(context.getElementsByTagNameNS("test", "aç"), []);
+  }, "AÇ, case sensitivity")
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("test", "test:BODY"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    assert_array_equals(context.getElementsByTagNameNS("test", "BODY"), [t]);
+    assert_array_equals(context.getElementsByTagNameNS("test", "body"), []);
+  }, "BODY element in test namespace, prefix")
+
+  test(function() {
+    var t = element.appendChild(document.createElementNS("test", "test:test"))
+    this.add_cleanup(function() {element.removeChild(t)})
+    var actual = context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "*");
+    var expected = [];
+    var get_elements = function(node) {
+      for (var i = 0; i < node.childNodes.length; i++) {
+        var child = node.childNodes[i];
+        if (child.nodeType === child.ELEMENT_NODE) {
+          if (child !== t) {
+            expected.push(child);
+          }
+          get_elements(child);
+        }
+      }
+    }
+    get_elements(context);
+    assert_array_equals(actual, expected);
+  }, "getElementsByTagNameNS('http://www.w3.org/1999/xhtml', '*')")
+
+  test(function() {
+    var actual = context.getElementsByTagNameNS("*", "*");
+    var expected = [];
+    var get_elements = function(node) {
+      for (var i = 0; i < node.childNodes.length; i++) {
+        var child = node.childNodes[i];
+        if (child.nodeType === child.ELEMENT_NODE) {
+          expected.push(child);
+          get_elements(child);
+        }
+      }
+    }
+    get_elements(context);
+    assert_array_equals(actual, expected);
+  }, "getElementsByTagNameNS('*', '*')")
+
+  test(function() {
+    assert_array_equals(context.getElementsByTagNameNS("**", "*"), []);
+    assert_array_equals(context.getElementsByTagNameNS(null, "0"), []);
+    assert_array_equals(context.getElementsByTagNameNS(null, "div"), []);
+  }, "Empty lists")
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-adoptNode.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-adoptNode.html
new file mode 100644
index 0000000..76d28022
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-adoptNode.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Document.adoptNode</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-adoptnode">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<!-- creates an element with local name "x<":  --><x<>x</x<>
+<script>
+test(function() {
+  var y = document.getElementsByTagName("x<")[0]
+  var child = y.firstChild
+  assert_equals(y.parentNode, document.body)
+  assert_equals(y.ownerDocument, document)
+  assert_equals(document.adoptNode(y), y)
+  assert_equals(y.parentNode, null)
+  assert_equals(y.firstChild, child)
+  assert_equals(y.ownerDocument, document)
+  assert_equals(child.ownerDocument, document)
+  var doc = document.implementation.createDocument(null, null, null)
+  assert_equals(doc.adoptNode(y), y)
+  assert_equals(y.parentNode, null)
+  assert_equals(y.firstChild, child)
+  assert_equals(y.ownerDocument, doc)
+  assert_equals(child.ownerDocument, doc)
+}, "Adopting an Element called 'x<' should work.")
+
+test(function() {
+  var x = document.createElement(":good:times:")
+  assert_equals(document.adoptNode(x), x);
+  var doc = document.implementation.createDocument(null, null, null)
+  assert_equals(doc.adoptNode(x), x)
+  assert_equals(x.parentNode, null)
+  assert_equals(x.ownerDocument, doc)
+}, "Adopting an Element called ':good:times:' should work.")
+
+test(function() {
+  var doctype = document.doctype;
+  assert_equals(doctype.parentNode, document)
+  assert_equals(doctype.ownerDocument, document)
+  assert_equals(document.adoptNode(doctype), doctype)
+  assert_equals(doctype.parentNode, null)
+  assert_equals(doctype.ownerDocument, document)
+}, "Explicitly adopting a DocumentType should work.")
+
+test(function() {
+  var doc = document.implementation.createDocument(null, null, null)
+  assert_throws("NOT_SUPPORTED_ERR", function() { document.adoptNode(doc) })
+}, "Adopting a Document should throw.")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-constructor-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-constructor-expected.txt
new file mode 100644
index 0000000..bfd1f56
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-constructor-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+FAIL new Document(): interfaces Illegal constructor
+FAIL new Document(): children Illegal constructor
+FAIL new Document(): metadata Illegal constructor
+FAIL new Document(): characterSet aliases Illegal constructor
+FAIL new Document(): URL parsing Illegal constructor
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-constructor.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-constructor.html
new file mode 100644
index 0000000..e1926a87
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-constructor.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<meta charset=windows-1252>
+<!--  Using windows-1252 to ensure that new Document() doesn't inherit utf-8
+     from the parent document.  -->
+<title>Document constructor</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var doc = new Document();
+  assert_true(doc instanceof Node, "Should be a Node");
+  assert_true(doc instanceof Document, "Should be a Document");
+  assert_false(doc instanceof XMLDocument, "Should not be an XMLDocument");
+  assert_equals(Object.getPrototypeOf(doc), Document.prototype,
+                "Document should be the primary interface");
+}, "new Document(): interfaces")
+
+test(function() {
+  var doc = new Document();
+  assert_equals(doc.firstChild, null, "firstChild");
+  assert_equals(doc.lastChild, null, "lastChild");
+  assert_equals(doc.doctype, null, "doctype");
+  assert_equals(doc.documentElement, null, "documentElement");
+  assert_array_equals(doc.childNodes, [], "childNodes");
+}, "new Document(): children")
+
+test(function() {
+  var doc = new Document();
+  assert_equals(doc.URL, "about:blank");
+  assert_equals(doc.documentURI, "about:blank");
+  assert_equals(doc.compatMode, "CSS1Compat");
+  assert_equals(doc.characterSet, "UTF-8");
+  assert_equals(doc.contentType, "application/xml");
+  assert_equals(doc.createElement("DIV").localName, "DIV");
+}, "new Document(): metadata")
+
+test(function() {
+  var doc = new Document();
+  assert_equals(doc.characterSet, "UTF-8", "characterSet");
+  assert_equals(doc.charset, "UTF-8", "charset");
+  assert_equals(doc.inputEncoding, "UTF-8", "inputEncoding");
+}, "new Document(): characterSet aliases")
+
+test(function() {
+  var doc = new Document();
+  var a = doc.createElement("a");
+  // In UTF-8: 0xC3 0xA4
+  a.href = "http://example.org/?\u00E4";
+  assert_equals(a.href, "http://example.org/?%C3%A4");
+}, "new Document(): URL parsing")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_bmp.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_bmp.html
new file mode 100644
index 0000000..77cdc63
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_bmp.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>BMP document.contentType === 'image/bmp'</title>
+<script src="../../../../../../resources/testharness.js"></script>
+<script src="../../../../../../resources/testharnessreport.js"></script>
+<iframe style="display:none"></iframe>
+<div id=log></div>
+<script>
+async_test(function() {
+  var iframe = document.getElementsByTagName('iframe')[0];
+  iframe.addEventListener('load', this.step_func_done(function() {
+    assert_equals(iframe.contentDocument.contentType, "image/bmp");
+  }), false);
+  iframe.src = "../resources/t.bmp";
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_css.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_css.html
new file mode 100644
index 0000000..1e04b2a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_css.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>CSS document.contentType === 'text/css'</title>
+<script src="../../../../../../resources/testharness.js"></script>
+<script src="../../../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+  var iframe = document.getElementsByTagName('iframe')[0];
+  iframe.addEventListener('load', this.step_func_done(function() {
+    assert_equals(iframe.contentDocument.contentType, "text/css");
+  }), false);
+  iframe.src = "../resources/style.css";
+});
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_01.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_01.html
new file mode 100644
index 0000000..d0fbfaba7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_01.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Data URI document.contentType === 'text/plain' when data URI MIME type is not set</title>
+<script src="../../../../../../resources/testharness.js"></script>
+<script src="../../../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+  var iframe = document.getElementsByTagName('iframe')[0];
+  iframe.addEventListener('load', this.step_func_done(function() {
+    assert_equals(iframe.contentDocument.contentType, "text/plain");
+  }), false);
+  iframe.src = "data:;,<!DOCTYPE html>";
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_02.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_02.html
new file mode 100644
index 0000000..c4e144b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_02.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Data URI document.contentType === 'text/html' when data URI MIME type is set</title>
+<script src="../../../../../../resources/testharness.js"></script>
+<script src="../../../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+  var iframe = document.getElementsByTagName('iframe')[0];
+  iframe.addEventListener('load', this.step_func_done(function() {
+    assert_equals(iframe.contentDocument.contentType, "text/html");
+  }), false);
+  iframe.src = "data:text/html;charset=utf-8,<!DOCTYPE html>";
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_gif.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_gif.html
new file mode 100644
index 0000000..4dc0617
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_gif.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>GIF document.contentType === 'image/gif'</title>
+<script src="../../../../../../resources/testharness.js"></script>
+<script src="../../../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+  var iframe = document.getElementsByTagName('iframe')[0];
+  iframe.addEventListener('load', this.step_func_done(function() {
+    assert_equals(iframe.contentDocument.contentType, "image/gif");
+  }), false);
+  iframe.src = "../resources/t.gif";
+});
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_html.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_html.html
new file mode 100644
index 0000000..9b08b6f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_html.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>HTM document.contentType === 'text/html'</title>
+<script src="../../../../../../resources/testharness.js"></script>
+<script src="../../../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+  var iframe = document.getElementsByTagName('iframe')[0];
+  iframe.addEventListener('load', this.step_func_done(function() {
+    assert_equals(iframe.contentDocument.contentType, "text/html");
+  }), false);
+  iframe.src = "../resources/blob.htm";
+});
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_javascripturi.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_javascripturi.html
new file mode 100644
index 0000000..382119fa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_javascripturi.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Javascript URI document.contentType === 'text/html'</title>
+<script src="../../../../../../resources/testharness.js"></script>
+<script src="../../../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+  var iframe = document.getElementsByTagName('iframe')[0];
+  iframe.addEventListener('load', this.step_func_done(function() {
+    assert_equals(iframe.contentDocument.contentType, "text/html");
+    assert_equals(iframe.contentDocument.documentElement.textContent, "text/html");
+  }), false);
+  iframe.src = "javascript:document.contentType";
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_jpg.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_jpg.html
new file mode 100644
index 0000000..723001a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_jpg.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>JPG document.contentType === 'image/jpeg'</title>
+<script src="../../../../../../resources/testharness.js"></script>
+<script src="../../../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+  var iframe = document.getElementsByTagName('iframe')[0];
+  iframe.addEventListener('load', this.step_func_done(function() {
+    assert_equals(iframe.contentDocument.contentType, "image/jpeg");
+  }), false);
+  iframe.src = "../resources/t.jpg";
+});
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_png.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_png.html
new file mode 100644
index 0000000..73812c01
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_png.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>PNG document.contentType === 'image/png'</title>
+<script src="../../../../../../resources/testharness.js"></script>
+<script src="../../../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+  var iframe = document.getElementsByTagName('iframe')[0];
+  iframe.addEventListener('load', this.step_func_done(function() {
+    assert_equals(iframe.contentDocument.contentType, "image/png");
+  }), false);
+  iframe.src = "../resources/t.png";
+});
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_txt.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_txt.html
new file mode 100644
index 0000000..b09a9dc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_txt.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>TXT document.contentType === 'text/plain'</title>
+<script src="../../../../../../resources/testharness.js"></script>
+<script src="../../../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+  var iframe = document.getElementsByTagName('iframe')[0];
+  iframe.addEventListener('load', this.step_func_done(function() {
+    assert_equals(iframe.contentDocument.contentType, "text/plain");
+  }), false);
+  iframe.src = "../resources/blob.txt";
+});
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/createDocument-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/createDocument-expected.txt
new file mode 100644
index 0000000..f7e2582
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/createDocument-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL document.implementation.createDocument: document.contentType === 'application/xml' assert_equals: expected "application/xml" but got "application/xhtml+xml"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/createDocument.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/createDocument.html
new file mode 100644
index 0000000..d86b661f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/createDocument.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>document.implementation.createDocument: document.contentType === 'application/xml'</title>
+<script src="../../../../../../resources/testharness.js"></script>
+<script src="../../../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+  var doc = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", null);
+  assert_equals(doc.contentType, "application/xml");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/createHTMLDocument.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/createHTMLDocument.html
new file mode 100644
index 0000000..da30deb4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/contentType/createHTMLDocument.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>document.implementation.createHTMLDocument: document.contentType === 'text/html'</title>
+<script src="../../../../../../resources/testharness.js"></script>
+<script src="../../../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+  var doc = document.implementation.createHTMLDocument("test");
+  assert_equals(doc.contentType, "text/html");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/blob.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/blob.htm
new file mode 100644
index 0000000..9d235ed
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/blob.htm
@@ -0,0 +1 @@
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/blob.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/blob.txt
new file mode 100644
index 0000000..9d235ed
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/blob.txt
@@ -0,0 +1 @@
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/blob.xml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/blob.xml
new file mode 100644
index 0000000..0922ed1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/blob.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<blob>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</blob>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/lib.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/lib.js
new file mode 100644
index 0000000..c41d336c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/lib.js
@@ -0,0 +1 @@
+var t;
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/style.css b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/style.css
new file mode 100644
index 0000000..bb4ff57
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/style.css
@@ -0,0 +1,12 @@
+.unknown
+{
+  background-color:lightblue;
+}
+.pass
+{
+  background-color:lime;
+}
+.fail
+{
+  background-color:red;
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/t.bmp b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/t.bmp
new file mode 100644
index 0000000..5697c0ae
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/t.bmp
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/t.gif b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/t.gif
new file mode 100644
index 0000000..91f2692
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/t.gif
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/t.jpg b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/t.jpg
new file mode 100644
index 0000000..72b5189
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/t.jpg
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/t.png b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/t.png
new file mode 100644
index 0000000..447d9e3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/resources/t.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/support/contenttype_setter.py b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/support/contenttype_setter.py
new file mode 100644
index 0000000..02eff65
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-contentType/support/contenttype_setter.py
@@ -0,0 +1,20 @@
+def main(request, response):
+    type = request.GET.first("type", None)
+    subtype = request.GET.first("subtype", None)
+    if type and subtype:
+        response.headers["Content-Type"] = type + "/" + subtype
+
+    removeContentType = request.GET.first("removeContentType", None)
+    if removeContentType:
+        try:
+            del response.headers["Content-Type"]
+        except KeyError:
+            pass
+
+    content = '<head>'
+    mimeHead = request.GET.first("mime", None);
+    if mimeHead:
+        content += '<meta http-equiv="Content-Type" content="%s; charset=utf-8"/>' % mimeHead
+    content += "</head>"
+
+    return content
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createAttribute-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createAttribute-expected.txt
new file mode 100644
index 0000000..91aeeece
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createAttribute-expected.txt
@@ -0,0 +1,25 @@
+This is a testharness.js-based test.
+PASS HTML document.createAttribute("") 
+PASS XML document.createAttribute("") 
+PASS HTML document.createAttribute("invalid^Name") 
+PASS XML document.createAttribute("invalid^Name") 
+PASS HTML document.createAttribute("\\") 
+PASS XML document.createAttribute("\\") 
+PASS HTML document.createAttribute("'") 
+PASS XML document.createAttribute("'") 
+PASS HTML document.createAttribute("\"") 
+PASS XML document.createAttribute("\"") 
+PASS HTML document.createAttribute("0") 
+PASS XML document.createAttribute("0") 
+PASS HTML document.createAttribute("0:a") 
+PASS XML document.createAttribute("0:a") 
+PASS HTML document.createAttribute("title") 
+PASS XML document.createAttribute("title") 
+FAIL HTML document.createAttribute("TITLE") assert_equals: expected "title" but got "TITLE"
+PASS XML document.createAttribute("TITLE") 
+PASS HTML document.createAttribute(null) 
+PASS XML document.createAttribute(null) 
+PASS HTML document.createAttribute(undefined) 
+PASS XML document.createAttribute(undefined) 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createAttribute.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createAttribute.html
new file mode 100644
index 0000000..ae57307
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createAttribute.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Document.createAttribute</title>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<script src=attributes.js></script>
+<script src=productions.js></script>
+<div id=log>
+<script>
+var xml_document;
+setup(function() {
+  xml_document = document.implementation.createDocument(null, null, null);
+});
+
+invalid_names.forEach(function(name) {
+  test(function() {
+    assert_throws("INVALID_CHARACTER_ERR", function() {
+      document.createAttribute(name, "test");
+    });
+  }, "HTML document.createAttribute(" + format_value(name) + ")");
+
+  test(function() {
+    assert_throws("INVALID_CHARACTER_ERR", function() {
+      xml_document.createAttribute(name, "test");
+    });
+  }, "XML document.createAttribute(" + format_value(name) + ")");
+});
+
+var tests = ["title", "TITLE", null, undefined];
+tests.forEach(function(name) {
+  test(function() {
+    var attribute = document.createAttribute(name);
+    attr_is(attribute, "", String(name).toLowerCase(), null, null, String(name).toLowerCase());
+    assert_equals(attribute.ownerElement, null);
+  }, "HTML document.createAttribute(" + format_value(name) + ")");
+
+  test(function() {
+    var attribute = xml_document.createAttribute(name);
+    attr_is(attribute, "", String(name), null, null, String(name));
+    assert_equals(attribute.ownerElement, null);
+  }, "XML document.createAttribute(" + format_value(name) + ")");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createComment-createTextNode.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createComment-createTextNode.js
new file mode 100644
index 0000000..62a38d3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createComment-createTextNode.js
@@ -0,0 +1,22 @@
+function test_create(method, iface, nodeType, nodeName) {
+  ["\u000b", "a -- b", "a-", "-b", null, undefined].forEach(function(value) {
+    test(function() {
+      var c = document[method](value);
+      var expected = String(value);
+      assert_true(c instanceof iface);
+      assert_true(c instanceof CharacterData);
+      assert_true(c instanceof Node);
+      assert_equals(c.ownerDocument, document);
+      assert_equals(c.data, expected, "data");
+      assert_equals(c.nodeValue, expected, "nodeValue");
+      assert_equals(c.textContent, expected, "textContent");
+      assert_equals(c.length, expected.length);
+      assert_equals(c.nodeType, nodeType);
+      assert_equals(c.nodeName, nodeName);
+      assert_equals(c.hasChildNodes(), false);
+      assert_equals(c.childNodes.length, 0);
+      assert_equals(c.firstChild, null);
+      assert_equals(c.lastChild, null);
+    }, method + "(" + format_value(value) + ")");
+  });
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createComment.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createComment.html
new file mode 100644
index 0000000..d316772a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createComment.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.createComment</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createcomment">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-ownerdocument">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodevalue">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-textcontent">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-length">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodetype">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-haschildnodes">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-childnodes">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-firstchild">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-lastchild">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="Document-createComment-createTextNode.js"></script>
+<div id="log"></div>
+<script>
+test_create("createComment", Comment, 8, "#comment");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElement-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElement-expected.txt
new file mode 100644
index 0000000..f88ee11
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElement-expected.txt
@@ -0,0 +1,39 @@
+This is a testharness.js-based test.
+PASS Document.createElement 
+PASS createElement(undefined) 
+PASS createElement(null) 
+PASS createElement("foo") 
+PASS createElement("f1oo") 
+PASS createElement("foo1") 
+PASS createElement("f̀oo") 
+PASS createElement("foò") 
+PASS createElement(":foo") 
+PASS createElement("f:oo") 
+PASS createElement("foo:") 
+PASS createElement("xml") 
+PASS createElement("xmlns") 
+PASS createElement("xmlfoo") 
+PASS createElement("xml:foo") 
+PASS createElement("xmlns:foo") 
+PASS createElement("xmlfoo:bar") 
+PASS createElement("svg") 
+PASS createElement("math") 
+PASS createElement("FOO") 
+FAIL createElement("marK") assert_equals: expected "marK" but got "mark"
+FAIL createElement("İnput") assert_equals: expected "İnput" but got "i̇nput"
+FAIL createElement("ınput") assert_equals: expected "ıNPUT" but got "INPUT"
+PASS createElement("") 
+PASS createElement("1foo") 
+PASS createElement("̀foo") 
+PASS createElement("}foo") 
+PASS createElement("f}oo") 
+PASS createElement("foo}") 
+PASS createElement("￿foo") 
+PASS createElement("f￿oo") 
+PASS createElement("foo￿") 
+PASS createElement("<foo") 
+PASS createElement("foo>") 
+PASS createElement("<foo>") 
+PASS createElement("f<oo") 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/generate.py b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/generate.py
new file mode 100755
index 0000000..88c4da19
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/generate.py
@@ -0,0 +1,77 @@
+#!/usr/bin/python
+import os
+import sys
+
+THIS_NAME = "generate.py"
+
+# Note: these lists must be kept in sync with the lists in
+# Document-createElement-namespace.html, and this script must be run whenever
+# the lists are updated.  (We could keep the lists in a shared JSON file, but
+# seems like too much effort.)
+FILES = (
+    ("empty", ""),
+    ("minimal_html", "<!doctype html><title></title>"),
+
+    ("xhtml", '<html xmlns="http://www.w3.org/1999/xhtml"></html>'),
+    ("svg", '<svg xmlns="http://www.w3.org/2000/svg"></svg>'),
+    ("mathml", '<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml>'),
+
+    ("bare_xhtml", "<html></html>"),
+    ("bare_svg", "<svg></svg>"),
+    ("bare_mathml", "<math></math>"),
+
+    ("xhtml_ns_removed", """\
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head><script>
+    var newRoot = document.createElementNS(null, "html");
+    document.removeChild(document.documentElement);
+    document.appendChild(newRoot);
+  </script></head>
+</html>
+"""),
+    ("xhtml_ns_changed", """\
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head><script>
+    var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc");
+    document.removeChild(document.documentElement);
+    document.appendChild(newRoot);
+  </script></head>
+</html>
+"""),
+)
+
+EXTENSIONS = (
+    "html",
+    "xhtml",
+    "xml",
+    "svg",
+    # Was not able to get server MIME type working properly :(
+    #"mml",
+)
+
+def __main__():
+    if len(sys.argv) > 1:
+        print "No arguments expected, aborting"
+        return
+
+    if not os.access(THIS_NAME, os.F_OK):
+        print "Must be run from the directory of " + THIS_NAME + ", aborting"
+        return
+
+    for name in os.listdir("."):
+        if name == THIS_NAME:
+            continue
+        os.remove(name)
+
+    manifest = open("MANIFEST", "w")
+
+    for name, contents in FILES:
+        for extension in EXTENSIONS:
+            f = open(name + "." + extension, "w")
+            f.write(contents)
+            f.close()
+            manifest.write("support " + name + "." + extension + "\n")
+
+    manifest.close()
+
+__main__()
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElement.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElement.html
new file mode 100644
index 0000000..316b2e6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElement.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.createElement</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelement">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-localname">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-tagname">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-prefix">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-namespaceuri">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function toASCIIUppercase(str) {
+  var diff = "a".charCodeAt(0) - "A".charCodeAt(0);
+  var res = "";
+  for (var i = 0; i < str.length; ++i) {
+    if ("a" <= str[i] && str[i] <= "z") {
+      res += String.fromCharCode(str.charCodeAt(i) - diff);
+    } else {
+      res += str[i];
+    }
+  }
+  return res;
+}
+test(function() {
+  var HTMLNS = "http://www.w3.org/1999/xhtml",
+      valid = [
+        //[input, localName],
+        [undefined, "undefined"],
+        [null, "null"],
+        ["foo", "foo"],
+        ["f1oo", "f1oo"],
+        ["foo1", "foo1"],
+        ["f\u0300oo", "f\u0300oo"],
+        ["foo\u0300", "foo\u0300"],
+        [":foo", ":foo"],
+        ["f:oo", "f:oo"],
+        ["foo:", "foo:"],
+        ["xml", "xml"],
+        ["xmlns", "xmlns"],
+        ["xmlfoo", "xmlfoo"],
+        ["xml:foo", "xml:foo"],
+        ["xmlns:foo", "xmlns:foo"],
+        ["xmlfoo:bar", "xmlfoo:bar"],
+        ["svg", "svg"],
+        ["math", "math"],
+        ["FOO", "foo"],
+        ["mar\u212a", "mar\u212a"],
+        ["\u0130nput", "\u0130nput"],
+        ["\u0131nput", "\u0131nput"]
+     ],
+     invalid = [
+       "",
+       "1foo",
+       "\u0300foo",
+       "}foo",
+       "f}oo",
+       "foo}",
+       "\ufffffoo",
+       "f\uffffoo",
+       "foo\uffff",
+       "<foo",
+       "foo>",
+       "<foo>",
+       "f<oo"
+     ]
+
+  valid.forEach(function(t) {
+    test(function() {
+      var elt = document.createElement(t[0])
+      assert_true(elt instanceof Element)
+      assert_true(elt instanceof Node)
+      assert_equals(elt.localName, t[1])
+      assert_equals(elt.tagName, toASCIIUppercase(t[1]))
+      assert_equals(elt.prefix, null)
+      assert_equals(elt.namespaceURI, HTMLNS)
+    }, "createElement(" + format_value(t[0]) + ")");
+  });
+  invalid.forEach(function(arg) {
+    test(function() {
+      assert_throws("INVALID_CHARACTER_ERR", function() { document.createElement(arg) })
+    }, "createElement(" + format_value(arg) + ")");
+  });
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElementNS-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElementNS-expected.txt
new file mode 100644
index 0000000..2bb85df
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElementNS-expected.txt
@@ -0,0 +1,186 @@
+This is a testharness.js-based test.
+PASS Document.createElementNS 
+PASS createElementNS test 0: null,undefined,null 
+PASS createElementNS test 1: null,"foo",null 
+PASS createElementNS test 2: null,"1foo","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 3: null,"f1oo",null 
+PASS createElementNS test 4: null,"foo1",null 
+PASS createElementNS test 5: null,"1foo","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 6: null,"̀foo","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 7: null,"}foo","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 8: null,"f}oo","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 9: null,"foo}","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 10: null,"￿foo","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 11: null,"f￿oo","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 12: null,"foo￿","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 13: null,"<foo","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 14: null,"foo>","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 15: null,"<foo>","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 16: null,"f<oo","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 17: null,"^^","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 18: null,":foo","NAMESPACE_ERR" 
+PASS createElementNS test 19: null,"f:oo","NAMESPACE_ERR" 
+PASS createElementNS test 20: null,"foo:","NAMESPACE_ERR" 
+PASS createElementNS test 21: null,":","NAMESPACE_ERR" 
+PASS createElementNS test 22: null,"xml",null 
+PASS createElementNS test 23: null,"xmlns","NAMESPACE_ERR" 
+PASS createElementNS test 24: null,"xmlfoo",null 
+PASS createElementNS test 25: null,"xml:foo","NAMESPACE_ERR" 
+PASS createElementNS test 26: null,"xmlns:foo","NAMESPACE_ERR" 
+PASS createElementNS test 27: null,"xmlfoo:bar","NAMESPACE_ERR" 
+PASS createElementNS test 28: null,"null:xml","NAMESPACE_ERR" 
+PASS createElementNS test 29: "",":foo","NAMESPACE_ERR" 
+PASS createElementNS test 30: "","f:oo","NAMESPACE_ERR" 
+PASS createElementNS test 31: "","foo:","NAMESPACE_ERR" 
+FAIL createElementNS test 32: undefined,undefined,null assert_equals: expected (object) null but got (string) "undefined"
+FAIL createElementNS test 33: undefined,"foo",null assert_equals: expected (object) null but got (string) "undefined"
+PASS createElementNS test 34: undefined,"1foo","INVALID_CHARACTER_ERR" 
+FAIL createElementNS test 35: undefined,"f1oo",null assert_equals: expected (object) null but got (string) "undefined"
+FAIL createElementNS test 36: undefined,"foo1",null assert_equals: expected (object) null but got (string) "undefined"
+PASS createElementNS test 37: undefined,":foo","NAMESPACE_ERR" 
+FAIL createElementNS test 38: undefined,"f:oo","NAMESPACE_ERR" assert_throws: function "function () { document.createElementNS(namespace, qualifi..." did not throw
+PASS createElementNS test 39: undefined,"foo:","NAMESPACE_ERR" 
+FAIL createElementNS test 40: undefined,"xml",null assert_equals: expected (object) null but got (string) "undefined"
+PASS createElementNS test 41: undefined,"xmlns","NAMESPACE_ERR" 
+FAIL createElementNS test 42: undefined,"xmlfoo",null assert_equals: expected (object) null but got (string) "undefined"
+PASS createElementNS test 43: undefined,"xml:foo","NAMESPACE_ERR" 
+PASS createElementNS test 44: undefined,"xmlns:foo","NAMESPACE_ERR" 
+FAIL createElementNS test 45: undefined,"xmlfoo:bar","NAMESPACE_ERR" assert_throws: function "function () { document.createElementNS(namespace, qualifi..." did not throw
+PASS createElementNS test 46: "http://example.com/","foo",null 
+PASS createElementNS test 47: "http://example.com/","1foo","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 48: "http://example.com/","f1oo",null 
+PASS createElementNS test 49: "http://example.com/","foo1",null 
+PASS createElementNS test 50: "http://example.com/",":foo","NAMESPACE_ERR" 
+PASS createElementNS test 51: "http://example.com/","f:oo",null 
+PASS createElementNS test 52: "http://example.com/","foo:","NAMESPACE_ERR" 
+PASS createElementNS test 53: "http://example.com/","_:_",null 
+PASS createElementNS test 54: "http://example.com/","_:h0",null 
+PASS createElementNS test 55: "http://example.com/","_:test",null 
+PASS createElementNS test 56: "http://example.com/","l_:_",null 
+PASS createElementNS test 57: "http://example.com/","ns:_0",null 
+PASS createElementNS test 58: "http://example.com/","ns:a0",null 
+PASS createElementNS test 59: "http://example.com/","ns0:test",null 
+PASS createElementNS test 60: "http://example.com/","a.b:c",null 
+PASS createElementNS test 61: "http://example.com/","a-b:c",null 
+PASS createElementNS test 62: "http://example.com/","a-b:c",null 
+PASS createElementNS test 63: "http://example.com/","xml",null 
+PASS createElementNS test 64: "http://example.com/","xmlns","NAMESPACE_ERR" 
+PASS createElementNS test 65: "http://example.com/","XMLNS",null 
+PASS createElementNS test 66: "http://example.com/","xmlfoo",null 
+PASS createElementNS test 67: "http://example.com/","xml:foo","NAMESPACE_ERR" 
+PASS createElementNS test 68: "http://example.com/","XML:foo",null 
+PASS createElementNS test 69: "http://example.com/","xmlns:foo","NAMESPACE_ERR" 
+PASS createElementNS test 70: "http://example.com/","XMLNS:foo",null 
+PASS createElementNS test 71: "http://example.com/","xmlfoo:bar",null 
+PASS createElementNS test 72: "http://example.com/","prefix::local","NAMESPACE_ERR" 
+PASS createElementNS test 73: "http://example.com/","namespaceURI:{","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 74: "http://example.com/","namespaceURI:}","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 75: "http://example.com/","namespaceURI:~","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 76: "http://example.com/","namespaceURI:'","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 77: "http://example.com/","namespaceURI:!","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 78: "http://example.com/","namespaceURI:@","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 79: "http://example.com/","namespaceURI:#","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 80: "http://example.com/","namespaceURI:$","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 81: "http://example.com/","namespaceURI:%","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 82: "http://example.com/","namespaceURI:^","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 83: "http://example.com/","namespaceURI:&","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 84: "http://example.com/","namespaceURI:*","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 85: "http://example.com/","namespaceURI:(","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 86: "http://example.com/","namespaceURI:)","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 87: "http://example.com/","namespaceURI:+","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 88: "http://example.com/","namespaceURI:=","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 89: "http://example.com/","namespaceURI:[","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 90: "http://example.com/","namespaceURI:]","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 91: "http://example.com/","namespaceURI:\\","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 92: "http://example.com/","namespaceURI:/","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 93: "http://example.com/","namespaceURI:;","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 94: "http://example.com/","namespaceURI:`","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 95: "http://example.com/","namespaceURI:<","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 96: "http://example.com/","namespaceURI:>","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 97: "http://example.com/","namespaceURI:,","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 98: "http://example.com/","namespaceURI:a ","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 99: "http://example.com/","namespaceURI:\"","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 100: "/","foo",null 
+PASS createElementNS test 101: "/","1foo","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 102: "/","f1oo",null 
+PASS createElementNS test 103: "/","foo1",null 
+PASS createElementNS test 104: "/",":foo","NAMESPACE_ERR" 
+PASS createElementNS test 105: "/","f:oo",null 
+PASS createElementNS test 106: "/","foo:","NAMESPACE_ERR" 
+PASS createElementNS test 107: "/","xml",null 
+PASS createElementNS test 108: "/","xmlns","NAMESPACE_ERR" 
+PASS createElementNS test 109: "/","xmlfoo",null 
+PASS createElementNS test 110: "/","xml:foo","NAMESPACE_ERR" 
+PASS createElementNS test 111: "/","xmlns:foo","NAMESPACE_ERR" 
+PASS createElementNS test 112: "/","xmlfoo:bar",null 
+PASS createElementNS test 113: "http://www.w3.org/XML/1998/namespace","foo",null 
+PASS createElementNS test 114: "http://www.w3.org/XML/1998/namespace","1foo","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 115: "http://www.w3.org/XML/1998/namespace","f1oo",null 
+PASS createElementNS test 116: "http://www.w3.org/XML/1998/namespace","foo1",null 
+PASS createElementNS test 117: "http://www.w3.org/XML/1998/namespace",":foo","NAMESPACE_ERR" 
+PASS createElementNS test 118: "http://www.w3.org/XML/1998/namespace","f:oo",null 
+PASS createElementNS test 119: "http://www.w3.org/XML/1998/namespace","foo:","NAMESPACE_ERR" 
+PASS createElementNS test 120: "http://www.w3.org/XML/1998/namespace","xml",null 
+PASS createElementNS test 121: "http://www.w3.org/XML/1998/namespace","xmlns","NAMESPACE_ERR" 
+PASS createElementNS test 122: "http://www.w3.org/XML/1998/namespace","xmlfoo",null 
+PASS createElementNS test 123: "http://www.w3.org/XML/1998/namespace","xml:foo",null 
+PASS createElementNS test 124: "http://www.w3.org/XML/1998/namespace","xmlns:foo","NAMESPACE_ERR" 
+PASS createElementNS test 125: "http://www.w3.org/XML/1998/namespace","xmlfoo:bar",null 
+PASS createElementNS test 126: "http://www.w3.org/XML/1998/namespaces","xml:foo","NAMESPACE_ERR" 
+PASS createElementNS test 127: "http://www.w3.org/xml/1998/namespace","xml:foo","NAMESPACE_ERR" 
+PASS createElementNS test 128: "http://www.w3.org/2000/xmlns/","foo","NAMESPACE_ERR" 
+PASS createElementNS test 129: "http://www.w3.org/2000/xmlns/","1foo","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 130: "http://www.w3.org/2000/xmlns/","f1oo","NAMESPACE_ERR" 
+PASS createElementNS test 131: "http://www.w3.org/2000/xmlns/","foo1","NAMESPACE_ERR" 
+PASS createElementNS test 132: "http://www.w3.org/2000/xmlns/",":foo","NAMESPACE_ERR" 
+PASS createElementNS test 133: "http://www.w3.org/2000/xmlns/","f:oo","NAMESPACE_ERR" 
+PASS createElementNS test 134: "http://www.w3.org/2000/xmlns/","foo:","NAMESPACE_ERR" 
+PASS createElementNS test 135: "http://www.w3.org/2000/xmlns/","xml","NAMESPACE_ERR" 
+PASS createElementNS test 136: "http://www.w3.org/2000/xmlns/","xmlns",null 
+PASS createElementNS test 137: "http://www.w3.org/2000/xmlns/","xmlfoo","NAMESPACE_ERR" 
+PASS createElementNS test 138: "http://www.w3.org/2000/xmlns/","xml:foo","NAMESPACE_ERR" 
+PASS createElementNS test 139: "http://www.w3.org/2000/xmlns/","xmlns:foo",null 
+PASS createElementNS test 140: "http://www.w3.org/2000/xmlns/","xmlfoo:bar","NAMESPACE_ERR" 
+PASS createElementNS test 141: "http://www.w3.org/2000/xmlns/","foo:xmlns","NAMESPACE_ERR" 
+PASS createElementNS test 142: "foo:","foo",null 
+PASS createElementNS test 143: "foo:","1foo","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 144: "foo:","f1oo",null 
+PASS createElementNS test 145: "foo:","foo1",null 
+PASS createElementNS test 146: "foo:",":foo","NAMESPACE_ERR" 
+PASS createElementNS test 147: "foo:","f:oo",null 
+PASS createElementNS test 148: "foo:","foo:","NAMESPACE_ERR" 
+PASS createElementNS test 149: "foo:","xml",null 
+PASS createElementNS test 150: "foo:","xmlns","NAMESPACE_ERR" 
+PASS createElementNS test 151: "foo:","xmlfoo",null 
+PASS createElementNS test 152: "foo:","xml:foo","NAMESPACE_ERR" 
+PASS createElementNS test 153: "foo:","xmlns:foo","NAMESPACE_ERR" 
+PASS createElementNS test 154: "foo:","xmlfoo:bar",null 
+PASS createElementNS test 155: "","","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 156: null,null,null 
+PASS createElementNS test 157: null,"","INVALID_CHARACTER_ERR" 
+FAIL createElementNS test 158: undefined,null,null assert_equals: expected (object) null but got (string) "undefined"
+FAIL createElementNS test 159: undefined,undefined,null assert_equals: expected (object) null but got (string) "undefined"
+PASS createElementNS test 160: undefined,"","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 161: "http://example.com/",null,null 
+PASS createElementNS test 162: "http://example.com/","","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 163: "/",null,null 
+PASS createElementNS test 164: "/","","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 165: "http://www.w3.org/XML/1998/namespace",null,null 
+PASS createElementNS test 166: "http://www.w3.org/XML/1998/namespace","","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 167: "http://www.w3.org/2000/xmlns/",null,"NAMESPACE_ERR" 
+PASS createElementNS test 168: "http://www.w3.org/2000/xmlns/","","INVALID_CHARACTER_ERR" 
+PASS createElementNS test 169: "foo:",null,null 
+PASS createElementNS test 170: "foo:","","INVALID_CHARACTER_ERR" 
+PASS Lower-case HTML element without a prefix 
+PASS Lower-case HTML element with a prefix 
+PASS Lower-case non-HTML element without a prefix 
+PASS Lower-case non-HTML element with a prefix 
+PASS Upper-case HTML element without a prefix 
+PASS Upper-case HTML element with a prefix 
+PASS Upper-case non-HTML element without a prefix 
+PASS Upper-case non-HTML element with a prefix 
+PASS null namespace 
+FAIL undefined namespace assert_equals: expected (object) null but got (string) "undefined"
+PASS empty string namespace 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElementNS.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElementNS.html
new file mode 100644
index 0000000..38735c8c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElementNS.html
@@ -0,0 +1,199 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.createElementNS</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelementns">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="Document-createElementNS.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var tests = createElementNS_tests.concat([
+    /* Arrays with three elements:
+     *   the namespace argument
+     *   the qualifiedName argument
+     *   the expected exception, or null if none
+     */
+    ["", "", "INVALID_CHARACTER_ERR"],
+    [null, null, null],
+    [null, "", "INVALID_CHARACTER_ERR"],
+    [undefined, null, null],
+    [undefined, undefined, null],
+    [undefined, "", "INVALID_CHARACTER_ERR"],
+    ["http://example.com/", null, null],
+    ["http://example.com/", "", "INVALID_CHARACTER_ERR"],
+    ["/", null, null],
+    ["/", "", "INVALID_CHARACTER_ERR"],
+    ["http://www.w3.org/XML/1998/namespace", null, null],
+    ["http://www.w3.org/XML/1998/namespace", "", "INVALID_CHARACTER_ERR"],
+    ["http://www.w3.org/2000/xmlns/", null, "NAMESPACE_ERR"],
+    ["http://www.w3.org/2000/xmlns/", "", "INVALID_CHARACTER_ERR"],
+    ["foo:", null, null],
+    ["foo:", "", "INVALID_CHARACTER_ERR"],
+  ])
+
+  tests.forEach(function(t, i) {
+    test(function() {
+      var namespace = t[0], qualifiedName = t[1], expected = t[2]
+      if (expected != null) {
+        assert_throws(expected, function() { document.createElementNS(namespace, qualifiedName) })
+      } else {
+        var element = document.createElementNS(namespace, qualifiedName)
+        assert_not_equals(element, null)
+        assert_equals(element.nodeType, Node.ELEMENT_NODE)
+        assert_equals(element.nodeType, element.ELEMENT_NODE)
+        assert_equals(element.nodeValue, null)
+        assert_equals(element.ownerDocument, document)
+        var qualified = String(qualifiedName), names = []
+        if (qualified.indexOf(":") >= 0) {
+          names = qualified.split(":", 2)
+        } else {
+          names = [null, qualified]
+        }
+        assert_equals(element.prefix, names[0])
+        assert_equals(element.localName, names[1])
+        assert_equals(element.tagName, qualified)
+        assert_equals(element.nodeName, qualified)
+        assert_equals(element.namespaceURI, namespace === undefined ? null : namespace)
+      }
+    }, "createElementNS test " + i + ": " + t.map(function(el) { return format_value(el) }))
+  })
+})
+
+test(function() {
+  var HTMLNS = "http://www.w3.org/1999/xhtml";
+  var element = document.createElementNS(HTMLNS, "span");
+  assert_equals(element.namespaceURI, HTMLNS);
+  assert_equals(element.prefix, null);
+  assert_equals(element.localName, "span");
+  assert_equals(element.tagName, "SPAN");
+  assert_true(element instanceof Node, "Should be a Node");
+  assert_true(element instanceof Element, "Should be an Element");
+  assert_true(element instanceof HTMLElement, "Should be an HTMLElement");
+  assert_true(element instanceof HTMLSpanElement, "Should be an HTMLSpanElement");
+}, "Lower-case HTML element without a prefix");
+
+test(function() {
+  var HTMLNS = "http://www.w3.org/1999/xhtml";
+  var element = document.createElementNS(HTMLNS, "html:span");
+  assert_equals(element.namespaceURI, HTMLNS);
+  assert_equals(element.prefix, "html");
+  assert_equals(element.localName, "span");
+  assert_equals(element.tagName, "HTML:SPAN");
+  assert_true(element instanceof Node, "Should be a Node");
+  assert_true(element instanceof Element, "Should be an Element");
+  assert_true(element instanceof HTMLElement, "Should be an HTMLElement");
+  assert_true(element instanceof HTMLSpanElement, "Should be an HTMLSpanElement");
+}, "Lower-case HTML element with a prefix");
+
+test(function() {
+  var element = document.createElementNS("test", "span");
+  assert_equals(element.namespaceURI, "test");
+  assert_equals(element.prefix, null);
+  assert_equals(element.localName, "span");
+  assert_equals(element.tagName, "span");
+  assert_true(element instanceof Node, "Should be a Node");
+  assert_true(element instanceof Element, "Should be an Element");
+  assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
+  assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "Lower-case non-HTML element without a prefix");
+
+test(function() {
+  var element = document.createElementNS("test", "html:span");
+  assert_equals(element.namespaceURI, "test");
+  assert_equals(element.prefix, "html");
+  assert_equals(element.localName, "span");
+  assert_equals(element.tagName, "html:span");
+  assert_true(element instanceof Node, "Should be a Node");
+  assert_true(element instanceof Element, "Should be an Element");
+  assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
+  assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "Lower-case non-HTML element with a prefix");
+
+test(function() {
+  var HTMLNS = "http://www.w3.org/1999/xhtml";
+  var element = document.createElementNS(HTMLNS, "SPAN");
+  assert_equals(element.namespaceURI, HTMLNS);
+  assert_equals(element.prefix, null);
+  assert_equals(element.localName, "SPAN");
+  assert_equals(element.tagName, "SPAN");
+  assert_true(element instanceof Node, "Should be a Node");
+  assert_true(element instanceof Element, "Should be an Element");
+  assert_true(element instanceof HTMLElement, "Should be an HTMLElement");
+  assert_true(element instanceof HTMLUnknownElement, "Should be an HTMLUnknownElement");
+  assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "Upper-case HTML element without a prefix");
+
+test(function() {
+  var HTMLNS = "http://www.w3.org/1999/xhtml";
+  var element = document.createElementNS(HTMLNS, "html:SPAN");
+  assert_equals(element.namespaceURI, HTMLNS);
+  assert_equals(element.prefix, "html");
+  assert_equals(element.localName, "SPAN");
+  assert_equals(element.tagName, "HTML:SPAN");
+  assert_true(element instanceof Node, "Should be a Node");
+  assert_true(element instanceof Element, "Should be an Element");
+  assert_true(element instanceof HTMLElement, "Should be an HTMLElement");
+  assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "Upper-case HTML element with a prefix");
+
+test(function() {
+  var element = document.createElementNS("test", "SPAN");
+  assert_equals(element.namespaceURI, "test");
+  assert_equals(element.prefix, null);
+  assert_equals(element.localName, "SPAN");
+  assert_equals(element.tagName, "SPAN");
+  assert_true(element instanceof Node, "Should be a Node");
+  assert_true(element instanceof Element, "Should be an Element");
+  assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
+  assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "Upper-case non-HTML element without a prefix");
+
+test(function() {
+  var element = document.createElementNS("test", "html:SPAN");
+  assert_equals(element.namespaceURI, "test");
+  assert_equals(element.prefix, "html");
+  assert_equals(element.localName, "SPAN");
+  assert_equals(element.tagName, "html:SPAN");
+  assert_true(element instanceof Node, "Should be a Node");
+  assert_true(element instanceof Element, "Should be an Element");
+  assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
+  assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "Upper-case non-HTML element with a prefix");
+
+test(function() {
+  var element = document.createElementNS(null, "span");
+  assert_equals(element.namespaceURI, null);
+  assert_equals(element.prefix, null);
+  assert_equals(element.localName, "span");
+  assert_equals(element.tagName, "span");
+  assert_true(element instanceof Node, "Should be a Node");
+  assert_true(element instanceof Element, "Should be an Element");
+  assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
+  assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "null namespace");
+
+test(function() {
+  var element = document.createElementNS(undefined, "span");
+  assert_equals(element.namespaceURI, null);
+  assert_equals(element.prefix, null);
+  assert_equals(element.localName, "span");
+  assert_equals(element.tagName, "span");
+  assert_true(element instanceof Node, "Should be a Node");
+  assert_true(element instanceof Element, "Should be an Element");
+  assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
+  assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "undefined namespace");
+
+test(function() {
+  var element = document.createElementNS("", "span");
+  assert_equals(element.namespaceURI, null);
+  assert_equals(element.prefix, null);
+  assert_equals(element.localName, "span");
+  assert_equals(element.tagName, "span");
+  assert_true(element instanceof Node, "Should be a Node");
+  assert_true(element instanceof Element, "Should be an Element");
+  assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
+  assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "empty string namespace");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElementNS.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElementNS.js
new file mode 100644
index 0000000..8488877
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createElementNS.js
@@ -0,0 +1,162 @@
+var createElementNS_tests = [
+  /* Arrays with three elements:
+   *   the namespace argument
+   *   the qualifiedName argument
+   *   the expected exception, or null if none
+   */
+  [null, undefined, null],
+  [null, "foo", null],
+  [null, "1foo", "INVALID_CHARACTER_ERR"],
+  [null, "f1oo", null],
+  [null, "foo1", null],
+  [null, "1foo", "INVALID_CHARACTER_ERR"],
+  [null, "\u0300foo", "INVALID_CHARACTER_ERR"],
+  [null, "}foo", "INVALID_CHARACTER_ERR"],
+  [null, "f}oo", "INVALID_CHARACTER_ERR"],
+  [null, "foo}", "INVALID_CHARACTER_ERR"],
+  [null, "\uFFFFfoo", "INVALID_CHARACTER_ERR"],
+  [null, "f\uFFFFoo", "INVALID_CHARACTER_ERR"],
+  [null, "foo\uFFFF", "INVALID_CHARACTER_ERR"],
+  [null, "<foo", "INVALID_CHARACTER_ERR"],
+  [null, "foo>", "INVALID_CHARACTER_ERR"],
+  [null, "<foo>", "INVALID_CHARACTER_ERR"],
+  [null, "f<oo", "INVALID_CHARACTER_ERR"],
+  [null, "^^", "INVALID_CHARACTER_ERR"],
+  [null, ":foo", "NAMESPACE_ERR"],
+  [null, "f:oo", "NAMESPACE_ERR"],
+  [null, "foo:", "NAMESPACE_ERR"],
+  [null, ":", "NAMESPACE_ERR"],
+  [null, "xml", null],
+  [null, "xmlns", "NAMESPACE_ERR"],
+  [null, "xmlfoo", null],
+  [null, "xml:foo", "NAMESPACE_ERR"],
+  [null, "xmlns:foo", "NAMESPACE_ERR"],
+  [null, "xmlfoo:bar", "NAMESPACE_ERR"],
+  [null, "null:xml", "NAMESPACE_ERR"],
+  ["", ":foo", "NAMESPACE_ERR"],
+  ["", "f:oo", "NAMESPACE_ERR"],
+  ["", "foo:", "NAMESPACE_ERR"],
+  [undefined, undefined, null],
+  [undefined, "foo", null],
+  [undefined, "1foo", "INVALID_CHARACTER_ERR"],
+  [undefined, "f1oo", null],
+  [undefined, "foo1", null],
+  [undefined, ":foo", "NAMESPACE_ERR"],
+  [undefined, "f:oo", "NAMESPACE_ERR"],
+  [undefined, "foo:", "NAMESPACE_ERR"],
+  [undefined, "xml", null],
+  [undefined, "xmlns", "NAMESPACE_ERR"],
+  [undefined, "xmlfoo", null],
+  [undefined, "xml:foo", "NAMESPACE_ERR"],
+  [undefined, "xmlns:foo", "NAMESPACE_ERR"],
+  [undefined, "xmlfoo:bar", "NAMESPACE_ERR"],
+  ["http://example.com/", "foo", null],
+  ["http://example.com/", "1foo", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "f1oo", null],
+  ["http://example.com/", "foo1", null],
+  ["http://example.com/", ":foo", "NAMESPACE_ERR"],
+  ["http://example.com/", "f:oo", null],
+  ["http://example.com/", "foo:", "NAMESPACE_ERR"],
+  ["http://example.com/", "_:_", null],
+  ["http://example.com/", "_:h0", null],
+  ["http://example.com/", "_:test", null],
+  ["http://example.com/", "l_:_", null],
+  ["http://example.com/", "ns:_0", null],
+  ["http://example.com/", "ns:a0", null],
+  ["http://example.com/", "ns0:test", null],
+  ["http://example.com/", "a.b:c", null],
+  ["http://example.com/", "a-b:c", null],
+  ["http://example.com/", "a-b:c", null],
+  ["http://example.com/", "xml", null],
+  ["http://example.com/", "xmlns", "NAMESPACE_ERR"],
+  ["http://example.com/", "XMLNS", null],
+  ["http://example.com/", "xmlfoo", null],
+  ["http://example.com/", "xml:foo", "NAMESPACE_ERR"],
+  ["http://example.com/", "XML:foo", null],
+  ["http://example.com/", "xmlns:foo", "NAMESPACE_ERR"],
+  ["http://example.com/", "XMLNS:foo", null],
+  ["http://example.com/", "xmlfoo:bar", null],
+  ["http://example.com/", "prefix::local", "NAMESPACE_ERR"],
+  ["http://example.com/", "namespaceURI:{", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:}", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:~", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:'", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:!", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:@", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:#", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:$", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:%", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:^", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:&", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:*", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:(", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:)", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:+", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:=", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:[", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:]", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:\\", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:/", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:;", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:`", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:<", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:>", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:,", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:a ", "INVALID_CHARACTER_ERR"],
+  ["http://example.com/", "namespaceURI:\"", "INVALID_CHARACTER_ERR"],
+  ["/", "foo", null],
+  ["/", "1foo", "INVALID_CHARACTER_ERR"],
+  ["/", "f1oo", null],
+  ["/", "foo1", null],
+  ["/", ":foo", "NAMESPACE_ERR"],
+  ["/", "f:oo", null],
+  ["/", "foo:", "NAMESPACE_ERR"],
+  ["/", "xml", null],
+  ["/", "xmlns", "NAMESPACE_ERR"],
+  ["/", "xmlfoo", null],
+  ["/", "xml:foo", "NAMESPACE_ERR"],
+  ["/", "xmlns:foo", "NAMESPACE_ERR"],
+  ["/", "xmlfoo:bar", null],
+  ["http://www.w3.org/XML/1998/namespace", "foo", null],
+  ["http://www.w3.org/XML/1998/namespace", "1foo", "INVALID_CHARACTER_ERR"],
+  ["http://www.w3.org/XML/1998/namespace", "f1oo", null],
+  ["http://www.w3.org/XML/1998/namespace", "foo1", null],
+  ["http://www.w3.org/XML/1998/namespace", ":foo", "NAMESPACE_ERR"],
+  ["http://www.w3.org/XML/1998/namespace", "f:oo", null],
+  ["http://www.w3.org/XML/1998/namespace", "foo:", "NAMESPACE_ERR"],
+  ["http://www.w3.org/XML/1998/namespace", "xml", null],
+  ["http://www.w3.org/XML/1998/namespace", "xmlns", "NAMESPACE_ERR"],
+  ["http://www.w3.org/XML/1998/namespace", "xmlfoo", null],
+  ["http://www.w3.org/XML/1998/namespace", "xml:foo", null],
+  ["http://www.w3.org/XML/1998/namespace", "xmlns:foo", "NAMESPACE_ERR"],
+  ["http://www.w3.org/XML/1998/namespace", "xmlfoo:bar", null],
+  ["http://www.w3.org/XML/1998/namespaces", "xml:foo", "NAMESPACE_ERR"],
+  ["http://www.w3.org/xml/1998/namespace", "xml:foo", "NAMESPACE_ERR"],
+  ["http://www.w3.org/2000/xmlns/", "foo", "NAMESPACE_ERR"],
+  ["http://www.w3.org/2000/xmlns/", "1foo", "INVALID_CHARACTER_ERR"],
+  ["http://www.w3.org/2000/xmlns/", "f1oo", "NAMESPACE_ERR"],
+  ["http://www.w3.org/2000/xmlns/", "foo1", "NAMESPACE_ERR"],
+  ["http://www.w3.org/2000/xmlns/", ":foo", "NAMESPACE_ERR"],
+  ["http://www.w3.org/2000/xmlns/", "f:oo", "NAMESPACE_ERR"],
+  ["http://www.w3.org/2000/xmlns/", "foo:", "NAMESPACE_ERR"],
+  ["http://www.w3.org/2000/xmlns/", "xml", "NAMESPACE_ERR"],
+  ["http://www.w3.org/2000/xmlns/", "xmlns", null],
+  ["http://www.w3.org/2000/xmlns/", "xmlfoo", "NAMESPACE_ERR"],
+  ["http://www.w3.org/2000/xmlns/", "xml:foo", "NAMESPACE_ERR"],
+  ["http://www.w3.org/2000/xmlns/", "xmlns:foo", null],
+  ["http://www.w3.org/2000/xmlns/", "xmlfoo:bar", "NAMESPACE_ERR"],
+  ["http://www.w3.org/2000/xmlns/", "foo:xmlns", "NAMESPACE_ERR"],
+  ["foo:", "foo", null],
+  ["foo:", "1foo", "INVALID_CHARACTER_ERR"],
+  ["foo:", "f1oo", null],
+  ["foo:", "foo1", null],
+  ["foo:", ":foo", "NAMESPACE_ERR"],
+  ["foo:", "f:oo", null],
+  ["foo:", "foo:", "NAMESPACE_ERR"],
+  ["foo:", "xml", null],
+  ["foo:", "xmlns", "NAMESPACE_ERR"],
+  ["foo:", "xmlfoo", null],
+  ["foo:", "xml:foo", "NAMESPACE_ERR"],
+  ["foo:", "xmlns:foo", "NAMESPACE_ERR"],
+  ["foo:", "xmlfoo:bar", null],
+]
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent-expected.txt
new file mode 100644
index 0000000..5a1eb87
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent-expected.txt
@@ -0,0 +1,76 @@
+This is a testharness.js-based test.
+PASS CustomEvent should be an alias for CustomEvent. 
+PASS createEvent('CustomEvent') should be initialized correctly. 
+PASS customevent should be an alias for CustomEvent. 
+PASS createEvent('customevent') should be initialized correctly. 
+PASS CUSTOMEVENT should be an alias for CustomEvent. 
+PASS createEvent('CUSTOMEVENT') should be initialized correctly. 
+PASS Event should be an alias for Event. 
+PASS createEvent('Event') should be initialized correctly. 
+PASS event should be an alias for Event. 
+PASS createEvent('event') should be initialized correctly. 
+PASS EVENT should be an alias for Event. 
+PASS createEvent('EVENT') should be initialized correctly. 
+PASS Events should be an alias for Event. 
+PASS createEvent('Events') should be initialized correctly. 
+PASS events should be an alias for Event. 
+PASS createEvent('events') should be initialized correctly. 
+PASS EVENTS should be an alias for Event. 
+PASS createEvent('EVENTS') should be initialized correctly. 
+PASS HTMLEvents should be an alias for Event. 
+PASS createEvent('HTMLEvents') should be initialized correctly. 
+PASS htmlevents should be an alias for Event. 
+PASS createEvent('htmlevents') should be initialized correctly. 
+PASS HTMLEVENTS should be an alias for Event. 
+PASS createEvent('HTMLEVENTS') should be initialized correctly. 
+PASS KeyboardEvent should be an alias for KeyboardEvent. 
+PASS createEvent('KeyboardEvent') should be initialized correctly. 
+FAIL keyboardevent should be an alias for KeyboardEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('keyboardevent') is invalid.
+FAIL createEvent('keyboardevent') should be initialized correctly. Cannot read property 'type' of undefined
+FAIL KEYBOARDEVENT should be an alias for KeyboardEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('KEYBOARDEVENT') is invalid.
+FAIL createEvent('KEYBOARDEVENT') should be initialized correctly. Cannot read property 'type' of undefined
+FAIL KeyEvents should be an alias for KeyboardEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('KeyEvents') is invalid.
+FAIL createEvent('KeyEvents') should be initialized correctly. Cannot read property 'type' of undefined
+FAIL keyevents should be an alias for KeyboardEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('keyevents') is invalid.
+FAIL createEvent('keyevents') should be initialized correctly. Cannot read property 'type' of undefined
+FAIL KEYEVENTS should be an alias for KeyboardEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('KEYEVENTS') is invalid.
+FAIL createEvent('KEYEVENTS') should be initialized correctly. Cannot read property 'type' of undefined
+PASS MessageEvent should be an alias for MessageEvent. 
+PASS createEvent('MessageEvent') should be initialized correctly. 
+FAIL messageevent should be an alias for MessageEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('messageevent') is invalid.
+FAIL createEvent('messageevent') should be initialized correctly. Cannot read property 'type' of undefined
+FAIL MESSAGEEVENT should be an alias for MessageEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('MESSAGEEVENT') is invalid.
+FAIL createEvent('MESSAGEEVENT') should be initialized correctly. Cannot read property 'type' of undefined
+PASS MouseEvent should be an alias for MouseEvent. 
+PASS createEvent('MouseEvent') should be initialized correctly. 
+PASS mouseevent should be an alias for MouseEvent. 
+PASS createEvent('mouseevent') should be initialized correctly. 
+PASS MOUSEEVENT should be an alias for MouseEvent. 
+PASS createEvent('MOUSEEVENT') should be initialized correctly. 
+PASS MouseEvents should be an alias for MouseEvent. 
+PASS createEvent('MouseEvents') should be initialized correctly. 
+PASS mouseevents should be an alias for MouseEvent. 
+PASS createEvent('mouseevents') should be initialized correctly. 
+PASS MOUSEEVENTS should be an alias for MouseEvent. 
+PASS createEvent('MOUSEEVENTS') should be initialized correctly. 
+PASS TouchEvent should be an alias for TouchEvent. 
+PASS createEvent('TouchEvent') should be initialized correctly. 
+FAIL touchevent should be an alias for TouchEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('touchevent') is invalid.
+FAIL createEvent('touchevent') should be initialized correctly. Cannot read property 'type' of undefined
+FAIL TOUCHEVENT should be an alias for TouchEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('TOUCHEVENT') is invalid.
+FAIL createEvent('TOUCHEVENT') should be initialized correctly. Cannot read property 'type' of undefined
+PASS UIEvent should be an alias for UIEvent. 
+PASS createEvent('UIEvent') should be initialized correctly. 
+PASS uievent should be an alias for UIEvent. 
+PASS createEvent('uievent') should be initialized correctly. 
+PASS UIEVENT should be an alias for UIEvent. 
+PASS createEvent('UIEVENT') should be initialized correctly. 
+PASS UIEvents should be an alias for UIEvent. 
+PASS createEvent('UIEvents') should be initialized correctly. 
+PASS uievents should be an alias for UIEvent. 
+PASS createEvent('uievents') should be initialized correctly. 
+PASS UIEVENTS should be an alias for UIEvent. 
+PASS createEvent('UIEVENTS') should be initialized correctly. 
+PASS Should throw NOT_SUPPORTED_ERR for unrecognized arguments 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent.html
new file mode 100644
index 0000000..e33424f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.createEvent</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createevent">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="Document-createEvent.js"></script>
+<div id="log"></div>
+<script>
+function testAlias(arg, iface) {
+  var ev;
+  test(function() {
+    ev = document.createEvent(arg);
+    assert_true(ev instanceof window[iface]);
+    assert_true(ev instanceof Event);
+  }, arg + " should be an alias for " + iface + ".");
+  test(function() {
+    assert_equals(ev.type, "",
+                  "type should be initialized to the empty string");
+    assert_equals(ev.target, null,
+                  "target should be initialized to null");
+    assert_equals(ev.currentTarget, null,
+                  "currentTarget should be initialized to null");
+    assert_equals(ev.eventPhase, 0,
+                  "eventPhase should be initialized to NONE (0)");
+    assert_equals(ev.bubbles, false,
+                  "bubbles should be initialized to false");
+    assert_equals(ev.cancelable, false,
+                  "cancelable should be initialized to false");
+    assert_equals(ev.defaultPrevented, false,
+                  "defaultPrevented should be initialized to false");
+    assert_equals(ev.isTrusted, false,
+                  "isTrusted should be initialized to false");
+  }, "createEvent('" + arg + "') should be initialized correctly.");
+}
+aliases.forEach(function(alias) {
+  testAlias(alias[0], alias[1]);
+  testAlias(alias[0].toLowerCase(), alias[1]);
+  testAlias(alias[0].toUpperCase(), alias[1]);
+});
+
+test(function() {
+  assert_throws("NOT_SUPPORTED_ERR", function() {
+    var evt = document.createEvent("foo");
+  });
+  assert_throws("NOT_SUPPORTED_ERR", function() {
+    // 'LATIN CAPITAL LETTER I WITH DOT ABOVE' (U+0130)
+    var evt = document.createEvent("U\u0130Event");
+  });
+  assert_throws("NOT_SUPPORTED_ERR", function() {
+    // 'LATIN SMALL LETTER DOTLESS I' (U+0131)
+    var evt = document.createEvent("U\u0131Event");
+  });
+}, "Should throw NOT_SUPPORTED_ERR for unrecognized arguments");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent.js
new file mode 100644
index 0000000..90cc73c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent.js
@@ -0,0 +1,14 @@
+var aliases = [
+  ["CustomEvent", "CustomEvent"],
+  ["Event", "Event"],
+  ["Events", "Event"],
+  ["HTMLEvents", "Event"],
+  ["KeyboardEvent", "KeyboardEvent"],
+  ["KeyEvents", "KeyboardEvent"],
+  ["MessageEvent", "MessageEvent"],
+  ["MouseEvent", "MouseEvent"],
+  ["MouseEvents", "MouseEvent"],
+  ["TouchEvent", "TouchEvent"],
+  ["UIEvent", "UIEvent"],
+  ["UIEvents", "UIEvent"]
+];
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createProcessingInstruction-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createProcessingInstruction-xhtml.xhtml
new file mode 100644
index 0000000..73a41fdf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createProcessingInstruction-xhtml.xhtml
@@ -0,0 +1,15 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Document.createProcessingInstruction in XML documents</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-document-createprocessinginstruction"/>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-processinginstruction-target"/>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-characterdata-data"/>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-node-ownerdocument"/>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"/>
+<script src="Document-createProcessingInstruction.js"/>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createProcessingInstruction.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createProcessingInstruction.html
new file mode 100644
index 0000000..4a6231d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createProcessingInstruction.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.createProcessingInstruction in HTML documents</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createprocessinginstruction">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-processinginstruction-target">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-ownerdocument">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src="Document-createProcessingInstruction.js"></script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createProcessingInstruction.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createProcessingInstruction.js
new file mode 100644
index 0000000..114ac35
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createProcessingInstruction.js
@@ -0,0 +1,39 @@
+test(function() {
+  var invalid = [
+        ["A", "?>"],
+        ["\u00B7A", "x"],
+        ["\u00D7A", "x"],
+        ["A\u00D7", "x"],
+        ["\\A", "x"],
+        ["\f", "x"],
+        [0, "x"],
+        ["0", "x"]
+      ],
+      valid = [
+        ["xml:fail", "x"],
+        ["A\u00B7A", "x"],
+        ["a0", "x"]
+      ]
+
+  for (var i = 0, il = invalid.length; i < il; i++) {
+    test(function() {
+      assert_throws("INVALID_CHARACTER_ERR", function() {
+        document.createProcessingInstruction(invalid[i][0], invalid[i][1])
+      })
+    }, "Should throw an INVALID_CHARACTER_ERR for target " +
+       format_value(invalid[i][0]) + " and data " +
+       format_value(invalid[i][1]) + ".")
+  }
+  for (var i = 0, il = valid.length; i < il; ++i) {
+    test(function() {
+      var pi = document.createProcessingInstruction(valid[i][0], valid[i][1]);
+      assert_equals(pi.target, valid[i][0]);
+      assert_equals(pi.data, valid[i][1]);
+      assert_equals(pi.ownerDocument, document);
+      assert_true(pi instanceof ProcessingInstruction);
+      assert_true(pi instanceof Node);
+    }, "Should get a ProcessingInstruction for target " +
+      format_value(valid[i][0]) + " and data " +
+      format_value(valid[i][1]) + ".")
+  }
+})
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createTextNode.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createTextNode.html
new file mode 100644
index 0000000..c48423af
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createTextNode.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.createTextNode</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createtextnode">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-ownerdocument">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodevalue">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-textcontent">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-length">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodetype">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-haschildnodes">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-childnodes">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-firstchild">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-lastchild">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="Document-createComment-createTextNode.js"></script>
+<div id="log"></div>
+<script>
+test_create("createTextNode", Text, 3, "#text");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createTreeWalker-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createTreeWalker-expected.txt
new file mode 100644
index 0000000..f5d55b3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createTreeWalker-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+PASS Required arguments to createTreeWalker should be required. 
+PASS Optional arguments to createTreeWalker should be optional (1 passed). 
+PASS Optional arguments to createTreeWalker should be optional (2 passed). 
+PASS Optional arguments to createTreeWalker should be optional (3 passed, null). 
+FAIL Optional arguments to createTreeWalker should be optional (3 passed, function). assert_equals: expected (function) function "function () {}" but got (object) object "[object NodeFilter]"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createTreeWalker.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createTreeWalker.html
new file mode 100644
index 0000000..b1a2c3d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createTreeWalker.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Document.createTreeWalker</title>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+  assert_throws(new TypeError(), function() {
+    document.createTreeWalker();
+  });
+}, "Required arguments to createTreeWalker should be required.");
+test(function() {
+  var tw = document.createTreeWalker(document.body);
+  assert_equals(tw.root, document.body);
+  assert_equals(tw.currentNode, document.body);
+  assert_equals(tw.whatToShow, 0xFFFFFFFF);
+  assert_equals(tw.filter, null);
+}, "Optional arguments to createTreeWalker should be optional (1 passed).");
+test(function() {
+  var tw = document.createTreeWalker(document.body, 42);
+  assert_equals(tw.root, document.body);
+  assert_equals(tw.currentNode, document.body);
+  assert_equals(tw.whatToShow, 42);
+  assert_equals(tw.filter, null);
+}, "Optional arguments to createTreeWalker should be optional (2 passed).");
+test(function() {
+  var tw = document.createTreeWalker(document.body, 42, null);
+  assert_equals(tw.root, document.body);
+  assert_equals(tw.currentNode, document.body);
+  assert_equals(tw.whatToShow, 42);
+  assert_equals(tw.filter, null);
+}, "Optional arguments to createTreeWalker should be optional (3 passed, null).");
+test(function() {
+  var fn = function() {};
+  var tw = document.createTreeWalker(document.body, 42, fn);
+  assert_equals(tw.root, document.body);
+  assert_equals(tw.currentNode, document.body);
+  assert_equals(tw.whatToShow, 42);
+  assert_equals(tw.filter, fn);
+}, "Optional arguments to createTreeWalker should be optional (3 passed, function).");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-doctype-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-doctype-expected.txt
new file mode 100644
index 0000000..fcffef53
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-doctype-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+PASS Window document with doctype 
+FAIL new Document() Illegal constructor
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-doctype.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-doctype.html
new file mode 100644
index 0000000..6b4396e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-doctype.html
@@ -0,0 +1,21 @@
+<!--  comment  -->
+<!doctype html>
+<meta charset=utf-8>
+<title>Document.doctype</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-doctype">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  assert_true(document.doctype instanceof DocumentType,
+              "Doctype should be a DocumentType");
+  assert_equals(document.doctype, document.childNodes[1]);
+}, "Window document with doctype");
+
+test(function() {
+  var newdoc = new Document();
+  newdoc.appendChild(newdoc.createElement("html"));
+  assert_equals(newdoc.doctype, null);
+}, "new Document()");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementById.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementById.html
new file mode 100644
index 0000000..f4c1604
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementById.html
@@ -0,0 +1,350 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.getElementById</title>
+<link rel="author" title="Tetsuharu OHZEKI" href="mailto:saneyuki.snyk@gmail.com">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementbyid">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<body>
+  <div id="log"></div>
+
+  <!--  test 0  -->
+  <div id=""></div>
+
+  <!--  test 1  -->
+  <div id="test1"></div>
+
+  <!--  test 5  -->
+  <div id="test5" data-name="1st">
+    <p id="test5" data-name="2nd">P</p>
+    <input id="test5" type="submit" value="Submit" data-name="3rd">
+  </div>
+
+  <!--  test 15  -->
+  <div id="outer">
+    <div id="middle">
+      <div id="inner"></div>
+    </div>
+  </div>
+
+<script>
+  var gBody = document.getElementsByTagName("body")[0];
+
+  test(function() {
+    assert_equals(document.getElementById(""), null);
+  }, "Calling document.getElementById with an empty string argument.");
+
+  test(function() {
+    var element = document.createElement("div");
+    element.setAttribute("id", "null");
+    document.body.appendChild(element);
+    this.add_cleanup(function() { document.body.removeChild(element) });
+    assert_equals(document.getElementById(null), element);
+  }, "Calling document.getElementById with a null argument.");
+
+  test(function() {
+    var element = document.createElement("div");
+    element.setAttribute("id", "undefined");
+    document.body.appendChild(element);
+    this.add_cleanup(function() { document.body.removeChild(element) });
+    assert_equals(document.getElementById(undefined), element);
+  }, "Calling document.getElementById with an undefined argument.");
+
+
+  test(function() {
+    var bar = document.getElementById("test1");
+    assert_not_equals(bar, null, "should not be null");
+    assert_equals(bar.tagName, "DIV", "should have expected tag name.");
+    assert_true(bar instanceof HTMLDivElement, "should be a valid Element instance");
+  }, "on static page");
+
+
+  test(function() {
+    var TEST_ID = "test2";
+
+    var test = document.createElement("div");
+    test.setAttribute("id", TEST_ID);
+    gBody.appendChild(test);
+
+    // test: appended element
+    var result = document.getElementById(TEST_ID);
+    assert_not_equals(result, null, "should not be null.");
+    assert_equals(result.tagName, "DIV", "should have appended element's tag name");
+    assert_true(result instanceof HTMLDivElement, "should be a valid Element instance");
+
+    // test: removed element
+    gBody.removeChild(test);
+    var removed = document.getElementById(TEST_ID);
+    // `document.getElementById()` returns `null` if there is none.
+    // https://dom.spec.whatwg.org/#dom-nonelementparentnode-getelementbyid
+    assert_equals(removed, null, "should not get removed element.");
+  }, "Document.getElementById with a script-inserted element");
+
+
+  test(function() {
+    // setup fixtures.
+    var TEST_ID = "test3";
+    var test = document.createElement("div");
+    test.setAttribute("id", TEST_ID);
+    gBody.appendChild(test);
+
+    // update id
+    var UPDATED_ID = "test3-updated";
+    test.setAttribute("id", UPDATED_ID);
+    var e = document.getElementById(UPDATED_ID);
+    assert_equals(e, test, "should get the element with id.");
+
+    var old = document.getElementById(TEST_ID);
+    assert_equals(old, null, "shouldn't get the element by the old id.");
+
+    // remove id.
+    test.removeAttribute("id");
+    var e2 = document.getElementById(UPDATED_ID);
+    assert_equals(e2, null, "should return null when the passed id is none in document.");
+  }, "update `id` attribute via setAttribute/removeAttribute");
+
+
+  test(function() {
+    var TEST_ID = "test4-should-not-exist";
+
+    var e = document.createElement('div');
+    e.setAttribute("id", TEST_ID);
+
+    assert_equals(document.getElementById(TEST_ID), null, "should be null");
+    document.body.appendChild(e);
+    assert_equals(document.getElementById(TEST_ID), e, "should be the appended element");
+  }, "Ensure that the id attribute only affects elements present in a document");
+
+
+  test(function() {
+    // the method should return the 1st element.
+    var TEST_ID = "test5";
+    var target = document.getElementById(TEST_ID);
+    assert_not_equals(target, null, "should not be null");
+    assert_equals(target.getAttribute("data-name"), "1st", "should return the 1st");
+
+    // even if after the new element was appended.
+    var element4 = document.createElement("div");
+    element4.setAttribute("id", TEST_ID);
+    element4.setAttribute("data-name", "4th");
+    gBody.appendChild(element4);
+    var target2 = document.getElementById(TEST_ID);
+    assert_not_equals(target2, null, "should not be null");
+    assert_equals(target2.getAttribute("data-name"), "1st", "should be the 1st");
+
+    // should return the next element after removed the subtree including the 1st element.
+    target2.parentNode.removeChild(target2);
+    var target3 = document.getElementById(TEST_ID);
+    assert_not_equals(target3, null, "should not be null");
+    assert_equals(target3.getAttribute("data-name"), "4th", "should be the 4th");
+  }, "in tree order, within the context object's tree");
+
+
+  test(function() {
+    var TEST_ID = "test6";
+    var s = document.createElement("div");
+    s.setAttribute("id", TEST_ID);
+    // append to Element, not Document.
+    document.createElement("div").appendChild(s);
+
+    assert_equals(document.getElementById(TEST_ID), null, "should be null");
+  }, "Modern browsers optimize this method with using internal id cache. " +
+     "This test checks that their optimization should effect only append to `Document`, not append to `Node`.");
+
+
+  test(function() {
+    var TEST_ID = "test7"
+    var element = document.createElement("div");
+    element.setAttribute("id", TEST_ID);
+    gBody.appendChild(element);
+
+    var target = document.getElementById(TEST_ID);
+    assert_equals(target, element, "should return the element before changing the value");
+
+    element.attributes[0].value = TEST_ID + "-updated";
+    var target2 = document.getElementById(TEST_ID);
+    assert_equals(target2, null, "should return null after updated id via Attr.value");
+    var target3 = document.getElementById(TEST_ID + "-updated");
+    assert_equals(target3, element, "should be equal to the updated element.");
+  }, "changing attribute's value via `Attr` gotten from `Element.attribute`.");
+
+
+  test(function() {
+    var TEST_ID = "test8";
+
+    // setup fixture
+    var element = document.createElement("div");
+    element.setAttribute("id", TEST_ID + "-fixture");
+    gBody.appendChild(element);
+
+    // add id-ed element with using innerHTML
+    element.innerHTML = "<div id='"+ TEST_ID +"'></div>";
+    var test = document.getElementById(TEST_ID);
+    assert_equals(test, element.firstChild, "should not be null");
+    assert_equals(test.tagName, "DIV", "should have expected tag name.");
+    assert_true(test instanceof HTMLDivElement, "should be a valid Element instance");
+  }, "add id attribute via innerHTML");
+
+
+  test(function() {
+    var TEST_ID = "test9";
+
+    // add fixture
+    var fixture = document.createElement("div");
+    fixture.setAttribute("id", TEST_ID + "-fixture");
+    gBody.appendChild(fixture);
+
+    var element = document.createElement("div");
+    element.setAttribute("id", TEST_ID);
+    fixture.appendChild(element);
+
+    // check 'getElementById' should get the 'element'
+    assert_equals(document.getElementById(TEST_ID), element, "should not be null");
+
+    // remove id-ed element with using innerHTML (clear 'element')
+    fixture.innerHTML = "";
+    var test = document.getElementById(TEST_ID);
+    assert_equals(test, null, "should be null.");
+  }, "remove id attribute via innerHTML");
+
+
+  test(function() {
+    var TEST_ID = "test10";
+
+    // setup fixture
+    var element = document.createElement("div");
+    element.setAttribute("id", TEST_ID + "-fixture");
+    gBody.appendChild(element);
+
+    // add id-ed element with using outerHTML
+    element.outerHTML = "<div id='"+ TEST_ID +"'></div>";
+    var test = document.getElementById(TEST_ID);
+    assert_not_equals(test, null, "should not be null");
+    assert_equals(test.tagName, "DIV", "should have expected tag name.");
+    assert_true(test instanceof HTMLDivElement,"should be a valid Element instance");
+  }, "add id attribute via outerHTML");
+
+
+  test(function() {
+    var TEST_ID = "test11";
+
+    var element = document.createElement("div");
+    element.setAttribute("id", TEST_ID);
+    gBody.appendChild(element);
+
+    var test = document.getElementById(TEST_ID);
+    assert_equals(test, element, "should be equal to the appended element.");
+
+    // remove id-ed element with using outerHTML
+    element.outerHTML = "<div></div>";
+    var test = document.getElementById(TEST_ID);
+    assert_equals(test, null, "should be null.");
+  }, "remove id attribute via outerHTML");
+
+
+  test(function() {
+    // setup fixtures.
+    var TEST_ID = "test12";
+    var test = document.createElement("div");
+    test.id = TEST_ID;
+    gBody.appendChild(test);
+
+    // update id
+    var UPDATED_ID = TEST_ID + "-updated";
+    test.id =  UPDATED_ID;
+    var e = document.getElementById(UPDATED_ID);
+    assert_equals(e, test, "should get the element with id.");
+
+    var old = document.getElementById(TEST_ID);
+    assert_equals(old, null, "shouldn't get the element by the old id.");
+
+    // remove id.
+    test.id = "";
+    var e2 = document.getElementById(UPDATED_ID);
+    assert_equals(e2, null, "should return null when the passed id is none in document.");
+  }, "update `id` attribute via element.id");
+
+
+  test(function() {
+    var TEST_ID = "test13";
+
+    var create_same_id_element = function (order) {
+      var element = document.createElement("div");
+      element.setAttribute("id", TEST_ID);
+      element.setAttribute("data-order", order);// for debug
+      return element;
+    };
+
+    // create fixture
+    var container = document.createElement("div");
+    container.setAttribute("id", TEST_ID + "-fixture");
+    gBody.appendChild(container);
+
+    var element1 = create_same_id_element("1");
+    var element2 = create_same_id_element("2");
+    var element3 = create_same_id_element("3");
+    var element4 = create_same_id_element("4");
+
+    // append element: 2 -> 4 -> 3 -> 1
+    container.appendChild(element2);
+    container.appendChild(element4);
+    container.insertBefore(element3, element4);
+    container.insertBefore(element1, element2);
+
+
+    var test = document.getElementById(TEST_ID);
+    assert_equals(test, element1, "should return 1st element");
+    container.removeChild(element1);
+
+    test = document.getElementById(TEST_ID);
+    assert_equals(test, element2, "should return 2nd element");
+    container.removeChild(element2);
+
+    test = document.getElementById(TEST_ID);
+    assert_equals(test, element3, "should return 3rd element");
+    container.removeChild(element3);
+
+    test = document.getElementById(TEST_ID);
+    assert_equals(test, element4, "should return 4th element");
+    container.removeChild(element4);
+
+
+  }, "where insertion order and tree order don't match");
+
+  test(function() {
+    var TEST_ID = "test14";
+    var a = document.createElement("a");
+    var b = document.createElement("b");
+    a.appendChild(b);
+    b.id = TEST_ID;
+    assert_equals(document.getElementById(TEST_ID), null);
+
+    gBody.appendChild(a);
+    assert_equals(document.getElementById(TEST_ID), b);
+  }, "Inserting an id by inserting its parent node");
+
+  test(function () {
+    var TEST_ID = "test15"
+    var outer = document.getElementById("outer");
+    var middle = document.getElementById("middle");
+    var inner = document.getElementById("inner");
+    outer.removeChild(middle);
+
+    var new_el = document.createElement("h1");
+    new_el.id = "heading";
+    inner.appendChild(new_el);
+    // the new element is not part of the document since
+    // "middle" element was removed previously
+    assert_equals(document.getElementById("heading"), null);
+  }, "Document.getElementById must not return nodes not present in document");
+
+  // TODO:
+  // id attribute in a namespace
+
+
+  // TODO:
+  // SVG + MathML elements with id attributes
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-expected.txt
new file mode 100644
index 0000000..0149f41e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-expected.txt
@@ -0,0 +1,23 @@
+This is a testharness.js-based test.
+PASS Interfaces 
+PASS Caching is allowed 
+FAIL Shouldn't be able to set unsigned properties on a HTMLCollection (non-strict mode) assert_equals: expected (undefined) undefined but got (string) "foopy"
+FAIL Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode) assert_throws: function "function () {
+      "use strict";
+      l[5] = "foopy"
+    }" did not throw
+PASS Should be able to set expando shadowing a proto prop (item) 
+PASS Should be able to set expando shadowing a proto prop (namedItem) 
+FAIL hasOwnProperty, getOwnPropertyDescriptor, getOwnPropertyNames assert_true: desc.enumerable expected true got false
+PASS HTML element with uppercase tagName never matches in HTML Documents 
+PASS Element in non-HTML namespace, no prefix, lowercase name 
+PASS Element in non-HTML namespace, no prefix, uppercase name 
+PASS Element in non-HTML namespace, prefix, lowercase name 
+PASS Element in non-HTML namespace, prefix, uppercase name 
+FAIL Element in HTML namespace, no prefix, non-ascii characters in name assert_equals: expected "aÇ" but got "aç"
+PASS Element in non-HTML namespace, non-ascii characters in name 
+FAIL Element in HTML namespace, prefix, non-ascii characters in name assert_array_equals: All uppercase input lengths differ, expected 1 got 0
+PASS Element in non-HTML namespace, prefix, non-ascii characters in name 
+PASS getElementsByTagName('*') 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-xhtml.xhtml
new file mode 100644
index 0000000..bdafb07
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-xhtml.xhtml
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Document.getElementsByTagName</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<pre id="x"></pre>
+<script>
+test(function() {
+  var t = document.body.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "I"))
+  this.add_cleanup(function() {document.body.removeChild(t)})
+  assert_equals(t.localName, "I")
+  assert_equals(t.tagName, "I")
+  assert_array_equals(document.getElementsByTagName("I"), [t])
+  assert_array_equals(document.getElementsByTagName("i"), [])
+  assert_array_equals(document.body.getElementsByTagName("I"), [t])
+  assert_array_equals(document.body.getElementsByTagName("i"), [])
+}, "HTML element with uppercase tag name matches in XHTML documents")
+
+test(function() {
+  var t = document.body.appendChild(document.createElementNS("test", "st"))
+  this.add_cleanup(function() {document.body.removeChild(t)})
+  assert_array_equals(document.getElementsByTagName("st"), [t])
+  assert_array_equals(document.getElementsByTagName("ST"), [])
+}, "Element in non-HTML namespace, no prefix, lowercase name")
+
+test(function() {
+  var t = document.body.appendChild(document.createElementNS("test", "ST"))
+  this.add_cleanup(function() {document.body.removeChild(t)})
+  assert_array_equals(document.getElementsByTagName("ST"), [t])
+  assert_array_equals(document.getElementsByTagName("st"), [])
+}, "Element in non-HTML namespace, no prefix, uppercase name")
+
+test(function() {
+  var t = document.body.appendChild(document.createElementNS("test", "te:st"))
+  this.add_cleanup(function() {document.body.removeChild(t)})
+  assert_array_equals(document.getElementsByTagName("st"), [t])
+  assert_array_equals(document.getElementsByTagName("ST"), [])
+}, "Element in non-HTML namespace, prefix, lowercase name")
+
+test(function() {
+  var t = document.body.appendChild(document.createElementNS("test", "te:ST"))
+  this.add_cleanup(function() {document.body.removeChild(t)})
+  assert_array_equals(document.getElementsByTagName("ST"), [t])
+  assert_array_equals(document.getElementsByTagName("st"), [])
+  assert_array_equals(document.getElementsByTagName("te:st"), [])
+  assert_array_equals(document.getElementsByTagName("te:ST"), [])
+}, "Element in non-HTML namespace, prefix, uppercase name")
+
+test(function() {
+  var t = document.body.appendChild(document.createElement("AÇ"))
+  this.add_cleanup(function() {document.body.removeChild(t)})
+  assert_array_equals(document.getElementsByTagName("AÇ"), [t], "All uppercase input")
+  assert_array_equals(document.getElementsByTagName("aÇ"), [], "Ascii lowercase input")
+  assert_array_equals(document.getElementsByTagName("aç"), [], "All lowercase input")
+}, "Element in HTML namespace, no prefix, non-ascii characters in name")
+
+test(function() {
+  var t = document.body.appendChild(document.createElementNS("test", "AÇ"))
+  this.add_cleanup(function() {document.body.removeChild(t)})
+  assert_array_equals(document.getElementsByTagName("AÇ"), [t], "All uppercase input")
+  assert_array_equals(document.getElementsByTagName("aÇ"), [], "Ascii lowercase input")
+  assert_array_equals(document.getElementsByTagName("aç"), [], "All lowercase input")
+}, "Element in non-HTML namespace, non-ascii characters in name")
+
+test(function() {
+  var t = document.body.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "test:aÇ"))
+  this.add_cleanup(function() {document.body.removeChild(t)})
+  assert_array_equals(document.getElementsByTagName("AÇ"), [], "All uppercase input")
+  assert_array_equals(document.getElementsByTagName("aÇ"), [t], "Ascii lowercase input")
+  assert_array_equals(document.getElementsByTagName("aç"), [], "All lowercase input")
+}, "Element in HTML namespace, prefix, non-ascii characters in name")
+
+test(function() {
+  var t = document.body.appendChild(document.createElementNS("test", "test:AÇ"))
+  this.add_cleanup(function() {document.body.removeChild(t)})
+  assert_array_equals(document.getElementsByTagName("AÇ"), [t], "All uppercase input")
+  assert_array_equals(document.getElementsByTagName("aÇ"), [], "Ascii lowercase input")
+  assert_array_equals(document.getElementsByTagName("aç"), [], "All lowercase input")
+}, "Element in non-HTML namespace, prefix, non-ascii characters in name")
+
+test(function() {
+  var actual = document.getElementsByTagName("*");
+  var expected = [];
+  var get_elements = function(node) {
+    for (var i = 0; i &lt; node.childNodes.length; i++) {
+      var child = node.childNodes[i];
+      if (child.nodeType === child.ELEMENT_NODE) {
+        expected.push(child);
+        get_elements(child);
+      }
+    }
+  }
+  get_elements(document);
+  assert_array_equals(actual, expected);
+}, "getElementsByTagName('*')")
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName.html
new file mode 100644
index 0000000..d5750bf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.getElementsByTagName</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagname">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="Document-Element-getElementsByTagName.js"></script>
+<div id="log"></div>
+<script>
+test_getElementsByTagName(document, document.body);
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagNameNS.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagNameNS.html
new file mode 100644
index 0000000..c0ff8440
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagNameNS.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.getElementsByTagNameNS</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagnamens">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="Document-Element-getElementsByTagNameNS.js"></script>
+<div id="log"></div>
+<script>
+test_getElementsByTagNameNS(document, document.body);
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-implementation.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-implementation.html
new file mode 100644
index 0000000..10704f1e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-implementation.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.implementation</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-implementation">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var implementation = document.implementation;
+  assert_true(implementation instanceof DOMImplementation,
+              "implementation should implement DOMImplementation");
+  assert_equals(document.implementation, implementation);
+}, "Getting implementation off the same document");
+
+test(function() {
+  var doc = document.implementation.createHTMLDocument();
+  assert_not_equals(document.implementation, doc.implementation);
+}, "Getting implementation off different documents");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-importNode.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-importNode.html
new file mode 100644
index 0000000..4207740
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-importNode.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.importNode</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-importnode">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var doc = document.implementation.createHTMLDocument("Title");
+  var div = doc.body.appendChild(doc.createElement("div"));
+  div.appendChild(doc.createElement("span"));
+  assert_equals(div.ownerDocument, doc);
+  assert_equals(div.firstChild.ownerDocument, doc);
+  var newDiv = document.importNode(div);
+  assert_equals(div.ownerDocument, doc);
+  assert_equals(div.firstChild.ownerDocument, doc);
+  assert_equals(newDiv.ownerDocument, document);
+  assert_equals(newDiv.firstChild, null);
+}, "No 'deep' argument.")
+test(function() {
+  var doc = document.implementation.createHTMLDocument("Title");
+  var div = doc.body.appendChild(doc.createElement("div"));
+  div.appendChild(doc.createElement("span"));
+  assert_equals(div.ownerDocument, doc);
+  assert_equals(div.firstChild.ownerDocument, doc);
+  var newDiv = document.importNode(div, undefined);
+  assert_equals(div.ownerDocument, doc);
+  assert_equals(div.firstChild.ownerDocument, doc);
+  assert_equals(newDiv.ownerDocument, document);
+  assert_equals(newDiv.firstChild, null);
+}, "Undefined 'deep' argument.")
+test(function() {
+  var doc = document.implementation.createHTMLDocument("Title");
+  var div = doc.body.appendChild(doc.createElement("div"));
+  div.appendChild(doc.createElement("span"));
+  assert_equals(div.ownerDocument, doc);
+  assert_equals(div.firstChild.ownerDocument, doc);
+  var newDiv = document.importNode(div, true);
+  assert_equals(div.ownerDocument, doc);
+  assert_equals(div.firstChild.ownerDocument, doc);
+  assert_equals(newDiv.ownerDocument, document);
+  assert_equals(newDiv.firstChild.ownerDocument, document);
+}, "True 'deep' argument.")
+test(function() {
+  var doc = document.implementation.createHTMLDocument("Title");
+  var div = doc.body.appendChild(doc.createElement("div"));
+  div.appendChild(doc.createElement("span"));
+  assert_equals(div.ownerDocument, doc);
+  assert_equals(div.firstChild.ownerDocument, doc);
+  var newDiv = document.importNode(div, false);
+  assert_equals(div.ownerDocument, doc);
+  assert_equals(div.firstChild.ownerDocument, doc);
+  assert_equals(newDiv.ownerDocument, document);
+  assert_equals(newDiv.firstChild, null);
+}, "False 'deep' argument.")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DocumentType-literal-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DocumentType-literal-xhtml.xhtml
new file mode 100644
index 0000000..a430ccb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DocumentType-literal-xhtml.xhtml
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "STAFF" "staffNS.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>DocumentType literals</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-name"/>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-publicid"/>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-systemid"/>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"/>
+<script>
+test(function() {
+  var doctype = document.firstChild;
+  assert_true(doctype instanceof DocumentType)
+  assert_equals(doctype.name, "html")
+  assert_equals(doctype.publicId, 'STAFF')
+  assert_equals(doctype.systemId, 'staffNS.dtd')
+})
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DocumentType-literal.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DocumentType-literal.html
new file mode 100644
index 0000000..51eb327
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DocumentType-literal.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "STAFF" "staffNS.dtd">
+<title>DocumentType literals</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-name">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-publicid">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-systemid">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var doctype = document.firstChild;
+  assert_true(doctype instanceof DocumentType)
+  assert_equals(doctype.name, "html")
+  assert_equals(doctype.publicId, 'STAFF')
+  assert_equals(doctype.systemId, 'staffNS.dtd')
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DocumentType-remove.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DocumentType-remove.html
new file mode 100644
index 0000000..63f312e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/DocumentType-remove.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>DocumentType.remove</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-childnode-remove">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="ChildNode-remove.js"></script>
+<div id=log></div>
+<script>
+var node, parentNode;
+setup(function() {
+  node = document.implementation.createDocumentType("html", "", "");
+  parentNode = document.implementation.createDocument(null, "", null);
+});
+testRemove(node, parentNode, "doctype");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElement-null-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElement-null-xhtml.xhtml
new file mode 100644
index 0000000..367ae85
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElement-null-xhtml.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Null Test</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of firstElementChild and lastChildElement returning null</h1>
+<div id="log"></div>
+<p id="parentEl" style="font-weight:bold;">Test.</p>
+<script><![CDATA[
+test(function() {
+  var parentEl = document.getElementById("parentEl")
+  assert_equals(parentEl.firstElementChild, null)
+  assert_equals(parentEl.lastElementChild, null)
+})
+]]></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElement-null.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElement-null.html
new file mode 100644
index 0000000..9e91cb95
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElement-null.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Null test</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<h1>Test of firstElementChild and lastChildElement returning null</h1>
+<div id="log"></div>
+<p id="parentEl" style="font-weight:bold;">Test.</p>
+<script>
+test(function() {
+  var parentEl = document.getElementById("parentEl")
+  assert_equals(parentEl.firstElementChild, null)
+  assert_equals(parentEl.lastElementChild, null)
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add-xhtml.xhtml
new file mode 100644
index 0000000..04dfd15
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add-xhtml.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dynamic Adding of Elements</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of Dynamic Adding of Elements</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is
+<span id="first_element_child" style="font-weight:bold;">logged above.</span></p>
+<script><![CDATA[
+test(function() {
+  var parentEl = document.getElementById("parentEl");
+  var newChild = document.createElement("span");
+  parentEl.appendChild(newChild);
+  assert_equals(parentEl.childElementCount, 2)
+})
+]]></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add.html
new file mode 100644
index 0000000..e954fe8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Dynamic Adding of Elements</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<h1>Test of Dynamic Adding of Elements</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is
+<span id="first_element_child" style="font-weight:bold;">logged above.</span></p>
+<script>
+test(function() {
+  var parentEl = document.getElementById("parentEl");
+  var newChild = document.createElement("span");
+  parentEl.appendChild(newChild);
+  assert_equals(parentEl.childElementCount, 2)
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove-xhtml.xhtml
new file mode 100644
index 0000000..d08625ea
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove-xhtml.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dynamic Removal of Elements</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of Removal Adding of Elements</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is
+<span id="first_element_child" style="font-weight:bold;">logged above.</span><span id="last_element_child"> </span></p>
+<script><![CDATA[
+test(function() {
+  var parentEl = document.getElementById("parentEl");
+  var lec = parentEl.lastElementChild;
+  parentEl.removeChild(lec);
+  assert_equals(parentEl.childElementCount, 1)
+})
+]]></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove.html
new file mode 100644
index 0000000..8a3118ab
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Dynamic Removal of Elements</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<h1>Test of Dynamic Removal of Elements</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is
+<span id="first_element_child" style="font-weight:bold;">unknown.</span><span id="last_element_child"> </span></p>
+<script>
+test(function() {
+  var parentEl = document.getElementById("parentEl");
+  var lec = parentEl.lastElementChild;
+  parentEl.removeChild(lec);
+  assert_equals(parentEl.childElementCount, 1)
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-nochild-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-nochild-xhtml.xhtml
new file mode 100644
index 0000000..03560c7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-nochild-xhtml.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>childElementCount without Child Element Nodes</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of childElementCount with No Child Element Nodes</h1>
+<div id="log"></div>
+<p id="parentEl" style="font-weight:bold;">Test.</p>
+<script><![CDATA[
+test(function() {
+  var parentEl = document.getElementById("parentEl")
+  assert_equals(parentEl.childElementCount, 0)
+})
+]]></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-nochild.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-nochild.html
new file mode 100644
index 0000000..08fcc32
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-nochild.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>childElementCount without Child Element Nodes</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<h1>Test of childElementCount with No Child Element Nodes</h1>
+<div id="log"></div>
+<p id="parentEl" style="font-weight:bold;">Test.</p>
+<script>
+test(function() {
+  var parentEl = document.getElementById("parentEl")
+  assert_equals(parentEl.childElementCount, 0)
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-xhtml.xhtml
new file mode 100644
index 0000000..e96ef68
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount-xhtml.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>childElementCount</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of childElementCount</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child"><span>this</span> <span>test</span></span> is
+<span id="middle_element_child" style="font-weight:bold;">unknown.</span>
+
+
+
+<span id="last_element_child" style="display:none;">fnord</span> </p>
+<script><![CDATA[
+test(function() {
+  var parentEl = document.getElementById("parentEl")
+  assert_true("childElementCount" in parentEl)
+  assert_equals(parentEl.childElementCount, 3)
+})
+]]></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount.html
new file mode 100644
index 0000000..f0f8141
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-childElementCount.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>childElementCount</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<h1>Test of childElementCount</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child"><span>this</span> <span>test</span></span> is
+<span id="middle_element_child" style="font-weight:bold;">given above.</span>
+
+
+
+<span id="last_element_child" style="display:none;">fnord</span> </p>
+<script>
+test(function() {
+  var parentEl = document.getElementById("parentEl")
+  assert_true("childElementCount" in parentEl)
+  assert_equals(parentEl.childElementCount, 3)
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-children-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-children-expected.txt
new file mode 100644
index 0000000..40506e3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-children-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+PASS HTMLCollection edge cases 
+FAIL HTMLCollection edge cases 1 assert_array_equals: lengths differ, expected 6 got 9
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-children.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-children.html
new file mode 100644
index 0000000..88d6a5d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-children.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<title>HTMLCollection edge cases</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test"><img><img id=foo><img id=foo><img name="bar"></div>
+<script>
+setup(function() {
+  // Add some non-HTML elements in there to test what happens with those.
+  var container = document.getElementById("test");
+  var child = document.createElementNS("", "img");
+  child.setAttribute("id", "baz");
+  container.appendChild(child);
+
+  child = document.createElementNS("", "img");
+  child.setAttribute("name", "qux");
+  container.appendChild(child);
+});
+
+test(function() {
+  var container = document.getElementById("test");
+  var result = container.children.item("foo");
+  assert_true(result instanceof Element, "Expected an Element.");
+  assert_false(result.hasAttribute("id"), "Expected the IDless Element.")
+})
+
+test(function() {
+  var container = document.getElementById("test");
+  var list = container.children;
+  var result = [];
+  for (var p in list) {
+    if (list.hasOwnProperty(p)) {
+      result.push(p);
+    }
+  }
+  assert_array_equals(result, ['0', '1', '2', '3', '4', '5']);
+  result = Object.getOwnPropertyNames(list);
+  assert_array_equals(result, ['0', '1', '2', '3', '4', '5', 'foo', 'bar', 'baz']);
+
+  // Mapping of exposed names to their indices in the list.
+  var exposedNames = { 'foo': 1, 'bar': 3, 'baz': 4 };
+  for (var exposedName in exposedNames) {
+    assert_true(exposedName in list);
+    assert_true(list.hasOwnProperty(exposedName));
+    assert_equals(list[exposedName], list.namedItem(exposedName));
+    assert_equals(list[exposedName], list.item(exposedNames[exposedName]));
+    assert_true(list[exposedName] instanceof Element);
+  }
+
+  var unexposedNames = ['qux'];
+  for (var unexposedName of unexposedNames) {
+    assert_false(unexposedName in list);
+    assert_false(list.hasOwnProperty(unexposedName));
+    assert_equals(list[unexposedName], undefined);
+    assert_equals(list.namedItem(unexposedName), null);
+  }
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-classlist-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-classlist-expected.txt
new file mode 100644
index 0000000..077f8ca71
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-classlist-expected.txt
@@ -0,0 +1,67 @@
+This is a testharness.js-based test.
+PASS Element.classList must exist as an object 
+PASS Element.classList must exist as an object even if the element has no class attribute 
+PASS DOMTokenList should be exposed for prototyping 
+PASS prototyping DOMTokenList should work 
+PASS Element.classList must implement DOMTokenList 
+PASS CSS .foo selectors must not match elements without any class 
+FAIL classList must be correct for an element that has classes assert_equals: duplicates in initial string should be removed per https://dom.spec.whatwg.org/#concept-class expected 1 but got 2
+PASS classList.length must be 0 for an element that has no classes 
+PASS classList must not contain an undefined class 
+PASS classList.item() must return null for out-of-range index 
+PASS classList.item() must return null for negative index 
+PASS classList[index] must be undefined for out-of-range index 
+PASS classList[index] must be undefined for negative index 
+FAIL className should contain initial markup whitespace assert_equals: expected " " but got ""
+FAIL empty classList should return the empty string since the ordered set parser skip the whitespaces assert_equals: implicit expected "" but got " "
+PASS .contains(empty_string) must throw a SYNTAX_ERR 
+PASS .add(empty_string) must throw a SYNTAX_ERR 
+PASS .remove(empty_string) must throw a SYNTAX_ERR 
+PASS .toggle(empty_string) must throw a SYNTAX_ERR 
+PASS .contains(string_with_spaces) must throw an INVALID_CHARACTER_ERR 
+PASS .add(string_with_spaces) must throw an INVALID_CHARACTER_ERR 
+PASS .remove(string_with_spaces) must throw an INVALID_CHARACTER_ERR 
+PASS .toggle(string_with_spaces) must throw an INVALID_CHARACTER_ERR 
+PASS computed style must update when setting .className 
+PASS classList.contains must update when .className is changed 
+PASS classList.contains must be case sensitive 
+PASS classList.contains must not match when punctuation characters are added 
+PASS classList.add must not cause the CSS selector to stop matching 
+PASS classList.add must not remove existing classes 
+PASS classList.contains case sensitivity must match a case-specific string 
+PASS classList.length must correctly reflect the number of tokens 
+PASS classList.item(0) must return the first token 
+PASS classList.item must return case-sensitive strings and preserve token order 
+PASS classList[0] must return the first token 
+PASS classList[index] must return case-sensitive strings and preserve token order 
+PASS classList[index] must still be undefined for out-of-range index when earlier indexes exist 
+PASS className must update correctly when items have been added through classList 
+PASS classList must stringify correctly when items have been added 
+PASS classList.add should not add a token if it already exists 
+PASS classList.remove removes arguments passed, if they are present. 
+PASS classList.remove must remove existing tokens 
+PASS classList.remove must not break case-sensitive CSS selector matching 
+PASS classList.remove must remove duplicated tokens 
+PASS classList.remove must collapse whitespace around removed tokens 
+PASS classList.remove must collapse whitespaces around each token 
+FAIL classList.remove must collapse whitespaces around each token and remove duplicates assert_equals: implicit expected "token1" but got "token1 token1"
+PASS classList.remove must collapse whitespace when removing duplicate tokens 
+FAIL classList.add must collapse whitespaces and remove duplicates when adding a token that already exists assert_equals: implicit expected "token1" but got "  token1  token1  "
+PASS classList.toggle must toggle tokens case-sensitively when adding 
+PASS classList.toggle must not break case-sensitive CSS selector matching 
+PASS classList.toggle must be able to remove tokens 
+PASS classList.toggle must be case-sensitive when removing tokens 
+PASS CSS class selectors must stop matching when all classes have been removed 
+PASS className must be empty when all classes have been removed 
+PASS classList must stringify to an empty string when all classes have been removed 
+PASS classList.item(0) must return null when all classes have been removed 
+PASS classList[0] must be undefined when all classes have been removed 
+PASS classList.add should treat " " as a space 
+FAIL classList.add should treat \t as a space assert_equals: expected "a b" but got "a\tb"
+FAIL classList.add should treat \r as a space assert_equals: expected "a b" but got "a\rb"
+FAIL classList.add should treat \n as a space assert_equals: expected "a b" but got "a\nb"
+FAIL classList.add should treat \f as a space assert_equals: expected "a b" but got "a\fb"
+PASS classList.length must be read-only 
+PASS classList must be read-only 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-classlist.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-classlist.html
new file mode 100644
index 0000000..c25a12a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-classlist.html
@@ -0,0 +1,309 @@
+<!doctype html>
+<html>
+  <head class="test test">
+    <title class=" ">Element.classList in case-sensitive documents</title>
+    <link rel="help" href="https://dom.spec.whatwg.org/#concept-class">
+    <script type="text/javascript" src="../../../../resources/testharness.js"></script>
+    <script type="text/javascript" src="../../../../resources/testharnessreport.js"></script>
+    <style type="text/css">
+.foo { font-style: italic; }
+    </style>
+    <script type="text/javascript">
+var elem = document.getElementsByTagName('title')[0], secondelem = document.getElementsByTagName('head')[0];
+test(function () {
+  assert_equals( typeof elem.classList, 'object', 'critical test; ignore any results after this' );
+}, 'Element.classList must exist as an object');
+test(function () {
+  assert_equals( typeof document.documentElement.classList, 'object' );
+}, 'Element.classList must exist as an object even if the element has no class attribute');
+test(function () {
+  assert_true( !!window.DOMTokenList );
+}, 'DOMTokenList should be exposed for prototyping');
+test(function () {
+  DOMTokenList.prototype.customProperty = true;
+  assert_true( elem.classList.customProperty );
+}, 'prototyping DOMTokenList should work');
+test(function () {
+  assert_true( elem.classList instanceof window.DOMTokenList );
+  assert_equals( elem.classList.constructor, window.DOMTokenList );
+}, 'Element.classList must implement DOMTokenList');
+test(function () {
+  assert_not_equals( getComputedStyle(elem,null).fontStyle, 'italic', 'critical test; required by the testsuite' );
+}, 'CSS .foo selectors must not match elements without any class');
+test(function () {
+  assert_equals( secondelem.classList.length, 1, 'duplicates in initial string should be removed per https://dom.spec.whatwg.org/#concept-class' );
+  assert_equals( secondelem.classList.item(0), 'test' );
+  assert_true( secondelem.classList.contains('test') );
+}, 'classList must be correct for an element that has classes');
+test(function () {
+  assert_equals( elem.classList.length, 0 );
+}, 'classList.length must be 0 for an element that has no classes');
+test(function () {
+  assert_false( elem.classList.contains('foo') );
+}, 'classList must not contain an undefined class');
+test(function () {
+  assert_equals( elem.classList.item(0), null );
+}, 'classList.item() must return null for out-of-range index');
+test(function () {
+  assert_equals( elem.classList.item(-1), null );
+}, 'classList.item() must return null for negative index');
+test(function () {
+  /* the normative part of the spec states that:
+  "unless tokens is empty, in which case there are no supported property indices"
+  ...
+  "The term[...] supported property indices [is] used as defined in the WebIDL specification."
+  WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
+  assert_equals( elem.classList[0], undefined );
+}, 'classList[index] must be undefined for out-of-range index');
+test(function () {
+  assert_equals( elem.classList[-1], undefined );
+}, 'classList[index] must be undefined for negative index');
+test(function () {
+  assert_equals( elem.className, ' ' );
+}, 'className should contain initial markup whitespace');
+test(function () {
+  assert_equals( elem.classList + '', '', 'implicit' );
+  assert_equals( elem.classList.toString(), '', 'explicit' );
+}, 'empty classList should return the empty string since the ordered set parser skip the whitespaces');
+test(function () {
+  assert_throws( 'SYNTAX_ERR', function () { elem.classList.contains(''); } );
+}, '.contains(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+  assert_throws( 'SYNTAX_ERR', function () { elem.classList.add(''); } );
+}, '.add(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+  assert_throws( 'SYNTAX_ERR', function () { elem.classList.remove(''); } );
+}, '.remove(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+  assert_throws( 'SYNTAX_ERR', function () { elem.classList.toggle(''); } );
+}, '.toggle(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+  assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.contains('a b'); } );
+}, '.contains(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+  assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.add('a b'); } );
+}, '.add(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+  assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.remove('a b'); } );
+}, '.remove(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+  assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.toggle('a b'); } );
+}, '.toggle(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+elem.className = 'foo';
+test(function () {
+  assert_equals( getComputedStyle(elem,null).fontStyle, 'italic', 'critical test; required by the testsuite' );
+}, 'computed style must update when setting .className');
+test(function () {
+  assert_true( elem.classList.contains('foo') );
+}, 'classList.contains must update when .className is changed');
+test(function () {
+  assert_false( elem.classList.contains('FOO') );
+}, 'classList.contains must be case sensitive');
+test(function () {
+  assert_false( elem.classList.contains('foo.') );
+  assert_false( elem.classList.contains('foo)') );
+  assert_false( elem.classList.contains('foo\'') );
+  assert_false( elem.classList.contains('foo$') );
+  assert_false( elem.classList.contains('foo~') );
+  assert_false( elem.classList.contains('foo?') );
+  assert_false( elem.classList.contains('foo\\') );
+}, 'classList.contains must not match when punctuation characters are added');
+test(function () {
+  elem.classList.add('FOO');
+  assert_equals( getComputedStyle(elem,null).fontStyle, 'italic' );
+}, 'classList.add must not cause the CSS selector to stop matching');
+test(function () {
+  assert_true( elem.classList.contains('foo') );
+}, 'classList.add must not remove existing classes');
+test(function () {
+  assert_true( elem.classList.contains('FOO') );
+}, 'classList.contains case sensitivity must match a case-specific string');
+test(function () {
+  assert_equals( elem.classList.length, 2 );
+}, 'classList.length must correctly reflect the number of tokens');
+test(function () {
+  assert_equals( elem.classList.item(0), 'foo' );
+}, 'classList.item(0) must return the first token');
+test(function () {
+  assert_equals( elem.classList.item(1), 'FOO' );
+}, 'classList.item must return case-sensitive strings and preserve token order');
+test(function () {
+  assert_equals( elem.classList[0], 'foo' );
+}, 'classList[0] must return the first token');
+test(function () {
+  assert_equals( elem.classList[1], 'FOO' );
+}, 'classList[index] must return case-sensitive strings and preserve token order');
+test(function () {
+  /* the normative part of the spec states that:
+  "The object's supported property indices are the numbers in the range zero to the number of tokens in tokens minus one"
+  ...
+  "The term[...] supported property indices [is] used as defined in the WebIDL specification."
+  WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
+  assert_equals( elem.classList[2], undefined );
+}, 'classList[index] must still be undefined for out-of-range index when earlier indexes exist');
+test(function () {
+  assert_equals( elem.className, 'foo FOO' );
+}, 'className must update correctly when items have been added through classList');
+test(function () {
+  assert_equals( elem.classList + '', 'foo FOO', 'implicit' );
+  assert_equals( elem.classList.toString(), 'foo FOO', 'explicit' );
+}, 'classList must stringify correctly when items have been added');
+test(function () {
+  elem.classList.add('foo');
+  assert_equals( elem.classList.length, 2 );
+  assert_equals( elem.classList + '', 'foo FOO', 'implicit' );
+  assert_equals( elem.classList.toString(), 'foo FOO', 'explicit' );
+}, 'classList.add should not add a token if it already exists');
+test(function () {
+  elem.classList.remove('bar');
+  assert_equals( elem.classList.length, 2 );
+  assert_equals( elem.classList + '', 'foo FOO', 'implicit' );
+  assert_equals( elem.classList.toString(), 'foo FOO', 'explicit' );
+}, 'classList.remove removes arguments passed, if they are present.');
+test(function () {
+  elem.classList.remove('foo');
+  assert_equals( elem.classList.length, 1 );
+  assert_equals( elem.classList + '', 'FOO', 'implicit' );
+  assert_equals( elem.classList.toString(), 'FOO', 'explicit' );
+  assert_false( elem.classList.contains('foo') );
+  assert_true( elem.classList.contains('FOO') );
+}, 'classList.remove must remove existing tokens');
+test(function () {
+  assert_not_equals( getComputedStyle(elem,null).fontStyle, 'italic' );
+}, 'classList.remove must not break case-sensitive CSS selector matching');
+test(function () {
+  secondelem.classList.remove('test');
+  assert_equals( secondelem.classList.length, 0 );
+  assert_false( secondelem.classList.contains('test') );
+}, 'classList.remove must remove duplicated tokens');
+test(function () {
+  secondelem.className = 'token1 token2 token3';
+  secondelem.classList.remove('token2');
+  assert_equals( secondelem.classList + '', 'token1 token3', 'implicit' );
+  assert_equals( secondelem.classList.toString(), 'token1 token3', 'explicit' );
+}, 'classList.remove must collapse whitespace around removed tokens');
+test(function () {
+  secondelem.className = ' token1 token2  ';
+  secondelem.classList.remove('token2');
+  assert_equals( secondelem.classList + '', 'token1', 'implicit' );
+  assert_equals( secondelem.classList.toString(), 'token1', 'explicit' );
+}, 'classList.remove must collapse whitespaces around each token');
+test(function () {
+  secondelem.className = '  token1  token2  token1  ';
+  secondelem.classList.remove('token2');
+  assert_equals( secondelem.classList + '', 'token1', 'implicit' );
+  assert_equals( secondelem.classList.toString(), 'token1', 'explicit' );
+}, 'classList.remove must collapse whitespaces around each token and remove duplicates');
+test(function () {
+  secondelem.className = '  token1  token2  token1  ';
+  secondelem.classList.remove('token1');
+  assert_equals( secondelem.classList + '', 'token2', 'implicit' );
+  assert_equals( secondelem.classList.toString(), 'token2', 'explicit' );
+}, 'classList.remove must collapse whitespace when removing duplicate tokens');
+test(function () {
+  secondelem.className = '  token1  token1  ';
+  secondelem.classList.add('token1');
+  assert_equals( secondelem.classList + '', 'token1', 'implicit' );
+  assert_equals( secondelem.classList.toString(), 'token1', 'explicit' );
+}, 'classList.add must collapse whitespaces and remove duplicates when adding a token that already exists');
+test(function () {
+  assert_true(elem.classList.toggle('foo'));
+  assert_equals( elem.classList.length, 2 );
+  assert_true( elem.classList.contains('foo') );
+  assert_true( elem.classList.contains('FOO') );
+}, 'classList.toggle must toggle tokens case-sensitively when adding');
+test(function () {
+  assert_equals( getComputedStyle(elem,null).fontStyle, 'italic' );
+}, 'classList.toggle must not break case-sensitive CSS selector matching');
+test(function () {
+  assert_false(elem.classList.toggle('foo'));
+}, 'classList.toggle must be able to remove tokens');
+test(function () {
+  //will return true if the last test incorrectly removed both
+  assert_false(elem.classList.toggle('FOO'));
+  assert_false( elem.classList.contains('foo') );
+  assert_false( elem.classList.contains('FOO') );
+}, 'classList.toggle must be case-sensitive when removing tokens');
+test(function () {
+  assert_not_equals( getComputedStyle(elem,null).fontStyle, 'italic' );
+}, 'CSS class selectors must stop matching when all classes have been removed');
+test(function () {
+  assert_equals( elem.className, '' );
+}, 'className must be empty when all classes have been removed');
+test(function () {
+  assert_equals( elem.classList + '', '', 'implicit' );
+  assert_equals( elem.classList.toString(), '', 'explicit' );
+}, 'classList must stringify to an empty string when all classes have been removed');
+test(function () {
+  assert_equals( elem.classList.item(0), null );
+}, 'classList.item(0) must return null when all classes have been removed');
+test(function () {
+  /* the normative part of the spec states that:
+  "unless the length is zero, in which case there are no supported property indices"
+  ...
+  "The term[...] supported property indices [is] used as defined in the WebIDL specification."
+  WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
+  assert_equals( elem.classList[0], undefined );
+}, 'classList[0] must be undefined when all classes have been removed');
+// The ordered set parser must skip ASCII whitespace (U+0009, U+000A, U+000C, U+000D, and U+0020.)
+test(function () {
+  var foo = document.createElement('div');
+  foo.className = 'a ';
+  foo.classList.add('b');
+  assert_equals(foo.className,'a b');
+}, 'classList.add should treat " " as a space');
+test(function () {
+  var foo = document.createElement('div');
+  foo.className = 'a\t';
+  foo.classList.add('b');
+  assert_equals(foo.className,'a b');
+}, 'classList.add should treat \\t as a space');
+test(function () {
+  var foo = document.createElement('div');
+  foo.className = 'a\r';
+  foo.classList.add('b');
+  assert_equals(foo.className,'a b');
+}, 'classList.add should treat \\r as a space');
+test(function () {
+  var foo = document.createElement('div');
+  foo.className = 'a\n';
+  foo.classList.add('b');
+  assert_equals(foo.className,'a b');
+}, 'classList.add should treat \\n as a space');
+test(function () {
+  var foo = document.createElement('div');
+  foo.className = 'a\f';
+  foo.classList.add('b');
+  assert_equals(foo.className,'a b');
+}, 'classList.add should treat \\f as a space');
+test(function () {
+  //WebIDL and ECMAScript 5 - a readonly property has a getter but not a setter
+  //ES5 makes [[Put]] fail but not throw
+  var failed = false;
+  secondelem.className = 'token1';
+  try {
+    secondelem.classList.length = 0;
+  } catch(e) {
+    failed = e;
+  }
+  assert_equals(secondelem.classList.length,1);
+  assert_false(failed,'an error was thrown');
+}, 'classList.length must be read-only');
+test(function () {
+  var failed = false, realList = secondelem.classList;
+  try {
+    secondelem.classList = '';
+  } catch(e) {
+    failed = e;
+  }
+  assert_equals(secondelem.classList,realList);
+  assert_false(failed,'an error was thrown');
+}, 'classList must be read-only');
+    </script>
+  </head>
+  <body>
+
+    <div id="log"></div>
+
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-closest-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-closest-expected.txt
new file mode 100644
index 0000000..41dd051
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-closest-expected.txt
@@ -0,0 +1,32 @@
+This is a testharness.js-based test.
+PASS Element.closest with context node 'test12' and selector 'select' 
+PASS Element.closest with context node 'test13' and selector 'fieldset' 
+PASS Element.closest with context node 'test13' and selector 'div' 
+PASS Element.closest with context node 'test3' and selector 'body' 
+PASS Element.closest with context node 'test4' and selector '[default]' 
+PASS Element.closest with context node 'test4' and selector '[selected]' 
+PASS Element.closest with context node 'test11' and selector '[selected]' 
+PASS Element.closest with context node 'test12' and selector '[name="form-a"]' 
+PASS Element.closest with context node 'test13' and selector 'form[name="form-a"]' 
+PASS Element.closest with context node 'test9' and selector 'input[required]' 
+PASS Element.closest with context node 'test9' and selector 'select[required]' 
+PASS Element.closest with context node 'test13' and selector 'div:not(.div1)' 
+PASS Element.closest with context node 'test6' and selector 'div.div3' 
+PASS Element.closest with context node 'test1' and selector 'div#test7' 
+PASS Element.closest with context node 'test12' and selector '.div3 > .div2' 
+PASS Element.closest with context node 'test12' and selector '.div3 > .div1' 
+PASS Element.closest with context node 'test9' and selector 'form > input[required]' 
+PASS Element.closest with context node 'test12' and selector 'fieldset > select[required]' 
+PASS Element.closest with context node 'test6' and selector 'input + fieldset' 
+PASS Element.closest with context node 'test3' and selector 'form + form' 
+PASS Element.closest with context node 'test5' and selector 'form + form' 
+PASS Element.closest with context node 'test10' and selector ':empty' 
+PASS Element.closest with context node 'test11' and selector ':last-child' 
+PASS Element.closest with context node 'test12' and selector ':first-child' 
+PASS Element.closest with context node 'test11' and selector ':invalid' 
+PASS Element.closest with context node 'test4' and selector ':scope' 
+PASS Element.closest with context node 'test4' and selector 'select > :scope' 
+PASS Element.closest with context node 'test4' and selector 'div > :scope' 
+FAIL Element.closest with context node 'test4' and selector ':has(> :scope)' Failed to execute 'closest' on 'Element': ':has(> :scope)' is not a valid selector.
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-closest.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-closest.html
new file mode 100644
index 0000000..2978f68
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-closest.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML>
+<meta charset=utf8>
+<title>Test for Element.closest</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<body id="body">
+  <div id="test8" class="div3" style="display:none">
+    <div id="test7" class="div2">
+      <div id="test6" class="div1">
+        <form id="test10" class="form2"></form>
+        <form id="test5" class="form1" name="form-a">
+          <input id="test1" class="input1" required>
+          <fieldset class="fieldset2" id="test2">
+            <select id="test3" class="select1" required>
+              <option default id="test4" value="">Test4</option>
+              <option selected id="test11">Test11</option>
+              <option id="test12">Test12</option>
+              <option id="test13">Test13</option>
+            </select>
+            <input id="test9" type="text" required>
+          </fieldset>
+        </form>
+      </div>
+    </div>
+  </div>
+  <div id=log></div>
+<script>
+  do_test("select"                     , "test12", "test3");
+  do_test("fieldset"                   , "test13", "test2");
+  do_test("div"                        , "test13", "test6");
+  do_test("body"                       , "test3" , "body");
+
+  do_test("[default]"                  , "test4" , "test4");
+  do_test("[selected]"                 , "test4" , "");
+  do_test("[selected]"                 , "test11", "test11");
+  do_test('[name="form-a"]'            , "test12", "test5");
+  do_test('form[name="form-a"]'        , "test13", "test5");
+  do_test("input[required]"            , "test9" , "test9");
+  do_test("select[required]"           , "test9" , "");
+
+  do_test("div:not(.div1)"             , "test13", "test7");
+  do_test("div.div3"                   , "test6" , "test8");
+  do_test("div#test7"                  , "test1" , "test7");
+
+  do_test(".div3 > .div2"              , "test12", "test7");
+  do_test(".div3 > .div1"              , "test12", "");
+  do_test("form > input[required]"     , "test9" , "");
+  do_test("fieldset > select[required]", "test12", "test3");
+
+  do_test("input + fieldset"           , "test6" , "");
+  do_test("form + form"                , "test3" , "test5");
+  do_test("form + form"                , "test5" , "test5");
+
+  do_test(":empty"                     , "test10", "test10");
+  do_test(":last-child"                , "test11", "test2");
+  do_test(":first-child"               , "test12", "test3");
+  do_test(":invalid"                   , "test11", "test2");
+
+  do_test(":scope"                     , "test4",  "test4");
+  do_test("select > :scope"            , "test4",  "test4");
+  do_test("div > :scope"               , "test4",  "");
+  do_test(":has(> :scope)"             , "test4",  "test3");
+function do_test(aSelector, aElementId, aTargetId) {
+  test(function() {
+    var el = document.getElementById(aElementId).closest(aSelector);
+    if (el === null) {
+      assert_equals("", aTargetId, aSelector);
+    } else {
+      assert_equals(el.id, aTargetId, aSelector);
+    }
+  }, "Element.closest with context node '" + aElementId + "' and selector '" + aSelector + "'");
+}
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-firstElementChild-entity-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-firstElementChild-entity-xhtml.xhtml
new file mode 100644
index 0000000..fe51af6d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-firstElementChild-entity-xhtml.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+[
+<!ENTITY tree "<span id='first_element_child' style='font-weight:bold;'>unknown.</span>">
+]>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<title>Entity References</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of Entity References</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is &tree;</p>
+<script><![CDATA[
+test(function() {
+  var parentEl = document.getElementById("parentEl")
+  var fec = parentEl.firstElementChild;
+  assert_true(!!fec)
+  assert_equals(fec.nodeType, 1)
+  assert_equals(fec.getAttribute("id"), "first_element_child")
+})
+]]></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-firstElementChild-namespace-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-firstElementChild-namespace-xhtml.xhtml
new file mode 100644
index 0000000..79ba778
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-firstElementChild-namespace-xhtml.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:pickle="http://ns.example.org/pickle">
+<head>
+<title>firstElementChild with namespaces</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of firstElementChild with namespaces</h1>
+<div id="parentEl">
+  <pickle:dill id="first_element_child"/>
+</div>
+<div id="log"></div>
+<p id="parentEl">The result of this test is
+<span id="first_element_child" style="font-weight:bold;">logged above.</span></p>
+<script><![CDATA[
+test(function() {
+  var parentEl = document.getElementById("parentEl");
+  var fec = parentEl.firstElementChild;
+  assert_true(!!fec)
+  assert_equals(fec.nodeType, 1)
+  assert_equals(fec.getAttribute("id"), "first_element_child")
+  assert_equals(fec.localName, "dill")
+})
+]]></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-firstElementChild-namespace.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-firstElementChild-namespace.html
new file mode 100644
index 0000000..11235db
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-firstElementChild-namespace.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>firstElementChild with namespaces</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<h1>Test of firstElementChild with namespaces</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is a unknown.</p>
+<script>
+test(function() {
+  var parentEl = document.getElementById("parentEl")
+  var el = document.createElementNS("http://ns.example.org/pickle", "pickle:dill")
+  el.setAttribute("id", "first_element_child")
+  parentEl.appendChild(el)
+  var fec = parentEl.firstElementChild
+  assert_true(!!fec)
+  assert_equals(fec.nodeType, 1)
+  assert_equals(fec.getAttribute("id"), "first_element_child")
+  assert_equals(fec.localName, "dill")
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-firstElementChild-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-firstElementChild-xhtml.xhtml
new file mode 100644
index 0000000..7fd9ff3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-firstElementChild-xhtml.xhtml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>firstElementChild</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of firstElementChild</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is
+<span id="first_element_child" style="font-weight:bold;">logged above.</span></p>
+<script><![CDATA[
+test(function() {
+  var parentEl = document.getElementById("parentEl");
+  var fec = parentEl.firstElementChild;
+  assert_true(!!fec)
+  assert_equals(fec.nodeType, 1)
+  assert_equals(fec.getAttribute("id"), "first_element_child")
+})
+]]></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-firstElementChild.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-firstElementChild.html
new file mode 100644
index 0000000..0fc65e6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-firstElementChild.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>firstElementChild</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<h1>Test of firstElementChild</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is
+<span id="first_element_child" style="font-weight:bold;">logged above.</span></p>
+<script>
+test(function() {
+  var parentEl = document.getElementById("parentEl");
+  var fec = parentEl.firstElementChild;
+  assert_true(!!fec)
+  assert_equals(fec.nodeType, 1)
+  assert_equals(fec.getAttribute("id"), "first_element_child")
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByClassName.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByClassName.html
new file mode 100644
index 0000000..69c86e3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByClassName.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>Element.getElementsByClassName</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var a = document.createElement("a"), b = document.createElement("b")
+  b.className = "foo"
+  a.appendChild(b)
+  var list = a.getElementsByClassName("foo")
+  assert_array_equals(list, [b])
+  var secondList = a.getElementsByClassName("foo")
+  assert_true(list === secondList || list !== secondList, "Caching is allowed.")
+}, "getElementsByClassName should work on disconnected subtrees.")
+test(function() {
+  var list = document.getElementsByClassName("foo")
+  assert_false(list instanceof NodeList, "NodeList")
+  assert_true(list instanceof HTMLCollection, "HTMLCollection")
+}, "Interface should be correct.")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByTagName-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByTagName-expected.txt
new file mode 100644
index 0000000..68f72da
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByTagName-expected.txt
@@ -0,0 +1,24 @@
+This is a testharness.js-based test.
+PASS Interfaces 
+PASS Caching is allowed 
+FAIL Shouldn't be able to set unsigned properties on a HTMLCollection (non-strict mode) assert_equals: expected (undefined) undefined but got (string) "foopy"
+FAIL Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode) assert_throws: function "function () {
+      "use strict";
+      l[5] = "foopy"
+    }" did not throw
+PASS Should be able to set expando shadowing a proto prop (item) 
+PASS Should be able to set expando shadowing a proto prop (namedItem) 
+FAIL hasOwnProperty, getOwnPropertyDescriptor, getOwnPropertyNames assert_true: desc.enumerable expected true got false
+PASS HTML element with uppercase tagName never matches in HTML Documents 
+PASS Element in non-HTML namespace, no prefix, lowercase name 
+PASS Element in non-HTML namespace, no prefix, uppercase name 
+PASS Element in non-HTML namespace, prefix, lowercase name 
+PASS Element in non-HTML namespace, prefix, uppercase name 
+FAIL Element in HTML namespace, no prefix, non-ascii characters in name assert_equals: expected "aÇ" but got "aç"
+PASS Element in non-HTML namespace, non-ascii characters in name 
+FAIL Element in HTML namespace, prefix, non-ascii characters in name assert_array_equals: All uppercase input lengths differ, expected 1 got 0
+PASS Element in non-HTML namespace, prefix, non-ascii characters in name 
+PASS getElementsByTagName('*') 
+PASS Matching the context object 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByTagName.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByTagName.html
new file mode 100644
index 0000000..d1509aa1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByTagName.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Element.getElementsByTagName</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-getelementsbytagname">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="Document-Element-getElementsByTagName.js"></script>
+<div id="log"></div>
+<script>
+var element;
+setup(function() {
+  element = document.createElement("div");
+  element.appendChild(document.createTextNode("text"));
+  var p = element.appendChild(document.createElement("p"));
+  p.appendChild(document.createElement("a"))
+   .appendChild(document.createTextNode("link"));
+  p.appendChild(document.createElement("b"))
+   .appendChild(document.createTextNode("bold"));
+  p.appendChild(document.createElement("em"))
+   .appendChild(document.createElement("u"))
+   .appendChild(document.createTextNode("emphasized"));
+  element.appendChild(document.createComment("comment"));
+});
+
+test_getElementsByTagName(element, element);
+
+test(function() {
+  assert_array_equals(element.getElementsByTagName(element.localName), []);
+}, "Matching the context object");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByTagNameNS.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByTagNameNS.html
new file mode 100644
index 0000000..aa675fa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByTagNameNS.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Element.getElementsByTagNameNS</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-getelementsbytagnamens">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="Document-Element-getElementsByTagNameNS.js"></script>
+<div id="log"></div>
+<script>
+var element;
+setup(function() {
+  element = document.createElement("div");
+  element.appendChild(document.createTextNode("text"));
+  var p = element.appendChild(document.createElement("p"));
+  p.appendChild(document.createElement("a"))
+   .appendChild(document.createTextNode("link"));
+  p.appendChild(document.createElement("b"))
+   .appendChild(document.createTextNode("bold"));
+  p.appendChild(document.createElement("em"))
+   .appendChild(document.createElement("u"))
+   .appendChild(document.createTextNode("emphasized"));
+  element.appendChild(document.createComment("comment"));
+});
+
+test_getElementsByTagNameNS(element, element);
+
+test(function() {
+  assert_array_equals(element.getElementsByTagNameNS("*", element.localName), []);
+}, "Matching the context object (wildcard namespace)");
+
+test(function() {
+  assert_array_equals(
+    element.getElementsByTagNameNS("http://www.w3.org/1999/xhtml",
+                                   element.localName),
+    []);
+}, "Matching the context object (specific namespace)");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-lastElementChild-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-lastElementChild-xhtml.xhtml
new file mode 100644
index 0000000..7c3106544
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-lastElementChild-xhtml.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>firstElementChild</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of firstElementChild</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child">this test</span> is <span id="last_element_child" style="font-weight:bold;">logged</span> above.</p>
+<script><![CDATA[
+test(function() {
+  var parentEl = document.getElementById("parentEl");
+  var lec = parentEl.lastElementChild;
+  assert_true(!!lec)
+  assert_equals(lec.nodeType, 1)
+  assert_equals(lec.getAttribute("id"), "last_element_child")
+})
+]]></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-lastElementChild.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-lastElementChild.html
new file mode 100644
index 0000000..dd80043
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-lastElementChild.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>lastElementChild</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<h1>Test of lastElementChild</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child">this test</span> is <span id="last_element_child" style="font-weight:bold;">logged</span> above.</p>
+<script>
+test(function() {
+  var parentEl = document.getElementById("parentEl");
+  var lec = parentEl.lastElementChild;
+  assert_true(!!lec)
+  assert_equals(lec.nodeType, 1)
+  assert_equals(lec.getAttribute("id"), "last_element_child")
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-matches.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-matches.js
new file mode 100644
index 0000000..1bc0f3d0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-matches.js
@@ -0,0 +1,127 @@
+/*
+ * Check that the matches() method exists on the given Node
+ */
+function interfaceCheckMatches(type, obj) {
+  if (obj.nodeType === obj.ELEMENT_NODE) {
+    test(function() {
+      assert_idl_attribute(obj, "matches", type + " supports matches");
+    }, type + " supports matches")
+  }
+}
+
+function runSpecialMatchesTests(type, element) {
+  test(function() { // 1
+    if (element.tagName.toLowerCase() === "null") {
+      assert_true(element.matches(null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match.");
+    } else {
+      assert_false(element.matches(null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match.");
+    }
+  }, type + ".matches(null)")
+
+  test(function() { // 2
+    if (element.tagName.toLowerCase() === "undefined") {
+      assert_true(element.matches(undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match.");
+    } else {
+      assert_false(element.matches(undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match.");
+    }
+  }, type + ".matches(undefined)")
+
+  test(function() { // 3
+    assert_throws(TypeError(), function() {
+      element.matches();
+    }, "This should throw a TypeError.")
+  }, type + ".matches no parameter")
+}
+
+/*
+ * Execute queries with the specified invalid selectors for matches()
+ * Only run these tests when errors are expected. Don't run for valid selector tests.
+ */
+function runInvalidSelectorTestMatches(type, root, selectors) {
+  if (root.nodeType === root.ELEMENT_NODE) {
+    for (var i = 0; i < selectors.length; i++) {
+      var s = selectors[i];
+      var n = s["name"];
+      var q = s["selector"];
+
+      test(function() {
+        assert_throws("SyntaxError", function() {
+          root.matches(q)
+        })
+      }, type + ".matches: " + n + ": " + q);
+    }
+  }
+}
+
+function runMatchesTest(type, root, selectors, docType) {
+  var nodeType = getNodeType(root);
+
+  for (var i = 0; i < selectors.length; i++) {
+    var s = selectors[i];
+    var n = s["name"];
+    var q = s["selector"];
+    var e = s["expect"];
+    var u = s["unexpected"];
+
+    var ctx = s["ctx"];
+    var ref = s["ref"];
+
+    if ((!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1))
+     && (s["testType"] & TEST_MATCH) ) {
+
+      if (ctx && !ref) {
+        test(function() {
+          var j, element, refNode;
+          for (j = 0; j < e.length; j++) {
+            element = root.querySelector("#" + e[j]);
+            refNode = root.querySelector(ctx);
+            assert_true(element.matches(q, refNode), "The element #" + e[j] + " should match the selector.")
+          }
+
+          if (u) {
+            for (j = 0; j < u.length; j++) {
+              element = root.querySelector("#" + u[j]);
+              refNode = root.querySelector(ctx);
+              assert_false(element.matches(q, refNode), "The element #" + u[j] + " should not match the selector.")
+            }
+          }
+        }, type + " Element.matches: " + n + " (with refNode Element): " + q);
+      }
+
+      if (ref) {
+        test(function() {
+          var j, element, refNodes;
+          for (j = 0; j < e.length; j++) {
+            element = root.querySelector("#" + e[j]);
+            refNodes = root.querySelectorAll(ref);
+            assert_true(element.matches(q, refNodes), "The element #" + e[j] + " should match the selector.")
+          }
+
+          if (u) {
+            for (j = 0; j < u.length; j++) {
+              element = root.querySelector("#" + u[j]);
+              refNodes = root.querySelectorAll(ref);
+              assert_false(element.matches(q, refNodes), "The element #" + u[j] + " should not match the selector.")
+            }
+          }
+        }, type + " Element.matches: " + n + " (with refNodes NodeList): " + q);
+      }
+
+      if (!ctx && !ref) {
+        test(function() {
+          for (var j = 0; j < e.length; j++) {
+            var element = root.querySelector("#" + e[j]);
+            assert_true(element.matches(q), "The element #" + e[j] + " should match the selector.")
+          }
+
+          if (u) {
+            for (j = 0; j < u.length; j++) {
+              element = root.querySelector("#" + u[j]);
+              assert_false(element.matches(q), "The element #" + u[j] + " should not match the selector.")
+            }
+          }
+        }, type + " Element.matches: " + n + " (with no refNodes): " + q);
+      }
+    }
+  }
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-nextElementSibling-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-nextElementSibling-xhtml.xhtml
new file mode 100644
index 0000000..5b2ed8ff
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-nextElementSibling-xhtml.xhtml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>nextElementSibling</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of nextElementSibling</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child">this test</span> is <span id="last_element_child" style="font-weight:bold;">unknown.</span></p>
+<script><![CDATA[
+test(function() {
+  var parentEl = document.getElementById("parentEl");
+  var fec = document.getElementById("first_element_child");
+  var nes = fec.nextElementSibling;
+  assert_true(!!nes)
+  assert_equals(nes.nodeType, 1)
+  assert_equals(nes.getAttribute("id"), "last_element_child")
+})
+]]></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-nextElementSibling.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-nextElementSibling.html
new file mode 100644
index 0000000..73d39fe1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-nextElementSibling.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>nextElementSibling</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<h1>Test of nextElementSibling</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child">this test</span> is <span id="last_element_child" style="font-weight:bold;">unknown.</span></p>
+<script>
+test(function() {
+  var parentEl = document.getElementById("parentEl");
+  var fec = document.getElementById("first_element_child");
+  var nes = fec.nextElementSibling;
+  assert_true(!!nes)
+  assert_equals(nes.nodeType, 1)
+  assert_equals(nes.getAttribute("id"), "last_element_child")
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-previousElementSibling-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-previousElementSibling-xhtml.xhtml
new file mode 100644
index 0000000..509eb61
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-previousElementSibling-xhtml.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>previousElementSibling</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of previousElementSibling</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child">this test</span> is
+<span id="middle_element_child" style="font-weight:bold;">unknown.</span>
+
+
+
+<span id="last_element_child" style="display:none;">fnord</span> </p>
+<script><![CDATA[
+test(function() {
+  var parentEl = document.getElementById("parentEl");
+  var lec = document.getElementById("last_element_child");
+  var pes = lec.previousElementSibling;
+  assert_true(!!pes)
+  assert_equals(pes.nodeType, 1)
+  assert_equals(pes.getAttribute("id"), "middle_element_child")
+})
+]]></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-previousElementSibling.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-previousElementSibling.html
new file mode 100644
index 0000000..03ae757
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-previousElementSibling.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>previousElementSibling</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<h1>Test of previousElementSibling</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child">this test</span> is
+<span id="middle_element_child" style="font-weight:bold;">unknown.</span>
+
+
+
+<span id="last_element_child" style="display:none;">fnord</span> </p>
+<script>
+test(function() {
+  var parentEl = document.getElementById("parentEl");
+  var lec = document.getElementById("last_element_child");
+  var pes = lec.previousElementSibling;
+  assert_true(!!pes)
+  assert_equals(pes.nodeType, 1)
+  assert_equals(pes.getAttribute("id"), "middle_element_child")
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-remove.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-remove.html
new file mode 100644
index 0000000..8efcc98e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-remove.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Element.remove</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-childnode-remove">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="ChildNode-remove.js"></script>
+<div id=log></div>
+<script>
+var node, parentNode;
+setup(function() {
+  node = document.createElement("div");
+  parentNode = document.createElement("div");
+});
+testRemove(node, parentNode, "element");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-removeAttributeNS.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-removeAttributeNS.html
new file mode 100644
index 0000000..1ffa78aa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-removeAttributeNS.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>Element.removeAttributeNS</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="attributes.js"></script>
+<div id="log"></div>
+<script>
+var XML = "http://www.w3.org/XML/1998/namespace"
+
+test(function() {
+  var el = document.createElement("foo")
+  el.setAttributeNS(XML, "a:bb", "pass")
+  attr_is(el.attributes[0], "pass", "bb", XML, "a", "a:bb")
+  el.removeAttributeNS(XML, "a:bb")
+  assert_equals(el.attributes.length, 1)
+  attr_is(el.attributes[0], "pass", "bb", XML, "a", "a:bb")
+}, "removeAttributeNS should take a local name.")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-siblingElement-null-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-siblingElement-null-xhtml.xhtml
new file mode 100644
index 0000000..df9493f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-siblingElement-null-xhtml.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Null Test</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of previousElementSibling and nextElementSibling returning null</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is <span id="first_element_child" style="font-weight:bold;">unknown.</span></p>
+<script><![CDATA[
+test(function() {
+  var fec = document.getElementById("first_element_child");
+  assert_equals(fec.previousElementSibling, null)
+  assert_equals(fec.nextElementSibling, null)
+})
+]]></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-siblingElement-null.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-siblingElement-null.html
new file mode 100644
index 0000000..918a385
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-siblingElement-null.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Null test</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<h1>Test of previousElementSibling and nextElementSibling returning null</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is <span id="first_element_child" style="font-weight:bold;">unknown.</span></p>
+<script>
+test(function() {
+  var fec = document.getElementById("first_element_child");
+  assert_equals(fec.previousElementSibling, null)
+  assert_equals(fec.nextElementSibling, null)
+})
+</script>
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-tagName.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-tagName.html
new file mode 100644
index 0000000..7e7ffeff
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-tagName.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<title>Element.tagName</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var HTMLNS = "http://www.w3.org/1999/xhtml"
+  assert_equals(document.createElementNS(HTMLNS, "I").tagName, "I")
+  assert_equals(document.createElementNS(HTMLNS, "i").tagName, "I")
+  assert_equals(document.createElementNS(HTMLNS, "x:b").tagName, "X:B")
+}, "tagName should upper-case for HTML elements in HTML documents.")
+
+test(function() {
+  var SVGNS = "http://www.w3.org/2000/svg"
+  assert_equals(document.createElementNS(SVGNS, "svg").tagName, "svg")
+  assert_equals(document.createElementNS(SVGNS, "SVG").tagName, "SVG")
+  assert_equals(document.createElementNS(SVGNS, "s:svg").tagName, "s:svg")
+  assert_equals(document.createElementNS(SVGNS, "s:SVG").tagName, "s:SVG")
+}, "tagName should not upper-case for SVG elements in HTML documents.")
+
+test(function() {
+  if ("DOMParser" in window) {
+    var xmlel = new DOMParser()
+      .parseFromString('<div xmlns="http://www.w3.org/1999/xhtml">Test</div>', 'text/xml')
+      .documentElement;
+    assert_equals(xmlel.tagName, "div", "tagName should be lowercase in XML")
+    var htmlel = document.importNode(xmlel, true)
+    assert_equals(htmlel.tagName, "DIV", "tagName should be uppercase in HTML")
+  }
+}, "tagName should be updated when changing ownerDocument")
+
+test(function() {
+  var xmlel = document.implementation
+    .createDocument("http://www.w3.org/1999/xhtml", "div", null)
+    .documentElement;
+  assert_equals(xmlel.tagName, "div", "tagName should be lowercase in XML")
+  var htmlel = document.importNode(xmlel, true)
+  assert_equals(htmlel.tagName, "DIV", "tagName should be uppercase in HTML")
+}, "tagName should be updated when changing ownerDocument (createDocument without prefix)")
+
+test(function() {
+  var xmlel = document.implementation
+    .createDocument("http://www.w3.org/1999/xhtml", "foo:div", null)
+    .documentElement;
+  assert_equals(xmlel.tagName, "foo:div", "tagName should be lowercase in XML")
+  var htmlel = document.importNode(xmlel, true)
+  assert_equals(htmlel.tagName, "FOO:DIV", "tagName should be uppercase in HTML")
+}, "tagName should be updated when changing ownerDocument (createDocument with prefix)")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-attributes-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-attributes-expected.txt
new file mode 100644
index 0000000..d2b7bb2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-attributes-expected.txt
@@ -0,0 +1,45 @@
+This is a testharness.js-based test.
+PASS attributes Element.id: update, no oldValue, mutation 
+PASS attributes Element.id: update mutation 
+PASS attributes Element.id: empty string update mutation 
+PASS attributes Element.id: same value mutation 
+PASS attributes Element.unknown: IDL attribute no mutation 
+PASS attributes HTMLInputElement.type: type update mutation 
+PASS attributes Element.className: new value mutation 
+PASS attributes Element.className: empty string update mutation 
+PASS attributes Element.className: same value mutation 
+PASS attributes Element.className: same multiple values mutation 
+PASS attributes Element.classList.add: single token addition mutation 
+PASS attributes Element.classList.add: multiple tokens addition mutation 
+PASS attributes Element.classList.add: syntax err/no mutation 
+PASS attributes Element.classList.add: invalid character/no mutation 
+FAIL attributes Element.classList.add: same value mutation assert_equals: mutation records must match expected 2 but got 1
+PASS attributes Element.classList.remove: single token removal mutation 
+PASS attributes Element.classList.remove: multiple tokens removal mutation 
+FAIL attributes Element.classList.remove: missing token removal mutation assert_equals: mutation records must match expected 2 but got 1
+PASS attributes Element.classList.toggle: token removal mutation 
+PASS attributes Element.classList.toggle: token addition mutation 
+PASS attributes Element.classList.toggle: forced token removal mutation 
+PASS attributes Element.classList.toggle: forced missing token removal no mutation 
+PASS attributes Element.classList.toggle: forced existing token addition no mutation 
+PASS attributes Element.classList.toggle: forced token addition mutation 
+PASS attributes Element.attributes.value: update mutation 
+PASS attributes Element.attributes.value: same id mutation 
+PASS attributes Element.setAttribute: id mutation 
+PASS attributes Element.setAttribute: same class mutation 
+PASS attributes Element.setAttribute: classname mutation 
+PASS attributes Element.removeAttribute: removal mutation 
+PASS attributes Element.removeAttribute: removal no mutation 
+PASS childList HTMLInputElement.removeAttribute: type removal mutation 
+PASS attributes Element.setAttributeNS: creation mutation 
+PASS attributes Element.setAttributeNS: prefixed attribute creation mutation 
+PASS attributes Element.removeAttributeNS: removal mutation 
+PASS attributes Element.removeAttributeNS: removal no mutation 
+PASS attributes Element.removeAttributeNS: prefixed attribute removal no mutation 
+PASS attributes/attributeFilter Element.id/Element.className: update mutation 
+PASS attributes/attributeFilter Element.id/Element.className: multiple filter update mutation 
+PASS attributeOldValue alone Element.id: update mutation 
+PASS attributeFilter alone Element.id/Element.className: multiple filter update mutation 
+PASS childList false: no childList mutation 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-attributes.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-attributes.html
new file mode 100644
index 0000000..462c997
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-attributes.html
@@ -0,0 +1,406 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>MutationObservers: attributes mutations</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="mutationobservers.js"></script>
+<h1>MutationObservers: attributes mutations</h1>
+<div id="log"></div>
+
+<section style="display: none">
+<p id='n'></p>
+
+<p id='n00'></p>
+<p id='n01'></p>
+<p id='n02'></p>
+<p id='n03'></p>
+<input id="n04" type="text">
+
+<p id='n10'></p>
+<p id='n11'></p>
+<p id='n12' class='c01'></p>
+<p id='n13' class='c01 c02'></p>
+
+<p id='n20'></p>
+<p id='n21'></p>
+<p id='n22'></p>
+<p id='n23'></p>
+<p id='n24' class="c01 c02"></p>
+
+<p id='n30' class="c01 c02"></p>
+<p id='n31' class="c01 c02"></p>
+<p id='n32' class="c01 c02"></p>
+
+<p id='n40' class="c01 c02"></p>
+<p id='n41' class="c01 c02"></p>
+<p id='n42' class="c01 c02"></p>
+<p id='n43' class="c01 c02"></p>
+<p id='n44' class="c01 c02"></p>
+<p id='n45' class="c01 c02"></p>
+
+<p id='n50' class="c01 c02"></p>
+<p id='n51'></p>
+
+<p id='n60'></p>
+<p id='n61' class="c01"></p>
+<p id='n62'></p>
+
+<p id='n70' class="c01"></p>
+<p id='n71'></p>
+<input id="n72" type="text">
+
+<p id='n80'></p>
+<p id='n81'></p>
+
+<p id='n90'></p>
+<p id='n91'></p>
+<p id='n92'></p>
+
+<p id='n1000'></p>
+<p id='n1001' class='c01'></p>
+
+<p id='n2000'></p>
+<p id='n2001' class='c01'></p>
+
+<p id='n3000'></p>
+
+</section>
+
+<script>
+
+var n = document.getElementById('n');
+
+runMutationTest(n,
+                  {"attributes":true},
+                  [{type: "attributes", attributeName: "id"}],
+                  function() { n.id = "n000";},
+                  "attributes Element.id: update, no oldValue, mutation");
+
+var n00 = document.getElementById('n00');
+runMutationTest(n00,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "n00", attributeName: "id"}],
+                  function() { n00.id = "n000";},
+                  "attributes Element.id: update mutation");
+
+var n01 = document.getElementById('n01');
+runMutationTest(n01,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "n01", attributeName: "id"}],
+                  function() { n01.id = "";},
+                  "attributes Element.id: empty string update mutation");
+
+var n02 = document.getElementById('n02');
+runMutationTest(n02,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "n02", attributeName: "id"}, {type: "attributes", attributeName: "class"}],
+                  function() { n02.id = "n02"; n02.setAttribute("class", "c01");},
+                  "attributes Element.id: same value mutation");
+
+var n03 = document.getElementById('n03');
+runMutationTest(n03,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "n03", attributeName: "id"}],
+                  function() { n03.unknown = "c02"; n03.id = "n030";},
+                  "attributes Element.unknown: IDL attribute no mutation");
+
+var n04 = document.getElementById('n04');
+runMutationTest(n04,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "text", attributeName: "type"}, {type: "attributes", oldValue: "n04", attributeName: "id"}],
+                  function() { n04.type = "unknown"; n04.id = "n040";},
+                  "attributes HTMLInputElement.type: type update mutation");
+
+  var n10 = document.getElementById('n10');
+runMutationTest(n10,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", attributeName: "class"}],
+                  function() { n10.className = "c01";},
+                  "attributes Element.className: new value mutation");
+
+  var n11 = document.getElementById('n11');
+runMutationTest(n11,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", attributeName: "class"}],
+                  function() { n11.className = "";},
+                  "attributes Element.className: empty string update mutation");
+
+  var n12 = document.getElementById('n12');
+runMutationTest(n12,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "c01", attributeName: "class"}],
+                  function() { n12.className = "c01";},
+                  "attributes Element.className: same value mutation");
+
+  var n13 = document.getElementById('n13');
+runMutationTest(n13,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+                  function() { n13.className = "c01 c02";},
+                  "attributes Element.className: same multiple values mutation");
+
+  var n20 = document.getElementById('n20');
+runMutationTest(n20,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", attributeName: "class"}],
+                  function() { n20.classList.add("c01");},
+                  "attributes Element.classList.add: single token addition mutation");
+
+  var n21 = document.getElementById('n21');
+runMutationTest(n21,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", attributeName: "class"}],
+                  function() { n21.classList.add("c01", "c02", "c03");},
+                  "attributes Element.classList.add: multiple tokens addition mutation");
+
+  var n22 = document.getElementById('n22');
+runMutationTest(n22,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "n22", attributeName: "id"}],
+                  function() { try { n22.classList.add("c01", "", "c03"); } catch (e) { };
+                               n22.id = "n220"; },
+                  "attributes Element.classList.add: syntax err/no mutation");
+
+  var n23 = document.getElementById('n23');
+runMutationTest(n23,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "n23", attributeName: "id"}],
+                  function() { try { n23.classList.add("c01", "c 02", "c03"); } catch (e) { };
+                               n23.id = "n230"; },
+                  "attributes Element.classList.add: invalid character/no mutation");
+
+  var n24 = document.getElementById('n24');
+runMutationTest(n24,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}, {type: "attributes", oldValue: "n24", attributeName: "id"}],
+                  function() { n24.classList.add("c02"); n24.id = "n240";},
+                  "attributes Element.classList.add: same value mutation");
+
+  var n30 = document.getElementById('n30');
+runMutationTest(n30,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+                  function() { n30.classList.remove("c01");},
+                  "attributes Element.classList.remove: single token removal mutation");
+
+  var n31 = document.getElementById('n31');
+runMutationTest(n31,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+                  function() { n31.classList.remove("c01", "c02");},
+                  "attributes Element.classList.remove: multiple tokens removal mutation");
+
+  var n32 = document.getElementById('n32');
+runMutationTest(n32,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}, {type: "attributes", oldValue: "n32", attributeName: "id"}],
+                  function() { n32.classList.remove("c03"); n32.id = "n320";},
+                  "attributes Element.classList.remove: missing token removal mutation");
+
+  var n40 = document.getElementById('n40');
+runMutationTest(n40,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+                  function() { n40.classList.toggle("c01");},
+                  "attributes Element.classList.toggle: token removal mutation");
+
+  var n41 = document.getElementById('n41');
+runMutationTest(n41,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+                  function() { n41.classList.toggle("c03");},
+                  "attributes Element.classList.toggle: token addition mutation");
+
+  var n42 = document.getElementById('n42');
+runMutationTest(n42,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+                  function() { n42.classList.toggle("c01", false);},
+                  "attributes Element.classList.toggle: forced token removal mutation");
+
+  var n43 = document.getElementById('n43');
+runMutationTest(n43,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "n43", attributeName: "id"}],
+                  function() { n43.classList.toggle("c03", false); n43.id = "n430"; },
+                  "attributes Element.classList.toggle: forced missing token removal no mutation");
+
+  var n44 = document.getElementById('n44');
+runMutationTest(n44,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "n44", attributeName: "id"}],
+                  function() { n44.classList.toggle("c01", true); n44.id = "n440"; },
+                  "attributes Element.classList.toggle: forced existing token addition no mutation");
+
+  var n45 = document.getElementById('n45');
+runMutationTest(n45,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+                  function() { n45.classList.toggle("c03", true);},
+                  "attributes Element.classList.toggle: forced token addition mutation");
+
+  var n50 = document.getElementById('n50');
+runMutationTest(n50,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+                  function() {
+                    for (var i = 0; i < n50.attributes.length; i++) {
+                      var attr = n50.attributes[i];
+                      if (attr.localName === "class") {
+                        attr.value = "c03";
+                      }
+                    };
+                  },
+                  "attributes Element.attributes.value: update mutation");
+
+  var n51 = document.getElementById('n51');
+runMutationTest(n51,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "n51", attributeName: "id"}],
+                  function() {
+                    n51.attributes[0].value = "n51";
+                  },
+                  "attributes Element.attributes.value: same id mutation");
+
+  var n60 = document.getElementById('n60');
+runMutationTest(n60,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "n60", attributeName: "id"}],
+                  function() {
+                    n60.setAttribute("id", "n601");
+                  },
+                  "attributes Element.setAttribute: id mutation");
+
+  var n61 = document.getElementById('n61');
+runMutationTest(n61,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "c01", attributeName: "class"}],
+                  function() {
+                    n61.setAttribute("class", "c01");
+                  },
+                  "attributes Element.setAttribute: same class mutation");
+
+  var n62 = document.getElementById('n62');
+runMutationTest(n62,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", attributeName: "classname"}],
+                  function() {
+                    n62.setAttribute("classname", "c01");
+                  },
+                  "attributes Element.setAttribute: classname mutation");
+
+  var n70 = document.getElementById('n70');
+runMutationTest(n70,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "c01", attributeName: "class"}],
+                  function() {
+                    n70.removeAttribute("class");
+                  },
+                  "attributes Element.removeAttribute: removal mutation");
+
+  var n71 = document.getElementById('n71');
+runMutationTest(n71,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "n71", attributeName: "id"}],
+                  function() {
+                    n71.removeAttribute("class");
+                    n71.id = "n710";
+                  },
+                  "attributes Element.removeAttribute: removal no mutation");
+
+  var n72 = document.getElementById('n72');
+runMutationTest(n72,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "text", attributeName: "type"}, {type: "attributes", oldValue: "n72", attributeName: "id"}],
+                  function() {
+                    n72.removeAttribute("type");
+                    n72.id = "n720";
+                  },
+                  "childList HTMLInputElement.removeAttribute: type removal mutation");
+
+  var n80 = document.getElementById('n80');
+runMutationTest(n80,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", attributeName: "private", attributeNamespace: "http://example.org/"}],
+                  function() {
+                    n80.setAttributeNS("http://example.org/", "private", "42");
+                  },
+                  "attributes Element.setAttributeNS: creation mutation");
+
+  var n81 = document.getElementById('n81');
+runMutationTest(n81,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", attributeName: "lang", attributeNamespace: "http://www.w3.org/XML/1998/namespace"}],
+                  function() {
+                    n81.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:lang", "42");
+                  },
+                  "attributes Element.setAttributeNS: prefixed attribute creation mutation");
+
+  var n90 = document.getElementById('n90');
+  n90.setAttributeNS("http://example.org/", "private", "42");
+runMutationTest(n90,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "42", attributeName: "private", attributeNamespace: "http://example.org/"}],
+                  function() {
+                    n90.removeAttributeNS("http://example.org/", "private");
+                  },
+                  "attributes Element.removeAttributeNS: removal mutation");
+
+  var n91 = document.getElementById('n91');
+runMutationTest(n91,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "n91", attributeName: "id"}],
+                  function() {
+                    n91.removeAttributeNS("http://example.org/", "private");
+                    n91.id = "n910";
+                  },
+                  "attributes Element.removeAttributeNS: removal no mutation");
+
+  var n92 = document.getElementById('n92');
+runMutationTest(n92,
+                  {"attributes":true, "attributeOldValue": true},
+                  [{type: "attributes", oldValue: "n92", attributeName: "id"}],
+                  function() {
+                    n92.removeAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:lang");
+                    n92.id = "n920";
+                  },
+                  "attributes Element.removeAttributeNS: prefixed attribute removal no mutation");
+
+  var n1000 = document.getElementById('n1000');
+runMutationTest(n1000,
+                  {"attributes":true, "attributeOldValue": true,"attributeFilter": ["id"]},
+                  [{type: "attributes", oldValue: "n1000", attributeName: "id"}],
+                  function() { n1000.id = "abc"; n1000.className = "c01"},
+                  "attributes/attributeFilter Element.id/Element.className: update mutation");
+
+  var n1001 = document.getElementById('n1001');
+runMutationTest(n1001,
+                  {"attributes":true, "attributeOldValue": true,"attributeFilter": ["id", "class"]},
+                  [{type: "attributes", oldValue: "n1001", attributeName: "id"},
+                   {type: "attributes", oldValue: "c01", attributeName: "class"}],
+                  function() { n1001.id = "abc"; n1001.className = "c02"; n1001.setAttribute("lang", "fr");},
+                  "attributes/attributeFilter Element.id/Element.className: multiple filter update mutation");
+
+  var n2000 = document.getElementById('n2000');
+runMutationTest(n2000,
+                  {"attributeOldValue": true},
+                  [{type: "attributes", oldValue: "n2000", attributeName: "id"}],
+                  function() { n2000.id = "abc";},
+                  "attributeOldValue alone Element.id: update mutation");
+
+  var n2001 = document.getElementById('n2001');
+runMutationTest(n2001,
+                  {"attributeFilter": ["id", "class"]},
+                  [{type: "attributes", attributeName: "id"},
+                   {type: "attributes", attributeName: "class"}],
+                  function() { n2001.id = "abcd"; n2001.className = "c02"; n2001.setAttribute("lang", "fr");},
+                  "attributeFilter alone Element.id/Element.className: multiple filter update mutation");
+
+  var n3000 = document.getElementById('n3000');
+runMutationTest(n3000,
+                  {"subtree": true, "childList":false, "attributes" : true},
+                  [{type: "attributes", attributeName: "id" }],
+                  function() { n3000.textContent = "CHANGED"; n3000.id = "abc";},
+                  "childList false: no childList mutation");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-characterData-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-characterData-expected.txt
new file mode 100644
index 0000000..043722f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-characterData-expected.txt
@@ -0,0 +1,26 @@
+This is a testharness.js-based test.
+PASS characterData Text.data: simple mutation without oldValue 
+PASS characterData Text.data: simple mutation 
+PASS characterData Text.appendData: simple mutation 
+PASS characterData Text.appendData: empty string mutation 
+PASS characterData Text.appendData: null string mutation 
+PASS characterData Text.insertData: simple mutation 
+PASS characterData Text.insertData: empty string mutation 
+PASS characterData Text.insertData: null string mutation 
+PASS characterData Text.deleteData: simple mutation 
+PASS characterData Text.deleteData: empty mutation 
+PASS characterData Text.replaceData: simple mutation 
+PASS characterData Text.replaceData: empty mutation 
+PASS characterData ProcessingInstruction: data mutations 
+FAIL characterData Comment: data mutations assert_equals: oldValue didn't match expected " data " but got "  data  "
+PASS Range (r70) is created 
+PASS characterData Range.deleteContents: child and data removal mutation 
+PASS Range (r71) is created 
+PASS characterData Range.deleteContents: child and data removal mutation (2) 
+PASS Range (r80) is created 
+PASS characterData Range.extractContents: child and data removal mutation 
+PASS Range (r81) is created 
+PASS characterData Range.extractContents: child and data removal mutation (2) 
+PASS characterData/characterDataOldValue alone Text.data: simple mutation 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-characterData.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-characterData.html
new file mode 100644
index 0000000..af5f821
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-characterData.html
@@ -0,0 +1,215 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>MutationObservers: characterData mutations</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="mutationobservers.js"></script>
+<h1>MutationObservers: characterData mutations</h1>
+<div id="log"></div>
+
+<section style="display: none">
+
+<p id='n'>text content</p>
+
+<p id='n00'>text content</p>
+
+<p id='n10'>CHAN</p>
+<p id='n11'>CHANGED</p>
+<p id='n12'>CHANGED</p>
+
+<p id='n20'>CHGED</p>
+<p id='n21'>CHANGED</p>
+<p id='n22'>CHANGED</p>
+
+<p id='n30'>CCCHANGED</p>
+<p id='n31'>CHANGED</p>
+
+<p id='n40'>CCCHANGED</p>
+<p id='n41'>CHANGED</p>
+
+<p id="n50"><?processing data?></p>
+
+<p id="n60"><!--  data  --></p>
+
+<p id='n70'>CHANN</p>
+<p id='n71'>CHANN</p>
+
+<p id='n80'>CHANN</p>
+<p id='n81'>CHANN</p>
+
+<p id='n90'>CHANN</p>
+
+</section>
+
+<script>
+  var n = document.getElementById('n').firstChild;
+runMutationTest(n,
+                  {"characterData":true},
+                  [{type: "characterData"}],
+                  function() { n.data = "NEW VALUE"; },
+                  "characterData Text.data: simple mutation without oldValue");
+
+  var n00 = document.getElementById('n00').firstChild;
+runMutationTest(n00,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "text content" }],
+                  function() { n00.data = "CHANGED"; },
+                  "characterData Text.data: simple mutation");
+
+  var n10 = document.getElementById('n10').firstChild;
+runMutationTest(n10,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "CHAN" }],
+                  function() { n10.appendData("GED"); },
+                  "characterData Text.appendData: simple mutation");
+
+  var n11 = document.getElementById('n11').firstChild;
+runMutationTest(n11,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "CHANGED" }],
+                  function() { n11.appendData(""); },
+                  "characterData Text.appendData: empty string mutation");
+
+  var n12 = document.getElementById('n12').firstChild;
+runMutationTest(n12,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "CHANGED" }],
+                  function() { n12.appendData(null); },
+                  "characterData Text.appendData: null string mutation");
+
+  var n20 = document.getElementById('n20').firstChild;
+runMutationTest(n20,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "CHGED" }],
+                  function() { n20.insertData(2, "AN"); },
+                  "characterData Text.insertData: simple mutation");
+
+  var n21 = document.getElementById('n21').firstChild;
+runMutationTest(n21,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "CHANGED" }],
+                  function() { n21.insertData(2, ""); },
+                  "characterData Text.insertData: empty string mutation");
+
+  var n22 = document.getElementById('n22').firstChild;
+runMutationTest(n22,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "CHANGED" }],
+                  function() { n22.insertData(2, null); },
+                  "characterData Text.insertData: null string mutation");
+
+  var n30 = document.getElementById('n30').firstChild;
+runMutationTest(n30,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "CCCHANGED" }],
+                  function() { n30.deleteData(0, 2); },
+                  "characterData Text.deleteData: simple mutation");
+
+  var n31 = document.getElementById('n31').firstChild;
+runMutationTest(n31,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "CHANGED" }, {type: "characterData", oldValue: "CHANGED" }],
+                  function() { n31.deleteData(0, 0); n31.data = "n31"; },
+                  "characterData Text.deleteData: empty mutation");
+
+  var n40 = document.getElementById('n40').firstChild;
+runMutationTest(n40,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "CCCHANGED" }],
+                  function() { n40.replaceData(0, 2, "CH"); },
+                  "characterData Text.replaceData: simple mutation");
+
+  var n41 = document.getElementById('n41').firstChild;
+runMutationTest(n41,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "CHANGED" }],
+                  function() { n41.replaceData(0, 0, "CH"); },
+                  "characterData Text.replaceData: empty mutation");
+
+  var n50 = document.getElementById('n50').firstChild;
+runMutationTest(n50,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "?processing data?" },{type: "characterData", oldValue: "CHANGED" },{type: "characterData", oldValue: "CHANGED" }],
+                  function() {
+                    n50.data = "CHANGED";
+                    n50.deleteData(0, 0);
+                    n50.replaceData(0, 2, "CH"); },
+                  "characterData ProcessingInstruction: data mutations");
+
+  var n60 = document.getElementById('n60').firstChild;
+runMutationTest(n60,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: " data " },{type: "characterData", oldValue: "CHANGED" },{type: "characterData", oldValue: "CHANGED" }],
+                  function() {
+                    n60.data = "CHANGED";
+                    n60.deleteData(0, 0);
+                    n60.replaceData(0, 2, "CH"); },
+                  "characterData Comment: data mutations");
+
+  var n70 = document.getElementById('n70');
+  var r70 = null;
+  test(function () {
+    n70.appendChild(document.createTextNode("NNN"));
+    n70.appendChild(document.createTextNode("NGED"));
+    r70 = document.createRange();
+    r70.setStart(n70.firstChild, 4);
+    r70.setEnd(n70.lastChild, 1);
+   }, "Range (r70) is created");
+runMutationTest(n70.firstChild,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "CHANN" }],
+                  function() { r70.deleteContents(); },
+                  "characterData Range.deleteContents: child and data removal mutation");
+
+  var n71 = document.getElementById('n71');
+  var r71 = null;
+  test(function () {
+    n71.appendChild(document.createTextNode("NNN"));
+    n71.appendChild(document.createTextNode("NGED"));
+    r71 = document.createRange();
+    r71.setStart(n71.firstChild, 4);
+    r71.setEnd(n71.lastChild, 1);
+   }, "Range (r71) is created");
+runMutationTest(n71.lastChild,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "NGED"}],
+                  function() { r71.deleteContents(); },
+                  "characterData Range.deleteContents: child and data removal mutation (2)");
+
+  var n80 = document.getElementById('n80');
+  var r80 = null;
+  test(function () {
+    n80.appendChild(document.createTextNode("NNN"));
+    n80.appendChild(document.createTextNode("NGED"));
+    r80 = document.createRange();
+    r80.setStart(n80.firstChild, 4);
+    r80.setEnd(n80.lastChild, 1);
+   }, "Range (r80) is created");
+runMutationTest(n80.firstChild,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "CHANN" }],
+                  function() { r80.extractContents(); },
+                  "characterData Range.extractContents: child and data removal mutation");
+
+  var n81 = document.getElementById('n81');
+  var r81 = null;
+  test(function () {
+    n81.appendChild(document.createTextNode("NNN"));
+    n81.appendChild(document.createTextNode("NGED"));
+    r81 = document.createRange();
+    r81.setStart(n81.firstChild, 4);
+    r81.setEnd(n81.lastChild, 1);
+   }, "Range (r81) is created");
+runMutationTest(n81.lastChild,
+                  {"characterData":true,"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "NGED" }],
+                  function() { r81.extractContents(); },
+                  "characterData Range.extractContents: child and data removal mutation (2)");
+
+  var n90 = document.getElementById('n90').firstChild;
+runMutationTest(n90,
+                  {"characterDataOldValue":true},
+                  [{type: "characterData", oldValue: "CHANN" }],
+                  function() { n90.data = "CHANGED"; },
+                  "characterData/characterDataOldValue alone Text.data: simple mutation");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-disconnect.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-disconnect.html
new file mode 100644
index 0000000..ab7e083
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-disconnect.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>MutationObservers: disconnect</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<h1>MutationObservers: disconnect</h1>
+<div id="log"></div>
+<section style="display: none">
+<p id='n00'></p>
+</section>
+<script>
+var n00 = document.getElementById('n00');
+var parentTest = async_test("subtree mutations");
+function masterMO(sequence, obs) {
+  parentTest.step(function() {
+    assert_equals(sequence.length, 4, "mutation records must match");
+  });
+  parentTest.done();
+}
+parentTest.step(function() {
+  (new MutationObserver(masterMO)).observe(n00.parentNode, {"subtree": true, "attributes": true});
+});
+
+var disconnectTest = async_test("disconnect discarded some mutations");
+function observerCallback(sequence, obs) {
+  disconnectTest.step(function() {
+    assert_equals(sequence.length, 1);
+    assert_equals(sequence[0].type, "attributes");
+    assert_equals(sequence[0].attributeName, "id");
+    assert_equals(sequence[0].oldValue, "latest");
+    disconnectTest.done();
+  });
+}
+
+var observer;
+disconnectTest.step(function() {
+  observer = new MutationObserver(observerCallback);
+  observer.observe(n00, {"attributes": true});
+  n00.id = "foo";
+  n00.id = "bar";
+  observer.disconnect();
+  observer.observe(n00, {"attributes": true, "attributeOldValue": true});
+  n00.id = "latest";
+  observer.disconnect();
+  observer.observe(n00, {"attributes": true, "attributeOldValue": true});
+  n00.id = "n0000";
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-document-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-document-expected.txt
new file mode 100644
index 0000000..cd54c00
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-document-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+PASS setup test 
+PASS parser insertion mutations 
+FAIL parser script insertion mutation assert_equals: target node must match expected Element node <p id="n00"><script id="inserted_script">document.body.ap... but got Element node <body><h1>MutationObservers: document mutations</h1>
+<div...
+PASS removal of parent during parsing 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-document.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-document.html
new file mode 100644
index 0000000..4bcd3da
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-document.html
@@ -0,0 +1,167 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>MutationObservers: takeRecords</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="mutationobservers.js"></script>
+<h1>MutationObservers: document mutations</h1>
+<div id="log"></div>
+
+<script id='s001'>
+  var setupTest = async_test("setup test");
+  var insertionTest = async_test("parser insertion mutations");
+  var insertionTest2 = async_test("parser script insertion mutation");
+  var testCounter = 0;
+
+  function masterMO(sequence, obs) {
+    testCounter++;
+    if (testCounter == 1) {
+      insertionTest.step(
+        function () {
+          checkRecords(document, sequence,
+                       [{type: "childList",
+                         addedNodes: function () {
+                           return [ document.getElementById("n00") ];
+                         },
+                         previousSibling: function () {
+                           return document.getElementById("s001");
+                         },
+                         target: document.body},
+                        {type: "childList",
+                         addedNodes: function () {
+                           return [ document.getElementById("s002") ];
+                         },
+                         previousSibling: function () {
+                           return document.getElementById("n00");
+                         },
+                         target: document.body},
+                        {type: "childList",
+                         addedNodes: function () {
+                           return [ document.getElementById("s002").firstChild ];
+                         },
+                         target: function () {
+                           return document.getElementById("s002");
+                         }}]);
+        });
+    } else if (testCounter == 2) {
+      insertionTest2.step(
+        function () {
+          checkRecords(document, sequence,
+                       [{type: "childList",
+                         addedNodes: function () {
+                           return [ document.getElementById("inserted_script") ];
+                         },
+                         target: function () {
+                          return document.getElementById("n00");
+                         }},
+                        {type: "childList",
+                         addedNodes: function () {
+                           return [ document.getElementById("inserted_element") ];
+                         },
+                         previousSibling: function () {
+                           return document.getElementById("s002");
+                         },
+                         target: document.body}
+                        ]);
+        });
+    }
+  }
+  var document_observer;
+  var newElement;
+  setupTest.step(function() {
+    document_observer = new MutationObserver(masterMO);
+    newElement = document.createElement("span");
+    document_observer.observe(document, {subtree:true,childList:true});
+    newElement.id = "inserted_element";
+    newElement.setAttribute("style", "display: none");
+    newElement.textContent = "my new span for n00";
+  });
+</script><p id='n00'></p><script id='s002'>
+  var newScript = document.createElement("script");
+  setupTest.step(function() {
+    newScript.textContent = "document.body.appendChild(newElement);";
+    newScript.id = "inserted_script";
+    document.getElementById("n00").appendChild(newScript);
+  });
+  if (testCounter < 1) {
+    insertionTest.step(
+      function () {
+        assert_unreached("document observer did not trigger");
+      });
+  }
+</script><script id='s003'>
+  setupTest.step(function() {
+    document_observer.disconnect();
+  });
+  if (testCounter < 2) {
+    insertionTest2.step(
+      function () {
+        assert_unreached("document observer did not trigger");
+      });
+  }
+  insertionTest.done();
+  insertionTest2.done();
+</script>
+
+<p id='n012'></p><div id='d01'>
+<script id='s011'>
+  var removalTest = async_test("removal of parent during parsing");
+  var d01 = document.getElementById("d01");
+  testCounter = 0;
+
+  function removalMO(sequence, obs) {
+    testCounter++;
+    if (testCounter == 1) {
+      removalTest.step(
+        function () {
+          checkRecords(document, sequence,
+                       [{type: "childList",
+                         removedNodes: function () {
+                           return [ d01 ];
+                         },
+                         previousSibling: function () {
+                           return document.getElementById("n012");
+                         },
+                         target: document.body}]);
+        });
+    } else if (testCounter == 2) {
+      removalTest.step(
+        function () {
+          checkRecords(document, sequence,
+                       [{type: "childList",
+                         addedNodes: function () {
+                           return [ document.getElementById("s012") ];
+                         },
+                         previousSibling: function () {
+                           return document.getElementById("n012");
+                         },
+                         target: document.body},
+                        {type: "childList",
+                          addedNodes: function () {
+                            return [ document.getElementById("s012").firstChild ];
+                          },
+                          target: function () {
+                            return document.getElementById("s012");
+                          }}]);
+        });
+    }
+  }
+  var document2_observer;
+  setupTest.step(function() {
+    document2_observer = new MutationObserver(removalMO);
+    document2_observer.observe(document, {subtree:true,childList:true});
+    d01.parentNode.removeChild(d01);
+  });
+</script><p id='n01'></p></div><script id='s012'>
+  setupTest.step(function() {
+    document2_observer.disconnect();
+  });
+  if (testCounter < 2) {
+    removalTest.step(
+      function () {
+        assert_unreached("document observer did not trigger");
+      });
+  }
+  removalTest.done();
+  setupTest.done();
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-inner-outer-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-inner-outer-expected.txt
new file mode 100644
index 0000000..901c9c1d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-inner-outer-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+FAIL innerHTML mutation assert_equals: mutation records must match expected 2 but got 1
+PASS innerHTML with 2 children mutation 
+PASS outerHTML mutation 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-inner-outer.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-inner-outer.html
new file mode 100644
index 0000000..ecd39da
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-inner-outer.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>MutationObservers: innerHTML, outerHTML mutations</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="mutationobservers.js"></script>
+<h1>MutationObservers: innerHTML, outerHTML mutations</h1>
+<div id="log"></div>
+
+<section style="display: none">
+
+<p id='n00'>old text</p>
+
+<p id='n01'>old text</p>
+
+<div id='n02'><p>old text</p></div>
+</section>
+
+<script>
+  var n00;
+  var n00oldText;
+  var n01;
+  var n01oldText;
+  var n02;
+
+  setup(function() {
+    n00 = document.getElementById('n00');
+    n00oldText = n00.firstChild;
+    n01 = document.getElementById('n01');
+    n01oldText = n01.firstChild;
+    n02 = document.getElementById('n02');
+  })
+
+  runMutationTest(n00,
+                  {childList:true,attributes:true},
+                  [{type: "childList",
+                    removedNodes: [n00oldText],
+                    addedNodes: function() {
+                      return [document.getElementById("n00").firstChild];
+                    }},
+                    {type: "attributes", attributeName: "class"}],
+                  function() { n00.innerHTML = "new text"; n00.className = "c01"},
+                  "innerHTML mutation");
+
+  runMutationTest(n01,
+                  {childList:true},
+                  [{type: "childList",
+                    removedNodes: [n01oldText],
+                    addedNodes: function() {
+                      return [document.getElementById("n01").firstChild,
+                              document.getElementById("n01").lastChild];
+                    }}],
+                  function() { n01.innerHTML = "<span>new</span><span>text</span>"; },
+                  "innerHTML with 2 children mutation");
+
+  runMutationTest(n02,
+                  {childList:true},
+                  [{type: "childList",
+                    removedNodes: [n02.firstChild],
+                    addedNodes: function() {
+                      return [n02.firstChild];
+                    }}],
+                  function() { n02.firstChild.outerHTML = "<p>next text</p>"; },
+                  "outerHTML mutation");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-takeRecords.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-takeRecords.html
new file mode 100644
index 0000000..95af2d2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/MutationObserver-takeRecords.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>MutationObservers: takeRecords</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="mutationobservers.js"></script>
+<h1>MutationObservers: takeRecords</h1>
+<div id="log"></div>
+
+<section style="display: none">
+
+<p id='n00'></p>
+
+</section>
+
+<script>
+
+  var n00 = document.getElementById('n00');
+
+  var unused = async_test("unreachabled test");
+
+  var observer;
+  unused.step(function () {
+    observer = new MutationObserver(unused.unreached_func("the observer callback should not fire"));
+    observer.observe(n00, { "subtree": true,
+                          "childList": true,
+                          "attributes": true,
+                          "characterData": true,
+                          "attributeOldValue": true,
+                          "characterDataOldValue": true});
+    n00.id = "foo";
+    n00.id = "bar";
+    n00.className = "bar";
+    n00.textContent = "old data";
+    n00.firstChild.data = "new data";
+  });
+
+  test(function() {
+    checkRecords(n00, observer.takeRecords(), [{type: "attributes", attributeName: "id", oldValue: "n00"},
+                           {type: "attributes", attributeName: "id", oldValue: "foo"},
+                           {type: "attributes", attributeName: "class"},
+                           {type: "childList", addedNodes: [n00.firstChild]},
+                           {type: "characterData", oldValue: "old data", target: n00.firstChild}]);
+  }, "All records present");
+
+  test(function() {
+    checkRecords(n00, observer.takeRecords(), []);
+  }, "No more records present");
+</script>
+<script>
+  unused.done();
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-appendChild.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-appendChild.html
new file mode 100644
index 0000000..08fc9756
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-appendChild.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Node.appendChild</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-appendchild">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src=about:blank></iframe>
+<script>
+// TODO: Exhaustive tests
+function testLeaf(node, desc) {
+  // WebIDL.
+  test(function() {
+    assert_throws(new TypeError(), function() { node.appendChild(null) })
+  }, "Appending null to a " + desc)
+
+  // Pre-insert step 1.
+  test(function() {
+    assert_throws("HIERARCHY_REQUEST_ERR", function() { node.appendChild(document.createTextNode("fail")) })
+  }, "Appending to a " + desc)
+}
+
+// WebIDL.
+test(function() {
+  assert_throws(new TypeError(), function() { document.body.appendChild(null) })
+  assert_throws(new TypeError(), function() { document.body.appendChild({'a':'b'}) })
+}, "WebIDL tests")
+
+// WebIDL and pre-insert step 1.
+test(function() {
+  testLeaf(document.createTextNode("Foo"), "text node")
+  testLeaf(document.createComment("Foo"), "comment")
+  testLeaf(document.doctype, "doctype")
+}, "Appending to a leaf node.")
+
+// Pre-insert step 5.
+test(function() {
+  var frameDoc = frames[0].document
+  assert_throws("HIERARCHY_REQUEST_ERR", function() { document.body.appendChild(frameDoc) })
+}, "Appending a document")
+
+// Pre-insert step 8.
+test(function() {
+  var frameDoc = frames[0].document
+  var s = frameDoc.createElement("a")
+  assert_equals(s.ownerDocument, frameDoc)
+  document.body.appendChild(s)
+  assert_equals(s.ownerDocument, document)
+}, "Adopting an orphan")
+test(function() {
+  var frameDoc = frames[0].document
+  var s = frameDoc.createElement("b")
+  assert_equals(s.ownerDocument, frameDoc)
+  frameDoc.body.appendChild(s)
+  assert_equals(s.ownerDocument, frameDoc)
+  document.body.appendChild(s)
+  assert_equals(s.ownerDocument, document)
+}, "Adopting a non-orphan")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-childNodes-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-childNodes-expected.txt
new file mode 100644
index 0000000..23d1b487
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-childNodes-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+PASS Caching of Node.childNodes 
+PASS Node.childNodes on an Element. 
+PASS Node.childNodes on a DocumentFragment. 
+FAIL Node.childNodes on a Document. Illegal constructor
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-childNodes.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-childNodes.html
new file mode 100644
index 0000000..d1458aa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-childNodes.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Node.childNodes</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-childnodes">
+<link rel=author title="Tim Taubert" href="mailto:ttaubert@mozilla.com">
+<link rel=author title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var element = document.createElement("p");
+  assert_equals(element.childNodes, element.childNodes);
+}, "Caching of Node.childNodes");
+
+var check_parent_node = function(node) {
+  assert_array_equals(node.childNodes, []);
+
+  var children = node.childNodes;
+  var child = document.createElement("p");
+  node.appendChild(child);
+  assert_equals(node.childNodes, children);
+  assert_array_equals(children, [child]);
+  assert_equals(children.item(0), child);
+
+  var child2 = document.createComment("comment");
+  node.appendChild(child2);
+  assert_array_equals(children, [child, child2]);
+  assert_equals(children.item(0), child);
+  assert_equals(children.item(1), child2);
+
+  assert_false(2 in children);
+  assert_equals(children[2], undefined);
+  assert_equals(children.item(2), null);
+};
+
+test(function() {
+  check_parent_node(document.createElement("p"));
+}, "Node.childNodes on an Element.");
+
+test(function() {
+  check_parent_node(document.createDocumentFragment());
+}, "Node.childNodes on a DocumentFragment.");
+
+test(function() {
+  check_parent_node(new Document());
+}, "Node.childNodes on a Document.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-cloneNode-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-cloneNode-expected.txt
new file mode 100644
index 0000000..cf452c1a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-cloneNode-expected.txt
@@ -0,0 +1,19 @@
+This is a testharness.js-based test.
+FAIL Node.cloneNode HTMLAppletElement is not defined
+PASS createElement(a) 
+PASS createElement(abbr) 
+PASS createElement(acronym) 
+PASS createElement(address) 
+PASS createDocumentFragment 
+PASS createTextNode 
+PASS createComment 
+PASS createElement with attributes 
+PASS createElementNS HTML 
+PASS createElementNS non-HTML 
+PASS createProcessingInstruction 
+PASS implementation.createDocumentType 
+PASS implementation.createDocument 
+PASS implementation.createHTMLDocument 
+PASS node with children 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-cloneNode.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-cloneNode.html
new file mode 100644
index 0000000..a3cd31a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-cloneNode.html
@@ -0,0 +1,272 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Node.cloneNode</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-clonenode">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function assert_equal_node(nodeA, nodeB) {
+  assert_equals(nodeB.nodeType, nodeA.nodeType, "nodeType");
+  assert_equals(nodeB.nodeName, nodeA.nodeName, "nodeName");
+
+  if (nodeA.nodeType === Node.ELEMENT_NODE) {
+    assert_equals(nodeB.prefix, nodeA.prefix);
+    assert_equals(nodeB.namespaceURI, nodeA.namespaceURI);
+    assert_equals(nodeB.localName, nodeA.localName);
+    assert_equals(nodeB.tagName, nodeA.tagName);
+    assert_not_equals(nodeB.attributes != nodeA.attributes);
+    assert_equals(nodeB.attributes.length, nodeA.attributes.length);
+    for (var i = 0, il = nodeA.attributes.length; i < il; ++i) {
+      assert_not_equals(nodeB.attributes[i], nodeA.attributes[i]);
+      assert_equals(nodeB.attributes[i].name, nodeA.attributes[i].name);
+      assert_equals(nodeB.attributes[i].prefix, nodeA.attributes[i].prefix);
+      assert_equals(nodeB.attributes[i].namespaceURI, nodeA.attributes[i].namespaceURI);
+      assert_equals(nodeB.attributes[i].value, nodeA.attributes[i].value);
+    }
+  }
+}
+
+function check_copy(orig, copy, type) {
+    assert_not_equals(orig, copy);
+    assert_equal_node(orig, copy);
+    assert_true(orig instanceof type, "Should be type");
+    assert_true(copy instanceof type, "Should be type");
+}
+
+function create_element_and_check(localName, type) {
+  test(function() {
+    var element = document.createElement(localName);
+    var copy = element.cloneNode();
+    check_copy(element, copy, type);
+  }, "createElement(" + localName + ")");
+}
+
+// test1: createElement
+test(function() {
+    create_element_and_check("a",         HTMLAnchorElement);
+    create_element_and_check("abbr",      HTMLElement);
+    create_element_and_check("acronym",   HTMLElement);
+    create_element_and_check("address",   HTMLElement);
+    create_element_and_check("applet",    HTMLAppletElement);
+    create_element_and_check("area",      HTMLAreaElement);
+    create_element_and_check("article",   HTMLElement);
+    create_element_and_check("aside",     HTMLElement);
+    create_element_and_check("audio",     HTMLAudioElement);
+    create_element_and_check("b",         HTMLElement);
+    create_element_and_check("base",      HTMLBaseElement);
+    create_element_and_check("bdi",       HTMLElement);
+    create_element_and_check("bdo",       HTMLElement);
+    create_element_and_check("bgsound",   HTMLElement);
+    create_element_and_check("big",       HTMLElement);
+    create_element_and_check("blockquote",HTMLElement);
+    create_element_and_check("body",      HTMLBodyElement);
+    create_element_and_check("br",        HTMLBRElement);
+    create_element_and_check("button",    HTMLButtonElement);
+    create_element_and_check("canvas",    HTMLCanvasElement);
+    create_element_and_check("caption",   HTMLTableCaptionElement);
+    create_element_and_check("center",    HTMLElement);
+    create_element_and_check("cite",      HTMLElement);
+    create_element_and_check("code",      HTMLElement);
+    create_element_and_check("col",       HTMLTableColElement);
+    create_element_and_check("colgroup",  HTMLTableColElement);
+    create_element_and_check("data",      HTMLDataElement);
+    create_element_and_check("datalist",  HTMLDataListElement);
+    create_element_and_check("dialog",    HTMLDialogElement);
+    create_element_and_check("dd",        HTMLElement);
+    create_element_and_check("del",       HTMLModElement);
+    create_element_and_check("details",   HTMLElement);
+    create_element_and_check("dfn",       HTMLElement);
+    create_element_and_check("dir",       HTMLDirectoryElement);
+    create_element_and_check("div",       HTMLDivElement);
+    create_element_and_check("dl",        HTMLDListElement);
+    create_element_and_check("dt",        HTMLElement);
+    create_element_and_check("embed",     HTMLEmbedElement);
+    create_element_and_check("fieldset",  HTMLFieldSetElement);
+    create_element_and_check("figcaption",HTMLElement);
+    create_element_and_check("figure",    HTMLElement);
+    create_element_and_check("font",      HTMLFontElement);
+    create_element_and_check("footer",    HTMLElement);
+    create_element_and_check("form",      HTMLFormElement);
+    create_element_and_check("frame",     HTMLFrameElement);
+    create_element_and_check("frameset",  HTMLFrameSetElement);
+    create_element_and_check("h1",        HTMLHeadingElement);
+    create_element_and_check("h2",        HTMLHeadingElement);
+    create_element_and_check("h3",        HTMLHeadingElement);
+    create_element_and_check("h4",        HTMLHeadingElement);
+    create_element_and_check("h5",        HTMLHeadingElement);
+    create_element_and_check("h6",        HTMLHeadingElement);
+    create_element_and_check("head",      HTMLHeadElement);
+    create_element_and_check("header",    HTMLElement);
+    create_element_and_check("hgroup",    HTMLElement);
+    create_element_and_check("hr",        HTMLHRElement);
+    create_element_and_check("html",      HTMLHtmlElement);
+    create_element_and_check("i",         HTMLElement);
+    create_element_and_check("iframe",    HTMLIFrameElement);
+    create_element_and_check("img",       HTMLImageElement);
+    create_element_and_check("input",     HTMLInputElement);
+    create_element_and_check("ins",       HTMLModElement);
+    create_element_and_check("isindex",   HTMLElement);
+    create_element_and_check("kbd",       HTMLElement);
+    create_element_and_check("label",     HTMLLabelElement);
+    create_element_and_check("legend",    HTMLLegendElement);
+    create_element_and_check("li",        HTMLLIElement);
+    create_element_and_check("link",      HTMLLinkElement);
+    create_element_and_check("main",      HTMLElement);
+    create_element_and_check("map",       HTMLMapElement);
+    create_element_and_check("mark",      HTMLElement);
+    create_element_and_check("marquee",   HTMLElement);
+    create_element_and_check("meta",      HTMLMetaElement);
+    create_element_and_check("meter",     HTMLMeterElement);
+    create_element_and_check("nav",       HTMLElement);
+    create_element_and_check("nobr",      HTMLElement);
+    create_element_and_check("noframes",  HTMLElement);
+    create_element_and_check("noscript",  HTMLElement);
+    create_element_and_check("object",    HTMLObjectElement);
+    create_element_and_check("ol",        HTMLOListElement);
+    create_element_and_check("optgroup",  HTMLOptGroupElement);
+    create_element_and_check("option",    HTMLOptionElement);
+    create_element_and_check("output",    HTMLOutputElement);
+    create_element_and_check("p",         HTMLParagraphElement);
+    create_element_and_check("param",     HTMLParamElement);
+    create_element_and_check("pre",       HTMLPreElement);
+    create_element_and_check("progress",  HTMLProgressElement);
+    create_element_and_check("q",         HTMLQuoteElement);
+    create_element_and_check("rp",        HTMLElement);
+    create_element_and_check("rt",        HTMLElement);
+    create_element_and_check("ruby",      HTMLElement);
+    create_element_and_check("s",         HTMLElement);
+    create_element_and_check("samp",      HTMLElement);
+    create_element_and_check("script",    HTMLScriptElement);
+    create_element_and_check("section",   HTMLElement);
+    create_element_and_check("select",    HTMLSelectElement);
+    create_element_and_check("small",     HTMLElement);
+    create_element_and_check("source",    HTMLSourceElement);
+    create_element_and_check("spacer",    HTMLElement);
+    create_element_and_check("span",      HTMLSpanElement);
+    create_element_and_check("strike",    HTMLElement);
+    create_element_and_check("style",     HTMLStyleElement);
+    create_element_and_check("sub",       HTMLElement);
+    create_element_and_check("summary",   HTMLElement);
+    create_element_and_check("sup",       HTMLElement);
+    create_element_and_check("table",     HTMLTableElement);
+    create_element_and_check("tbody",     HTMLTableSectionElement);
+    create_element_and_check("td",        HTMLTableDataCellElement);
+    create_element_and_check("template",  HTMLTemplateElement);
+    create_element_and_check("textarea",  HTMLTextAreaElement);
+    create_element_and_check("th",        HTMLTableHeaderCellElement);
+    create_element_and_check("time",      HTMLTimeElement);
+    create_element_and_check("title",     HTMLTitleElement);
+    create_element_and_check("tr",        HTMLTableRowElement);
+    create_element_and_check("tt",        HTMLElement);
+    create_element_and_check("track",     HTMLTrackElement);
+    create_element_and_check("u",         HTMLElement);
+    create_element_and_check("ul",        HTMLUListElement);
+    create_element_and_check("var",       HTMLElement);
+    create_element_and_check("video",     HTMLVideoElement);
+    create_element_and_check("unknown",   HTMLUnknownElement);
+    create_element_and_check("wbr",       HTMLElement);
+}, "");
+
+test(function() {
+    var fragment = document.createDocumentFragment();
+    var copy = fragment.cloneNode();
+    check_copy(fragment, copy, DocumentFragment);
+}, "createDocumentFragment");
+
+test(function() {
+    var text = document.createTextNode("hello world");
+    var copy = text.cloneNode();
+    check_copy(text, copy, Text);
+    assert_equals(text.data, copy.data);
+    assert_equals(text.wholeText, copy.wholeText);
+}, "createTextNode");
+
+test(function() {
+    var comment = document.createComment("a comment");
+    var copy = comment.cloneNode();
+    check_copy(comment, copy, Comment);
+    assert_equals(comment.data, copy.data);
+}, "createComment");
+
+test(function() {
+  var el = document.createElement("foo");
+  el.setAttribute("a", "b");
+  el.setAttribute("c", "d");
+  var c = el.cloneNode();
+  check_copy(el, c, Element);
+}, "createElement with attributes")
+
+test(function() {
+  var el = document.createElementNS("http://www.w3.org/1999/xhtml", "foo:div");
+  var c = el.cloneNode();
+  check_copy(el, c, HTMLDivElement);
+}, "createElementNS HTML")
+
+test(function() {
+  var el = document.createElementNS("http://www.example.com/", "foo:div");
+  var c = el.cloneNode();
+  check_copy(el, c, Element);
+}, "createElementNS non-HTML")
+
+test(function() {
+    var pi = document.createProcessingInstruction("target", "data");
+    var copy = pi.cloneNode();
+    check_copy(pi, copy, ProcessingInstruction);
+    assert_equals(pi.data, copy.data);
+    assert_equals(pi.target, pi.target);
+}, "createProcessingInstruction");
+
+test(function() {
+    var doctype = document.implementation.createDocumentType("html", "public", "system");
+    var copy = doctype.cloneNode();
+    check_copy(doctype, copy, DocumentType);
+    assert_equals(doctype.name, copy.name);
+    assert_equals(doctype.publicId, copy.publicId);
+    assert_equals(doctype.systemId, copy.systemId);
+}, "implementation.createDocumentType");
+
+test(function() {
+    var doc = document.implementation.createDocument(null, null);
+    var copy = doc.cloneNode();
+    check_copy(doc, copy, Document);
+    assert_equals(doc.contentType, copy.contentType);
+}, "implementation.createDocument");
+
+test(function() {
+    var html = document.implementation.createHTMLDocument("title");
+    var copy = html.cloneNode();
+    check_copy(html, copy, Document);
+    assert_equals(copy.title, "");
+}, "implementation.createHTMLDocument");
+
+test(function() {
+    var parent = document.createElement("div");
+    var child1 = document.createElement("div");
+    var child2 = document.createElement("div");
+    var grandChild = document.createElement("div");
+
+    child2.appendChild(grandChild);
+    parent.appendChild(child1);
+    parent.appendChild(child2);
+
+    var deep = true;
+    var copy = parent.cloneNode(deep);
+
+    check_copy(parent, copy, HTMLDivElement);
+    assert_equals(copy.childNodes.length, 2);
+
+    check_copy(child1, copy.childNodes[0], HTMLDivElement);
+    assert_equals(copy.childNodes[0].childNodes.length, 0);
+
+    check_copy(child2, copy.childNodes[1], HTMLDivElement);
+    assert_equals(copy.childNodes[1].childNodes.length, 1);
+    check_copy(grandChild, copy.childNodes[1].childNodes[0], HTMLDivElement);
+
+    deep = false;
+    copy = parent.cloneNode(deep);
+
+    check_copy(parent, copy, HTMLDivElement);
+    assert_equals(copy.childNodes.length, 0);
+}, "node with children");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-compareDocumentPosition.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-compareDocumentPosition.html
new file mode 100644
index 0000000..7ac02c6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-compareDocumentPosition.html
@@ -0,0 +1,87 @@
+<!doctype html>
+<title>Node.compareDocumentPosition() tests</title>
+<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
+<div id=log></div>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+testNodes.forEach(function(referenceName) {
+  var reference = eval(referenceName);
+  testNodes.forEach(function(otherName) {
+    var other = eval(otherName);
+    test(function() {
+      var result = reference.compareDocumentPosition(other);
+
+      // "If other and reference are the same object, return zero and
+      // terminate these steps."
+      if (other === reference) {
+        assert_equals(result, 0);
+        return;
+      }
+
+      // "If other and reference are not in the same tree, return the result of
+      // adding DOCUMENT_POSITION_DISCONNECTED,
+      // DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC, and either
+      // DOCUMENT_POSITION_PRECEDING or DOCUMENT_POSITION_FOLLOWING, with the
+      // constraint that this is to be consistent, together and terminate these
+      // steps."
+      if (furthestAncestor(reference) !== furthestAncestor(other)) {
+        // TODO: Test that it's consistent.
+        assert_in_array(result, [Node.DOCUMENT_POSITION_DISCONNECTED +
+                                 Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC +
+                                 Node.DOCUMENT_POSITION_PRECEDING,
+                                 Node.DOCUMENT_POSITION_DISCONNECTED +
+                                 Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC +
+                                 Node.DOCUMENT_POSITION_FOLLOWING]);
+        return;
+      }
+
+      // "If other is an ancestor of reference, return the result of
+      // adding DOCUMENT_POSITION_CONTAINS to DOCUMENT_POSITION_PRECEDING
+      // and terminate these steps."
+      var ancestor = reference.parentNode;
+      while (ancestor && ancestor !== other) {
+        ancestor = ancestor.parentNode;
+      }
+      if (ancestor === other) {
+        assert_equals(result, Node.DOCUMENT_POSITION_CONTAINS +
+                              Node.DOCUMENT_POSITION_PRECEDING);
+        return;
+      }
+
+      // "If other is a descendant of reference, return the result of adding
+      // DOCUMENT_POSITION_CONTAINED_BY to DOCUMENT_POSITION_FOLLOWING and
+      // terminate these steps."
+      ancestor = other.parentNode;
+      while (ancestor && ancestor !== reference) {
+        ancestor = ancestor.parentNode;
+      }
+      if (ancestor === reference) {
+        assert_equals(result, Node.DOCUMENT_POSITION_CONTAINED_BY +
+                              Node.DOCUMENT_POSITION_FOLLOWING);
+        return;
+      }
+
+      // "If other is preceding reference return DOCUMENT_POSITION_PRECEDING
+      // and terminate these steps."
+      var prev = previousNode(reference);
+      while (prev && prev !== other) {
+        prev = previousNode(prev);
+      }
+      if (prev === other) {
+        assert_equals(result, Node.DOCUMENT_POSITION_PRECEDING);
+        return;
+      }
+
+      // "Return DOCUMENT_POSITION_FOLLOWING."
+      assert_equals(result, Node.DOCUMENT_POSITION_FOLLOWING);
+    }, referenceName + ".compareDocumentPosition(" + otherName + ")");
+  });
+});
+
+testDiv.parentNode.removeChild(testDiv);
+</script>
+<!--  vim: set expandtab tabstop=2 shiftwidth=2:  -->
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-constants.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-constants.html
new file mode 100644
index 0000000..dc505a4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-constants.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<title>Node constants</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="../constants.js"></script>
+<div id="log"></div>
+<script>
+var objects;
+setup(function() {
+  objects = [
+    [Node, "Node interface object"],
+    [Node.prototype, "Node prototype object"],
+    [document.createElement("foo"), "Element object"],
+    [document.createTextNode("bar"), "Text object"]
+  ]
+})
+testConstants(objects, [
+  ["ELEMENT_NODE", 1],
+  ["ATTRIBUTE_NODE", 2],
+  ["TEXT_NODE", 3],
+  ["CDATA_SECTION_NODE", 4],
+  ["ENTITY_REFERENCE_NODE", 5],
+  ["ENTITY_NODE", 6],
+  ["PROCESSING_INSTRUCTION_NODE", 7],
+  ["COMMENT_NODE", 8],
+  ["DOCUMENT_NODE", 9],
+  ["DOCUMENT_TYPE_NODE", 10],
+  ["DOCUMENT_FRAGMENT_NODE", 11],
+  ["NOTATION_NODE", 12]
+], "nodeType")
+testConstants(objects, [
+  ["DOCUMENT_POSITION_DISCONNECTED", 0x01],
+  ["DOCUMENT_POSITION_PRECEDING", 0x02],
+  ["DOCUMENT_POSITION_FOLLOWING", 0x04],
+  ["DOCUMENT_POSITION_CONTAINS", 0x08],
+  ["DOCUMENT_POSITION_CONTAINED_BY", 0x10],
+  ["DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", 0x20]
+], "createDocumentPosition")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-contains.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-contains.html
new file mode 100644
index 0000000..b8baf7c9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-contains.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<title>Node.contains() tests</title>
+<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
+<div id=log></div>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+testNodes.forEach(function(referenceName) {
+  var reference = eval(referenceName);
+
+  test(function() {
+    assert_false(reference.contains(null));
+  }, referenceName + ".contains(null)");
+
+  testNodes.forEach(function(otherName) {
+    var other = eval(otherName);
+    test(function() {
+      var ancestor = other;
+      while (ancestor && ancestor !== reference) {
+        ancestor = ancestor.parentNode;
+      }
+      if (ancestor === reference) {
+        assert_true(reference.contains(other));
+      } else {
+        assert_false(reference.contains(other));
+      }
+    }, referenceName + ".compareDocumentPosition(" + otherName + ")");
+  });
+});
+
+testDiv.parentNode.removeChild(testDiv);
+</script>
+<!--  vim: set expandtab tabstop=2 shiftwidth=2:  -->
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-contains.xml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-contains.xml
new file mode 100644
index 0000000..8decfa9f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-contains.xml
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Node.nodeName</title>
+<link rel="author" title="Olli Pettay" href="mailto:Olli@Pettay.fi"/>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com"/>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"/>
+<div id="test">
+  <input type="button" id="testbutton"/>
+  <a id="link">Link text</a>
+</div>
+<script>
+<![CDATA[
+test(function() {
+  assert_throws(new TypeError(), function() {
+    document.contains();
+  });
+  assert_throws(new TypeError(), function() {
+    document.contains(9);
+  });
+}, "Should throw TypeError if the arguments are wrong.");
+
+test(function() {
+  assert_equals(document.contains(null), false, "Document shouldn't contain null.");
+}, "contains(null) should be false");
+
+test(function() {
+  assert_equals(document.contains(document), true, "Document should contain itself!");
+  assert_equals(document.contains(document.createElement("foo")), false, "Document shouldn't contain element which is't in the document");
+  assert_equals(document.contains(document.createTextNode("foo")), false, "Document shouldn't contain text node which is't in the document");
+}, "document.contains");
+
+test(function() {
+  var tb = document.getElementById("testbutton");
+  assert_equals(tb.contains(tb), true, "Element should contain itself.")
+  assert_equals(document.contains(tb), true, "Document should contain element in it!");
+  assert_equals(document.documentElement.contains(tb), true, "Element should contain element in it!");
+}, "contains with a button");
+
+test(function() {
+  var link = document.getElementById("link");
+  var text = link.firstChild;
+  assert_equals(document.contains(text), true, "Document should contain a text node in it.");
+  assert_equals(link.contains(text), true, "Element should contain a text node in it.");
+  assert_equals(text.contains(text), true, "Text node should contain itself.");
+  assert_equals(text.contains(link), false, "text node shouldn't contain its parent.");
+}, "contains with a text node");
+
+test(function() {
+  var pi = document.createProcessingInstruction("adf", "asd");
+  assert_equals(pi.contains(document), false, "Processing instruction shouldn't contain document");
+  assert_equals(document.contains(pi), false, "Document shouldn't contain newly created processing instruction");
+  document.documentElement.appendChild(pi);
+  document.contains(pi, true, "Document should contain processing instruction");
+}, "contains with a processing instruction");
+
+test(function() {
+  if ("createContextualFragment" in document.createRange()) {
+    var df = document.createRange().createContextualFragment("<div>foo</div>");
+    assert_equals(df.contains(df.firstChild), true, "Document fragment should contain its child");
+    assert_equals(df.contains(df.firstChild.firstChild), true,
+       "Document fragment should contain its descendant");
+    assert_equals(df.contains(df), true, "Document fragment should contain itself.");
+  }
+}, "contains with a document fragment");
+
+test(function() {
+  var d = document.implementation.createHTMLDocument("");
+  assert_equals(document.contains(d), false,
+     "Document shouldn't contain another document.");
+  assert_equals(document.contains(d.createElement("div")), false,
+     "Document shouldn't contain an element from another document.");
+  assert_equals(document.contains(d.documentElement), false,
+     "Document shouldn't contain an element from another document.");
+}, "contaibs with another document");
+]]>
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-insertBefore-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-insertBefore-expected.txt
new file mode 100644
index 0000000..884f0500
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-insertBefore-expected.txt
@@ -0,0 +1,41 @@
+This is a testharness.js-based test.
+PASS Calling insertBefore with a non-Node first argument must throw TypeError. 
+PASS Calling insertBefore with a non-Node first argument on a leaf node DocumentType must throw TypeError. 
+PASS Calling insertBefore an a leaf node DocumentType must throw HIERARCHY_REQUEST_ERR. 
+PASS Calling insertBefore with a non-Node first argument on a leaf node Text must throw TypeError. 
+PASS Calling insertBefore an a leaf node Text must throw HIERARCHY_REQUEST_ERR. 
+PASS Calling insertBefore with a non-Node first argument on a leaf node Comment must throw TypeError. 
+PASS Calling insertBefore an a leaf node Comment must throw HIERARCHY_REQUEST_ERR. 
+PASS Calling insertBefore with a non-Node first argument on a leaf node ProcessingInstruction must throw TypeError. 
+PASS Calling insertBefore an a leaf node ProcessingInstruction must throw HIERARCHY_REQUEST_ERR. 
+PASS Calling insertBefore with an inclusive ancestor of the context object must throw HIERARCHY_REQUEST_ERR. 
+PASS Calling insertBefore with a reference child whose parent is not the context node must throw a NotFoundError. 
+PASS If the context node is a document, inserting a document or text node should throw a HierarchyRequestError. 
+PASS If the context node is a document, appending a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError. 
+PASS If the context node is a document, inserting a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError. 
+PASS If the context node is a document, inserting a DocumentFragment with an element if there already is an element child should throw a HierarchyRequestError. 
+FAIL If the context node is a document and a doctype is following the reference child, inserting a DocumentFragment with an element should throw a HierarchyRequestError. assert_throws: function "function () {
+    doc.insertBefore(df, doc.doctype);
+  }" did not throw
+FAIL If the context node is a document, inserting a DocumentFragment with an element before the doctype should throw a HierarchyRequestError. assert_throws: function "function () {
+    doc.insertBefore(df, comment);
+  }" did not throw
+PASS If the context node is a document, inserting an element if there already is an element child should throw a HierarchyRequestError. 
+FAIL If the context node is a document, inserting an element before the doctype should throw a HierarchyRequestError. assert_throws: function "function () {
+    doc.insertBefore(a, doc.doctype);
+  }" did not throw
+FAIL If the context node is a document and a doctype is following the reference child, inserting an element should throw a HierarchyRequestError. assert_throws: function "function () {
+    doc.insertBefore(a, comment);
+  }" did not throw
+PASS If the context node is a document, inserting a doctype if there already is a doctype child should throw a HierarchyRequestError. 
+FAIL If the context node is a document, inserting a doctype after the document element should throw a HierarchyRequestError. assert_throws: function "function () {
+    doc.insertBefore(doctype, comment);
+  }" did not throw
+FAIL If the context node is a document with and element child, appending a doctype should throw a HierarchyRequestError. assert_throws: function "function () {
+    doc.insertBefore(doctype, null);
+  }" did not throw
+PASS If the context node is a DocumentFragment, inserting a document or a doctype should throw a HierarchyRequestError. 
+PASS If the context node is an element, inserting a document or a doctype should throw a HierarchyRequestError. 
+PASS Inserting a node before itself should not move the node 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-insertBefore.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-insertBefore.html
new file mode 100644
index 0000000..d37148c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-insertBefore.html
@@ -0,0 +1,306 @@
+<!DOCTYPE html>
+<title>Node.insertBefore</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testLeafNode(nodeName, createNodeFunction) {
+  test(function() {
+    var node = createNodeFunction();
+    assert_throws(new TypeError(), function() { node.insertBefore(null, null) })
+  }, "Calling insertBefore with a non-Node first argument on a leaf node " + nodeName + " must throw TypeError.")
+  test(function() {
+    var node = createNodeFunction();
+    assert_throws("HIERARCHY_REQUEST_ERR", function() { node.insertBefore(document.createTextNode("fail"), null) })
+    // Would be step 2.
+    assert_throws("HIERARCHY_REQUEST_ERR", function() { node.insertBefore(node, null) })
+    // Would be step 3.
+    assert_throws("HIERARCHY_REQUEST_ERR", function() { node.insertBefore(node, document.createTextNode("child")) })
+  }, "Calling insertBefore an a leaf node " + nodeName + " must throw HIERARCHY_REQUEST_ERR.")
+}
+
+test(function() {
+  // WebIDL.
+  assert_throws(new TypeError(), function() { document.body.insertBefore(null, null) })
+  assert_throws(new TypeError(), function() { document.body.insertBefore(null, document.body.firstChild) })
+  assert_throws(new TypeError(), function() { document.body.insertBefore({'a':'b'}, document.body.firstChild) })
+}, "Calling insertBefore with a non-Node first argument must throw TypeError.")
+
+testLeafNode("DocumentType", function () { return document.doctype; } )
+testLeafNode("Text", function () { return document.createTextNode("Foo") })
+testLeafNode("Comment", function () { return document.createComment("Foo") })
+testLeafNode("ProcessingInstruction", function () { return document.createProcessingInstruction("foo", "bar") })
+
+test(function() {
+  // Step 2.
+  assert_throws("HIERARCHY_REQUEST_ERR", function() { document.body.insertBefore(document.body, document.getElementById("log")) })
+  assert_throws("HIERARCHY_REQUEST_ERR", function() { document.body.insertBefore(document.documentElement, document.getElementById("log")) })
+}, "Calling insertBefore with an inclusive ancestor of the context object must throw HIERARCHY_REQUEST_ERR.")
+
+// Step 3.
+test(function() {
+  var a = document.createElement("div");
+  var b = document.createElement("div");
+  var c = document.createElement("div");
+  assert_throws("NotFoundError", function() {
+    a.insertBefore(b, c);
+  });
+}, "Calling insertBefore with a reference child whose parent is not the context node must throw a NotFoundError.")
+
+// Step 4.1.
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  var doc2 = document.implementation.createHTMLDocument("title2");
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(doc2, doc.documentElement);
+  });
+
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(doc.createTextNode("text"), doc.documentElement);
+  });
+}, "If the context node is a document, inserting a document or text node should throw a HierarchyRequestError.")
+
+// Step 4.2.1.
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  doc.removeChild(doc.documentElement);
+
+  var df = doc.createDocumentFragment();
+  df.appendChild(doc.createElement("a"));
+  df.appendChild(doc.createElement("b"));
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(df, null);
+  });
+
+  df = doc.createDocumentFragment();
+  df.appendChild(doc.createTextNode("text"));
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(df, null);
+  });
+
+  df = doc.createDocumentFragment();
+  df.appendChild(doc.createComment("comment"));
+  df.appendChild(doc.createTextNode("text"));
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(df, null);
+  });
+}, "If the context node is a document, appending a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError.")
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  doc.removeChild(doc.documentElement);
+
+  var df = doc.createDocumentFragment();
+  df.appendChild(doc.createElement("a"));
+  df.appendChild(doc.createElement("b"));
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(df, doc.firstChild);
+  });
+
+  df = doc.createDocumentFragment();
+  df.appendChild(doc.createTextNode("text"));
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(df, doc.firstChild);
+  });
+
+  df = doc.createDocumentFragment();
+  df.appendChild(doc.createComment("comment"));
+  df.appendChild(doc.createTextNode("text"));
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(df, doc.firstChild);
+  });
+}, "If the context node is a document, inserting a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError.")
+
+// Step 4.2.2.
+test(function() {
+  // The context node has an element child.
+  var doc = document.implementation.createHTMLDocument("title");
+  var comment = doc.appendChild(doc.createComment("foo"));
+  assert_array_equals(doc.childNodes, [doc.doctype, doc.documentElement, comment]);
+
+  var df = doc.createDocumentFragment();
+  df.appendChild(doc.createElement("a"));
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(df, doc.doctype);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(df, doc.documentElement);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(df, comment);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(df, null);
+  });
+}, "If the context node is a document, inserting a DocumentFragment with an element if there already is an element child should throw a HierarchyRequestError.")
+test(function() {
+  // /child/ is a doctype.
+  var doc = document.implementation.createHTMLDocument("title");
+  var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+  doc.removeChild(doc.documentElement);
+  assert_array_equals(doc.childNodes, [comment, doc.doctype]);
+
+  var df = doc.createDocumentFragment();
+  df.appendChild(doc.createElement("a"));
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(df, doc.doctype);
+  });
+}, "If the context node is a document and a doctype is following the reference child, inserting a DocumentFragment with an element should throw a HierarchyRequestError.")
+test(function() {
+  // /child/ is not null and a doctype is following /child/.
+  var doc = document.implementation.createHTMLDocument("title");
+  var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+  doc.removeChild(doc.documentElement);
+  assert_array_equals(doc.childNodes, [comment, doc.doctype]);
+
+  var df = doc.createDocumentFragment();
+  df.appendChild(doc.createElement("a"));
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(df, comment);
+  });
+}, "If the context node is a document, inserting a DocumentFragment with an element before the doctype should throw a HierarchyRequestError.")
+
+// Step 4.3.
+test(function() {
+  // The context node has an element child.
+  var doc = document.implementation.createHTMLDocument("title");
+  var comment = doc.appendChild(doc.createComment("foo"));
+  assert_array_equals(doc.childNodes, [doc.doctype, doc.documentElement, comment]);
+
+  var a = doc.createElement("a");
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(a, doc.doctype);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(a, doc.documentElement);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(a, comment);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(a, null);
+  });
+}, "If the context node is a document, inserting an element if there already is an element child should throw a HierarchyRequestError.")
+test(function() {
+  // /child/ is a doctype.
+  var doc = document.implementation.createHTMLDocument("title");
+  var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+  doc.removeChild(doc.documentElement);
+  assert_array_equals(doc.childNodes, [comment, doc.doctype]);
+
+  var a = doc.createElement("a");
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(a, doc.doctype);
+  });
+}, "If the context node is a document, inserting an element before the doctype should throw a HierarchyRequestError.")
+test(function() {
+  // /child/ is not null and a doctype is following /child/.
+  var doc = document.implementation.createHTMLDocument("title");
+  var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+  doc.removeChild(doc.documentElement);
+  assert_array_equals(doc.childNodes, [comment, doc.doctype]);
+
+  var a = doc.createElement("a");
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(a, comment);
+  });
+}, "If the context node is a document and a doctype is following the reference child, inserting an element should throw a HierarchyRequestError.")
+
+// Step 4.4.
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+  assert_array_equals(doc.childNodes, [comment, doc.doctype, doc.documentElement]);
+
+  var doctype = document.implementation.createDocumentType("html", "", "");
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(doctype, comment);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(doctype, doc.doctype);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(doctype, doc.documentElement);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(doctype, null);
+  });
+}, "If the context node is a document, inserting a doctype if there already is a doctype child should throw a HierarchyRequestError.")
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  var comment = doc.appendChild(doc.createComment("foo"));
+  doc.removeChild(doc.doctype);
+  assert_array_equals(doc.childNodes, [doc.documentElement, comment]);
+
+  var doctype = document.implementation.createDocumentType("html", "", "");
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(doctype, comment);
+  });
+}, "If the context node is a document, inserting a doctype after the document element should throw a HierarchyRequestError.")
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  var comment = doc.appendChild(doc.createComment("foo"));
+  doc.removeChild(doc.doctype);
+  assert_array_equals(doc.childNodes, [doc.documentElement, comment]);
+
+  var doctype = document.implementation.createDocumentType("html", "", "");
+  assert_throws("HierarchyRequestError", function() {
+    doc.insertBefore(doctype, null);
+  });
+}, "If the context node is a document with and element child, appending a doctype should throw a HierarchyRequestError.")
+
+// Step 5.
+test(function() {
+  var df = document.createDocumentFragment();
+  var a = df.appendChild(document.createElement("a"));
+
+  var doc = document.implementation.createHTMLDocument("title");
+  assert_throws("HierarchyRequestError", function() {
+    df.insertBefore(doc, a);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    df.insertBefore(doc, null);
+  });
+
+  var doctype = document.implementation.createDocumentType("html", "", "");
+  assert_throws("HierarchyRequestError", function() {
+    df.insertBefore(doctype, a);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    df.insertBefore(doctype, null);
+  });
+}, "If the context node is a DocumentFragment, inserting a document or a doctype should throw a HierarchyRequestError.")
+test(function() {
+  var el = document.createElement("div");
+  var a = el.appendChild(document.createElement("a"));
+
+  var doc = document.implementation.createHTMLDocument("title");
+  assert_throws("HierarchyRequestError", function() {
+    el.insertBefore(doc, a);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    el.insertBefore(doc, null);
+  });
+
+  var doctype = document.implementation.createDocumentType("html", "", "");
+  assert_throws("HierarchyRequestError", function() {
+    el.insertBefore(doctype, a);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    el.insertBefore(doctype, null);
+  });
+}, "If the context node is an element, inserting a document or a doctype should throw a HierarchyRequestError.")
+
+// Step 7.
+test(function() {
+  var a = document.createElement("div");
+  var b = document.createElement("div");
+  var c = document.createElement("div");
+  a.appendChild(b);
+  a.appendChild(c);
+  assert_array_equals(a.childNodes, [b, c]);
+  assert_equals(a.insertBefore(b, b), b);
+  assert_array_equals(a.childNodes, [b, c]);
+  assert_equals(a.insertBefore(c, c), c);
+  assert_array_equals(a.childNodes, [b, c]);
+}, "Inserting a node before itself should not move the node");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-lookupNamespaceURI-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-lookupNamespaceURI-expected.txt
new file mode 100644
index 0000000..ddc55a9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-lookupNamespaceURI-expected.txt
@@ -0,0 +1,61 @@
+This is a testharness.js-based test.
+PASS DocumentFragment should have null namespace, prefix null 
+PASS DocumentFragment should have null namespace, prefix "" 
+PASS DocumentFragment should have null namespace, prefix "foo" 
+PASS DocumentFragment should have null namespace, prefix "xmlns" 
+FAIL DocumentFragment is in default namespace, prefix null assert_equals: expected true but got false
+FAIL DocumentFragment is in default namespace, prefix "" assert_equals: expected true but got false
+PASS DocumentFragment is in default namespace, prefix "foo" 
+PASS DocumentFragment is in default namespace, prefix "xmlns" 
+PASS Element should have null namespace, prefix null 
+PASS Element should have null namespace, prefix "" 
+PASS Element should not have namespace matching prefix with namespaceURI value 
+PASS Element should not have XMLNS namespace 
+PASS Element has namespace URI matching prefix 
+FAIL Empty namespace is not default, prefix null assert_equals: expected true but got false
+FAIL Empty namespace is not default, prefix "" assert_equals: expected true but got false
+PASS fooNamespace is not default 
+PASS xmlns namespace is not default 
+PASS Element should have baz namespace, prefix null 
+FAIL Element should have baz namespace, prefix "" assert_equals: expected (string) "bazURI" but got (object) null
+PASS Element does not has namespace with xlmns prefix 
+PASS Element has bar namespace 
+PASS Empty namespace is not default on fooElem, prefix null 
+PASS Empty namespace is not default on fooElem, prefix "" 
+PASS bar namespace is not default 
+PASS baz namespace is default 
+PASS Comment should inherit baz namespace 
+FAIL Comment should inherit  baz namespace assert_equals: expected (string) "bazURI" but got (object) null
+PASS Comment should inherit namespace URI matching prefix 
+PASS Comment should inherit bar namespace 
+PASS For comment, empty namespace is not default, prefix null 
+PASS For comment, empty namespace is not default, prefix "" 
+PASS For comment, fooNamespace is not default 
+PASS For comment, xmlns namespace is not default 
+PASS For comment, inherited bar namespace is not default 
+PASS For comment, inherited baz namespace is default 
+PASS Child element should inherit baz namespace 
+FAIL Child element should have null namespace assert_equals: expected (string) "childNamespace" but got (object) null
+PASS Child element should not have XMLNS namespace 
+PASS Child element has namespace URI matching prefix 
+PASS Empty namespace is not default for child, prefix null 
+PASS Empty namespace is not default for child, prefix "" 
+PASS fooNamespace is not default for child 
+PASS xmlns namespace is not default for child 
+PASS bar namespace is not default for child 
+PASS baz namespace is default for child 
+PASS childNamespace is default for child 
+PASS Document should have xhtml namespace, prefix null 
+FAIL Document should have xhtml namespace, prefix "" assert_equals: expected (string) "http://www.w3.org/1999/xhtml" but got (object) null
+PASS Document has no namespace URI matching prefix 
+PASS Document has bar namespace 
+PASS For document, empty namespace is not default, prefix null 
+PASS For document, empty namespace is not default, prefix "" 
+PASS For document, fooNamespace is not default 
+PASS For document, xmlns namespace is not default 
+PASS For document, bar namespace is not default 
+PASS For document, baz namespace is not default 
+PASS For document, xhtml namespace is default 
+PASS Comment does not have bar namespace 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-lookupNamespaceURI.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-lookupNamespaceURI.html
new file mode 100644
index 0000000..cbc4069
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-lookupNamespaceURI.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>LookupNamespaceURI and IsDefaultNamespace tests</title>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+</head>
+<body>
+<h1>LookupNamespaceURI and IsDefaultNamespace</h1>
+<div id="log"/>
+<script>
+function lookupNamespaceURI(node, prefix, expected, name) {
+  test(function() {
+    assert_equals(node.lookupNamespaceURI(prefix), expected);
+  }, name);
+}
+
+function isDefaultNamespace(node, namespace, expected, name) {
+  test(function() {
+    assert_equals(node.isDefaultNamespace(namespace), expected);
+  }, name);
+}
+
+
+var frag = document.createDocumentFragment();
+lookupNamespaceURI(frag, null, null, 'DocumentFragment should have null namespace, prefix null');
+lookupNamespaceURI(frag, '', null, 'DocumentFragment should have null namespace, prefix ""');
+lookupNamespaceURI(frag, 'foo', null, 'DocumentFragment should have null namespace, prefix "foo"');
+lookupNamespaceURI(frag, 'xmlns', null, 'DocumentFragment should have null namespace, prefix "xmlns"');
+isDefaultNamespace(frag, null, true, 'DocumentFragment is in default namespace, prefix null');
+isDefaultNamespace(frag, '', true, 'DocumentFragment is in default namespace, prefix ""');
+isDefaultNamespace(frag, 'foo', false, 'DocumentFragment is in default namespace, prefix "foo"');
+isDefaultNamespace(frag, 'xmlns', false, 'DocumentFragment is in default namespace, prefix "xmlns"');
+
+
+
+var fooElem = document.createElementNS('fooNamespace', 'prefix:elem');
+fooElem.setAttribute('bar', 'value');
+
+lookupNamespaceURI(fooElem, null, null, 'Element should have null namespace, prefix null');
+lookupNamespaceURI(fooElem, '', null, 'Element should have null namespace, prefix ""');
+lookupNamespaceURI(fooElem, 'fooNamespace', null, 'Element should not have namespace matching prefix with namespaceURI value');
+lookupNamespaceURI(fooElem, 'xmlns', null, 'Element should not have XMLNS namespace');
+lookupNamespaceURI(fooElem, 'prefix', 'fooNamespace', 'Element has namespace URI matching prefix');
+isDefaultNamespace(fooElem, null, true, 'Empty namespace is not default, prefix null');
+isDefaultNamespace(fooElem, '', true, 'Empty namespace is not default, prefix ""');
+isDefaultNamespace(fooElem, 'fooNamespace', false, 'fooNamespace is not default');
+isDefaultNamespace(fooElem, 'http://www.w3.org/2000/xmlns/', false, 'xmlns namespace is not default');
+
+fooElem.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:bar', 'barURI');
+fooElem.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'bazURI');
+
+lookupNamespaceURI(fooElem, null, 'bazURI', 'Element should have baz namespace, prefix null');
+lookupNamespaceURI(fooElem, '', 'bazURI', 'Element should have baz namespace, prefix ""');
+lookupNamespaceURI(fooElem, 'xmlns', null, 'Element does not has namespace with xlmns prefix');
+lookupNamespaceURI(fooElem, 'bar', 'barURI', 'Element has bar namespace');
+
+isDefaultNamespace(fooElem, null, false, 'Empty namespace is not default on fooElem, prefix null');
+isDefaultNamespace(fooElem, '', false, 'Empty namespace is not default on fooElem, prefix ""');
+isDefaultNamespace(fooElem, 'barURI', false, 'bar namespace is not default');
+isDefaultNamespace(fooElem, 'bazURI', true, 'baz namespace is default');
+
+var comment = document.createComment('comment');
+fooElem.appendChild(comment);
+
+lookupNamespaceURI(comment, null, 'bazURI', 'Comment should inherit baz namespace');
+lookupNamespaceURI(comment, '', 'bazURI', 'Comment should inherit  baz namespace');
+lookupNamespaceURI(comment, 'prefix', 'fooNamespace', 'Comment should inherit namespace URI matching prefix');
+lookupNamespaceURI(comment, 'bar', 'barURI', 'Comment should inherit bar namespace');
+
+isDefaultNamespace(comment, null, false, 'For comment, empty namespace is not default, prefix null');
+isDefaultNamespace(comment, '', false, 'For comment, empty namespace is not default, prefix ""');
+isDefaultNamespace(comment, 'fooNamespace', false, 'For comment, fooNamespace is not default');
+isDefaultNamespace(comment, 'http://www.w3.org/2000/xmlns/', false, 'For comment, xmlns namespace is not default');
+isDefaultNamespace(comment, 'barURI', false, 'For comment, inherited bar namespace is not default');
+isDefaultNamespace(comment, 'bazURI', true, 'For comment, inherited baz namespace is default');
+
+var fooChild = document.createElementNS('childNamespace', 'childElem');
+fooElem.appendChild(fooChild);
+
+lookupNamespaceURI(fooChild, null, 'childNamespace', 'Child element should inherit baz namespace');
+lookupNamespaceURI(fooChild, '', 'childNamespace', 'Child element should have null namespace');
+lookupNamespaceURI(fooChild, 'xmlns', null, 'Child element should not have XMLNS namespace');
+lookupNamespaceURI(fooChild, 'prefix', 'fooNamespace', 'Child element has namespace URI matching prefix');
+
+isDefaultNamespace(fooChild, null, false, 'Empty namespace is not default for child, prefix null');
+isDefaultNamespace(fooChild, '', false, 'Empty namespace is not default for child, prefix ""');
+isDefaultNamespace(fooChild, 'fooNamespace', false, 'fooNamespace is not default for child');
+isDefaultNamespace(fooChild, 'http://www.w3.org/2000/xmlns/', false, 'xmlns namespace is not default for child');
+isDefaultNamespace(fooChild, 'barURI', false, 'bar namespace is not default for child');
+isDefaultNamespace(fooChild, 'bazURI', false, 'baz namespace is default for child');
+isDefaultNamespace(fooChild, 'childNamespace', true, 'childNamespace is default for child');
+
+document.documentElement.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:bar', 'barURI');
+document.documentElement.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'bazURI');
+
+lookupNamespaceURI(document, null, 'http://www.w3.org/1999/xhtml', 'Document should have xhtml namespace, prefix null');
+lookupNamespaceURI(document, '', 'http://www.w3.org/1999/xhtml', 'Document should have xhtml namespace, prefix ""');
+lookupNamespaceURI(document, 'prefix', null, 'Document has no namespace URI matching prefix');
+lookupNamespaceURI(document, 'bar', 'barURI', 'Document has bar namespace');
+
+isDefaultNamespace(document, null, false, 'For document, empty namespace is not default, prefix null');
+isDefaultNamespace(document, '', false, 'For document, empty namespace is not default, prefix ""');
+isDefaultNamespace(document, 'fooNamespace', false, 'For document, fooNamespace is not default');
+isDefaultNamespace(document, 'http://www.w3.org/2000/xmlns/', false, 'For document, xmlns namespace is not default');
+isDefaultNamespace(document, 'barURI', false, 'For document, bar namespace is not default');
+isDefaultNamespace(document, 'bazURI', false, 'For document, baz namespace is not default');
+isDefaultNamespace(document, 'http://www.w3.org/1999/xhtml', true, 'For document, xhtml namespace is default');
+
+var comment = document.createComment('comment');
+document.appendChild(comment);
+lookupNamespaceURI(comment, 'bar', null, 'Comment does not have bar namespace');
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-lookupPrefix.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-lookupPrefix.xhtml
new file mode 100644
index 0000000..f9cc3d2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-lookupPrefix.xhtml
@@ -0,0 +1,31 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:x="test">
+<head>
+<title>Node.lookupPrefix</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body xmlns:s="test">
+<div id="log"/>
+<x xmlns:t="test"><!-- comment --><?test test?>TEST<x/></x>
+<script>
+function lookupPrefix(node, ns, prefix) {
+  test(function() {
+    assert_equals(node.lookupPrefix(ns), prefix)
+  })
+}
+var x = document.getElementsByTagName("x")[0];
+lookupPrefix(document, "test", "x") // XXX add test for when there is no documentElement
+lookupPrefix(document, null, null)
+lookupPrefix(x, "http://www.w3.org/1999/xhtml", null)
+lookupPrefix(x, "something", null)
+lookupPrefix(x, null, null)
+lookupPrefix(x, "test", "t")
+lookupPrefix(x.parentNode, "test", "s")
+lookupPrefix(x.firstChild, "test", "t")
+lookupPrefix(x.childNodes[1], "test", "t")
+lookupPrefix(x.childNodes[2], "test", "t")
+lookupPrefix(x.lastChild, "test", "t")
+x.parentNode.removeChild(x)
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-nodeName-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-nodeName-xhtml.xhtml
new file mode 100644
index 0000000..376c5f0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-nodeName-xhtml.xhtml
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Node.nodeName</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"/>
+<script>
+test(function() {
+  var HTMLNS = "http://www.w3.org/1999/xhtml",
+      SVGNS = "http://www.w3.org/2000/svg"
+  assert_equals(document.createElementNS(HTMLNS, "I").nodeName, "I")
+  assert_equals(document.createElementNS(HTMLNS, "i").nodeName, "i")
+  assert_equals(document.createElementNS(SVGNS, "svg").nodeName, "svg")
+  assert_equals(document.createElementNS(SVGNS, "SVG").nodeName, "SVG")
+  assert_equals(document.createElementNS(HTMLNS, "x:b").nodeName, "x:b")
+}, "For Element nodes, nodeName should return the same as tagName.")
+test(function() {
+  assert_equals(document.createTextNode("foo").nodeName, "#text")
+}, "For Text nodes, nodeName should return \"#text\".")
+test(function() {
+  assert_equals(document.createProcessingInstruction("foo", "bar").nodeName,
+                "foo")
+}, "For ProcessingInstruction nodes, nodeName should return the target.")
+test(function() {
+  assert_equals(document.createComment("foo").nodeName, "#comment")
+}, "For Comment nodes, nodeName should return \"#comment\".")
+test(function() {
+  assert_equals(document.nodeName, "#document")
+}, "For Document nodes, nodeName should return \"#document\".")
+test(function() {
+  assert_equals(document.doctype.nodeName, "html")
+}, "For DocumentType nodes, nodeName should return the name.")
+test(function() {
+  assert_equals(document.createDocumentFragment().nodeName,
+                "#document-fragment")
+}, "For DocumentFragment nodes, nodeName should return \"#document-fragment\".")
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-nodeName.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-nodeName.html
new file mode 100644
index 0000000..c89d89a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-nodeName.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>Node.nodeName</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var HTMLNS = "http://www.w3.org/1999/xhtml",
+      SVGNS = "http://www.w3.org/2000/svg"
+  assert_equals(document.createElementNS(HTMLNS, "I").nodeName, "I")
+  assert_equals(document.createElementNS(HTMLNS, "i").nodeName, "I")
+  assert_equals(document.createElementNS(SVGNS, "svg").nodeName, "svg")
+  assert_equals(document.createElementNS(SVGNS, "SVG").nodeName, "SVG")
+  assert_equals(document.createElementNS(HTMLNS, "x:b").nodeName, "X:B")
+}, "For Element nodes, nodeName should return the same as tagName.")
+test(function() {
+  assert_equals(document.createTextNode("foo").nodeName, "#text")
+}, "For Text nodes, nodeName should return \"#text\".")
+test(function() {
+  assert_equals(document.createComment("foo").nodeName, "#comment")
+}, "For Comment nodes, nodeName should return \"#comment\".")
+test(function() {
+  assert_equals(document.nodeName, "#document")
+}, "For Document nodes, nodeName should return \"#document\".")
+test(function() {
+  assert_equals(document.doctype.nodeName, "html")
+}, "For DocumentType nodes, nodeName should return the name.")
+test(function() {
+  assert_equals(document.createDocumentFragment().nodeName,
+                "#document-fragment")
+}, "For DocumentFragment nodes, nodeName should return \"#document-fragment\".")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-nodeValue.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-nodeValue.html
new file mode 100644
index 0000000..ca12c8f6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-nodeValue.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Node.nodeValue</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodevalue">
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+  var the_text = document.createTextNode("A span!");
+  assert_equals(the_text.nodeValue, "A span!");
+  assert_equals(the_text.data, "A span!");
+  the_text.nodeValue = "test again";
+  assert_equals(the_text.nodeValue, "test again");
+  assert_equals(the_text.data, "test again");
+  the_text.nodeValue = null;
+  assert_equals(the_text.nodeValue, "");
+  assert_equals(the_text.data, "");
+}, "Text.nodeValue");
+
+test(function() {
+  var the_comment = document.createComment("A comment!");
+  assert_equals(the_comment.nodeValue, "A comment!");
+  assert_equals(the_comment.data, "A comment!");
+  the_comment.nodeValue = "test again";
+  assert_equals(the_comment.nodeValue, "test again");
+  assert_equals(the_comment.data, "test again");
+  the_comment.nodeValue = null;
+  assert_equals(the_comment.nodeValue, "");
+  assert_equals(the_comment.data, "");
+}, "Comment.nodeValue");
+
+test(function() {
+  var the_pi = document.createProcessingInstruction("pi", "A PI!");
+  assert_equals(the_pi.nodeValue, "A PI!");
+  assert_equals(the_pi.data, "A PI!");
+  the_pi.nodeValue = "test again";
+  assert_equals(the_pi.nodeValue, "test again");
+  assert_equals(the_pi.data, "test again");
+  the_pi.nodeValue = null;
+  assert_equals(the_pi.nodeValue, "");
+  assert_equals(the_pi.data, "");
+}, "ProcessingInstruction.nodeValue");
+
+test(function() {
+  var the_link = document.createElement("a");
+  assert_equals(the_link.nodeValue, null);
+  the_link.nodeValue = "foo";
+  assert_equals(the_link.nodeValue, null);
+}, "Element.nodeValue");
+
+test(function() {
+  assert_equals(document.nodeValue, null);
+  document.nodeValue = "foo";
+  assert_equals(document.nodeValue, null);
+}, "Document.nodeValue");
+
+test(function() {
+  var the_frag = document.createDocumentFragment();
+  assert_equals(the_frag.nodeValue, null);
+  the_frag.nodeValue = "foo";
+  assert_equals(the_frag.nodeValue, null);
+}, "DocumentFragment.nodeValue");
+
+test(function() {
+  var the_doctype = document.doctype;
+  assert_equals(the_doctype.nodeValue, null);
+  the_doctype.nodeValue = "foo";
+  assert_equals(the_doctype.nodeValue, null);
+}, "DocumentType.nodeValue");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-normalize.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-normalize.html
new file mode 100644
index 0000000..667668214
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-normalize.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>Node.normalize()</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+  var df = document.createDocumentFragment(),
+      t1 = document.createTextNode("1"),
+      t2 = document.createTextNode("2"),
+      t3 = document.createTextNode("3"),
+      t4 = document.createTextNode("4")
+  df.appendChild(t1)
+  df.appendChild(t2)
+  assert_equals(df.childNodes.length, 2)
+  assert_equals(df.textContent, "12")
+  var el = document.createElement('x')
+  df.appendChild(el)
+  el.appendChild(t3)
+  el.appendChild(t4)
+  document.normalize()
+  assert_equals(el.childNodes.length, 2)
+  assert_equals(el.textContent, "34")
+  assert_equals(df.childNodes.length, 3)
+  assert_equals(t1.data, "1")
+  df.normalize()
+  assert_equals(df.childNodes.length, 2)
+  assert_equals(df.firstChild, t1)
+  assert_equals(t1.data, "12")
+  assert_equals(t2.data, "2")
+  assert_equals(el.firstChild, t3)
+  assert_equals(t3.data, "34")
+  assert_equals(t4.data, "4")
+})
+
+// https://www.w3.org/Bugs/Public/show_bug.cgi?id=19837
+test(function() {
+  var div = document.createElement("div")
+  var t1 = div.appendChild(document.createTextNode(""))
+  var t2 = div.appendChild(document.createTextNode("a"))
+  var t3 = div.appendChild(document.createTextNode(""))
+  assert_array_equals(div.childNodes, [t1, t2, t3])
+  div.normalize();
+  assert_array_equals(div.childNodes, [t2])
+}, "Empty text nodes separated by a non-empty text node")
+test(function() {
+  var div = document.createElement("div")
+  var t1 = div.appendChild(document.createTextNode(""))
+  var t2 = div.appendChild(document.createTextNode(""))
+  assert_array_equals(div.childNodes, [t1, t2])
+  div.normalize();
+  assert_array_equals(div.childNodes, [])
+}, "Empty text nodes")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-parentElement.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-parentElement.html
new file mode 100644
index 0000000..af88cbe10
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-parentElement.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<title>Node.parentElement</title>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  assert_equals(document.parentElement, null)
+}, "When the parent is null, parentElement should be null")
+test(function() {
+  assert_equals(document.doctype.parentElement, null)
+}, "When the parent is a document, parentElement should be null (doctype)")
+test(function() {
+  assert_equals(document.documentElement.parentElement, null)
+}, "When the parent is a document, parentElement should be null (element)")
+test(function() {
+  var comment = document.appendChild(document.createComment("foo"))
+  assert_equals(comment.parentElement, null)
+}, "When the parent is a document, parentElement should be null (comment)")
+test(function() {
+  var df = document.createDocumentFragment()
+  assert_equals(df.parentElement, null)
+  var el = document.createElement("div")
+  assert_equals(el.parentElement, null)
+  df.appendChild(el)
+  assert_equals(el.parentNode, df)
+  assert_equals(el.parentElement, null)
+}, "parentElement should return null for children of DocumentFragments (element)")
+test(function() {
+  var df = document.createDocumentFragment()
+  assert_equals(df.parentElement, null)
+  var text = document.createTextNode("bar")
+  assert_equals(text.parentElement, null)
+  df.appendChild(text)
+  assert_equals(text.parentNode, df)
+  assert_equals(text.parentElement, null)
+}, "parentElement should return null for children of DocumentFragments (text)")
+test(function() {
+  var df = document.createDocumentFragment()
+  var parent = document.createElement("div")
+  df.appendChild(parent)
+  var el = document.createElement("div")
+  assert_equals(el.parentElement, null)
+  parent.appendChild(el)
+  assert_equals(el.parentElement, parent)
+}, "parentElement should work correctly with DocumentFragments (element)")
+test(function() {
+  var df = document.createDocumentFragment()
+  var parent = document.createElement("div")
+  df.appendChild(parent)
+  var text = document.createTextNode("bar")
+  assert_equals(text.parentElement, null)
+  parent.appendChild(text)
+  assert_equals(text.parentElement, parent)
+}, "parentElement should work correctly with DocumentFragments (text)")
+test(function() {
+  var parent = document.createElement("div")
+  var el = document.createElement("div")
+  assert_equals(el.parentElement, null)
+  parent.appendChild(el)
+  assert_equals(el.parentElement, parent)
+}, "parentElement should work correctly in disconnected subtrees (element)")
+test(function() {
+  var parent = document.createElement("div")
+  var text = document.createTextNode("bar")
+  assert_equals(text.parentElement, null)
+  parent.appendChild(text)
+  assert_equals(text.parentElement, parent)
+}, "parentElement should work correctly in disconnected subtrees (text)")
+test(function() {
+  var el = document.createElement("div")
+  assert_equals(el.parentElement, null)
+  document.body.appendChild(el)
+  assert_equals(el.parentElement, document.body)
+}, "parentElement should work correctly in a document (element)")
+test(function() {
+  var text = document.createElement("div")
+  assert_equals(text.parentElement, null)
+  document.body.appendChild(text)
+  assert_equals(text.parentElement, document.body)
+}, "parentElement should work correctly in a document (text)")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-properties-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-properties-expected.txt
new file mode 100644
index 0000000..b558c35c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-properties-expected.txt
@@ -0,0 +1,702 @@
+This is a testharness.js-based test.
+PASS testDiv.nodeType 
+PASS testDiv.ownerDocument 
+PASS testDiv.parentNode 
+PASS testDiv.parentElement 
+PASS testDiv.childNodes.length 
+PASS testDiv.childNodes[0] 
+PASS testDiv.childNodes[1] 
+PASS testDiv.childNodes[2] 
+PASS testDiv.childNodes[3] 
+PASS testDiv.childNodes[4] 
+PASS testDiv.childNodes[5] 
+PASS testDiv.previousSibling 
+PASS testDiv.nextSibling 
+PASS testDiv.textContent 
+PASS testDiv.namespaceURI 
+PASS testDiv.prefix 
+PASS testDiv.localName 
+PASS testDiv.tagName 
+PASS testDiv.id 
+PASS testDiv.children[0] 
+PASS testDiv.children[1] 
+PASS testDiv.children[2] 
+PASS testDiv.children[3] 
+PASS testDiv.children[4] 
+PASS testDiv.previousElementSibling 
+PASS testDiv.childElementCount 
+PASS testDiv.nodeName 
+PASS testDiv.nodeValue 
+PASS testDiv.children.length 
+PASS testDiv.className 
+PASS testDiv.firstElementChild 
+PASS testDiv.lastElementChild 
+PASS testDiv.firstChild 
+PASS testDiv.lastChild 
+PASS testDiv.hasChildNodes() 
+PASS detachedDiv.nodeType 
+PASS detachedDiv.ownerDocument 
+PASS detachedDiv.parentNode 
+PASS detachedDiv.parentElement 
+PASS detachedDiv.childNodes.length 
+PASS detachedDiv.childNodes[0] 
+PASS detachedDiv.childNodes[1] 
+PASS detachedDiv.previousSibling 
+PASS detachedDiv.nextSibling 
+PASS detachedDiv.textContent 
+PASS detachedDiv.namespaceURI 
+PASS detachedDiv.prefix 
+PASS detachedDiv.localName 
+PASS detachedDiv.tagName 
+PASS detachedDiv.children[0] 
+PASS detachedDiv.children[1] 
+PASS detachedDiv.previousElementSibling 
+PASS detachedDiv.nextElementSibling 
+PASS detachedDiv.childElementCount 
+PASS detachedDiv.nodeName 
+PASS detachedDiv.nodeValue 
+PASS detachedDiv.children.length 
+PASS detachedDiv.id 
+PASS detachedDiv.className 
+PASS detachedDiv.firstElementChild 
+PASS detachedDiv.lastElementChild 
+PASS detachedDiv.firstChild 
+PASS detachedDiv.lastChild 
+PASS detachedDiv.hasChildNodes() 
+PASS detachedPara1.nodeType 
+PASS detachedPara1.ownerDocument 
+PASS detachedPara1.parentNode 
+PASS detachedPara1.parentElement 
+PASS detachedPara1.childNodes.length 
+PASS detachedPara1.previousSibling 
+PASS detachedPara1.nextSibling 
+PASS detachedPara1.textContent 
+PASS detachedPara1.namespaceURI 
+PASS detachedPara1.prefix 
+PASS detachedPara1.localName 
+PASS detachedPara1.tagName 
+PASS detachedPara1.previousElementSibling 
+PASS detachedPara1.nextElementSibling 
+PASS detachedPara1.childElementCount 
+PASS detachedPara1.nodeName 
+PASS detachedPara1.nodeValue 
+PASS detachedPara1.children.length 
+PASS detachedPara1.id 
+PASS detachedPara1.className 
+PASS detachedPara1.lastElementChild 
+PASS detachedPara1.firstElementChild 
+PASS detachedPara1.firstChild 
+PASS detachedPara1.lastChild 
+PASS detachedPara1.hasChildNodes() 
+PASS detachedPara2.nodeType 
+PASS detachedPara2.ownerDocument 
+PASS detachedPara2.parentNode 
+PASS detachedPara2.parentElement 
+PASS detachedPara2.childNodes.length 
+PASS detachedPara2.previousSibling 
+PASS detachedPara2.nextSibling 
+PASS detachedPara2.textContent 
+PASS detachedPara2.namespaceURI 
+PASS detachedPara2.prefix 
+PASS detachedPara2.localName 
+PASS detachedPara2.tagName 
+PASS detachedPara2.previousElementSibling 
+PASS detachedPara2.nextElementSibling 
+PASS detachedPara2.childElementCount 
+PASS detachedPara2.nodeName 
+PASS detachedPara2.nodeValue 
+PASS detachedPara2.children.length 
+PASS detachedPara2.id 
+PASS detachedPara2.className 
+PASS detachedPara2.lastElementChild 
+PASS detachedPara2.firstElementChild 
+PASS detachedPara2.firstChild 
+PASS detachedPara2.lastChild 
+PASS detachedPara2.hasChildNodes() 
+PASS document.nodeType 
+PASS document.childNodes.length 
+PASS document.childNodes[0] 
+PASS document.childNodes[1] 
+PASS document.URL 
+PASS document.compatMode 
+PASS document.characterSet 
+PASS document.contentType 
+PASS document.doctype 
+PASS document.nodeName 
+PASS document.textContent 
+PASS document.nodeValue 
+PASS document.nextSibling 
+PASS document.previousSibling 
+PASS document.parentElement 
+PASS document.parentNode 
+PASS document.ownerDocument 
+PASS document.documentURI 
+PASS document.inputEncoding 
+PASS document.charset 
+PASS document.firstChild 
+PASS document.lastChild 
+PASS document.hasChildNodes() 
+PASS foreignDoc.nodeType 
+PASS foreignDoc.childNodes.length 
+PASS foreignDoc.childNodes[0] 
+PASS foreignDoc.childNodes[1] 
+PASS foreignDoc.childNodes[2] 
+FAIL foreignDoc.URL assert_equals: expected "about:blank" but got ""
+PASS foreignDoc.compatMode 
+PASS foreignDoc.characterSet 
+PASS foreignDoc.contentType 
+PASS foreignDoc.nodeName 
+PASS foreignDoc.textContent 
+PASS foreignDoc.nodeValue 
+PASS foreignDoc.nextSibling 
+PASS foreignDoc.previousSibling 
+PASS foreignDoc.parentElement 
+PASS foreignDoc.parentNode 
+PASS foreignDoc.ownerDocument 
+FAIL foreignDoc.documentURI assert_equals: expected (string) "about:blank" but got (object) null
+PASS foreignDoc.inputEncoding 
+PASS foreignDoc.charset 
+PASS foreignDoc.firstChild 
+PASS foreignDoc.lastChild 
+PASS foreignDoc.hasChildNodes() 
+PASS foreignPara1.nodeType 
+PASS foreignPara1.ownerDocument 
+PASS foreignPara1.parentNode 
+PASS foreignPara1.parentElement 
+PASS foreignPara1.childNodes.length 
+PASS foreignPara1.previousSibling 
+PASS foreignPara1.nextSibling 
+PASS foreignPara1.textContent 
+PASS foreignPara1.namespaceURI 
+PASS foreignPara1.prefix 
+PASS foreignPara1.localName 
+PASS foreignPara1.tagName 
+PASS foreignPara1.previousElementSibling 
+PASS foreignPara1.nextElementSibling 
+PASS foreignPara1.childElementCount 
+PASS foreignPara1.nodeName 
+PASS foreignPara1.nodeValue 
+PASS foreignPara1.children.length 
+PASS foreignPara1.id 
+PASS foreignPara1.className 
+PASS foreignPara1.lastElementChild 
+PASS foreignPara1.firstElementChild 
+PASS foreignPara1.firstChild 
+PASS foreignPara1.lastChild 
+PASS foreignPara1.hasChildNodes() 
+PASS foreignPara2.nodeType 
+PASS foreignPara2.ownerDocument 
+PASS foreignPara2.parentNode 
+PASS foreignPara2.parentElement 
+PASS foreignPara2.childNodes.length 
+PASS foreignPara2.previousSibling 
+PASS foreignPara2.nextSibling 
+PASS foreignPara2.textContent 
+PASS foreignPara2.namespaceURI 
+PASS foreignPara2.prefix 
+PASS foreignPara2.localName 
+PASS foreignPara2.tagName 
+PASS foreignPara2.previousElementSibling 
+PASS foreignPara2.nextElementSibling 
+PASS foreignPara2.childElementCount 
+PASS foreignPara2.nodeName 
+PASS foreignPara2.nodeValue 
+PASS foreignPara2.children.length 
+PASS foreignPara2.id 
+PASS foreignPara2.className 
+PASS foreignPara2.lastElementChild 
+PASS foreignPara2.firstElementChild 
+PASS foreignPara2.firstChild 
+PASS foreignPara2.lastChild 
+PASS foreignPara2.hasChildNodes() 
+PASS xmlDoc.nodeType 
+PASS xmlDoc.childNodes.length 
+PASS xmlDoc.childNodes[0] 
+PASS xmlDoc.childNodes[1] 
+PASS xmlDoc.childNodes[2] 
+PASS xmlDoc.childNodes[3] 
+FAIL xmlDoc.URL assert_equals: expected "about:blank" but got ""
+PASS xmlDoc.compatMode 
+PASS xmlDoc.characterSet 
+PASS xmlDoc.contentType 
+PASS xmlDoc.nodeName 
+PASS xmlDoc.textContent 
+PASS xmlDoc.nodeValue 
+PASS xmlDoc.nextSibling 
+PASS xmlDoc.previousSibling 
+PASS xmlDoc.parentElement 
+PASS xmlDoc.parentNode 
+PASS xmlDoc.ownerDocument 
+FAIL xmlDoc.documentURI assert_equals: expected (string) "about:blank" but got (object) null
+PASS xmlDoc.inputEncoding 
+PASS xmlDoc.charset 
+PASS xmlDoc.firstChild 
+PASS xmlDoc.lastChild 
+PASS xmlDoc.hasChildNodes() 
+PASS xmlElement.nodeType 
+PASS xmlElement.ownerDocument 
+PASS xmlElement.parentNode 
+PASS xmlElement.parentElement 
+PASS xmlElement.childNodes.length 
+PASS xmlElement.childNodes[0] 
+PASS xmlElement.previousSibling 
+PASS xmlElement.nextSibling 
+PASS xmlElement.textContent 
+FAIL xmlElement.namespaceURI assert_equals: expected (string) "http://www.w3.org/1999/xhtml" but got (object) null
+PASS xmlElement.prefix 
+PASS xmlElement.localName 
+PASS xmlElement.tagName 
+PASS xmlElement.previousElementSibling 
+PASS xmlElement.nextElementSibling 
+PASS xmlElement.childElementCount 
+PASS xmlElement.nodeName 
+PASS xmlElement.nodeValue 
+PASS xmlElement.children.length 
+PASS xmlElement.id 
+PASS xmlElement.className 
+PASS xmlElement.lastElementChild 
+PASS xmlElement.firstElementChild 
+PASS xmlElement.firstChild 
+PASS xmlElement.lastChild 
+PASS xmlElement.hasChildNodes() 
+PASS detachedXmlElement.nodeType 
+PASS detachedXmlElement.ownerDocument 
+PASS detachedXmlElement.parentNode 
+PASS detachedXmlElement.parentElement 
+PASS detachedXmlElement.childNodes.length 
+PASS detachedXmlElement.previousSibling 
+PASS detachedXmlElement.nextSibling 
+PASS detachedXmlElement.textContent 
+FAIL detachedXmlElement.namespaceURI assert_equals: expected (string) "http://www.w3.org/1999/xhtml" but got (object) null
+PASS detachedXmlElement.prefix 
+PASS detachedXmlElement.localName 
+PASS detachedXmlElement.tagName 
+PASS detachedXmlElement.previousElementSibling 
+PASS detachedXmlElement.nextElementSibling 
+PASS detachedXmlElement.childElementCount 
+PASS detachedXmlElement.nodeName 
+PASS detachedXmlElement.nodeValue 
+PASS detachedXmlElement.children.length 
+PASS detachedXmlElement.id 
+PASS detachedXmlElement.className 
+PASS detachedXmlElement.lastElementChild 
+PASS detachedXmlElement.firstElementChild 
+PASS detachedXmlElement.lastChild 
+PASS detachedXmlElement.firstChild 
+PASS detachedXmlElement.hasChildNodes() 
+PASS detachedTextNode.nodeType 
+PASS detachedTextNode.ownerDocument 
+PASS detachedTextNode.parentNode 
+PASS detachedTextNode.parentElement 
+PASS detachedTextNode.previousSibling 
+PASS detachedTextNode.nextSibling 
+PASS detachedTextNode.nodeValue 
+PASS detachedTextNode.wholeText 
+PASS detachedTextNode.nodeName 
+PASS detachedTextNode.childNodes.length 
+PASS detachedTextNode.data 
+PASS detachedTextNode.textContent 
+PASS detachedTextNode.length 
+PASS detachedTextNode.lastChild 
+PASS detachedTextNode.firstChild 
+PASS detachedTextNode.hasChildNodes() 
+PASS foreignTextNode.nodeType 
+PASS foreignTextNode.ownerDocument 
+PASS foreignTextNode.parentNode 
+PASS foreignTextNode.parentElement 
+PASS foreignTextNode.previousSibling 
+PASS foreignTextNode.nextSibling 
+PASS foreignTextNode.nodeValue 
+PASS foreignTextNode.wholeText 
+PASS foreignTextNode.nodeName 
+PASS foreignTextNode.childNodes.length 
+PASS foreignTextNode.data 
+PASS foreignTextNode.textContent 
+PASS foreignTextNode.length 
+PASS foreignTextNode.lastChild 
+PASS foreignTextNode.firstChild 
+PASS foreignTextNode.hasChildNodes() 
+PASS detachedForeignTextNode.nodeType 
+PASS detachedForeignTextNode.ownerDocument 
+PASS detachedForeignTextNode.parentNode 
+PASS detachedForeignTextNode.parentElement 
+PASS detachedForeignTextNode.previousSibling 
+PASS detachedForeignTextNode.nextSibling 
+PASS detachedForeignTextNode.nodeValue 
+PASS detachedForeignTextNode.wholeText 
+PASS detachedForeignTextNode.nodeName 
+PASS detachedForeignTextNode.childNodes.length 
+PASS detachedForeignTextNode.data 
+PASS detachedForeignTextNode.textContent 
+PASS detachedForeignTextNode.length 
+PASS detachedForeignTextNode.lastChild 
+PASS detachedForeignTextNode.firstChild 
+PASS detachedForeignTextNode.hasChildNodes() 
+PASS xmlTextNode.nodeType 
+PASS xmlTextNode.ownerDocument 
+PASS xmlTextNode.parentNode 
+PASS xmlTextNode.parentElement 
+PASS xmlTextNode.previousSibling 
+PASS xmlTextNode.nextSibling 
+PASS xmlTextNode.nodeValue 
+PASS xmlTextNode.wholeText 
+PASS xmlTextNode.nodeName 
+PASS xmlTextNode.childNodes.length 
+PASS xmlTextNode.data 
+PASS xmlTextNode.textContent 
+PASS xmlTextNode.length 
+PASS xmlTextNode.lastChild 
+PASS xmlTextNode.firstChild 
+PASS xmlTextNode.hasChildNodes() 
+PASS detachedXmlTextNode.nodeType 
+PASS detachedXmlTextNode.ownerDocument 
+PASS detachedXmlTextNode.parentNode 
+PASS detachedXmlTextNode.parentElement 
+PASS detachedXmlTextNode.previousSibling 
+PASS detachedXmlTextNode.nextSibling 
+PASS detachedXmlTextNode.nodeValue 
+PASS detachedXmlTextNode.wholeText 
+PASS detachedXmlTextNode.nodeName 
+PASS detachedXmlTextNode.childNodes.length 
+PASS detachedXmlTextNode.data 
+PASS detachedXmlTextNode.textContent 
+PASS detachedXmlTextNode.length 
+PASS detachedXmlTextNode.lastChild 
+PASS detachedXmlTextNode.firstChild 
+PASS detachedXmlTextNode.hasChildNodes() 
+PASS processingInstruction.nodeType 
+PASS processingInstruction.ownerDocument 
+PASS processingInstruction.parentNode 
+PASS processingInstruction.parentElement 
+PASS processingInstruction.previousSibling 
+PASS processingInstruction.nextSibling 
+PASS processingInstruction.nodeValue 
+PASS processingInstruction.target 
+PASS processingInstruction.nodeName 
+PASS processingInstruction.childNodes.length 
+PASS processingInstruction.data 
+PASS processingInstruction.textContent 
+PASS processingInstruction.length 
+PASS processingInstruction.lastChild 
+PASS processingInstruction.firstChild 
+PASS processingInstruction.hasChildNodes() 
+PASS detachedProcessingInstruction.nodeType 
+PASS detachedProcessingInstruction.ownerDocument 
+PASS detachedProcessingInstruction.parentNode 
+PASS detachedProcessingInstruction.parentElement 
+PASS detachedProcessingInstruction.previousSibling 
+PASS detachedProcessingInstruction.nextSibling 
+PASS detachedProcessingInstruction.nodeValue 
+PASS detachedProcessingInstruction.target 
+PASS detachedProcessingInstruction.nodeName 
+PASS detachedProcessingInstruction.childNodes.length 
+PASS detachedProcessingInstruction.data 
+PASS detachedProcessingInstruction.textContent 
+PASS detachedProcessingInstruction.length 
+PASS detachedProcessingInstruction.lastChild 
+PASS detachedProcessingInstruction.firstChild 
+PASS detachedProcessingInstruction.hasChildNodes() 
+PASS comment.nodeType 
+PASS comment.ownerDocument 
+PASS comment.parentNode 
+PASS comment.parentElement 
+PASS comment.previousSibling 
+PASS comment.nextSibling 
+PASS comment.nodeValue 
+PASS comment.nodeName 
+PASS comment.childNodes.length 
+PASS comment.data 
+PASS comment.textContent 
+PASS comment.length 
+PASS comment.lastChild 
+PASS comment.firstChild 
+PASS comment.hasChildNodes() 
+PASS detachedComment.nodeType 
+PASS detachedComment.ownerDocument 
+PASS detachedComment.parentNode 
+PASS detachedComment.parentElement 
+PASS detachedComment.previousSibling 
+PASS detachedComment.nextSibling 
+PASS detachedComment.nodeValue 
+PASS detachedComment.nodeName 
+PASS detachedComment.childNodes.length 
+PASS detachedComment.data 
+PASS detachedComment.textContent 
+PASS detachedComment.length 
+PASS detachedComment.lastChild 
+PASS detachedComment.firstChild 
+PASS detachedComment.hasChildNodes() 
+PASS foreignComment.nodeType 
+PASS foreignComment.ownerDocument 
+PASS foreignComment.parentNode 
+PASS foreignComment.parentElement 
+PASS foreignComment.previousSibling 
+PASS foreignComment.nextSibling 
+PASS foreignComment.nodeValue 
+PASS foreignComment.nodeName 
+PASS foreignComment.childNodes.length 
+PASS foreignComment.data 
+PASS foreignComment.textContent 
+PASS foreignComment.length 
+PASS foreignComment.lastChild 
+PASS foreignComment.firstChild 
+PASS foreignComment.hasChildNodes() 
+PASS detachedForeignComment.nodeType 
+PASS detachedForeignComment.ownerDocument 
+PASS detachedForeignComment.parentNode 
+PASS detachedForeignComment.parentElement 
+PASS detachedForeignComment.previousSibling 
+PASS detachedForeignComment.nextSibling 
+PASS detachedForeignComment.nodeValue 
+PASS detachedForeignComment.nodeName 
+PASS detachedForeignComment.childNodes.length 
+PASS detachedForeignComment.data 
+PASS detachedForeignComment.textContent 
+PASS detachedForeignComment.length 
+PASS detachedForeignComment.lastChild 
+PASS detachedForeignComment.firstChild 
+PASS detachedForeignComment.hasChildNodes() 
+PASS xmlComment.nodeType 
+PASS xmlComment.ownerDocument 
+PASS xmlComment.parentNode 
+PASS xmlComment.parentElement 
+PASS xmlComment.previousSibling 
+PASS xmlComment.nextSibling 
+PASS xmlComment.nodeValue 
+PASS xmlComment.nodeName 
+PASS xmlComment.childNodes.length 
+PASS xmlComment.data 
+PASS xmlComment.textContent 
+PASS xmlComment.length 
+PASS xmlComment.lastChild 
+PASS xmlComment.firstChild 
+PASS xmlComment.hasChildNodes() 
+PASS detachedXmlComment.nodeType 
+PASS detachedXmlComment.ownerDocument 
+PASS detachedXmlComment.parentNode 
+PASS detachedXmlComment.parentElement 
+PASS detachedXmlComment.previousSibling 
+PASS detachedXmlComment.nextSibling 
+PASS detachedXmlComment.nodeValue 
+PASS detachedXmlComment.nodeName 
+PASS detachedXmlComment.childNodes.length 
+PASS detachedXmlComment.data 
+PASS detachedXmlComment.textContent 
+PASS detachedXmlComment.length 
+PASS detachedXmlComment.lastChild 
+PASS detachedXmlComment.firstChild 
+PASS detachedXmlComment.hasChildNodes() 
+PASS docfrag.nodeType 
+PASS docfrag.ownerDocument 
+PASS docfrag.childNodes.length 
+PASS docfrag.textContent 
+PASS docfrag.nodeName 
+PASS docfrag.nodeValue 
+PASS docfrag.nextSibling 
+PASS docfrag.previousSibling 
+PASS docfrag.parentElement 
+PASS docfrag.parentNode 
+PASS docfrag.lastChild 
+PASS docfrag.firstChild 
+PASS docfrag.hasChildNodes() 
+PASS foreignDocfrag.nodeType 
+PASS foreignDocfrag.ownerDocument 
+PASS foreignDocfrag.childNodes.length 
+PASS foreignDocfrag.textContent 
+PASS foreignDocfrag.nodeName 
+PASS foreignDocfrag.nodeValue 
+PASS foreignDocfrag.nextSibling 
+PASS foreignDocfrag.previousSibling 
+PASS foreignDocfrag.parentElement 
+PASS foreignDocfrag.parentNode 
+PASS foreignDocfrag.lastChild 
+PASS foreignDocfrag.firstChild 
+PASS foreignDocfrag.hasChildNodes() 
+PASS xmlDocfrag.nodeType 
+PASS xmlDocfrag.ownerDocument 
+PASS xmlDocfrag.childNodes.length 
+PASS xmlDocfrag.textContent 
+PASS xmlDocfrag.nodeName 
+PASS xmlDocfrag.nodeValue 
+PASS xmlDocfrag.nextSibling 
+PASS xmlDocfrag.previousSibling 
+PASS xmlDocfrag.parentElement 
+PASS xmlDocfrag.parentNode 
+PASS xmlDocfrag.lastChild 
+PASS xmlDocfrag.firstChild 
+PASS xmlDocfrag.hasChildNodes() 
+PASS doctype.nodeType 
+PASS doctype.ownerDocument 
+PASS doctype.parentNode 
+PASS doctype.previousSibling 
+PASS doctype.nextSibling 
+PASS doctype.name 
+PASS doctype.publicId 
+PASS doctype.systemId 
+PASS doctype.nodeName 
+PASS doctype.childNodes.length 
+PASS doctype.textContent 
+PASS doctype.nodeValue 
+PASS doctype.parentElement 
+PASS doctype.lastChild 
+PASS doctype.firstChild 
+PASS doctype.hasChildNodes() 
+PASS foreignDoctype.nodeType 
+PASS foreignDoctype.ownerDocument 
+PASS foreignDoctype.parentNode 
+PASS foreignDoctype.previousSibling 
+PASS foreignDoctype.nextSibling 
+PASS foreignDoctype.name 
+PASS foreignDoctype.publicId 
+PASS foreignDoctype.systemId 
+PASS foreignDoctype.nodeName 
+PASS foreignDoctype.childNodes.length 
+PASS foreignDoctype.textContent 
+PASS foreignDoctype.nodeValue 
+PASS foreignDoctype.parentElement 
+PASS foreignDoctype.lastChild 
+PASS foreignDoctype.firstChild 
+PASS foreignDoctype.hasChildNodes() 
+PASS xmlDoctype.nodeType 
+PASS xmlDoctype.ownerDocument 
+PASS xmlDoctype.parentNode 
+PASS xmlDoctype.previousSibling 
+PASS xmlDoctype.nextSibling 
+PASS xmlDoctype.name 
+PASS xmlDoctype.publicId 
+PASS xmlDoctype.systemId 
+PASS xmlDoctype.nodeName 
+PASS xmlDoctype.childNodes.length 
+PASS xmlDoctype.textContent 
+PASS xmlDoctype.nodeValue 
+PASS xmlDoctype.parentElement 
+PASS xmlDoctype.lastChild 
+PASS xmlDoctype.firstChild 
+PASS xmlDoctype.hasChildNodes() 
+PASS paras[0].nodeType 
+PASS paras[0].ownerDocument 
+PASS paras[0].parentNode 
+PASS paras[0].parentElement 
+PASS paras[0].childNodes.length 
+PASS paras[0].previousSibling 
+PASS paras[0].nextSibling 
+PASS paras[0].textContent 
+PASS paras[0].namespaceURI 
+PASS paras[0].prefix 
+PASS paras[0].localName 
+PASS paras[0].tagName 
+PASS paras[0].id 
+PASS paras[0].previousElementSibling 
+PASS paras[0].nextElementSibling 
+PASS paras[0].childElementCount 
+PASS paras[0].nodeName 
+PASS paras[0].nodeValue 
+PASS paras[0].children.length 
+PASS paras[0].className 
+PASS paras[0].lastElementChild 
+PASS paras[0].firstElementChild 
+PASS paras[0].firstChild 
+PASS paras[0].lastChild 
+PASS paras[0].hasChildNodes() 
+PASS paras[1].nodeType 
+PASS paras[1].ownerDocument 
+PASS paras[1].parentNode 
+PASS paras[1].parentElement 
+PASS paras[1].childNodes.length 
+PASS paras[1].previousSibling 
+PASS paras[1].nextSibling 
+PASS paras[1].textContent 
+PASS paras[1].namespaceURI 
+PASS paras[1].prefix 
+PASS paras[1].localName 
+PASS paras[1].tagName 
+PASS paras[1].id 
+PASS paras[1].previousElementSibling 
+PASS paras[1].nextElementSibling 
+PASS paras[1].childElementCount 
+PASS paras[1].nodeName 
+PASS paras[1].nodeValue 
+PASS paras[1].children.length 
+PASS paras[1].className 
+PASS paras[1].lastElementChild 
+PASS paras[1].firstElementChild 
+PASS paras[1].firstChild 
+PASS paras[1].lastChild 
+PASS paras[1].hasChildNodes() 
+PASS paras[2].nodeType 
+PASS paras[2].ownerDocument 
+PASS paras[2].parentNode 
+PASS paras[2].parentElement 
+PASS paras[2].childNodes.length 
+PASS paras[2].previousSibling 
+PASS paras[2].nextSibling 
+PASS paras[2].textContent 
+PASS paras[2].namespaceURI 
+PASS paras[2].prefix 
+PASS paras[2].localName 
+PASS paras[2].tagName 
+PASS paras[2].id 
+PASS paras[2].previousElementSibling 
+PASS paras[2].nextElementSibling 
+PASS paras[2].childElementCount 
+PASS paras[2].nodeName 
+PASS paras[2].nodeValue 
+PASS paras[2].children.length 
+PASS paras[2].className 
+PASS paras[2].lastElementChild 
+PASS paras[2].firstElementChild 
+PASS paras[2].firstChild 
+PASS paras[2].lastChild 
+PASS paras[2].hasChildNodes() 
+PASS paras[3].nodeType 
+PASS paras[3].ownerDocument 
+PASS paras[3].parentNode 
+PASS paras[3].parentElement 
+PASS paras[3].childNodes.length 
+PASS paras[3].previousSibling 
+PASS paras[3].nextSibling 
+PASS paras[3].textContent 
+PASS paras[3].namespaceURI 
+PASS paras[3].prefix 
+PASS paras[3].localName 
+PASS paras[3].tagName 
+PASS paras[3].id 
+PASS paras[3].previousElementSibling 
+PASS paras[3].nextElementSibling 
+PASS paras[3].childElementCount 
+PASS paras[3].nodeName 
+PASS paras[3].nodeValue 
+PASS paras[3].children.length 
+PASS paras[3].className 
+PASS paras[3].lastElementChild 
+PASS paras[3].firstElementChild 
+PASS paras[3].firstChild 
+PASS paras[3].lastChild 
+PASS paras[3].hasChildNodes() 
+PASS paras[4].nodeType 
+PASS paras[4].ownerDocument 
+PASS paras[4].parentNode 
+PASS paras[4].parentElement 
+PASS paras[4].childNodes.length 
+PASS paras[4].previousSibling 
+PASS paras[4].nextSibling 
+PASS paras[4].textContent 
+PASS paras[4].namespaceURI 
+PASS paras[4].prefix 
+PASS paras[4].localName 
+PASS paras[4].tagName 
+PASS paras[4].id 
+PASS paras[4].previousElementSibling 
+PASS paras[4].nextElementSibling 
+PASS paras[4].childElementCount 
+PASS paras[4].nodeName 
+PASS paras[4].nodeValue 
+PASS paras[4].children.length 
+PASS paras[4].className 
+PASS paras[4].lastElementChild 
+PASS paras[4].firstElementChild 
+PASS paras[4].firstChild 
+PASS paras[4].lastChild 
+PASS paras[4].hasChildNodes() 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-properties.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-properties.html
new file mode 100644
index 0000000..98ea929
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-properties.html
@@ -0,0 +1,688 @@
+<!doctype html>
+<title>Node assorted property tests</title>
+<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta charset=utf-8>
+<div id=log></div>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+/**
+ * First we define a data structure to tell us what tests to run.  The keys
+ * will be eval()ed, and are mostly global variables defined in common.js.  The
+ * values are objects, which maps properties to expected values.  So
+ *
+ *     foo: {
+ *         bar: "baz",
+ *         quz: 7,
+ *     },
+ *
+ * will test that eval("foo.bar") === "baz" and eval("foo.quz") === 7.  "foo"
+ * and "bar" could thus be expressions, like "document.documentElement" and
+ * "childNodes[4]" respectively.
+ *
+ * To avoid repetition, some values are automatically added based on others.
+ * For instance, if we specify nodeType: Node.TEXT_NODE, we'll automatically
+ * also test nodeName: "#text".  This is handled by code after this variable is
+ * defined.
+ */
+var expected = {
+    testDiv: {
+        // Node
+        nodeType: Node.ELEMENT_NODE,
+        ownerDocument: document,
+        parentNode: document.body,
+        parentElement: document.body,
+        "childNodes.length": 6,
+        "childNodes[0]": paras[0],
+        "childNodes[1]": paras[1],
+        "childNodes[2]": paras[2],
+        "childNodes[3]": paras[3],
+        "childNodes[4]": paras[4],
+        "childNodes[5]": comment,
+        previousSibling: null,
+        nextSibling: document.getElementById("log"),
+        textContent: "A\u0308b\u0308c\u0308d\u0308e\u0308f\u0308g\u0308h\u0308\nIjklmnop\nQrstuvwxYzabcdefGhijklmn",
+
+        // Element
+        namespaceURI: "http://www.w3.org/1999/xhtml",
+        prefix: null,
+        localName: "div",
+        tagName: "DIV",
+        id: "test",
+        "children[0]": paras[0],
+        "children[1]": paras[1],
+        "children[2]": paras[2],
+        "children[3]": paras[3],
+        "children[4]": paras[4],
+        previousElementSibling: null,
+        // nextSibling isn't explicitly set
+        //nextElementSibling: ,
+        childElementCount: 5,
+    },
+    detachedDiv: {
+        // Node
+        nodeType: Node.ELEMENT_NODE,
+        ownerDocument: document,
+        parentNode: null,
+        parentElement: null,
+        "childNodes.length": 2,
+        "childNodes[0]": detachedPara1,
+        "childNodes[1]": detachedPara2,
+        previousSibling: null,
+        nextSibling: null,
+        textContent: "OpqrstuvWxyzabcd",
+
+        // Element
+        namespaceURI: "http://www.w3.org/1999/xhtml",
+        prefix: null,
+        localName: "div",
+        tagName: "DIV",
+        "children[0]": detachedPara1,
+        "children[1]": detachedPara2,
+        previousElementSibling: null,
+        nextElementSibling: null,
+        childElementCount: 2,
+    },
+    detachedPara1: {
+        // Node
+        nodeType: Node.ELEMENT_NODE,
+        ownerDocument: document,
+        parentNode: detachedDiv,
+        parentElement: detachedDiv,
+        "childNodes.length": 1,
+        previousSibling: null,
+        nextSibling: detachedPara2,
+        textContent: "Opqrstuv",
+
+        // Element
+        namespaceURI: "http://www.w3.org/1999/xhtml",
+        prefix: null,
+        localName: "p",
+        tagName: "P",
+        previousElementSibling: null,
+        nextElementSibling: detachedPara2,
+        childElementCount: 0,
+    },
+    detachedPara2: {
+        // Node
+        nodeType: Node.ELEMENT_NODE,
+        ownerDocument: document,
+        parentNode: detachedDiv,
+        parentElement: detachedDiv,
+        "childNodes.length": 1,
+        previousSibling: detachedPara1,
+        nextSibling: null,
+        textContent: "Wxyzabcd",
+
+        // Element
+        namespaceURI: "http://www.w3.org/1999/xhtml",
+        prefix: null,
+        localName: "p",
+        tagName: "P",
+        previousElementSibling: detachedPara1,
+        nextElementSibling: null,
+        childElementCount: 0,
+    },
+    document: {
+        // Node
+        nodeType: Node.DOCUMENT_NODE,
+        "childNodes.length": 2,
+        "childNodes[0]": document.doctype,
+        "childNodes[1]": document.documentElement,
+
+        // Document
+        URL: String(location),
+        compatMode: "CSS1Compat",
+        characterSet: "UTF-8",
+        contentType: "text/html",
+        doctype: doctype,
+        //documentElement: ,
+    },
+    foreignDoc: {
+        // Node
+        nodeType: Node.DOCUMENT_NODE,
+        "childNodes.length": 3,
+        "childNodes[0]": foreignDoc.doctype,
+        "childNodes[1]": foreignDoc.documentElement,
+        "childNodes[2]": foreignComment,
+
+        // Document
+        URL: "about:blank",
+        compatMode: "CSS1Compat",
+        characterSet: "UTF-8",
+        contentType: "text/html",
+        //doctype: ,
+        //documentElement: ,
+    },
+    foreignPara1: {
+        // Node
+        nodeType: Node.ELEMENT_NODE,
+        ownerDocument: foreignDoc,
+        parentNode: foreignDoc.body,
+        parentElement: foreignDoc.body,
+        "childNodes.length": 1,
+        previousSibling: null,
+        nextSibling: foreignPara2,
+        textContent: "Efghijkl",
+
+        // Element
+        namespaceURI: "http://www.w3.org/1999/xhtml",
+        prefix: null,
+        localName: "p",
+        tagName: "P",
+        previousElementSibling: null,
+        nextElementSibling: foreignPara2,
+        childElementCount: 0,
+    },
+    foreignPara2: {
+        // Node
+        nodeType: Node.ELEMENT_NODE,
+        ownerDocument: foreignDoc,
+        parentNode: foreignDoc.body,
+        parentElement: foreignDoc.body,
+        "childNodes.length": 1,
+        previousSibling: foreignPara1,
+        nextSibling: foreignTextNode,
+        textContent: "Mnopqrst",
+
+        // Element
+        namespaceURI: "http://www.w3.org/1999/xhtml",
+        prefix: null,
+        localName: "p",
+        tagName: "P",
+        previousElementSibling: foreignPara1,
+        nextElementSibling: null,
+        childElementCount: 0,
+    },
+    xmlDoc: {
+        // Node
+        nodeType: Node.DOCUMENT_NODE,
+        "childNodes.length": 4,
+        "childNodes[0]": xmlDoctype,
+        "childNodes[1]": xmlElement,
+        "childNodes[2]": processingInstruction,
+        "childNodes[3]": xmlComment,
+
+        // Document
+        URL: "about:blank",
+        compatMode: "CSS1Compat",
+        characterSet: "UTF-8",
+        contentType: "application/xml",
+        //doctype: ,
+        //documentElement: ,
+    },
+    xmlElement: {
+        // Node
+        nodeType: Node.ELEMENT_NODE,
+        ownerDocument: xmlDoc,
+        parentNode: xmlDoc,
+        parentElement: null,
+        "childNodes.length": 1,
+        "childNodes[0]": xmlTextNode,
+        previousSibling: xmlDoctype,
+        nextSibling: processingInstruction,
+        textContent: "do re mi fa so la ti",
+
+        // Element
+        namespaceURI: "http://www.w3.org/1999/xhtml",
+        prefix: null,
+        localName: "igiveuponcreativenames",
+        tagName: "igiveuponcreativenames",
+        previousElementSibling: null,
+        nextElementSibling: null,
+        childElementCount: 0,
+    },
+    detachedXmlElement: {
+        // Node
+        nodeType: Node.ELEMENT_NODE,
+        ownerDocument: xmlDoc,
+        parentNode: null,
+        parentElement: null,
+        "childNodes.length": 0,
+        previousSibling: null,
+        nextSibling: null,
+        textContent: "",
+
+        // Element
+        namespaceURI: "http://www.w3.org/1999/xhtml",
+        prefix: null,
+        localName: "everyone-hates-hyphenated-element-names",
+        tagName: "everyone-hates-hyphenated-element-names",
+        previousElementSibling: null,
+        nextElementSibling: null,
+        childElementCount: 0,
+    },
+    detachedTextNode: {
+        // Node
+        nodeType: Node.TEXT_NODE,
+        ownerDocument: document,
+        parentNode: null,
+        parentElement: null,
+        previousSibling: null,
+        nextSibling: null,
+        nodeValue: "Uvwxyzab",
+
+        // Text
+        wholeText: "Uvwxyzab",
+    },
+    foreignTextNode: {
+        // Node
+        nodeType: Node.TEXT_NODE,
+        ownerDocument: foreignDoc,
+        parentNode: foreignDoc.body,
+        parentElement: foreignDoc.body,
+        previousSibling: foreignPara2,
+        nextSibling: null,
+        nodeValue: "I admit that I harbor doubts about whether we really need so many things to test, but it's too late to stop now.",
+
+        // Text
+        wholeText: "I admit that I harbor doubts about whether we really need so many things to test, but it's too late to stop now.",
+    },
+    detachedForeignTextNode: {
+        // Node
+        nodeType: Node.TEXT_NODE,
+        ownerDocument: foreignDoc,
+        parentNode: null,
+        parentElement: null,
+        previousSibling: null,
+        nextSibling: null,
+        nodeValue: "Cdefghij",
+
+        // Text
+        wholeText: "Cdefghij",
+    },
+    xmlTextNode: {
+        // Node
+        nodeType: Node.TEXT_NODE,
+        ownerDocument: xmlDoc,
+        parentNode: xmlElement,
+        parentElement: xmlElement,
+        previousSibling: null,
+        nextSibling: null,
+        nodeValue: "do re mi fa so la ti",
+
+        // Text
+        wholeText: "do re mi fa so la ti",
+    },
+    detachedXmlTextNode: {
+        // Node
+        nodeType: Node.TEXT_NODE,
+        ownerDocument: xmlDoc,
+        parentNode: null,
+        parentElement: null,
+        previousSibling: null,
+        nextSibling: null,
+        nodeValue: "Klmnopqr",
+
+        // Text
+        wholeText: "Klmnopqr",
+    },
+    processingInstruction: {
+        // Node
+        nodeType: Node.PROCESSING_INSTRUCTION_NODE,
+        ownerDocument: xmlDoc,
+        parentNode: xmlDoc,
+        parentElement: null,
+        previousSibling: xmlElement,
+        nextSibling: xmlComment,
+        nodeValue: 'Did you know that ":syn sync fromstart" is very useful when using vim to edit large amounts of JavaScript embedded in HTML?',
+
+        // ProcessingInstruction
+        target: "somePI",
+    },
+    detachedProcessingInstruction: {
+        // Node
+        nodeType: Node.PROCESSING_INSTRUCTION_NODE,
+        ownerDocument: xmlDoc,
+        parentNode: null,
+        parentElement: null,
+        previousSibling: null,
+        nextSibling: null,
+        nodeValue: "chirp chirp chirp",
+
+        // ProcessingInstruction
+        target: "whippoorwill",
+    },
+    comment: {
+        // Node
+        nodeType: Node.COMMENT_NODE,
+        ownerDocument: document,
+        parentNode: testDiv,
+        parentElement: testDiv,
+        previousSibling: paras[4],
+        nextSibling: null,
+        nodeValue: "Alphabet soup?",
+    },
+    detachedComment: {
+        // Node
+        nodeType: Node.COMMENT_NODE,
+        ownerDocument: document,
+        parentNode: null,
+        parentElement: null,
+        previousSibling: null,
+        nextSibling: null,
+        nodeValue: "Stuvwxyz",
+    },
+    foreignComment: {
+        // Node
+        nodeType: Node.COMMENT_NODE,
+        ownerDocument: foreignDoc,
+        parentNode: foreignDoc,
+        parentElement: null,
+        previousSibling: foreignDoc.documentElement,
+        nextSibling: null,
+        nodeValue: '"Commenter" and "commentator" mean different things.  I\'ve seen non-native speakers trip up on this.',
+    },
+    detachedForeignComment: {
+        // Node
+        nodeType: Node.COMMENT_NODE,
+        ownerDocument: foreignDoc,
+        parentNode: null,
+        parentElement: null,
+        previousSibling: null,
+        nextSibling: null,
+        nodeValue: "אריה יהודה",
+    },
+    xmlComment: {
+        // Node
+        nodeType: Node.COMMENT_NODE,
+        ownerDocument: xmlDoc,
+        parentNode: xmlDoc,
+        parentElement: null,
+        previousSibling: processingInstruction,
+        nextSibling: null,
+        nodeValue: "I maliciously created a comment that will break incautious XML serializers, but Firefox threw an exception, so all I got was this lousy T-shirt",
+    },
+    detachedXmlComment: {
+        // Node
+        nodeType: Node.COMMENT_NODE,
+        ownerDocument: xmlDoc,
+        parentNode: null,
+        parentElement: null,
+        previousSibling: null,
+        nextSibling: null,
+        nodeValue: "בן חיים אליעזר",
+    },
+    docfrag: {
+        // Node
+        nodeType: Node.DOCUMENT_FRAGMENT_NODE,
+        ownerDocument: document,
+        "childNodes.length": 0,
+        textContent: "",
+    },
+    foreignDocfrag: {
+        // Node
+        nodeType: Node.DOCUMENT_FRAGMENT_NODE,
+        ownerDocument: foreignDoc,
+        "childNodes.length": 0,
+        textContent: "",
+    },
+    xmlDocfrag: {
+        // Node
+        nodeType: Node.DOCUMENT_FRAGMENT_NODE,
+        ownerDocument: xmlDoc,
+        "childNodes.length": 0,
+        textContent: "",
+    },
+    doctype: {
+        // Node
+        nodeType: Node.DOCUMENT_TYPE_NODE,
+        ownerDocument: document,
+        parentNode: document,
+        previousSibling: null,
+        nextSibling: document.documentElement,
+
+        // DocumentType
+        name: "html",
+        publicId: "",
+        systemId: "",
+    },
+    foreignDoctype: {
+        // Node
+        nodeType: Node.DOCUMENT_TYPE_NODE,
+        ownerDocument: foreignDoc,
+        parentNode: foreignDoc,
+        previousSibling: null,
+        nextSibling: foreignDoc.documentElement,
+
+        // DocumentType
+        name: "html",
+        publicId: "",
+        systemId: "",
+    },
+    xmlDoctype: {
+        // Node
+        nodeType: Node.DOCUMENT_TYPE_NODE,
+        ownerDocument: xmlDoc,
+        parentNode: xmlDoc,
+        previousSibling: null,
+        nextSibling: xmlElement,
+
+        // DocumentType
+        name: "qorflesnorf",
+        publicId: "abcde",
+        systemId: "x\"'y",
+    },
+    "paras[0]": {
+        // Node
+        nodeType: Node.ELEMENT_NODE,
+        ownerDocument: document,
+        parentNode: testDiv,
+        parentElement: testDiv,
+        "childNodes.length": 1,
+        previousSibling: null,
+        nextSibling: paras[1],
+        textContent: "A\u0308b\u0308c\u0308d\u0308e\u0308f\u0308g\u0308h\u0308\n",
+
+        // Element
+        namespaceURI: "http://www.w3.org/1999/xhtml",
+        prefix: null,
+        localName: "p",
+        tagName: "P",
+        id: "a",
+        previousElementSibling: null,
+        nextElementSibling: paras[1],
+        childElementCount: 0,
+    },
+    "paras[1]": {
+        // Node
+        nodeType: Node.ELEMENT_NODE,
+        ownerDocument: document,
+        parentNode: testDiv,
+        parentElement: testDiv,
+        "childNodes.length": 1,
+        previousSibling: paras[0],
+        nextSibling: paras[2],
+        textContent: "Ijklmnop\n",
+
+        // Element
+        namespaceURI: "http://www.w3.org/1999/xhtml",
+        prefix: null,
+        localName: "p",
+        tagName: "P",
+        id: "b",
+        previousElementSibling: paras[0],
+        nextElementSibling: paras[2],
+        childElementCount: 0,
+    },
+    "paras[2]": {
+        // Node
+        nodeType: Node.ELEMENT_NODE,
+        ownerDocument: document,
+        parentNode: testDiv,
+        parentElement: testDiv,
+        "childNodes.length": 1,
+        previousSibling: paras[1],
+        nextSibling: paras[3],
+        textContent: "Qrstuvwx",
+
+        // Element
+        namespaceURI: "http://www.w3.org/1999/xhtml",
+        prefix: null,
+        localName: "p",
+        tagName: "P",
+        id: "c",
+        previousElementSibling: paras[1],
+        nextElementSibling: paras[3],
+        childElementCount: 0,
+    },
+    "paras[3]": {
+        // Node
+        nodeType: Node.ELEMENT_NODE,
+        ownerDocument: document,
+        parentNode: testDiv,
+        parentElement: testDiv,
+        "childNodes.length": 1,
+        previousSibling: paras[2],
+        nextSibling: paras[4],
+        textContent: "Yzabcdef",
+
+        // Element
+        namespaceURI: "http://www.w3.org/1999/xhtml",
+        prefix: null,
+        localName: "p",
+        tagName: "P",
+        id: "d",
+        previousElementSibling: paras[2],
+        nextElementSibling: paras[4],
+        childElementCount: 0,
+    },
+    "paras[4]": {
+        // Node
+        nodeType: Node.ELEMENT_NODE,
+        ownerDocument: document,
+        parentNode: testDiv,
+        parentElement: testDiv,
+        "childNodes.length": 1,
+        previousSibling: paras[3],
+        nextSibling: comment,
+        textContent: "Ghijklmn",
+
+        // Element
+        namespaceURI: "http://www.w3.org/1999/xhtml",
+        prefix: null,
+        localName: "p",
+        tagName: "P",
+        id: "e",
+        previousElementSibling: paras[3],
+        nextElementSibling: null,
+        childElementCount: 0,
+    },
+};
+
+for (var node in expected) {
+    // Now we set various default values by node type.
+    switch (expected[node].nodeType) {
+    case Node.ELEMENT_NODE:
+        expected[node].nodeName = expected[node].tagName;
+        expected[node].nodeValue = null;
+        expected[node]["children.length"] = expected[node].childElementCount;
+
+        if (expected[node].id === undefined) {
+            expected[node].id = "";
+        }
+        if (expected[node].className === undefined) {
+            expected[node].className = "";
+        }
+
+        var len = expected[node].childElementCount;
+        if (len === 0) {
+            expected[node].firstElementChild =
+            expected[node].lastElementChild = null;
+        } else {
+            // If we have expectations for the first/last child in children,
+            // use those.  Otherwise, at least check that .firstElementChild ==
+            // .children[0] and .lastElementChild == .children[len - 1], even
+            // if we aren't sure what they should be.
+            expected[node].firstElementChild = expected[node]["children[0]"]
+                ? expected[node]["children[0]"]
+                : eval(node).children[0];
+            expected[node].lastElementChild =
+                expected[node]["children[" + (len - 1) + "]"]
+                ? expected[node]["children[" + (len - 1) + "]"]
+                : eval(node).children[len - 1];
+        }
+        break;
+
+    case Node.TEXT_NODE:
+        expected[node].nodeName = "#text";
+        expected[node]["childNodes.length"] = 0;
+        expected[node].textContent = expected[node].data =
+            expected[node].nodeValue;
+        expected[node].length = expected[node].nodeValue.length;
+        break;
+
+    case Node.PROCESSING_INSTRUCTION_NODE:
+        expected[node].nodeName = expected[node].target;
+        expected[node]["childNodes.length"] = 0;
+        expected[node].textContent = expected[node].data =
+            expected[node].nodeValue;
+        expected[node].length = expected[node].nodeValue.length;
+        break;
+
+    case Node.COMMENT_NODE:
+        expected[node].nodeName = "#comment";
+        expected[node]["childNodes.length"] = 0;
+        expected[node].textContent = expected[node].data =
+            expected[node].nodeValue;
+        expected[node].length = expected[node].nodeValue.length;
+        break;
+
+    case Node.DOCUMENT_NODE:
+        expected[node].nodeName = "#document";
+        expected[node].ownerDocument = expected[node].parentNode =
+            expected[node].parentElement = expected[node].previousSibling =
+            expected[node].nextSibling = expected[node].nodeValue =
+            expected[node].textContent = null;
+        expected[node].documentURI = expected[node].URL;
+        expected[node].charset = expected[node].inputEncoding =
+            expected[node].characterSet;
+        break;
+
+    case Node.DOCUMENT_TYPE_NODE:
+        expected[node].nodeName = expected[node].name;
+        expected[node]["childNodes.length"] = 0;
+        expected[node].parentElement = expected[node].nodeValue =
+            expected[node].textContent = null;
+        break;
+
+    case Node.DOCUMENT_FRAGMENT_NODE:
+        expected[node].nodeName = "#document-fragment";
+        expected[node].parentNode = expected[node].parentElement =
+            expected[node].previousSibling = expected[node].nextSibling =
+            expected[node].nodeValue = null;
+        break;
+    }
+
+    // Now we set some further default values that are independent of node
+    // type.
+    var len = expected[node]["childNodes.length"];
+    if (len === 0) {
+        expected[node].firstChild = expected[node].lastChild = null;
+    } else {
+        // If we have expectations for the first/last child in childNodes, use
+        // those.  Otherwise, at least check that .firstChild == .childNodes[0]
+        // and .lastChild == .childNodes[len - 1], even if we aren't sure what
+        // they should be.
+        expected[node].firstChild = expected[node]["childNodes[0]"]
+            ? expected[node]["childNodes[0]"]
+            : eval(node).childNodes[0];
+        expected[node].lastChild =
+            expected[node]["childNodes[" + (len - 1) + "]"]
+            ? expected[node]["childNodes[" + (len - 1) + "]"]
+            : eval(node).childNodes[len - 1];
+    }
+    expected[node]["hasChildNodes()"] = !!expected[node]["childNodes.length"];
+
+    // Finally, we test!
+    for (var prop in expected[node]) {
+        test(function() {
+            assert_equals(eval(node + "." + prop), expected[node][prop]);
+        }, node + "." + prop);
+    }
+}
+
+testDiv.parentNode.removeChild(testDiv);
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-removeChild-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-removeChild-expected.txt
new file mode 100644
index 0000000..f751f73
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-removeChild-expected.txt
@@ -0,0 +1,31 @@
+This is a testharness.js-based test.
+PASS Passing a detached element from the main document to removeChild should not affect it. 
+PASS Passing a non-detached element from the main document to removeChild should not affect it. 
+PASS Calling removeChild on a element from the main document with no children should throw NOT_FOUND_ERR. 
+PASS Passing a detached text from the main document to removeChild should not affect it. 
+PASS Passing a non-detached text from the main document to removeChild should not affect it. 
+PASS Calling removeChild on a text from the main document with no children should throw NOT_FOUND_ERR. 
+PASS Passing a detached comment from the main document to removeChild should not affect it. 
+PASS Passing a non-detached comment from the main document to removeChild should not affect it. 
+PASS Calling removeChild on a comment from the main document with no children should throw NOT_FOUND_ERR. 
+PASS Passing a detached element from a frame document to removeChild should not affect it. 
+PASS Passing a non-detached element from a frame document to removeChild should not affect it. 
+PASS Calling removeChild on a element from a frame document with no children should throw NOT_FOUND_ERR. 
+PASS Passing a detached text from a frame document to removeChild should not affect it. 
+PASS Passing a non-detached text from a frame document to removeChild should not affect it. 
+PASS Calling removeChild on a text from a frame document with no children should throw NOT_FOUND_ERR. 
+PASS Passing a detached comment from a frame document to removeChild should not affect it. 
+PASS Passing a non-detached comment from a frame document to removeChild should not affect it. 
+PASS Calling removeChild on a comment from a frame document with no children should throw NOT_FOUND_ERR. 
+PASS Passing a detached element from a synthetic document to removeChild should not affect it. 
+PASS Passing a non-detached element from a synthetic document to removeChild should not affect it. 
+PASS Calling removeChild on a element from a synthetic document with no children should throw NOT_FOUND_ERR. 
+PASS Passing a detached text from a synthetic document to removeChild should not affect it. 
+PASS Passing a non-detached text from a synthetic document to removeChild should not affect it. 
+PASS Calling removeChild on a text from a synthetic document with no children should throw NOT_FOUND_ERR. 
+PASS Passing a detached comment from a synthetic document to removeChild should not affect it. 
+PASS Passing a non-detached comment from a synthetic document to removeChild should not affect it. 
+PASS Calling removeChild on a comment from a synthetic document with no children should throw NOT_FOUND_ERR. 
+PASS Passing a value that is not a Node reference to removeChild should throw TypeError. 
+Harness: the test ran to completion.
+b
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-removeChild.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-removeChild.html
new file mode 100644
index 0000000..894f5ec5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-removeChild.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>Node.removeChild</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="creators.js"></script>
+<div id="log"></div>
+<iframe src=about:blank></iframe>
+<script>
+var documents = [
+  [function() { return document }, "the main document"],
+  [function() { return frames[0].document }, "a frame document"],
+  [function() { return document.implementation.createHTMLDocument() },
+   "a synthetic document"],
+];
+
+documents.forEach(function(d) {
+  var get = d[0], description = d[1]
+  for (var p in creators) {
+    var creator = creators[p];
+    test(function() {
+      var doc = get();
+      var s = doc[creator]("a")
+      assert_equals(s.ownerDocument, doc)
+      assert_throws("NOT_FOUND_ERR", function() { document.body.removeChild(s) })
+      assert_equals(s.ownerDocument, doc)
+    }, "Passing a detached " + p + " from " + description +
+       " to removeChild should not affect it.")
+
+    test(function() {
+      var doc = get();
+      var s = doc[creator]("b")
+      doc.documentElement.appendChild(s)
+      assert_equals(s.ownerDocument, doc)
+      assert_throws("NOT_FOUND_ERR", function() { document.body.removeChild(s) })
+      assert_equals(s.ownerDocument, doc)
+    }, "Passing a non-detached " + p + " from " + description +
+       " to removeChild should not affect it.")
+
+    test(function() {
+      var doc = get();
+      var s = doc[creator]("test")
+      doc.body.appendChild(s)
+      assert_equals(s.ownerDocument, doc)
+      assert_throws("NOT_FOUND_ERR", function() { s.removeChild(doc) })
+    }, "Calling removeChild on a " + p + " from " + description +
+       " with no children should throw NOT_FOUND_ERR.")
+  }
+});
+
+test(function() {
+  assert_throws(new TypeError(), function() { document.body.removeChild(null) })
+  assert_throws(new TypeError(), function() { document.body.removeChild({'a':'b'}) })
+}, "Passing a value that is not a Node reference to removeChild should throw TypeError.")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-replaceChild-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-replaceChild-expected.txt
new file mode 100644
index 0000000..ccdc0f7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-replaceChild-expected.txt
@@ -0,0 +1,35 @@
+This is a testharness.js-based test.
+PASS Passing null to replaceChild should throw a TypeError. 
+FAIL If child's parent is not the context node, a NotFoundError exception should be thrown assert_throws: function "function () {
+    a.replaceChild(a, c);
+  }" threw object "HierarchyRequestError: Failed to execute 'replaceChild' o..." that is not a DOMException NotFoundError: property "code" is equal to 3, expected 8
+PASS If the context node is not a node that can contain children, a NotFoundError exception should be thrown 
+PASS If node is an inclusive ancestor of the context node, a HierarchyRequestError should be thrown. 
+PASS If the context node is a document, inserting a document or text node should throw a HierarchyRequestError. 
+PASS If the context node is a document, inserting a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError. 
+PASS If the context node is a document (without element children), inserting a DocumentFragment that contains multiple elements should throw a HierarchyRequestError. 
+PASS If the context node is a document, inserting a DocumentFragment with an element if there already is an element child should throw a HierarchyRequestError. 
+FAIL If the context node is a document, inserting a DocumentFragment with an element before the doctype should throw a HierarchyRequestError. assert_throws: function "function () {
+    doc.replaceChild(df, comment);
+  }" did not throw
+PASS If the context node is a document, inserting an element if there already is an element child should throw a HierarchyRequestError. 
+FAIL If the context node is a document, inserting an element before the doctype should throw a HierarchyRequestError. assert_throws: function "function () {
+    doc.replaceChild(a, comment);
+  }" did not throw
+PASS If the context node is a document, inserting a doctype if there already is a doctype child should throw a HierarchyRequestError. 
+FAIL If the context node is a document, inserting a doctype after the document element should throw a HierarchyRequestError. assert_throws: function "function () {
+    doc.replaceChild(doctype, comment);
+  }" did not throw
+PASS If the context node is a DocumentFragment, inserting a document or a doctype should throw a HierarchyRequestError. 
+PASS If the context node is an element, inserting a document or a doctype should throw a HierarchyRequestError. 
+PASS Replacing a node with its next sibling should work (2 children) 
+PASS Replacing a node with its next sibling should work (4 children) 
+PASS Replacing a node with itself should not move the node 
+PASS If the context node is a document, inserting a new doctype should work. 
+PASS Replacing the document element with a DocumentFragment containing a single element should work. 
+PASS Replacing the document element with a DocumentFragment containing a single element and comments should work. 
+PASS Replacing the document element with a single element should work. 
+PASS replaceChild should work in the presence of mutation events. 
+PASS Replacing an element with a DocumentFragment should allow a child of the DocumentFragment to be found by Id. 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-replaceChild.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-replaceChild.html
new file mode 100644
index 0000000..6088f62
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-replaceChild.html
@@ -0,0 +1,346 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Node.replaceChild</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<body><a><b></b><c></c></a>
+<div id="log"></div>
+<script>
+// IDL.
+test(function() {
+  var a = document.createElement("div");
+  assert_throws(new TypeError(), function() {
+    a.replaceChild(null, null);
+  });
+
+  var b = document.createElement("div");
+  assert_throws(new TypeError(), function() {
+    a.replaceChild(b, null);
+  });
+  assert_throws(new TypeError(), function() {
+    a.replaceChild(null, b);
+  });
+}, "Passing null to replaceChild should throw a TypeError.")
+
+// Step 1.
+test(function() {
+  var a = document.createElement("div");
+  var b = document.createElement("div");
+  var c = document.createElement("div");
+  assert_throws("NotFoundError", function() {
+    a.replaceChild(b, c);
+  });
+
+  var d = document.createElement("div");
+  d.appendChild(b);
+  assert_throws("NotFoundError", function() {
+    a.replaceChild(b, c);
+  });
+  assert_throws("NotFoundError", function() {
+    a.replaceChild(a, c);
+  });
+  assert_throws("NotFoundError", function() {
+    a.replaceChild(b, a);
+  });
+  assert_throws("NotFoundError", function() {
+    a.replaceChild(a, a);
+  });
+}, "If child's parent is not the context node, a NotFoundError exception should be thrown")
+test(function() {
+  var nodes = [
+    document.implementation.createDocumentType("html", "", ""),
+    document.createTextNode("text"),
+    document.implementation.createDocument(null, "foo", null).createProcessingInstruction("foo", "bar"),
+    document.createComment("comment")
+  ];
+
+  var a = document.createElement("div");
+  var b = document.createElement("div");
+  nodes.forEach(function(node) {
+    assert_throws("HierarchyRequestError", function() {
+      node.replaceChild(a, b);
+    });
+  });
+}, "If the context node is not a node that can contain children, a NotFoundError exception should be thrown")
+
+// Step 2.
+test(function() {
+  var a = document.createElement("div");
+  var b = document.createElement("div");
+  a.appendChild(b);
+  assert_throws("HierarchyRequestError", function() {
+    a.replaceChild(a, b);
+  });
+
+  var c = document.createElement("div");
+  c.appendChild(a);
+  assert_throws("HierarchyRequestError", function() {
+    a.replaceChild(c, b);
+  });
+}, "If node is an inclusive ancestor of the context node, a HierarchyRequestError should be thrown.")
+
+// Step 3.1.
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  var doc2 = document.implementation.createHTMLDocument("title2");
+  assert_throws("HierarchyRequestError", function() {
+    doc.replaceChild(doc2, doc.documentElement);
+  });
+
+  assert_throws("HierarchyRequestError", function() {
+    doc.replaceChild(doc.createTextNode("text"), doc.documentElement);
+  });
+}, "If the context node is a document, inserting a document or text node should throw a HierarchyRequestError.")
+
+// Step 3.2.1.
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+
+  var df = doc.createDocumentFragment();
+  df.appendChild(doc.createElement("a"));
+  df.appendChild(doc.createElement("b"));
+  assert_throws("HierarchyRequestError", function() {
+    doc.replaceChild(df, doc.documentElement);
+  });
+
+  df = doc.createDocumentFragment();
+  df.appendChild(doc.createTextNode("text"));
+  assert_throws("HierarchyRequestError", function() {
+    doc.replaceChild(df, doc.documentElement);
+  });
+
+  df = doc.createDocumentFragment();
+  df.appendChild(doc.createComment("comment"));
+  df.appendChild(doc.createTextNode("text"));
+  assert_throws("HierarchyRequestError", function() {
+    doc.replaceChild(df, doc.documentElement);
+  });
+}, "If the context node is a document, inserting a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError.")
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  doc.removeChild(doc.documentElement);
+
+  var df = doc.createDocumentFragment();
+  df.appendChild(doc.createElement("a"));
+  df.appendChild(doc.createElement("b"));
+  assert_throws("HierarchyRequestError", function() {
+    doc.replaceChild(df, doc.doctype);
+  });
+}, "If the context node is a document (without element children), inserting a DocumentFragment that contains multiple elements should throw a HierarchyRequestError.")
+
+// Step 3.2.2.
+test(function() {
+  // The context node has an element child that is not /child/.
+  var doc = document.implementation.createHTMLDocument("title");
+  var comment = doc.appendChild(doc.createComment("foo"));
+  assert_array_equals(doc.childNodes, [doc.doctype, doc.documentElement, comment]);
+
+  var df = doc.createDocumentFragment();
+  df.appendChild(doc.createElement("a"));
+  assert_throws("HierarchyRequestError", function() {
+    doc.replaceChild(df, comment);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    doc.replaceChild(df, doc.doctype);
+  });
+}, "If the context node is a document, inserting a DocumentFragment with an element if there already is an element child should throw a HierarchyRequestError.")
+test(function() {
+  // A doctype is following /child/.
+  var doc = document.implementation.createHTMLDocument("title");
+  var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+  doc.removeChild(doc.documentElement);
+  assert_array_equals(doc.childNodes, [comment, doc.doctype]);
+
+  var df = doc.createDocumentFragment();
+  df.appendChild(doc.createElement("a"));
+  assert_throws("HierarchyRequestError", function() {
+    doc.replaceChild(df, comment);
+  });
+}, "If the context node is a document, inserting a DocumentFragment with an element before the doctype should throw a HierarchyRequestError.")
+
+// Step 3.3.
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  var comment = doc.appendChild(doc.createComment("foo"));
+  assert_array_equals(doc.childNodes, [doc.doctype, doc.documentElement, comment]);
+
+  var a = doc.createElement("a");
+  assert_throws("HierarchyRequestError", function() {
+    doc.replaceChild(a, comment);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    doc.replaceChild(a, doc.doctype);
+  });
+}, "If the context node is a document, inserting an element if there already is an element child should throw a HierarchyRequestError.")
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+  doc.removeChild(doc.documentElement);
+  assert_array_equals(doc.childNodes, [comment, doc.doctype]);
+
+  var a = doc.createElement("a");
+  assert_throws("HierarchyRequestError", function() {
+    doc.replaceChild(a, comment);
+  });
+}, "If the context node is a document, inserting an element before the doctype should throw a HierarchyRequestError.")
+
+// Step 3.4.
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+  assert_array_equals(doc.childNodes, [comment, doc.doctype, doc.documentElement]);
+
+  var doctype = document.implementation.createDocumentType("html", "", "");
+  assert_throws("HierarchyRequestError", function() {
+    doc.replaceChild(doctype, comment);
+  });
+  assert_throws("HierarchyRequestError", function() {
+    doc.replaceChild(doctype, doc.documentElement);
+  });
+}, "If the context node is a document, inserting a doctype if there already is a doctype child should throw a HierarchyRequestError.")
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  var comment = doc.appendChild(doc.createComment("foo"));
+  doc.removeChild(doc.doctype);
+  assert_array_equals(doc.childNodes, [doc.documentElement, comment]);
+
+  var doctype = document.implementation.createDocumentType("html", "", "");
+  assert_throws("HierarchyRequestError", function() {
+    doc.replaceChild(doctype, comment);
+  });
+}, "If the context node is a document, inserting a doctype after the document element should throw a HierarchyRequestError.")
+
+// Step 4.
+test(function() {
+  var df = document.createDocumentFragment();
+  var a = df.appendChild(document.createElement("a"));
+
+  var doc = document.implementation.createHTMLDocument("title");
+  assert_throws("HierarchyRequestError", function() {
+    df.replaceChild(doc, a);
+  });
+
+  var doctype = document.implementation.createDocumentType("html", "", "");
+  assert_throws("HierarchyRequestError", function() {
+    df.replaceChild(doctype, a);
+  });
+}, "If the context node is a DocumentFragment, inserting a document or a doctype should throw a HierarchyRequestError.")
+test(function() {
+  var el = document.createElement("div");
+  var a = el.appendChild(document.createElement("a"));
+
+  var doc = document.implementation.createHTMLDocument("title");
+  assert_throws("HierarchyRequestError", function() {
+    el.replaceChild(doc, a);
+  });
+
+  var doctype = document.implementation.createDocumentType("html", "", "");
+  assert_throws("HierarchyRequestError", function() {
+    el.replaceChild(doctype, a);
+  });
+}, "If the context node is an element, inserting a document or a doctype should throw a HierarchyRequestError.")
+
+// Step 6.
+test(function() {
+  var a = document.createElement("div");
+  var b = document.createElement("div");
+  var c = document.createElement("div");
+  a.appendChild(b);
+  a.appendChild(c);
+  assert_array_equals(a.childNodes, [b, c]);
+  assert_equals(a.replaceChild(c, b), b);
+  assert_array_equals(a.childNodes, [c]);
+}, "Replacing a node with its next sibling should work (2 children)");
+test(function() {
+  var a = document.createElement("div");
+  var b = document.createElement("div");
+  var c = document.createElement("div");
+  var d = document.createElement("div");
+  var e = document.createElement("div");
+  a.appendChild(b);
+  a.appendChild(c);
+  a.appendChild(d);
+  a.appendChild(e);
+  assert_array_equals(a.childNodes, [b, c, d, e]);
+  assert_equals(a.replaceChild(d, c), c);
+  assert_array_equals(a.childNodes, [b, d, e]);
+}, "Replacing a node with its next sibling should work (4 children)");
+test(function() {
+  var a = document.createElement("div");
+  var b = document.createElement("div");
+  var c = document.createElement("div");
+  a.appendChild(b);
+  a.appendChild(c);
+  assert_array_equals(a.childNodes, [b, c]);
+  assert_equals(a.replaceChild(b, b), b);
+  assert_array_equals(a.childNodes, [b, c]);
+  assert_equals(a.replaceChild(c, c), c);
+  assert_array_equals(a.childNodes, [b, c]);
+}, "Replacing a node with itself should not move the node");
+
+// Step 7.
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  var doctype = doc.doctype;
+  assert_array_equals(doc.childNodes, [doctype, doc.documentElement]);
+
+  var doc2 = document.implementation.createHTMLDocument("title2");
+  var doctype2 = doc2.doctype;
+  assert_array_equals(doc2.childNodes, [doctype2, doc2.documentElement]);
+
+  doc.replaceChild(doc2.doctype, doc.doctype);
+  assert_array_equals(doc.childNodes, [doctype2, doc.documentElement]);
+  assert_array_equals(doc2.childNodes, [doc2.documentElement]);
+  assert_equals(doctype.parentNode, null);
+  assert_equals(doctype.ownerDocument, doc);
+  assert_equals(doctype2.parentNode, doc);
+  assert_equals(doctype2.ownerDocument, doc);
+}, "If the context node is a document, inserting a new doctype should work.")
+
+// Bugs.
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  var df = doc.createDocumentFragment();
+  var a = df.appendChild(doc.createElement("a"));
+  assert_equals(doc.documentElement, doc.replaceChild(df, doc.documentElement));
+  assert_array_equals(doc.childNodes, [doc.doctype, a]);
+}, "Replacing the document element with a DocumentFragment containing a single element should work.");
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  var df = doc.createDocumentFragment();
+  var a = df.appendChild(doc.createComment("a"));
+  var b = df.appendChild(doc.createElement("b"));
+  var c = df.appendChild(doc.createComment("c"));
+  assert_equals(doc.documentElement, doc.replaceChild(df, doc.documentElement));
+  assert_array_equals(doc.childNodes, [doc.doctype, a, b, c]);
+}, "Replacing the document element with a DocumentFragment containing a single element and comments should work.");
+test(function() {
+  var doc = document.implementation.createHTMLDocument("title");
+  var a = doc.createElement("a");
+  assert_equals(doc.documentElement, doc.replaceChild(a, doc.documentElement));
+  assert_array_equals(doc.childNodes, [doc.doctype, a]);
+}, "Replacing the document element with a single element should work.");
+test(function() {
+  document.addEventListener("DOMNodeRemoved", function(e) {
+    document.body.appendChild(document.createElement("x"));
+  }, false);
+  var a = document.body.firstChild, b = a.firstChild, c = b.nextSibling;
+  assert_equals(a.replaceChild(c, b), b);
+  assert_equals(b.parentNode, null);
+  assert_equals(a.firstChild, c);
+  assert_equals(c.parentNode, a);
+}, "replaceChild should work in the presence of mutation events.")
+test(function() {
+  var TEST_ID = "findme";
+  var gBody = document.getElementsByTagName("body")[0];
+  var parent = document.createElement("div");
+  gBody.appendChild(parent);
+  var child = document.createElement("div");
+  parent.appendChild(child);
+  var df = document.createDocumentFragment();
+  var fragChild = df.appendChild(document.createElement("div"));
+  fragChild.setAttribute("id", TEST_ID);
+  parent.replaceChild(df, child);
+  assert_equals(document.getElementById(TEST_ID), fragChild, "should not be null");
+}, "Replacing an element with a DocumentFragment should allow a child of the DocumentFragment to be found by Id.")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-textContent-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-textContent-expected.txt
new file mode 100644
index 0000000..aa392a96
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-textContent-expected.txt
@@ -0,0 +1,84 @@
+This is a testharness.js-based test.
+PASS For an empty Element, textContent should be the empty string 
+PASS For an empty DocumentFragment, textContent should be the empty string 
+PASS Element with children 
+PASS Element with descendants 
+PASS DocumentFragment with children 
+PASS DocumentFragment with descendants 
+PASS For an empty Text, textContent should be the empty string 
+PASS For an empty ProcessingInstruction, textContent should be the empty string 
+PASS For an empty Comment, textContent should be the empty string 
+PASS For a Text with data, textContent should be that data 
+PASS For a ProcessingInstruction with data, textContent should be that data 
+PASS For a Comment with data, textContent should be that data 
+PASS For Documents created by parser, textContent should be null 
+PASS For Documents created by createDocument, textContent should be null 
+PASS For Documents created by createHTMLDocument, textContent should be null 
+PASS For DocumentType created by parser, textContent should be null 
+PASS For DocumentType created by script, textContent should be null 
+PASS Element without children set to null 
+PASS Element with empty text node as child set to null 
+PASS Element with children set to null 
+PASS Element with descendants set to null 
+PASS DocumentFragment without children set to null 
+PASS DocumentFragment with empty text node as child set to null 
+PASS DocumentFragment with children set to null 
+PASS DocumentFragment with descendants set to null 
+PASS Element without children set to undefined 
+PASS Element with empty text node as child set to undefined 
+PASS Element with children set to undefined 
+PASS Element with descendants set to undefined 
+PASS DocumentFragment without children set to undefined 
+PASS DocumentFragment with empty text node as child set to undefined 
+PASS DocumentFragment with children set to undefined 
+PASS DocumentFragment with descendants set to undefined 
+PASS Element without children set to "" 
+FAIL Element with empty text node as child set to "" assert_equals: expected null but got Text node ""
+PASS Element with children set to "" 
+PASS Element with descendants set to "" 
+PASS DocumentFragment without children set to "" 
+FAIL DocumentFragment with empty text node as child set to "" assert_equals: expected null but got Text node ""
+PASS DocumentFragment with children set to "" 
+PASS DocumentFragment with descendants set to "" 
+PASS Element without children set to 42 
+PASS Element with empty text node as child set to 42 
+PASS Element with children set to 42 
+PASS Element with descendants set to 42 
+PASS DocumentFragment without children set to 42 
+PASS DocumentFragment with empty text node as child set to 42 
+PASS DocumentFragment with children set to 42 
+PASS DocumentFragment with descendants set to 42 
+PASS Element without children set to "abc" 
+PASS Element with empty text node as child set to "abc" 
+PASS Element with children set to "abc" 
+PASS Element with descendants set to "abc" 
+PASS DocumentFragment without children set to "abc" 
+PASS DocumentFragment with empty text node as child set to "abc" 
+PASS DocumentFragment with children set to "abc" 
+PASS DocumentFragment with descendants set to "abc" 
+PASS Element without children set to "<b>xyz</b>" 
+PASS Element with empty text node as child set to "<b>xyz</b>" 
+PASS Element with children set to "<b>xyz</b>" 
+PASS Element with descendants set to "<b>xyz</b>" 
+PASS DocumentFragment without children set to "<b>xyz</b>" 
+PASS DocumentFragment with empty text node as child set to "<b>xyz</b>" 
+PASS DocumentFragment with children set to "<b>xyz</b>" 
+PASS DocumentFragment with descendants set to "<b>xyz</b>" 
+PASS Element without children set to "d\0e" 
+PASS Element with empty text node as child set to "d\0e" 
+PASS Element with children set to "d\0e" 
+PASS Element with descendants set to "d\0e" 
+PASS DocumentFragment without children set to "d\0e" 
+PASS DocumentFragment with empty text node as child set to "d\0e" 
+PASS DocumentFragment with children set to "d\0e" 
+PASS DocumentFragment with descendants set to "d\0e" 
+PASS For a Text, textContent should set the data 
+PASS For a ProcessingInstruction, textContent should set the data 
+PASS For a Comment, textContent should set the data 
+PASS For Documents created by parser, setting textContent should do nothing 
+PASS For Documents created by createDocument, setting textContent should do nothing 
+PASS For Documents created by createHTMLDocument, setting textContent should do nothing 
+PASS For DocumentType created by parser, setting textContent should do nothing 
+PASS For DocumentType created by script, setting textContent should do nothing 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-textContent.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-textContent.html
new file mode 100644
index 0000000..b66d023
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Node-textContent.html
@@ -0,0 +1,265 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Node.textContent</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// XXX mutation observers?
+// XXX Range gravitation?
+
+var documents, doctypes;
+setup(function() {
+  documents = [
+    [document, "parser"],
+    [document.implementation.createDocument("", "test", null), "createDocument"],
+    [document.implementation.createHTMLDocument("title"), "createHTMLDocument"],
+  ]
+  doctypes = [
+    [document.doctype, "parser"],
+    [document.implementation.createDocumentType("x", "", ""), "script"],
+  ]
+})
+
+// Getting
+// DocumentFragment, Element:
+test(function() {
+  var element = document.createElement("div")
+  assert_equals(element.textContent, "")
+}, "For an empty Element, textContent should be the empty string")
+
+test(function() {
+  assert_equals(document.createDocumentFragment().textContent, "")
+}, "For an empty DocumentFragment, textContent should be the empty string")
+
+test(function() {
+  var el = document.createElement("div")
+  el.appendChild(document.createComment(" abc "))
+  el.appendChild(document.createTextNode("\tDEF\t"))
+  el.appendChild(document.createProcessingInstruction("x", " ghi "))
+  assert_equals(el.textContent, "\tDEF\t")
+}, "Element with children")
+
+test(function() {
+  var el = document.createElement("div")
+  var child = document.createElement("div")
+  el.appendChild(child)
+  child.appendChild(document.createComment(" abc "))
+  child.appendChild(document.createTextNode("\tDEF\t"))
+  child.appendChild(document.createProcessingInstruction("x", " ghi "))
+  assert_equals(el.textContent, "\tDEF\t")
+}, "Element with descendants")
+
+test(function() {
+  var df = document.createDocumentFragment()
+  df.appendChild(document.createComment(" abc "))
+  df.appendChild(document.createTextNode("\tDEF\t"))
+  df.appendChild(document.createProcessingInstruction("x", " ghi "))
+  assert_equals(df.textContent, "\tDEF\t")
+}, "DocumentFragment with children")
+
+test(function() {
+  var df = document.createDocumentFragment()
+  var child = document.createElement("div")
+  df.appendChild(child)
+  child.appendChild(document.createComment(" abc "))
+  child.appendChild(document.createTextNode("\tDEF\t"))
+  child.appendChild(document.createProcessingInstruction("x", " ghi "))
+  assert_equals(df.textContent, "\tDEF\t")
+}, "DocumentFragment with descendants")
+
+// Text, ProcessingInstruction, Comment:
+test(function() {
+  assert_equals(document.createTextNode("").textContent, "")
+}, "For an empty Text, textContent should be the empty string")
+
+test(function() {
+  assert_equals(document.createProcessingInstruction("x", "").textContent, "")
+}, "For an empty ProcessingInstruction, textContent should be the empty string")
+
+test(function() {
+  assert_equals(document.createComment("").textContent, "")
+}, "For an empty Comment, textContent should be the empty string")
+
+test(function() {
+  assert_equals(document.createTextNode("abc").textContent, "abc")
+}, "For a Text with data, textContent should be that data")
+
+test(function() {
+  assert_equals(document.createProcessingInstruction("x", "abc").textContent,
+                "abc")
+}, "For a ProcessingInstruction with data, textContent should be that data")
+
+test(function() {
+  assert_equals(document.createComment("abc").textContent, "abc")
+}, "For a Comment with data, textContent should be that data")
+
+// Any other node:
+documents.forEach(function(argument) {
+  var doc = argument[0], creator = argument[1]
+  test(function() {
+    assert_equals(doc.textContent, null)
+  }, "For Documents created by " + creator + ", textContent should be null")
+})
+
+doctypes.forEach(function(argument) {
+  var doctype = argument[0], creator = argument[1]
+  test(function() {
+    assert_equals(doctype.textContent, null)
+  }, "For DocumentType created by " + creator + ", textContent should be null")
+})
+
+// Setting
+// DocumentFragment, Element:
+var arguments = [
+  [null, null],
+  [undefined, null],
+  ["", null],
+  [42, "42"],
+  ["abc", "abc"],
+  ["<b>xyz<\/b>", "<b>xyz<\/b>"],
+  ["d\0e", "d\0e"]
+  // XXX unpaired surrogate?
+]
+arguments.forEach(function(aValue) {
+  var argument = aValue[0], expectation = aValue[1]
+  var check = function(aElementOrDocumentFragment) {
+    if (expectation === null) {
+      assert_equals(aElementOrDocumentFragment.textContent, "")
+      assert_equals(aElementOrDocumentFragment.firstChild, null)
+    } else {
+      assert_equals(aElementOrDocumentFragment.textContent, expectation)
+      assert_equals(aElementOrDocumentFragment.childNodes.length, 1,
+                    "Should have one child")
+      var firstChild = aElementOrDocumentFragment.firstChild
+      assert_true(firstChild instanceof Text, "child should be a Text")
+      assert_equals(firstChild.data, expectation)
+    }
+  }
+
+  test(function() {
+    var el = document.createElement("div")
+    el.textContent = argument
+    check(el)
+  }, "Element without children set to " + format_value(argument))
+
+  test(function() {
+    var el = document.createElement("div")
+    var text = el.appendChild(document.createTextNode(""))
+    el.textContent = argument
+    check(el)
+    assert_equals(text.parentNode, null,
+                  "Preexisting Text should have been removed")
+  }, "Element with empty text node as child set to " + format_value(argument))
+
+  test(function() {
+    var el = document.createElement("div")
+    el.appendChild(document.createComment(" abc "))
+    el.appendChild(document.createTextNode("\tDEF\t"))
+    el.appendChild(document.createProcessingInstruction("x", " ghi "))
+    el.textContent = argument
+    check(el)
+  }, "Element with children set to " + format_value(argument))
+
+  test(function() {
+    var el = document.createElement("div")
+    var child = document.createElement("div")
+    el.appendChild(child)
+    child.appendChild(document.createComment(" abc "))
+    child.appendChild(document.createTextNode("\tDEF\t"))
+    child.appendChild(document.createProcessingInstruction("x", " ghi "))
+    el.textContent = argument
+    check(el)
+    assert_equals(child.childNodes.length, 3,
+                  "Should not have changed the internal structure of the removed nodes.")
+  }, "Element with descendants set to " + format_value(argument))
+
+  test(function() {
+    var df = document.createDocumentFragment()
+    df.textContent = argument
+    check(df)
+  }, "DocumentFragment without children set to " + format_value(argument))
+
+  test(function() {
+    var df = document.createDocumentFragment()
+    var text = df.appendChild(document.createTextNode(""))
+    df.textContent = argument
+    check(df)
+    assert_equals(text.parentNode, null,
+                  "Preexisting Text should have been removed")
+  }, "DocumentFragment with empty text node as child set to " + format_value(argument))
+
+  test(function() {
+    var df = document.createDocumentFragment()
+    df.appendChild(document.createComment(" abc "))
+    df.appendChild(document.createTextNode("\tDEF\t"))
+    df.appendChild(document.createProcessingInstruction("x", " ghi "))
+    df.textContent = argument
+    check(df)
+  }, "DocumentFragment with children set to " + format_value(argument))
+
+  test(function() {
+    var df = document.createDocumentFragment()
+    var child = document.createElement("div")
+    df.appendChild(child)
+    child.appendChild(document.createComment(" abc "))
+    child.appendChild(document.createTextNode("\tDEF\t"))
+    child.appendChild(document.createProcessingInstruction("x", " ghi "))
+    df.textContent = argument
+    check(df)
+    assert_equals(child.childNodes.length, 3,
+                  "Should not have changed the internal structure of the removed nodes.")
+  }, "DocumentFragment with descendants set to " + format_value(argument))
+})
+
+// Text, ProcessingInstruction, Comment:
+test(function() {
+  var text = document.createTextNode("abc")
+  text.textContent = "def"
+  assert_equals(text.textContent, "def")
+  assert_equals(text.data, "def")
+}, "For a Text, textContent should set the data")
+
+test(function() {
+  var pi = document.createProcessingInstruction("x", "abc")
+  pi.textContent = "def"
+  assert_equals(pi.textContent, "def")
+  assert_equals(pi.data, "def")
+  assert_equals(pi.target, "x")
+}, "For a ProcessingInstruction, textContent should set the data")
+
+test(function() {
+  var comment = document.createComment("abc")
+  comment.textContent = "def"
+  assert_equals(comment.textContent, "def")
+  assert_equals(comment.data, "def")
+}, "For a Comment, textContent should set the data")
+
+// Any other node:
+documents.forEach(function(argument) {
+  var doc = argument[0], creator = argument[1]
+  test(function() {
+    var root = doc.documentElement
+    doc.textContent = "a"
+    assert_equals(doc.textContent, null)
+    assert_equals(doc.documentElement, root)
+  }, "For Documents created by " + creator + ", setting textContent should do nothing")
+})
+
+doctypes.forEach(function(argument) {
+  var doctype = argument[0], creator = argument[1]
+  test(function() {
+    var props = {
+      name: doctype.name,
+      publicId: doctype.publicId,
+      systemId: doctype.systemId,
+    }
+    doctype.textContent = "b"
+    assert_equals(doctype.textContent, null)
+    assert_equals(doctype.name, props.name, "name should not change")
+    assert_equals(doctype.publicId, props.publicId, "publicId should not change")
+    assert_equals(doctype.systemId, props.systemId, "systemId should not change")
+  }, "For DocumentType created by " + creator + ", setting textContent should do nothing")
+})
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ParentNode-append-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ParentNode-append-expected.txt
new file mode 100644
index 0000000..673d6b3c1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ParentNode-append-expected.txt
@@ -0,0 +1,17 @@
+This is a testharness.js-based test.
+FAIL Element.append() without any argument, on a parent having no child. parent.append is not a function
+FAIL Element.append() with null as an argument, on a parent having no child. parent.append is not a function
+FAIL Element.append() with undefined as an argument, on a parent having no child. parent.append is not a function
+FAIL Element.append() with only text as an argument, on a parent having no child. parent.append is not a function
+FAIL Element.append() with only one element as an argument, on a parent having no child. parent.append is not a function
+FAIL Element.append() with null as an argument, on a parent having a child. parent.append is not a function
+FAIL Element.append() with one element and text as argument, on a parent having a child. parent.append is not a function
+FAIL DocumentFrgment.append() without any argument, on a parent having no child. parent.append is not a function
+FAIL DocumentFrgment.append() with null as an argument, on a parent having no child. parent.append is not a function
+FAIL DocumentFrgment.append() with undefined as an argument, on a parent having no child. parent.append is not a function
+FAIL DocumentFrgment.append() with only text as an argument, on a parent having no child. parent.append is not a function
+FAIL DocumentFrgment.append() with only one element as an argument, on a parent having no child. parent.append is not a function
+FAIL DocumentFrgment.append() with null as an argument, on a parent having a child. parent.append is not a function
+FAIL DocumentFrgment.append() with one element and text as argument, on a parent having a child. parent.append is not a function
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ParentNode-append.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ParentNode-append.html
new file mode 100644
index 0000000..baa69f57
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ParentNode-append.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>ParentNode.append</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-parentnode-append">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script>
+
+function test_append(node, nodeName) {
+
+    test(function() {
+        var parent = node.cloneNode();
+        parent.append();
+        assert_array_equals(parent.childNodes, []);
+    }, nodeName + '.append() without any argument, on a parent having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        parent.append(null);
+        assert_equals(parent.childNodes[0].textContent, 'null');
+    }, nodeName + '.append() with null as an argument, on a parent having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        parent.append(undefined);
+        assert_equals(parent.childNodes[0].textContent, 'undefined');
+    }, nodeName + '.append() with undefined as an argument, on a parent having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        parent.append('text');
+        assert_equals(parent.childNodes[0].textContent, 'text');
+    }, nodeName + '.append() with only text as an argument, on a parent having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        var x = document.createElement('x');
+        parent.append(x);
+        assert_array_equals(parent.childNodes, [x]);
+    }, nodeName + '.append() with only one element as an argument, on a parent having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        var child = document.createElement('test');
+        parent.appendChild(child);
+        parent.append(null);
+        assert_equals(parent.childNodes[0], child);
+        assert_equals(parent.childNodes[1].textContent, 'null');
+    }, nodeName + '.append() with null as an argument, on a parent having a child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        var x = document.createElement('x');
+        var child = document.createElement('test');
+        parent.appendChild(child);
+        parent.append(x, 'text');
+        assert_equals(parent.childNodes[0], child);
+        assert_equals(parent.childNodes[1], x);
+        assert_equals(parent.childNodes[2].textContent, 'text');
+    }, nodeName + '.append() with one element and text as argument, on a parent having a child.');
+}
+
+test_append(document.createElement('div'), 'Element');
+test_append(document.createDocumentFragment(), 'DocumentFrgment');
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ParentNode-prepend-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ParentNode-prepend-expected.txt
new file mode 100644
index 0000000..483d7f0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ParentNode-prepend-expected.txt
@@ -0,0 +1,17 @@
+This is a testharness.js-based test.
+FAIL Element.prepend() without any argument, on a parent having no child. parent.prepend is not a function
+FAIL Element.prepend() with null as an argument, on a parent having no child. parent.prepend is not a function
+FAIL Element.prepend() with undefined as an argument, on a parent having no child. parent.prepend is not a function
+FAIL Element.prepend() with only text as an argument, on a parent having no child. parent.prepend is not a function
+FAIL Element.prepend() with only one element as an argument, on a parent having no child. parent.prepend is not a function
+FAIL Element.prepend() with null as an argument, on a parent having a child. parent.prepend is not a function
+FAIL Element.prepend() with one element and text as argument, on a parent having a child. parent.prepend is not a function
+FAIL DocumentFrgment.prepend() without any argument, on a parent having no child. parent.prepend is not a function
+FAIL DocumentFrgment.prepend() with null as an argument, on a parent having no child. parent.prepend is not a function
+FAIL DocumentFrgment.prepend() with undefined as an argument, on a parent having no child. parent.prepend is not a function
+FAIL DocumentFrgment.prepend() with only text as an argument, on a parent having no child. parent.prepend is not a function
+FAIL DocumentFrgment.prepend() with only one element as an argument, on a parent having no child. parent.prepend is not a function
+FAIL DocumentFrgment.prepend() with null as an argument, on a parent having a child. parent.prepend is not a function
+FAIL DocumentFrgment.prepend() with one element and text as argument, on a parent having a child. parent.prepend is not a function
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ParentNode-prepend.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ParentNode-prepend.html
new file mode 100644
index 0000000..990ee04
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ParentNode-prepend.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>ParentNode.prepend</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-parentnode-prepend">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script>
+
+function test_prepend(node, nodeName) {
+
+    test(function() {
+        var parent = node.cloneNode();
+        parent.prepend();
+        assert_array_equals(parent.childNodes, []);
+    }, nodeName + '.prepend() without any argument, on a parent having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        parent.prepend(null);
+        assert_equals(parent.childNodes[0].textContent, 'null');
+    }, nodeName + '.prepend() with null as an argument, on a parent having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        parent.prepend(undefined);
+        assert_equals(parent.childNodes[0].textContent, 'undefined');
+    }, nodeName + '.prepend() with undefined as an argument, on a parent having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        parent.prepend('text');
+        assert_equals(parent.childNodes[0].textContent, 'text');
+    }, nodeName + '.prepend() with only text as an argument, on a parent having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        var x = document.createElement('x');
+        parent.prepend(x);
+        assert_array_equals(parent.childNodes, [x]);
+    }, nodeName + '.prepend() with only one element as an argument, on a parent having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        var child = document.createElement('test');
+        parent.appendChild(child);
+        parent.prepend(null);
+        assert_equals(parent.childNodes[0].textContent, 'null');
+        assert_equals(parent.childNodes[1], child);
+    }, nodeName + '.prepend() with null as an argument, on a parent having a child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        var x = document.createElement('x');
+        var child = document.createElement('test');
+        parent.appendChild(child);
+        parent.prepend(x, 'text');
+        assert_equals(parent.childNodes[0], x);
+        assert_equals(parent.childNodes[1].textContent, 'text');
+        assert_equals(parent.childNodes[2], child);
+    }, nodeName + '.prepend() with one element and text as argument, on a parent having a child.');
+}
+
+test_prepend(document.createElement('div'), 'Element');
+test_prepend(document.createDocumentFragment(), 'DocumentFrgment');
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ProcessingInstruction-literal-1.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ProcessingInstruction-literal-1.xhtml
new file mode 100644
index 0000000..1392918
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ProcessingInstruction-literal-1.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>&lt;?xml?> is not a ProcessingInstruction</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"/>
+<script>
+test(function() {
+  assert_equals(document.firstChild, document.documentElement)
+})
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ProcessingInstruction-literal-2.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ProcessingInstruction-literal-2.xhtml
new file mode 100644
index 0000000..0d066d3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/ProcessingInstruction-literal-2.xhtml
@@ -0,0 +1,21 @@
+<?xml-stylesheet href="support/style.css" type="text/css"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>ProcessingInstruction literals</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-processinginstruction-target"/>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-characterdata-data"/>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"/>
+<script>
+test(function() {
+  var pienc = document.firstChild;
+  assert_true(pienc instanceof ProcessingInstruction)
+  assert_equals(pienc.target, "xml-stylesheet")
+  assert_equals(pienc.data, 'href="support/style.css" type="text/css"')
+})
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Text-constructor.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Text-constructor.html
new file mode 100644
index 0000000..d09ca26
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Text-constructor.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Text constructor</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-text">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="Comment-Text-constructor.js"></script>
+<div id="log"></div>
+<script>
+test_constructor("Text");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Text-splitText.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Text-splitText.html
new file mode 100644
index 0000000..3ce2d0ad
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Text-splitText.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Text.splitText()</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-text-splittextoffset">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var text = document.createTextNode("camembert");
+  assert_throws("INDEX_SIZE_ERR", function () { text.splitText(10) });
+}, "Split text after end of data");
+
+test(function() {
+  var text = document.createTextNode("");
+  var new_text = text.splitText(0);
+  assert_equals(text.data, "");
+  assert_equals(new_text.data, "");
+}, "Split empty text");
+
+test(function() {
+  var text = document.createTextNode("comté");
+  var new_text = text.splitText(0);
+  assert_equals(text.data, "");
+  assert_equals(new_text.data, "comté");
+}, "Split text at beginning");
+
+test(function() {
+  var text = document.createTextNode("comté");
+  var new_text = text.splitText(5);
+  assert_equals(text.data, "comté");
+  assert_equals(new_text.data, "");
+}, "Split text at end");
+
+test(function() {
+  var text = document.createTextNode("comté");
+  var new_text = text.splitText(3);
+  assert_equals(text.data, "com");
+  assert_equals(new_text.data, "té");
+  assert_equals(new_text.parentNode, null);
+}, "Split root");
+
+test(function() {
+  var parent = document.createElement('div');
+  var text = document.createTextNode("bleu");
+  parent.appendChild(text);
+  var new_text = text.splitText(2);
+  assert_equals(text.data, "bl");
+  assert_equals(new_text.data, "eu");
+  assert_equals(text.nextSibling, new_text);
+  assert_equals(new_text.parentNode, parent);
+}, "Split child");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/append-on-Document-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/append-on-Document-expected.txt
new file mode 100644
index 0000000..83dd93c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/append-on-Document-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+FAIL Document.append() without any argument, on a Document having no child. parent.append is not a function
+FAIL Document.append() with only one element as an argument, on a Document having no child. parent.append is not a function
+FAIL Document.append() with only one element as an argument, on a Document having one child. assert_throws: function "function () { parent.append(y); }" threw object "TypeError: parent.append is not a function" that is not a DOMException HierarchyRequestError: property "code" is equal to undefined, expected 3
+FAIL Document.append() with text as an argument, on a Document having no child. assert_throws: function "function () { parent.append('text'); }" threw object "TypeError: parent.append is not a function" that is not a DOMException HierarchyRequestError: property "code" is equal to undefined, expected 3
+FAIL Document.append() with two elements as the argument, on a Document having no child. assert_throws: function "function () { parent.append(x, y); }" threw object "TypeError: parent.append is not a function" that is not a DOMException HierarchyRequestError: property "code" is equal to undefined, expected 3
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/append-on-Document.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/append-on-Document.html
new file mode 100644
index 0000000..1ce7d8f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/append-on-Document.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>DocumentType.append</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-parentnode-append">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script>
+
+function test_append_on_Document() {
+
+    var node = document.implementation.createDocument(null, null);
+    test(function() {
+        var parent = node.cloneNode();
+        parent.append();
+        assert_array_equals(parent.childNodes, []);
+    }, 'Document.append() without any argument, on a Document having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        var x = document.createElement('x');
+        parent.append(x);
+        assert_array_equals(parent.childNodes, [x]);
+    }, 'Document.append() with only one element as an argument, on a Document having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        parent.appendChild(x);
+        assert_throws('HierarchyRequestError', function() { parent.append(y); });
+        assert_array_equals(parent.childNodes, [x]);
+    }, 'Document.append() with only one element as an argument, on a Document having one child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        assert_throws('HierarchyRequestError', function() { parent.append('text'); });
+        assert_array_equals(parent.childNodes, []);
+    }, 'Document.append() with text as an argument, on a Document having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        assert_throws('HierarchyRequestError', function() { parent.append(x, y); });
+        assert_array_equals(parent.childNodes, []);
+    }, 'Document.append() with two elements as the argument, on a Document having no child.');
+
+}
+
+test_append_on_Document();
+
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/attributes-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/attributes-expected.txt
new file mode 100644
index 0000000..aa40064a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/attributes-expected.txt
@@ -0,0 +1,45 @@
+This is a testharness.js-based test.
+FAIL AttrExodus assert_false: expected false got true
+PASS When qualifiedName does not match the Name production, an INVALID_CHARACTER_ERR exception is to be thrown. (setAttribute) 
+PASS setAttribute should lowercase its name argument (upper case attribute) 
+PASS setAttribute should lowercase its name argument (mixed case attribute) 
+PASS setAttribute should not throw even when qualifiedName starts with 'xmlns' 
+PASS Basic functionality should be intact. 
+PASS setAttribute should not change the order of previously set attributes. 
+PASS setAttribute should set the first attribute with the given name 
+PASS setAttribute should set the attribute with the given qualified name 
+PASS When qualifiedName does not match the Name production, an INVALID_CHARACTER_ERR exception is to be thrown. (setAttributeNS) 
+PASS When qualifiedName does not match the QName production, an NAMESPACE_ERR exception is to be thrown. 
+PASS null and the empty string should result in a null namespace. 
+PASS A namespace is required to use a prefix. 
+PASS The xml prefix should not be allowed for arbitrary namespaces 
+PASS XML-namespaced attributes don't need an xml prefix 
+PASS The xmlns prefix should not be allowed for arbitrary namespaces 
+PASS The xmlns qualified name should not be allowed for arbitrary namespaces 
+PASS xmlns should be allowed as local name 
+PASS The XMLNS namespace should require xmlns as prefix or qualified name 
+PASS xmlns should be allowed as prefix in the XMLNS namespace 
+PASS xmlns should be allowed as qualified name in the XMLNS namespace 
+PASS Setting the same attribute with another prefix should not change the prefix 
+PASS setAttribute should not throw even if a load is not allowed 
+PASS Attributes should work in document fragments. 
+PASS Attribute values should not be parsed. 
+PASS Specified attributes should be accessible. 
+PASS Entities in attributes should have been expanded while parsing. 
+PASS Unset attributes return null 
+PASS First set attribute is returned by getAttribute 
+PASS Style attributes are not normalized 
+FAIL Only lowercase attributes are returned on HTML elements (upper case attribute) assert_equals: expected (object) null but got (string) "left"
+FAIL Only lowercase attributes are returned on HTML elements (mixed case attribute) assert_equals: expected (object) null but got (string) "tasty"
+PASS First set attribute is returned with mapped attribute set first 
+PASS First set attribute is returned with mapped attribute set later 
+FAIL Non-HTML element with upper-case attribute assert_equals: el.hasAttributeNS(undefined) expected true but got false
+PASS Attribute with prefix in local name 
+PASS Attribute loses its owner when removed 
+PASS Basic functionality of getAttributeNode/getAttributeNodeNS 
+PASS Basic functionality of setAttributeNode 
+PASS Basic functionality of setAttributeNodeNS 
+PASS Basic functionality of removeAttributeNode 
+PASS setAttributeNode on bound attribute should throw InUseAttributeError 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/attributes.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/attributes.html
new file mode 100644
index 0000000..94d82715
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/attributes.html
@@ -0,0 +1,462 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Attributes tests</title>
+<link rel=help href="https://dom.spec.whatwg.org/#attr">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-setattribute">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-setattributens">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="attributes.js"></script>
+<script src="productions.js"></script>
+<div id="log"></div>
+<span id="test1"></span>
+<span class="&amp;&lt;&gt;foo"></span>
+<script>
+var XML = "http://www.w3.org/XML/1998/namespace"
+var XMLNS = "http://www.w3.org/2000/xmlns/"
+
+// AttrExodus
+test(function() {
+  document.body.setAttribute("abc", "pass")
+  var attr = document.body.attributes[0]
+  assert_true(attr instanceof Attr)
+  assert_false(attr instanceof Node)
+  assert_throws(new TypeError(), function() { attr.appendChild(document.createTextNode("fail")) })
+  assert_throws(new TypeError(), function() { attr.appendChild(null) })
+  assert_equals(attr.value, "pass")
+  assert_false("childNodes" in attr, "Should not have childNodes")
+}, "AttrExodus")
+
+// setAttribute exhaustive tests
+// Step 1
+test(function() {
+  var el = document.createElement("foo")
+  for (var i = 0; i < invalid_names.length; i++) {
+    assert_throws("INVALID_CHARACTER_ERR", function() { el.setAttribute(invalid_names[i], "test") })
+  }
+}, "When qualifiedName does not match the Name production, an " +
+   "INVALID_CHARACTER_ERR exception is to be thrown. (setAttribute)")
+
+// Step 2
+test(function() {
+  var el = document.createElement("div")
+  el.setAttribute("ALIGN", "left")
+  assert_equals(el.getAttributeNS("", "ALIGN"), null)
+  assert_equals(el.getAttributeNS("", "align"), "left")
+  assert_equals(el.getAttribute("align"), "left")
+}, "setAttribute should lowercase its name argument (upper case attribute)")
+test(function() {
+  var el = document.createElement("div")
+  el.setAttribute("CHEEseCaKe", "tasty")
+  assert_equals(el.getAttributeNS("", "CHEEseCaKe"), null)
+  assert_equals(el.getAttributeNS("", "cheesecake"), "tasty")
+  assert_equals(el.getAttribute("cheesecake"), "tasty")
+}, "setAttribute should lowercase its name argument (mixed case attribute)")
+
+// Step 3
+test(function() {
+  var el = document.createElement("foo")
+  var tests = ["xmlns", "xmlns:a", "xmlnsx", "xmlns0"]
+  for (var i = 0; i < tests.length; i++) {
+    el.setAttribute(tests[i], "success");
+  }
+}, "setAttribute should not throw even when qualifiedName starts with 'xmlns'")
+
+// Step 4
+test(function() {
+  var el = document.createElement("foo")
+  for (var i = 0; i < valid_names.length; i++) {
+    el.setAttribute(valid_names[i], "test")
+    assert_equals(el.getAttribute(valid_names[i]), "test")
+  }
+}, "Basic functionality should be intact.")
+
+// Step 5
+test(function() {
+  var el = document.createElement("foo")
+  el.setAttribute("a", "1")
+  el.setAttribute("b", "2")
+  el.setAttribute("a", "3")
+  el.setAttribute("c", "4")
+  attributes_are(el, [["a", "3"],
+                      ["b", "2"],
+                      ["c", "4"]])
+}, "setAttribute should not change the order of previously set attributes.")
+test(function() {
+  var el = document.createElement("baz")
+  el.setAttributeNS("ab", "attr", "fail")
+  el.setAttributeNS("kl", "attr", "pass")
+  el.setAttribute("attr", "pass")
+  attributes_are(el, [["attr", "pass", "ab"],
+                      ["attr", "pass", "kl"]])
+}, "setAttribute should set the first attribute with the given name")
+test(function() {
+  // Based on a test by David Flanagan.
+  var el = document.createElement("baz")
+  el.setAttributeNS("foo", "foo:bar", "1");
+  assert_equals(el.getAttribute("foo:bar"), "1")
+  attr_is(el.attributes[0], "1", "bar", "foo", "foo", "foo:bar")
+  el.setAttribute("foo:bar", "2");
+  assert_equals(el.getAttribute("foo:bar"), "2")
+  attr_is(el.attributes[0], "2", "bar", "foo", "foo", "foo:bar")
+}, "setAttribute should set the attribute with the given qualified name")
+
+// setAttributeNS exhaustive tests
+// Step 1
+test(function() {
+  var el = document.createElement("foo")
+  for (var i = 0, il = invalid_names.length; i < il; ++i) {
+    assert_throws("INVALID_CHARACTER_ERR",
+                  function() { el.setAttributeNS("a", invalid_names[i], "fail") })
+  }
+}, "When qualifiedName does not match the Name production, an " +
+   "INVALID_CHARACTER_ERR exception is to be thrown. (setAttributeNS)")
+
+// Step 2
+test(function() {
+  var el = document.createElement("foo")
+  for (var i = 0, il = invalid_qnames.length; i < il; ++i) {
+    assert_throws("NAMESPACE_ERR",
+                  function() { el.setAttributeNS("a", invalid_qnames[i], "fail") },
+                  "Expected exception for " + invalid_qnames[i] + ".")
+  }
+}, "When qualifiedName does not match the QName production, an " +
+   "NAMESPACE_ERR exception is to be thrown.")
+
+// Step 3
+test(function() {
+  var el = document.createElement("foo")
+  el.setAttributeNS(null, "aa", "bb")
+  el.setAttributeNS("", "xx", "bb")
+  attributes_are(el, [["aa", "bb"],
+                      ["xx", "bb"]])
+}, "null and the empty string should result in a null namespace.")
+
+// Step 4
+test(function() {
+  var el = document.createElement("foo")
+  assert_throws("NAMESPACE_ERR",
+                function() { el.setAttributeNS("", "aa:bb", "fail") })
+  assert_throws("NAMESPACE_ERR",
+                function() { el.setAttributeNS(null, "aa:bb", "fail") })
+}, "A namespace is required to use a prefix.")
+
+// Step 5
+test(function() {
+  var el = document.createElement("foo")
+  assert_throws("NAMESPACE_ERR",
+                function() { el.setAttributeNS("a", "xml:bb", "fail") })
+}, "The xml prefix should not be allowed for arbitrary namespaces")
+test(function() {
+  var el = document.createElement("foo")
+  el.setAttributeNS(XML, "a:bb", "pass")
+  assert_equals(el.attributes.length, 1)
+  attr_is(el.attributes[0], "pass", "bb", XML, "a", "a:bb")
+}, "XML-namespaced attributes don't need an xml prefix")
+
+// Step 6
+test(function() {
+  var el = document.createElement("foo")
+  assert_throws("NAMESPACE_ERR",
+                function() { el.setAttributeNS("a", "xmlns:bb", "fail") })
+}, "The xmlns prefix should not be allowed for arbitrary namespaces")
+test(function() {
+  var el = document.createElement("foo")
+  assert_throws("NAMESPACE_ERR",
+                function() { el.setAttributeNS("a", "xmlns", "fail") })
+}, "The xmlns qualified name should not be allowed for arbitrary namespaces")
+test(function() {
+  var el = document.createElement("foo")
+  el.setAttributeNS("ns", "a:xmlns", "pass")
+  assert_equals(el.attributes.length, 1)
+  attr_is(el.attributes[0], "pass", "xmlns", "ns", "a", "a:xmlns")
+}, "xmlns should be allowed as local name")
+
+// Step 7
+test(function() {
+  var el = document.createElement("foo")
+  assert_throws("NAMESPACE_ERR",
+                function() { el.setAttributeNS(XMLNS, "a:xmlns", "fail") })
+  assert_throws("NAMESPACE_ERR",
+                function() { el.setAttributeNS(XMLNS, "b:foo", "fail") })
+}, "The XMLNS namespace should require xmlns as prefix or qualified name")
+test(function() {
+  var el = document.createElement("foo")
+  el.setAttributeNS(XMLNS, "xmlns:a", "pass")
+  assert_equals(el.attributes.length, 1)
+  attr_is(el.attributes[0], "pass", "a", XMLNS, "xmlns", "xmlns:a")
+}, "xmlns should be allowed as prefix in the XMLNS namespace")
+test(function() {
+  var el = document.createElement("foo")
+  el.setAttributeNS(XMLNS, "xmlns", "pass")
+  assert_equals(el.attributes.length, 1)
+  attr_is(el.attributes[0], "pass", "xmlns", XMLNS, null, "xmlns")
+}, "xmlns should be allowed as qualified name in the XMLNS namespace")
+
+// Step 8-9
+test(function() {
+  var el = document.createElement("foo")
+  el.setAttributeNS("a", "foo:bar", "X")
+  assert_equals(el.attributes.length, 1)
+  attr_is(el.attributes[0], "X", "bar", "a", "foo", "foo:bar")
+
+  el.setAttributeNS("a", "quux:bar", "Y")
+  assert_equals(el.attributes.length, 1)
+  attr_is(el.attributes[0], "Y", "bar", "a", "foo", "foo:bar")
+  el.removeAttributeNS("a", "bar")
+}, "Setting the same attribute with another prefix should not change the prefix")
+
+// Miscellaneous tests
+test(function() {
+  var el = document.createElement("iframe")
+  el.setAttribute("src", "file:///home")
+  assert_equals(el.getAttribute("src"), "file:///home")
+}, "setAttribute should not throw even if a load is not allowed")
+test(function() {
+  var docFragment = document.createDocumentFragment()
+  var newOne = document.createElement("newElement")
+  newOne.setAttribute("newdomestic", "Yes")
+  docFragment.appendChild(newOne)
+  var domesticNode = docFragment.firstChild
+  var attr = domesticNode.attributes.item(0)
+  attr_is(attr, "Yes", "newdomestic", null, null, "newdomestic")
+}, "Attributes should work in document fragments.")
+test(function() {
+  var el = document.createElement("foo")
+  el.setAttribute("x", "y")
+  var attr = el.attributes[0]
+  attr.value = "Y&lt;"
+  attr_is(attr, "Y&lt;", "x", null, null, "x")
+  assert_equals(el.getAttribute("x"), "Y&lt;")
+}, "Attribute values should not be parsed.")
+test(function() {
+  var el = document.getElementsByTagName("span")[0]
+  attr_is(el.attributes[0], "test1", "id", null, null, "id")
+}, "Specified attributes should be accessible.")
+test(function() {
+  var el = document.getElementsByTagName("span")[1]
+  attr_is(el.attributes[0], "&<>foo", "class", null, null, "class")
+}, "Entities in attributes should have been expanded while parsing.")
+
+test(function() {
+  var el = document.createElement("div")
+  assert_equals(el.hasAttribute("bar"), false)
+  assert_equals(el.hasAttributeNS(null, "bar"), false)
+  assert_equals(el.hasAttributeNS("", "bar"), false)
+  assert_equals(el.getAttribute("bar"), null)
+  assert_equals(el.getAttributeNS(null, "bar"), null)
+  assert_equals(el.getAttributeNS("", "bar"), null)
+}, "Unset attributes return null")
+test(function() {
+  var el = document.createElement("div")
+  el.setAttributeNS("ab", "attr", "t1")
+  el.setAttributeNS("kl", "attr", "t2")
+  assert_equals(el.hasAttribute("attr"), true)
+  assert_equals(el.hasAttributeNS("ab", "attr"), true)
+  assert_equals(el.hasAttributeNS("kl", "attr"), true)
+  assert_equals(el.getAttribute("attr"), "t1")
+  assert_equals(el.getAttributeNS("ab", "attr"), "t1")
+  assert_equals(el.getAttributeNS("kl", "attr"), "t2")
+  assert_equals(el.getAttributeNS(null, "attr"), null)
+  assert_equals(el.getAttributeNS("", "attr"), null)
+}, "First set attribute is returned by getAttribute")
+test(function() {
+  var el = document.createElement("div")
+  el.setAttribute("style", "color:#fff;")
+  assert_equals(el.hasAttribute("style"), true)
+  assert_equals(el.hasAttributeNS(null, "style"), true)
+  assert_equals(el.hasAttributeNS("", "style"), true)
+  assert_equals(el.getAttribute("style"), "color:#fff;")
+  assert_equals(el.getAttributeNS(null, "style"), "color:#fff;")
+  assert_equals(el.getAttributeNS("", "style"), "color:#fff;")
+}, "Style attributes are not normalized")
+test(function() {
+  var el = document.createElement("div")
+  el.setAttributeNS("", "ALIGN", "left")
+  assert_equals(el.hasAttribute("ALIGN"), false)
+  assert_equals(el.hasAttribute("align"), false)
+  assert_equals(el.hasAttributeNS(null, "ALIGN"), true)
+  assert_equals(el.hasAttributeNS(null, "align"), false)
+  assert_equals(el.hasAttributeNS("", "ALIGN"), true)
+  assert_equals(el.hasAttributeNS("", "align"), false)
+  assert_equals(el.getAttribute("ALIGN"), null)
+  assert_equals(el.getAttribute("align"), null)
+  assert_equals(el.getAttributeNS(null, "ALIGN"), "left")
+  assert_equals(el.getAttributeNS("", "ALIGN"), "left")
+  assert_equals(el.getAttributeNS(null, "align"), null)
+  assert_equals(el.getAttributeNS("", "align"), null)
+  el.removeAttributeNS("", "ALIGN")
+}, "Only lowercase attributes are returned on HTML elements (upper case attribute)")
+test(function() {
+  var el = document.createElement("div")
+  el.setAttributeNS("", "CHEEseCaKe", "tasty")
+  assert_equals(el.hasAttribute("CHEESECAKE"), false)
+  assert_equals(el.hasAttribute("CHEEseCaKe"), false)
+  assert_equals(el.hasAttribute("cheesecake"), false)
+  assert_equals(el.hasAttributeNS("", "CHEESECAKE"), false)
+  assert_equals(el.hasAttributeNS("", "CHEEseCaKe"), true)
+  assert_equals(el.hasAttributeNS("", "cheesecake"), false)
+  assert_equals(el.hasAttributeNS(null, "CHEESECAKE"), false)
+  assert_equals(el.hasAttributeNS(null, "CHEEseCaKe"), true)
+  assert_equals(el.hasAttributeNS(null, "cheesecake"), false)
+  assert_equals(el.getAttribute("CHEESECAKE"), null)
+  assert_equals(el.getAttribute("CHEEseCaKe"), null)
+  assert_equals(el.getAttribute("cheesecake"), null)
+  assert_equals(el.getAttributeNS(null, "CHEESECAKE"), null)
+  assert_equals(el.getAttributeNS("", "CHEESECAKE"), null)
+  assert_equals(el.getAttributeNS(null, "CHEEseCaKe"), "tasty")
+  assert_equals(el.getAttributeNS("", "CHEEseCaKe"), "tasty")
+  assert_equals(el.getAttributeNS(null, "cheesecake"), null)
+  assert_equals(el.getAttributeNS("", "cheesecake"), null)
+  el.removeAttributeNS("", "CHEEseCaKe")
+}, "Only lowercase attributes are returned on HTML elements (mixed case attribute)")
+test(function() {
+  var el = document.createElement("div")
+  document.body.appendChild(el)
+  el.setAttributeNS("", "align", "left")
+  el.setAttributeNS("xx", "align", "right")
+  el.setAttributeNS("", "foo", "left")
+  el.setAttributeNS("xx", "foo", "right")
+  assert_equals(el.hasAttribute("align"), true)
+  assert_equals(el.hasAttribute("foo"), true)
+  assert_equals(el.hasAttributeNS("xx", "align"), true)
+  assert_equals(el.hasAttributeNS(null, "foo"), true)
+  assert_equals(el.getAttribute("align"), "left")
+  assert_equals(el.getAttribute("foo"), "left")
+  assert_equals(el.getAttributeNS("xx", "align"), "right")
+  assert_equals(el.getAttributeNS(null, "foo"), "left")
+  assert_equals(el.getAttributeNS("", "foo"), "left")
+  el.removeAttributeNS("", "align")
+  el.removeAttributeNS("xx", "align")
+  el.removeAttributeNS("", "foo")
+  el.removeAttributeNS("xx", "foo")
+  document.body.removeChild(el)
+}, "First set attribute is returned with mapped attribute set first")
+test(function() {
+  var el = document.createElement("div")
+  el.setAttributeNS("xx", "align", "right")
+  el.setAttributeNS("", "align", "left")
+  el.setAttributeNS("xx", "foo", "right")
+  el.setAttributeNS("", "foo", "left")
+  assert_equals(el.hasAttribute("align"), true)
+  assert_equals(el.hasAttribute("foo"), true)
+  assert_equals(el.hasAttributeNS("xx", "align"), true)
+  assert_equals(el.hasAttributeNS(null, "foo"), true)
+  assert_equals(el.getAttribute("align"), "right")
+  assert_equals(el.getAttribute("foo"), "right")
+  assert_equals(el.getAttributeNS("xx", "align"), "right")
+  assert_equals(el.getAttributeNS(null, "foo"), "left")
+  assert_equals(el.getAttributeNS("", "foo"), "left")
+  el.removeAttributeNS("", "align")
+  el.removeAttributeNS("xx", "align")
+  el.removeAttributeNS("", "foo")
+  el.removeAttributeNS("xx", "foo")
+}, "First set attribute is returned with mapped attribute set later")
+
+test(function() {
+  var el = document.createElementNS("http://www.example.com", "foo")
+  el.setAttribute("A", "test")
+  assert_equals(el.hasAttribute("A"), true, "hasAttribute()")
+  assert_equals(el.hasAttributeNS("", "A"), true, "el.hasAttributeNS(\"\")")
+  assert_equals(el.hasAttributeNS(null, "A"), true, "el.hasAttributeNS(null)")
+  assert_equals(el.hasAttributeNS(undefined, "A"), true, "el.hasAttributeNS(undefined)")
+  assert_equals(el.hasAttributeNS("foo", "A"), false, "el.hasAttributeNS(\"foo\")")
+
+  assert_equals(el.getAttribute("A"), "test", "getAttribute()")
+  assert_equals(el.getAttributeNS("", "A"), "test", "el.getAttributeNS(\"\")")
+  assert_equals(el.getAttributeNS(null, "A"), "test", "el.getAttributeNS(null)")
+  assert_equals(el.getAttributeNS(undefined, "A"), "test", "el.getAttributeNS(undefined)")
+  assert_equals(el.getAttributeNS("foo", "A"), null, "el.getAttributeNS(\"foo\")")
+}, "Non-HTML element with upper-case attribute")
+
+test(function() {
+  var el = document.createElement("div")
+  el.setAttribute("pre:fix", "value 1")
+  el.setAttribute("fix", "value 2")
+
+  var prefixed = el.attributes[0]
+  assert_equals(prefixed.localName, "pre:fix", "prefixed local name")
+  assert_equals(prefixed.namespaceURI, null, "prefixed namespace")
+
+  var unprefixed = el.attributes[1]
+  assert_equals(unprefixed.localName, "fix", "unprefixed local name")
+  assert_equals(unprefixed.namespaceURI, null, "unprefixed namespace")
+
+  el.removeAttributeNS(null, "pre:fix")
+  assert_equals(el.attributes[0], unprefixed)
+}, "Attribute with prefix in local name")
+
+test(function() {
+  var el = document.createElement("div")
+  el.setAttribute("foo", "bar")
+  var attr = el.attributes[0]
+  assert_equals(attr.ownerElement, el)
+  el.removeAttribute("foo")
+  assert_equals(attr.ownerElement, null)
+}, "Attribute loses its owner when removed")
+
+test(function() {
+  var el = document.createElement("div")
+  el.setAttribute("foo", "bar")
+  var attr = el.attributes[0]
+  var attrNode = el.getAttributeNode("foo");
+  var attrNodeNS = el.getAttributeNodeNS("", "foo");
+  assert_equals(attr, attrNode);
+  assert_equals(attr, attrNodeNS);
+  el.setAttributeNS("x", "foo2", "bar2");
+  var attr2 = el.attributes[1];
+  var attrNodeNS2 = el.getAttributeNodeNS("x", "foo2");
+  assert_equals(attr2, attrNodeNS2);
+}, "Basic functionality of getAttributeNode/getAttributeNodeNS")
+
+test(function() {
+  var el = document.createElement("div")
+  el.setAttribute("foo", "bar")
+  var attrNode = el.getAttributeNode("foo");
+  var attrNodeNS = el.getAttributeNodeNS("", "foo");
+  assert_equals(attrNode, attrNodeNS);
+  el.removeAttribute("foo");
+  var el2 = document.createElement("div");
+  el2.setAttributeNode(attrNode);
+  assert_equals(attrNode, el2.getAttributeNode("foo"));
+  assert_equals(attrNode, el2.attributes[0]);
+  assert_equals(attrNode.ownerElement, el2);
+  assert_equals(attrNode.value, "bar");
+
+   var el3 = document.createElement("div");
+   el2.removeAttribute("foo");
+   el3.setAttribute("foo", "baz");
+   el3.setAttributeNode(attrNode);
+   assert_equals(el3.getAttribute("foo"), "bar");
+}, "Basic functionality of setAttributeNode")
+
+test(function() {
+  var el = document.createElement("div")
+  el.setAttributeNS("x", "foo", "bar")
+  var attrNode = el.getAttributeNodeNS("x", "foo");
+  el.removeAttribute("foo");
+  var el2 = document.createElement("div");
+  el2.setAttributeNS("x", "foo", "baz");
+  el2.setAttributeNodeNS(attrNode);
+  assert_equals(el2.getAttributeNS("x", "foo"), "bar");
+}, "Basic functionality of setAttributeNodeNS")
+
+test(function() {
+  var el = document.createElement("div")
+  el.setAttribute("foo", "bar")
+  var attrNode = el.getAttributeNode("foo");
+  el.removeAttributeNode(attrNode);
+  var el2 = document.createElement("div");
+  el2.setAttributeNode(attrNode);
+  assert_equals(el2.attributes[0], attrNode);
+  assert_equals(el.attributes.length, 0);
+}, "Basic functionality of removeAttributeNode")
+
+test(function() {
+  var el = document.createElement("div")
+  el.setAttribute("foo", "bar")
+  var attrNode = el.getAttributeNode("foo");
+  var el2 = document.createElement("div");
+  assert_throws("INUSE_ATTRIBUTE_ERR", function(){el2.setAttributeNode(attrNode)});
+}, "setAttributeNode on bound attribute should throw InUseAttributeError")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/attributes.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/attributes.js
new file mode 100644
index 0000000..096dd5fd7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/attributes.js
@@ -0,0 +1,17 @@
+function attr_is(attr, v, ln, ns, p, n) {
+  assert_equals(attr.value, v)
+  assert_equals(attr.nodeValue, v)
+  assert_equals(attr.textContent, v)
+  assert_equals(attr.localName, ln)
+  assert_equals(attr.namespaceURI, ns)
+  assert_equals(attr.prefix, p)
+  assert_equals(attr.name, n)
+  assert_equals(attr.specified, true)
+}
+
+function attributes_are(el, l) {
+  for (var i = 0, il = l.length; i < il; i++) {
+    attr_is(el.attributes[i], l[i][1], l[i][0], (l[i].length < 3) ? null : l[i][2], null, l[i][0])
+    assert_equals(el.attributes[i].ownerElement, el)
+  }
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case-expected.txt
new file mode 100644
index 0000000..46edb961
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case-expected.txt
@@ -0,0 +1,288 @@
+This is a testharness.js-based test.
+PASS createElement abc 
+PASS setAttribute abc 
+PASS getAttribute abc 
+PASS getElementsByTagName a:abc 
+PASS getElementsByTagName abc 
+PASS createElement Abc 
+PASS setAttribute Abc 
+PASS getAttribute Abc 
+PASS getElementsByTagName a:Abc 
+PASS getElementsByTagName Abc 
+PASS createElement ABC 
+PASS setAttribute ABC 
+PASS getAttribute ABC 
+PASS getElementsByTagName a:ABC 
+PASS getElementsByTagName ABC 
+PASS createElement ä 
+PASS setAttribute ä 
+PASS getAttribute ä 
+PASS getElementsByTagName a:ä 
+PASS getElementsByTagName ä 
+FAIL createElement Ä assert_equals: expected "Ä" but got "ä"
+FAIL setAttribute Ä assert_equals: expected "Ä" but got "ä"
+PASS getAttribute Ä 
+FAIL getElementsByTagName a:Ä assert_array_equals: property 0, expected Element node <Ä></Ä> but got Element node <ä></ä>
+FAIL getElementsByTagName Ä assert_array_equals: property 0, expected Element node <Ä></Ä> but got Element node <ä></ä>
+PASS createElementNS http://www.w3.org/1999/xhtml,abc,abc 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,abc,abc 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,abc,abc 
+PASS createElementNS http://www.w3.org/1999/xhtml,abc,Abc 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,abc,Abc 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,abc,Abc 
+PASS createElementNS http://www.w3.org/1999/xhtml,abc,ABC 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,abc,ABC 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,abc,ABC 
+PASS createElementNS http://www.w3.org/1999/xhtml,abc,ä 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,abc,ä 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,abc,ä 
+PASS createElementNS http://www.w3.org/1999/xhtml,abc,Ä 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,abc,Ä 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,abc,Ä 
+PASS createElementNS http://www.w3.org/1999/xhtml,Abc,abc 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,Abc,abc 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,Abc,abc 
+PASS createElementNS http://www.w3.org/1999/xhtml,Abc,Abc 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,Abc,Abc 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,Abc,Abc 
+PASS createElementNS http://www.w3.org/1999/xhtml,Abc,ABC 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,Abc,ABC 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,Abc,ABC 
+PASS createElementNS http://www.w3.org/1999/xhtml,Abc,ä 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,Abc,ä 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,Abc,ä 
+PASS createElementNS http://www.w3.org/1999/xhtml,Abc,Ä 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,Abc,Ä 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,Abc,Ä 
+PASS createElementNS http://www.w3.org/1999/xhtml,ABC,abc 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,ABC,abc 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,ABC,abc 
+PASS createElementNS http://www.w3.org/1999/xhtml,ABC,Abc 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,ABC,Abc 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,ABC,Abc 
+PASS createElementNS http://www.w3.org/1999/xhtml,ABC,ABC 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,ABC,ABC 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,ABC,ABC 
+PASS createElementNS http://www.w3.org/1999/xhtml,ABC,ä 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,ABC,ä 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,ABC,ä 
+PASS createElementNS http://www.w3.org/1999/xhtml,ABC,Ä 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,ABC,Ä 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,ABC,Ä 
+PASS createElementNS http://www.w3.org/1999/xhtml,ä,abc 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,ä,abc 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,ä,abc 
+PASS createElementNS http://www.w3.org/1999/xhtml,ä,Abc 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,ä,Abc 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,ä,Abc 
+PASS createElementNS http://www.w3.org/1999/xhtml,ä,ABC 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,ä,ABC 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,ä,ABC 
+PASS createElementNS http://www.w3.org/1999/xhtml,ä,ä 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,ä,ä 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,ä,ä 
+PASS createElementNS http://www.w3.org/1999/xhtml,ä,Ä 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,ä,Ä 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,ä,Ä 
+PASS createElementNS http://www.w3.org/1999/xhtml,Ä,abc 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,Ä,abc 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,Ä,abc 
+PASS createElementNS http://www.w3.org/1999/xhtml,Ä,Abc 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,Ä,Abc 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,Ä,Abc 
+PASS createElementNS http://www.w3.org/1999/xhtml,Ä,ABC 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,Ä,ABC 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,Ä,ABC 
+PASS createElementNS http://www.w3.org/1999/xhtml,Ä,ä 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,Ä,ä 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,Ä,ä 
+PASS createElementNS http://www.w3.org/1999/xhtml,Ä,Ä 
+PASS setAttributeNS http://www.w3.org/1999/xhtml,Ä,Ä 
+PASS getAttributeNS http://www.w3.org/1999/xhtml,Ä,Ä 
+PASS createElementNS http://www.w3.org/2000/svg,abc,abc 
+PASS setAttributeNS http://www.w3.org/2000/svg,abc,abc 
+PASS getAttributeNS http://www.w3.org/2000/svg,abc,abc 
+PASS createElementNS http://www.w3.org/2000/svg,abc,Abc 
+PASS setAttributeNS http://www.w3.org/2000/svg,abc,Abc 
+PASS getAttributeNS http://www.w3.org/2000/svg,abc,Abc 
+PASS createElementNS http://www.w3.org/2000/svg,abc,ABC 
+PASS setAttributeNS http://www.w3.org/2000/svg,abc,ABC 
+PASS getAttributeNS http://www.w3.org/2000/svg,abc,ABC 
+PASS createElementNS http://www.w3.org/2000/svg,abc,ä 
+PASS setAttributeNS http://www.w3.org/2000/svg,abc,ä 
+PASS getAttributeNS http://www.w3.org/2000/svg,abc,ä 
+PASS createElementNS http://www.w3.org/2000/svg,abc,Ä 
+PASS setAttributeNS http://www.w3.org/2000/svg,abc,Ä 
+PASS getAttributeNS http://www.w3.org/2000/svg,abc,Ä 
+PASS createElementNS http://www.w3.org/2000/svg,Abc,abc 
+PASS setAttributeNS http://www.w3.org/2000/svg,Abc,abc 
+PASS getAttributeNS http://www.w3.org/2000/svg,Abc,abc 
+PASS createElementNS http://www.w3.org/2000/svg,Abc,Abc 
+PASS setAttributeNS http://www.w3.org/2000/svg,Abc,Abc 
+PASS getAttributeNS http://www.w3.org/2000/svg,Abc,Abc 
+PASS createElementNS http://www.w3.org/2000/svg,Abc,ABC 
+PASS setAttributeNS http://www.w3.org/2000/svg,Abc,ABC 
+PASS getAttributeNS http://www.w3.org/2000/svg,Abc,ABC 
+PASS createElementNS http://www.w3.org/2000/svg,Abc,ä 
+PASS setAttributeNS http://www.w3.org/2000/svg,Abc,ä 
+PASS getAttributeNS http://www.w3.org/2000/svg,Abc,ä 
+PASS createElementNS http://www.w3.org/2000/svg,Abc,Ä 
+PASS setAttributeNS http://www.w3.org/2000/svg,Abc,Ä 
+PASS getAttributeNS http://www.w3.org/2000/svg,Abc,Ä 
+PASS createElementNS http://www.w3.org/2000/svg,ABC,abc 
+PASS setAttributeNS http://www.w3.org/2000/svg,ABC,abc 
+PASS getAttributeNS http://www.w3.org/2000/svg,ABC,abc 
+PASS createElementNS http://www.w3.org/2000/svg,ABC,Abc 
+PASS setAttributeNS http://www.w3.org/2000/svg,ABC,Abc 
+PASS getAttributeNS http://www.w3.org/2000/svg,ABC,Abc 
+PASS createElementNS http://www.w3.org/2000/svg,ABC,ABC 
+PASS setAttributeNS http://www.w3.org/2000/svg,ABC,ABC 
+PASS getAttributeNS http://www.w3.org/2000/svg,ABC,ABC 
+PASS createElementNS http://www.w3.org/2000/svg,ABC,ä 
+PASS setAttributeNS http://www.w3.org/2000/svg,ABC,ä 
+PASS getAttributeNS http://www.w3.org/2000/svg,ABC,ä 
+PASS createElementNS http://www.w3.org/2000/svg,ABC,Ä 
+PASS setAttributeNS http://www.w3.org/2000/svg,ABC,Ä 
+PASS getAttributeNS http://www.w3.org/2000/svg,ABC,Ä 
+PASS createElementNS http://www.w3.org/2000/svg,ä,abc 
+PASS setAttributeNS http://www.w3.org/2000/svg,ä,abc 
+PASS getAttributeNS http://www.w3.org/2000/svg,ä,abc 
+PASS createElementNS http://www.w3.org/2000/svg,ä,Abc 
+PASS setAttributeNS http://www.w3.org/2000/svg,ä,Abc 
+PASS getAttributeNS http://www.w3.org/2000/svg,ä,Abc 
+PASS createElementNS http://www.w3.org/2000/svg,ä,ABC 
+PASS setAttributeNS http://www.w3.org/2000/svg,ä,ABC 
+PASS getAttributeNS http://www.w3.org/2000/svg,ä,ABC 
+PASS createElementNS http://www.w3.org/2000/svg,ä,ä 
+PASS setAttributeNS http://www.w3.org/2000/svg,ä,ä 
+PASS getAttributeNS http://www.w3.org/2000/svg,ä,ä 
+PASS createElementNS http://www.w3.org/2000/svg,ä,Ä 
+PASS setAttributeNS http://www.w3.org/2000/svg,ä,Ä 
+PASS getAttributeNS http://www.w3.org/2000/svg,ä,Ä 
+PASS createElementNS http://www.w3.org/2000/svg,Ä,abc 
+PASS setAttributeNS http://www.w3.org/2000/svg,Ä,abc 
+PASS getAttributeNS http://www.w3.org/2000/svg,Ä,abc 
+PASS createElementNS http://www.w3.org/2000/svg,Ä,Abc 
+PASS setAttributeNS http://www.w3.org/2000/svg,Ä,Abc 
+PASS getAttributeNS http://www.w3.org/2000/svg,Ä,Abc 
+PASS createElementNS http://www.w3.org/2000/svg,Ä,ABC 
+PASS setAttributeNS http://www.w3.org/2000/svg,Ä,ABC 
+PASS getAttributeNS http://www.w3.org/2000/svg,Ä,ABC 
+PASS createElementNS http://www.w3.org/2000/svg,Ä,ä 
+PASS setAttributeNS http://www.w3.org/2000/svg,Ä,ä 
+PASS getAttributeNS http://www.w3.org/2000/svg,Ä,ä 
+PASS createElementNS http://www.w3.org/2000/svg,Ä,Ä 
+PASS setAttributeNS http://www.w3.org/2000/svg,Ä,Ä 
+PASS getAttributeNS http://www.w3.org/2000/svg,Ä,Ä 
+PASS createElementNS http://FOO,abc,abc 
+PASS setAttributeNS http://FOO,abc,abc 
+PASS getAttributeNS http://FOO,abc,abc 
+PASS createElementNS http://FOO,abc,Abc 
+PASS setAttributeNS http://FOO,abc,Abc 
+PASS getAttributeNS http://FOO,abc,Abc 
+PASS createElementNS http://FOO,abc,ABC 
+PASS setAttributeNS http://FOO,abc,ABC 
+PASS getAttributeNS http://FOO,abc,ABC 
+PASS createElementNS http://FOO,abc,ä 
+PASS setAttributeNS http://FOO,abc,ä 
+PASS getAttributeNS http://FOO,abc,ä 
+PASS createElementNS http://FOO,abc,Ä 
+PASS setAttributeNS http://FOO,abc,Ä 
+PASS getAttributeNS http://FOO,abc,Ä 
+PASS createElementNS http://FOO,Abc,abc 
+PASS setAttributeNS http://FOO,Abc,abc 
+PASS getAttributeNS http://FOO,Abc,abc 
+PASS createElementNS http://FOO,Abc,Abc 
+PASS setAttributeNS http://FOO,Abc,Abc 
+PASS getAttributeNS http://FOO,Abc,Abc 
+PASS createElementNS http://FOO,Abc,ABC 
+PASS setAttributeNS http://FOO,Abc,ABC 
+PASS getAttributeNS http://FOO,Abc,ABC 
+PASS createElementNS http://FOO,Abc,ä 
+PASS setAttributeNS http://FOO,Abc,ä 
+PASS getAttributeNS http://FOO,Abc,ä 
+PASS createElementNS http://FOO,Abc,Ä 
+PASS setAttributeNS http://FOO,Abc,Ä 
+PASS getAttributeNS http://FOO,Abc,Ä 
+PASS createElementNS http://FOO,ABC,abc 
+PASS setAttributeNS http://FOO,ABC,abc 
+PASS getAttributeNS http://FOO,ABC,abc 
+PASS createElementNS http://FOO,ABC,Abc 
+PASS setAttributeNS http://FOO,ABC,Abc 
+PASS getAttributeNS http://FOO,ABC,Abc 
+PASS createElementNS http://FOO,ABC,ABC 
+PASS setAttributeNS http://FOO,ABC,ABC 
+PASS getAttributeNS http://FOO,ABC,ABC 
+PASS createElementNS http://FOO,ABC,ä 
+PASS setAttributeNS http://FOO,ABC,ä 
+PASS getAttributeNS http://FOO,ABC,ä 
+PASS createElementNS http://FOO,ABC,Ä 
+PASS setAttributeNS http://FOO,ABC,Ä 
+PASS getAttributeNS http://FOO,ABC,Ä 
+PASS createElementNS http://FOO,ä,abc 
+PASS setAttributeNS http://FOO,ä,abc 
+PASS getAttributeNS http://FOO,ä,abc 
+PASS createElementNS http://FOO,ä,Abc 
+PASS setAttributeNS http://FOO,ä,Abc 
+PASS getAttributeNS http://FOO,ä,Abc 
+PASS createElementNS http://FOO,ä,ABC 
+PASS setAttributeNS http://FOO,ä,ABC 
+PASS getAttributeNS http://FOO,ä,ABC 
+PASS createElementNS http://FOO,ä,ä 
+PASS setAttributeNS http://FOO,ä,ä 
+PASS getAttributeNS http://FOO,ä,ä 
+PASS createElementNS http://FOO,ä,Ä 
+PASS setAttributeNS http://FOO,ä,Ä 
+PASS getAttributeNS http://FOO,ä,Ä 
+PASS createElementNS http://FOO,Ä,abc 
+PASS setAttributeNS http://FOO,Ä,abc 
+PASS getAttributeNS http://FOO,Ä,abc 
+PASS createElementNS http://FOO,Ä,Abc 
+PASS setAttributeNS http://FOO,Ä,Abc 
+PASS getAttributeNS http://FOO,Ä,Abc 
+PASS createElementNS http://FOO,Ä,ABC 
+PASS setAttributeNS http://FOO,Ä,ABC 
+PASS getAttributeNS http://FOO,Ä,ABC 
+PASS createElementNS http://FOO,Ä,ä 
+PASS setAttributeNS http://FOO,Ä,ä 
+PASS getAttributeNS http://FOO,Ä,ä 
+PASS createElementNS http://FOO,Ä,Ä 
+PASS setAttributeNS http://FOO,Ä,Ä 
+PASS getAttributeNS http://FOO,Ä,Ä 
+PASS getElementsByTagNameNS ,abc 
+PASS getElementsByTagNameNS ,Abc 
+PASS getElementsByTagNameNS ,ABC 
+PASS getElementsByTagNameNS ,ä 
+PASS getElementsByTagNameNS ,Ä 
+PASS getElementsByTagNameNS http://www.w3.org/1999/xhtml,abc 
+PASS getElementsByTagNameNS http://www.w3.org/1999/xhtml,Abc 
+PASS getElementsByTagNameNS http://www.w3.org/1999/xhtml,ABC 
+PASS getElementsByTagNameNS http://www.w3.org/1999/xhtml,ä 
+PASS getElementsByTagNameNS http://www.w3.org/1999/xhtml,Ä 
+PASS getElementsByTagNameNS http://www.w3.org/2000/svg,abc 
+PASS getElementsByTagNameNS http://www.w3.org/2000/svg,Abc 
+PASS getElementsByTagNameNS http://www.w3.org/2000/svg,ABC 
+PASS getElementsByTagNameNS http://www.w3.org/2000/svg,ä 
+PASS getElementsByTagNameNS http://www.w3.org/2000/svg,Ä 
+PASS getElementsByTagNameNS http://FOO,abc 
+PASS getElementsByTagNameNS http://FOO,Abc 
+PASS getElementsByTagNameNS http://FOO,ABC 
+PASS getElementsByTagNameNS http://FOO,ä 
+PASS getElementsByTagNameNS http://FOO,Ä 
+PASS createElementNS abc 
+PASS setAttributeNS abc 
+PASS getAttributeNS abc 
+PASS createElementNS Abc 
+PASS setAttributeNS Abc 
+PASS getAttributeNS Abc 
+PASS createElementNS ABC 
+PASS setAttributeNS ABC 
+PASS getAttributeNS ABC 
+PASS createElementNS ä 
+PASS setAttributeNS ä 
+PASS getAttributeNS ä 
+PASS createElementNS Ä 
+PASS setAttributeNS Ä 
+PASS getAttributeNS Ä 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case.html
new file mode 100644
index 0000000..5abbd49
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Tests for case-sensitivity in APIs</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelement">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelementns">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagname">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagnamens">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-setattribute">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-setattributens">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-hasattribute">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-hasattributens">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-getelementsbytagname">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-getelementsbytagnamens">
+<script>var is_html = true;</script>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="case.js"></script>
+<div id="log"></div>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case.js
new file mode 100644
index 0000000..fb28b95
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case.js
@@ -0,0 +1,179 @@
+/*
+ * document.createElement(NS)
+ *
+ * document.getElementsByTagName(NS)
+ *
+ * Element.setAttribute(NS)
+ *
+ * Element.getAttribute(NS)
+ * Element.hasAttribute(NS)
+ * Element.getElementsByTagName(NS)
+ */
+
+var tests = [];
+setup(function() {
+        var name_inputs = ["abc", "Abc", "ABC", "ä", "Ä"];
+        var namespaces = ["http://www.w3.org/1999/xhtml", "http://www.w3.org/2000/svg", "http://FOO"];
+        name_inputs.forEach(function(x) {
+                              tests.push(["createElement " + x, test_create_element, [x]]);
+                              tests.push(["setAttribute " +x, test_set_attribute, [x]]);
+                              tests.push(["getAttribute " +x, test_get_attribute, [x]]);
+                              tests.push(["getElementsByTagName a:" +x, test_get_elements_tag_name,
+                                          [outer_product(namespaces, ["a"], name_inputs),
+                                           x]]);
+                              tests.push(["getElementsByTagName " +x, test_get_elements_tag_name,
+                                          [outer_product(namespaces, [null], name_inputs),
+                                           x]]);
+                            });
+        outer_product(namespaces, name_inputs, name_inputs).forEach(function(x) {
+                                                                      tests.push(["createElementNS " + x, test_create_element_ns, x]);
+                                                                      tests.push(["setAttributeNS " + x, test_set_attribute_ns, x]);
+                                                                      tests.push(["getAttributeNS " + x, test_get_attribute_ns, x]);
+                                                                    });
+        outer_product([null].concat(namespaces), name_inputs).forEach(function(x) {
+                                                                        tests.push(["getElementsByTagNameNS " + x, test_get_elements_tag_name_ns,
+                                                                        outer_product(namespaces, name_inputs), x]);
+                                                                      });
+        name_inputs.forEach(function(x) {
+                              tests.push(["createElementNS " + x, test_create_element_ns, [null, null, x]]);
+                              tests.push(["setAttributeNS " + x, test_set_attribute_ns, [null, null, x]]);
+                              tests.push(["getAttributeNS " + x, test_get_attribute_ns, [null, null, x]]);
+                            });
+
+      });
+function outer_product() {
+  var rv = [];
+  function compute_outer_product() {
+    var args = Array.prototype.slice.call(arguments);
+    var index = args[0];
+    if (index < args.length) {
+      args[index].forEach(function(x) {
+                           compute_outer_product.apply(this, [index+1].concat(args.slice(1, index), x, args.slice(index+1)));
+                          });
+    } else {
+      rv.push(args.slice(1));
+    }
+  }
+  compute_outer_product.apply(this, [1].concat(Array.prototype.slice.call(arguments)));
+  return rv;
+}
+
+function expected_case(input) {
+  //is_html gets set by a global on the page loading the tests
+  if (is_html) {
+    return ascii_lowercase(input);
+  } else {
+    return input;
+  }
+}
+
+function ascii_lowercase(input) {
+  return input.replace(/[A-Z]/g, function(x) {
+                         return x.toLowerCase();
+                       });
+}
+
+function test_create_element(name) {
+  var node = document.createElement(name);
+  assert_equals(node.localName, expected_case(name));
+}
+
+function test_create_element_ns(namespace, prefix, local_name) {
+  var qualified_name = prefix ? prefix + ":" + local_name : local_name;
+  var node = document.createElementNS(namespace, qualified_name);
+  assert_equals(node.prefix, prefix, "prefix");
+  assert_equals(node.localName, local_name, "localName");
+}
+
+function test_set_attribute(name) {
+  var node = document.createElement("div");
+  node.setAttribute(name, "test");
+  assert_equals(node.attributes[0].localName, expected_case(name));
+}
+
+function test_set_attribute_ns(namespace, prefix, local_name) {
+  var qualified_name = prefix ? prefix + ":" + local_name : local_name;
+  var node = document.createElement("div");
+  node.setAttributeNS(namespace, qualified_name, "test");
+  var attr = node.attributes[0];
+  assert_equals(attr.prefix, prefix, "prefix");
+  assert_equals(attr.localName, local_name, "localName");
+}
+
+function test_get_attribute(name) {
+  var node = document.createElement("div");
+  node.setAttribute(name, "test");
+  var expected_name = expected_case(name);
+  assert_equals(node.getAttribute(expected_name), "test");
+  if (expected_name != name) {
+    assert_equals(node.getAttribute(expected_name), "test");
+  } else if (name !== ascii_lowercase(name)) {
+    assert_equals(node.getAttribute(ascii_lowercase(name)), null);
+  }
+}
+
+function test_get_attribute_ns(namespace, prefix, local_name) {
+  var qualified_name = prefix ? prefix + ":" + local_name : local_name;
+  var node = document.createElement("div");
+  node.setAttributeNS(namespace, qualified_name, "test");
+  var expected_name = local_name;
+  assert_equals(node.getAttributeNS(namespace, expected_name), "test");
+  if (local_name !== ascii_lowercase(local_name)) {
+    assert_equals(node.getAttributeNS(namespace, ascii_lowercase(local_name)), null);
+  }
+}
+
+function test_get_elements_tag_name(elements_to_create, search_string) {
+  var container = document.createElement("div");
+  elements_to_create.forEach(function(x) {
+                               var qualified_name = x[1] ? x[1] + ":" + x[2] : x[2];
+                               var element = document.createElementNS(x[0], qualified_name);
+                               container.appendChild(element);
+                             });
+  var expected = Array.prototype.filter.call(container.childNodes,
+                                            function(node) {
+                                              if (is_html && node.namespaceURI === "http://www.w3.org/1999/xhtml") {
+                                                return node.localName === expected_case(search_string);
+                                              } else {
+                                                return node.localName === search_string;
+                                              }
+                                            });
+  document.documentElement.appendChild(container);
+  try {
+    assert_array_equals(document.getElementsByTagName(search_string), expected);
+  } finally {
+    document.documentElement.removeChild(container);
+  }
+}
+
+function test_get_elements_tag_name_ns(elements_to_create, search_input) {
+  var search_uri = search_input[0];
+  var search_name = search_input[1];
+  var container = document.createElement("div");
+  elements_to_create.forEach(function(x) {
+                               var qualified_name = x[1] ? x[1] + ":" + x[2] : x[2];
+                               var element = document.createElementNS(x[0], qualified_name);
+                               container.appendChild(element);
+                             });
+  var expected = Array.prototype.filter.call(container.childNodes,
+                                            function(node) {
+                                              return node.namespaceURI === search_uri;
+                                              return node.localName === search_name;
+                                            });
+  document.documentElement.appendChild(container);
+  try {
+    assert_array_equals(document.getElementsByTagNameNS(search_uri, search_name), expected);
+  } catch(e) {
+    throw e;
+  } finally {
+    document.documentElement.removeChild(container);
+  }
+}
+
+function test_func() {
+  var func = arguments[0];
+  var rest = arguments[1];
+  func.apply(this, rest);
+}
+
+generate_tests(test_func, tests);
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/creators.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/creators.js
new file mode 100644
index 0000000..8b7415d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/creators.js
@@ -0,0 +1,5 @@
+var creators = {
+  "element": "createElement",
+  "text": "createTextNode",
+  "comment": "createComment"
+};
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/encoding.py b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/encoding.py
new file mode 100644
index 0000000..5f889e8db
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/encoding.py
@@ -0,0 +1,5 @@
+from cgi import escape
+
+def main(request, response):
+    label = request.GET.first('label')
+    return """<!doctype html><meta charset="%s">""" % escape(label)
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-01.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-01.htm
new file mode 100644
index 0000000..e4fb891
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-01.htm
@@ -0,0 +1,13 @@
+<!doctype html>
+<html class="a">
+ <head>
+  <title>document.getElementsByClassName(): simple</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+  <div id="log"></div>
+  <script> test(function() {assert_array_equals(document.getElementsByClassName("\ta\n"),
+                                                [document.documentElement, document.body])}) </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-02.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-02.htm
new file mode 100644
index 0000000..01afc83
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-02.htm
@@ -0,0 +1,14 @@
+<!doctype html>
+<html class="a
+b">
+ <head>
+  <title>document.getElementsByClassName(): also simple</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="a
+">
+  <div id="log"></div>
+  <script> test(function() {assert_array_equals(document.getElementsByClassName("a\n"), [document.documentElement, document.body])}) </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-03.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-03.htm
new file mode 100644
index 0000000..23a72e8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-03.htm
@@ -0,0 +1,18 @@
+<!doctype html>
+<html class="a">
+ <head>
+  <title>document.getElementsByClassName(): changing classes</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+  <div id="log"></div>
+  <script>
+   test(function() {
+          var collection = document.getElementsByClassName("a")
+          document.body.className = "b"
+          assert_array_equals(collection, [document.documentElement])
+        })
+  </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-04.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-04.htm
new file mode 100644
index 0000000..c0fa0e1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-04.htm
@@ -0,0 +1,18 @@
+<!doctype html>
+<html class="a">
+ <head>
+  <title>document.getElementsByClassName(): changing classes</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+  <div id="log"></div>
+  <script>
+   test(function() {
+          var collection = document.getElementsByClassName("a");
+          document.body.className += "\tb";
+          assert_array_equals(collection, [document.documentElement, document.body]);
+        })
+  </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-05.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-05.htm
new file mode 100644
index 0000000..2459493f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-05.htm
@@ -0,0 +1,18 @@
+<!doctype html>
+<html class="a">
+ <head>
+  <title>document.getElementsByClassName(): changing classes</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+  <div id="log"></div>
+  <script>
+   test(function() {
+          var collection = document.getElementsByClassName("a");
+          document.body.removeAttribute("class");
+          assert_array_equals(collection, [document.documentElement]);
+        })
+  </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-06.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-06.htm
new file mode 100644
index 0000000..d4f2e34
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-06.htm
@@ -0,0 +1,20 @@
+<!doctype html>
+<html>
+ <head>
+  <title>document.getElementsByClassName(): adding element with class</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+  <div id="log"></div>
+  <script>
+   test(function() {
+          var collection = document.getElementsByClassName("a");
+          var ele = document.createElement("foo");
+          ele.setAttribute("class", "a");
+          document.body.appendChild(ele);
+          assert_array_equals(collection, [document.body, ele]);
+        })
+  </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-07.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-07.htm
new file mode 100644
index 0000000..5c95a7f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-07.htm
@@ -0,0 +1,15 @@
+<!doctype html>
+<html>
+ <head>
+  <title>document.getElementsByClassName(): multiple classes</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="a b">
+  <div id="log"></div>
+  <script> test(function() {
+                  assert_array_equals(document.getElementsByClassName("b\t\f\n\na\rb"), [document.body]);
+               })
+  </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-08.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-08.htm
new file mode 100644
index 0000000..c93d036f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-08.htm
@@ -0,0 +1,15 @@
+<!doctype html>
+<html>
+ <head>
+  <title>document.getElementsByClassName(): multiple classes</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+  <div id="log"></div>
+  <script> test(function() {
+                  document.getElementsByClassName("a\fa"), [document.body]
+                })
+  </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-09.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-09.htm
new file mode 100644
index 0000000..f46001e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-09.htm
@@ -0,0 +1,15 @@
+<!doctype html>
+<html class="a A">
+ <head>
+  <title>document.getElementsByClassName(): case sensitive</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="a a">
+  <div id="log"></div>
+  <script>test(function() {
+                 assert_array_equals(document.getElementsByClassName("A a"), [document.documentElement])
+               })
+  </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-10.xml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-10.xml
new file mode 100644
index 0000000..bc37504
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-10.xml
@@ -0,0 +1,19 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:g="http://www.w3.org/2000/svg">
+ <head>
+  <title>document.getElementsByClassName(): compound</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+  <div id="log"/>
+  <div id="tests">
+    <x class="a"/>
+    <g:x class="a"/>
+  </div>
+  <script>test(function() {
+                 assert_array_equals(document.getElementsByClassName("a"),
+                                     document.getElementById("tests").children);
+               })
+  </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-11.xml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-11.xml
new file mode 100644
index 0000000..bb0c79b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-11.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:g="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:t="http://tc.labs.opera.com/#test">
+ <head>
+  <title>document.getElementsByClassName(): "tricky" compound</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+  <div id="log" />
+  <div id="tests">
+    <x class="a"/>
+    <g:x class="a"/>
+    <x t:class="a" h:class="a" g:class="a"/>
+    <g:x t:class="a" h:class="a" g:class="a"/>
+    <t:x class="a" t:class="a" h:class="a" g:class="a"/>
+  </div>
+  <script>
+   test(function() {
+          var collection = document.getElementsByClassName("a");
+          var test = document.getElementById("tests").children;
+          assert_array_equals(collection, [test[0], test[1], test[4]]);
+         })
+  </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-12.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-12.htm
new file mode 100644
index 0000000..b4a2eee
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-12.htm
@@ -0,0 +1,15 @@
+<!doctype html>
+<html class="a">
+ <head>
+  <title>element.getElementsByClassName(): simple</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+  <div id="log"></div>
+  <script>test(function() {
+                 assert_array_equals(document.body.getElementsByClassName("a"), [])
+               })
+  </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-13.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-13.htm
new file mode 100644
index 0000000..f5bb76706
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-13.htm
@@ -0,0 +1,19 @@
+<!doctype html>
+<html class="a">
+ <head>
+  <title>element.getElementsByClassName(): adding an element</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+  <div id="log"></div>
+  <script>test(function() {
+                 var collection = document.body.getElementsByClassName("a");
+                 var ele = document.createElement("x-y-z");
+                 ele.className = "a";
+                 document.body.appendChild(ele);
+                 assert_array_equals(collection, [ele]);
+               })
+  </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-14.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-14.htm
new file mode 100644
index 0000000..73c21ea
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-14.htm
@@ -0,0 +1,16 @@
+<!--  quirks mode  -->
+<html class="a A">
+ <head>
+  <title>document.getElementsByClassName(): case-insensitive (quirks mode)</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="a a">
+  <div id="log"></div>
+  <script>test(function() {
+             assert_array_equals(document.getElementsByClassName("A a"),
+                                 [document.documentElement, document.body]);
+          })
+  </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-15.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-15.htm
new file mode 100644
index 0000000..4623931
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-15.htm
@@ -0,0 +1,18 @@
+<!doctype html>
+<html class="a
+b">
+ <head>
+  <title>document.getElementsByClassName(array): "a\n"</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="a
+">
+  <div id="log"></div>
+  <script>test(function () {
+                 assert_array_equals(document.getElementsByClassName(["a\n"]),
+                                    [document.documentElement, document.body]);
+          })
+ </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-16.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-16.htm
new file mode 100644
index 0000000..242a00b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-16.htm
@@ -0,0 +1,16 @@
+<!doctype html>
+<html class="a
+b">
+ <head>
+  <title>document.getElementsByClassName(array): "b","a"</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="b,a">
+  <div id="log"></div>
+  <script>test(function() {
+                 assert_array_equals(document.getElementsByClassName(["b", "a"]), [document.body]);
+               })
+  </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-17.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-17.htm
new file mode 100644
index 0000000..cd7be595
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-17.htm
@@ -0,0 +1,15 @@
+<!doctype html>
+<html>
+ <head>
+  <title>document.getElementsByClassName(array): "b a"</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="a b">
+  <div id="log"></div>
+  <script>test(function() {
+                 assert_array_equals(document.getElementsByClassName(["b a"]), [document.body]);
+          })
+ </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-18.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-18.htm
new file mode 100644
index 0000000..e28e9d40
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-18.htm
@@ -0,0 +1,17 @@
+<!doctype html>
+<html class="a,b">
+ <head>
+  <title>element.getElementsByClassName(array): "a", "b"</title>
+  <script src="../../../../resources/testharness.js"></script>
+  <script src="../../../../resources/testharnessreport.js"></script>
+ </head>
+ <body class="a,b x">
+  <div id="log"></div>
+  <p id="r" class="a,bx"></p>
+  <script class="xa,b">test(function() {
+                             assert_array_equals(document.documentElement.getElementsByClassName(["\fa","b\n"]),
+                                                 [document.body])
+                            })
+  </script>
+ </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-19.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-19.htm
new file mode 100644
index 0000000..f19dad0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-19.htm
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html><head>
+    <title>getElementsByClassName</title>
+    <meta content="get elements in document" name="description">
+    <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+    <script src="../../../../resources/testharness.js"></script>
+    <script src="../../../../resources/testharnessreport.js"></script>
+</head>
+    <body>
+       <div id="log"></div>
+        <div>
+            <div>
+                <a class="text link" href="#foo">test link #foo</a>
+            </div>
+            <b class="text">text</b>
+        </div>
+        <table>
+            <caption class="text caption">text caption</caption>
+            <thead>
+                <tr>
+                    <td class="TEXT head">TEXT head</td>
+                </tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td class="td text1">td text1</td>
+                </tr>
+                <tr>
+                    <td class="td text">td text</td>
+                </tr>
+                <tr>
+                    <td class="td te xt">td te xt</td>
+                </tr>
+            </tbody>
+            <tfoot>
+                <tr>
+                    <td class="TEXT foot">TEXT foot</td>
+                </tr>
+            </tfoot>
+        </table>
+        <div class="xt te">xt te</div>
+
+        <script type="text/javascript">
+    test(function ()
+          {
+           var collection = document.getElementsByClassName("text");
+           assert_equals(collection.length, 4);
+           assert_equals(collection[0].parentNode.nodeName, "DIV");
+           assert_equals(collection[1].parentNode.nodeName, "DIV");
+           assert_equals(collection[2].parentNode.nodeName, "TABLE");
+           assert_equals(collection[3].parentNode.nodeName, "TR");
+          }, "get elements in document");
+        </script>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-20.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-20.htm
new file mode 100644
index 0000000..dec5928
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-20.htm
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html><head>
+        <title>getElementsByClassName</title>
+        <meta content="get elements in document then add element to collection" name="description">
+    <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+    <script src="../../../../resources/testharness.js"></script>
+    <script src="../../../../resources/testharnessreport.js"></script>
+</head>
+    <body>
+        <div id="log"></div>
+        <div>
+            <div>
+                <a class="text link" href="#foo">test link #foo</a>
+            </div>
+            <b class="text">text</b>
+        </div>
+        <table>
+            <caption class="text caption">text caption</caption>
+            <thead>
+                <tr>
+                    <td class="TEXT head">TEXT head</td>
+                </tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td class="td text1">td text1</td>
+                </tr>
+                <tr>
+                    <td class="td text">td text</td>
+                </tr>
+                <tr>
+                    <td class="td te xt">td te xt</td>
+                </tr>
+            </tbody>
+            <tfoot>
+                <tr>
+                    <td class="TEXT foot">TEXT foot</td>
+                </tr>
+            </tfoot>
+        </table>
+        <div class="xt te">xt te</div>
+
+        <script type="text/javascript">
+            test(function()
+            {
+                var collection = document.getElementsByClassName("text");
+                assert_equals(collection.length, 4);
+                var newDiv = document.createElement("div");
+                newDiv.setAttribute("class", "text");
+                newDiv.innerHTML = "text newDiv";
+                document.getElementsByTagName("table")[0].tBodies[0].rows[0].cells[0].appendChild(newDiv);
+
+                assert_equals(collection.length, 5);
+                assert_equals(collection[0].parentNode.nodeName, "DIV");
+                assert_equals(collection[1].parentNode.nodeName, "DIV");
+                assert_equals(collection[2].parentNode.nodeName, "TABLE");
+                assert_equals(collection[3].parentNode.nodeName, "TD");
+                assert_equals(collection[4].parentNode.nodeName, "TR");
+            }, "get elements in document then add element to collection");
+        </script>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-21.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-21.htm
new file mode 100644
index 0000000..5ae6675c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-21.htm
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html><head>
+        <title>getElementsByClassName</title>
+        <meta content="delete element from collection" name="description">
+    <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+    <script src="../../../../resources/testharness.js"></script>
+    <script src="../../../../resources/testharnessreport.js"></script>
+</head>
+    <body>
+        <div id="log"></div>
+        <div>
+            <div>
+                <a class="text link" href="#foo">test link #foo</a>
+            </div>
+            <b class="text">text</b>
+        </div>
+        <table>
+            <caption class="text caption">text caption</caption>
+            <thead>
+                <tr>
+                    <td class="TEXT head">TEXT head</td>
+                </tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td class="td text1">td text1</td>
+                </tr>
+                <tr>
+                    <td class="td text">td text</td>
+                </tr>
+                <tr>
+                    <td class="td te xt">td te xt</td>
+                </tr>
+            </tbody>
+            <tfoot>
+                <tr>
+                    <td class="TEXT foot">TEXT foot</td>
+                </tr>
+            </tfoot>
+        </table>
+        <div class="xt te">xt te</div>
+
+        <script type="text/javascript">
+            test(function()
+            {
+                var collection = document.getElementsByClassName("text1");
+                assert_equals(collection.length, 1)
+                document.getElementsByTagName("table")[0].deleteRow(1);
+                assert_equals(collection.length, 0);
+            }, "delete element from collection");
+        </script>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-22.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-22.htm
new file mode 100644
index 0000000..c4c59272
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-22.htm
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html><head>
+        <title>getElementsByClassName</title>
+        <meta content="move item in collection order" name="description">
+    <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+    <script src="../../../../resources/testharness.js"></script>
+    <script src="../../../../resources/testharnessreport.js"></script>
+</head>
+    <body>
+        <div id="log"></div>
+        <div>
+            <div>
+                <a class="text link" href="#foo">test link #foo</a>
+            </div>
+            <b class="text">text</b>
+        </div>
+        <table>
+            <caption class="text caption">text caption</caption>
+            <thead>
+                <tr>
+                    <td class="TEXT head">TEXT head</td>
+                </tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td class="td text1">td text1</td>
+                </tr>
+                <tr>
+                    <td class="td text">td text</td>
+                </tr>
+                <tr>
+                    <td class="td te xt">td te xt</td>
+                </tr>
+            </tbody>
+            <tfoot>
+                <tr>
+                    <td class="TEXT foot">TEXT foot</td>
+                </tr>
+            </tfoot>
+        </table>
+        <div class="xt te">xt te</div>
+
+        <script type="text/javascript">
+            test(function()
+            {
+                var collection = document.getElementsByClassName("text");
+                assert_equals(collection.length, 4);
+                var boldText = document.getElementsByTagName("b")[0];
+                document.getElementsByTagName("table")[0].tBodies[0].rows[0].cells[0].appendChild(boldText);
+
+                assert_equals(collection.length, 4);
+                assert_equals(collection[0].parentNode.nodeName, "DIV");
+                assert_equals(collection[1].parentNode.nodeName, "TABLE");
+                assert_equals(collection[2].parentNode.nodeName, "TD");
+                assert_equals(collection[3].parentNode.nodeName, "TR");
+            }, "move item in collection order");
+        </script>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-23.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-23.htm
new file mode 100644
index 0000000..f0beb0e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-23.htm
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html><head>
+        <title>getElementsByClassName</title>
+        <meta content="multiple defined classes" name="description">
+    <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+    <script src="../../../../resources/testharness.js"></script>
+    <script src="../../../../resources/testharnessreport.js"></script>
+</head>
+    <body>
+        <div id="log"></div>
+        <div>
+            <div>
+                <a class="text link" href="#foo">test link #foo</a>
+            </div>
+            <b class="text">text</b>
+        </div>
+        <table>
+            <caption class="text caption">text caption</caption>
+            <thead>
+                <tr>
+                    <td class="TEXT head">TEXT head</td>
+                </tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td class="td text1">td text1</td>
+                </tr>
+                <tr>
+                    <td class="td text">td text</td>
+                </tr>
+                <tr>
+                    <td class="td te xt">td te xt</td>
+                </tr>
+            </tbody>
+            <tfoot>
+                <tr>
+                    <td class="TEXT foot">TEXT foot</td>
+                </tr>
+            </tfoot>
+        </table>
+        <div class="xt te">xt te</div>
+
+        <script type="text/javascript">
+            test(function()
+            {
+                var collection = document.getElementsByClassName("te xt");
+                assert_equals(collection.length, 2);
+                assert_equals(collection[0].parentNode.nodeName, "TR");
+                assert_equals(collection[1].parentNode.nodeName, "BODY");
+            }, "multiple defined classes");
+        </script>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-24.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-24.htm
new file mode 100644
index 0000000..740efb1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-24.htm
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+        <meta charset='utf-8'>
+        <title>getElementsByClassName</title>
+        <meta content="handle unicode chars" name="description">
+    <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+    <script src="../../../../resources/testharness.js"></script>
+    <script src="../../../../resources/testharnessreport.js"></script>
+</head>
+    <body>
+        <div id="log"></div>
+        <div>
+            <div>
+                <a class="ΔЙあ叶葉 말 link" href="#foo">ΔЙあ叶葉 말 link</a>
+            </div>
+            <b class="text">text</b>
+        </div>
+        <div class="ΔЙあ叶葉 קم">ΔЙあ叶葉 קم</div>
+
+        <script type="text/javascript">
+            test(function()
+            {
+                var collection = document.getElementsByClassName("ΔЙあ叶葉");
+                assert_equals(collection.length, 2);
+                assert_equals(collection[0].parentNode.nodeName, "DIV");
+                assert_equals(collection[1].parentNode.nodeName, "BODY");
+            }, "handle unicode chars");
+        </script>
+
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-25.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-25.htm
new file mode 100644
index 0000000..9c00ec43
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-25.htm
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html><head>
+        <title>getElementsByClassName</title>
+        <meta content="verify spacing is handled correctly" name="description">
+    <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+    <script src="../../../../resources/testharness.js"></script>
+    <script src="../../../../resources/testharnessreport.js"></script>
+</head>
+    <body>
+        <div id="log"></div>
+         <div>
+            <div>
+                <a class="text link" href="#foo">test link #foo</a>
+            </div>
+            <b class="text">text</b>
+        </div>
+        <table>
+            <caption class="text caption">text caption</caption>
+            <thead>
+                <tr>
+                    <td class="TEXT head">TEXT head</td>
+                </tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td class="td text1">td text1</td>
+                </tr>
+                <tr>
+                    <td class="td text">td text</td>
+                </tr>
+                <tr>
+                    <td class="td te xt">td te xt</td>
+                </tr>
+            </tbody>
+            <tfoot>
+                <tr>
+                    <td class="TEXT foot">TEXT foot</td>
+                </tr>
+            </tfoot>
+        </table>
+        <div class="xt te">xt te</div>
+
+        <script type="text/javascript">
+          test(function()
+          {
+            var collection = document.getElementsByClassName("text ");
+            assert_equals(collection.length, 4);
+            var boldText = document.getElementsByTagName("b")[0];
+            document.getElementsByTagName("table")[0].tBodies[0].rows[0].cells[0].appendChild(boldText);
+            assert_equals(collection.length, 4);
+            assert_equals(collection[0].parentNode.nodeName, "DIV");
+            assert_equals(collection[1].parentNode.nodeName, "TABLE");
+            assert_equals(collection[2].parentNode.nodeName, "TD");
+            assert_equals(collection[3].parentNode.nodeName, "TR");
+          }, "verify spacing is handled correctly");
+        </script>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-26.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-26.htm
new file mode 100644
index 0000000..900b9791
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-26.htm
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+        <title>getElementsByClassName</title>
+        <meta content="multiple class attributes" name="description">
+    <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+    <script src="../../../../resources/testharness.js"></script>
+    <script src="../../../../resources/testharnessreport.js"></script>
+</head>
+    <body>
+       <div id="log"></div>
+         <div class="te xt">
+            te xt
+            <div class="te">
+                te; xt
+                <a class="text link" href="#foo">test link #foo</a>
+            </div>
+            <b class="text">text</b>
+        </div>
+        <div class="xt te">xt te</div>
+         <script type="text/javascript">
+            test(function()
+            {
+                var collection = document.getElementsByClassName("te xt");
+
+                assert_equals(collection.length, 2);
+                assert_equals(collection[0].parentNode.nodeName, "BODY");
+                assert_equals(collection[1].parentNode.nodeName, "BODY");
+            }, "multiple class attributes");
+        </script>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-27.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-27.htm
new file mode 100644
index 0000000..ca5f8a5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-27.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html><head>
+        <title>getElementsByClassName</title>
+        <meta content="generic element listed" name="description">
+    <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+    <script src="../../../../resources/testharness.js"></script>
+    <script src="../../../../resources/testharnessreport.js"></script>
+</head>
+    <body>
+      <div id="log"></div>
+         <div class="te xt">
+            te xt
+            <div class="te">
+                te; xt
+                <a class="text link" href="#foo">test link #foo</a>
+                <foo class="te xt">dummy tag</foo>
+            </div>
+            <b class="text">text</b>
+        </div>
+        <div class="xt te">xt te</div>
+        <script type="text/javascript">
+            test(function()
+            {
+                var collection = document.getElementsByClassName("te xt");
+
+                assert_equals(collection.length, 3);
+                assert_equals(collection[0].parentNode.nodeName, "BODY");
+                assert_equals(collection[1].parentNode.nodeName, "DIV");
+                assert_equals(collection[2].parentNode.nodeName, "BODY");
+            }, "generic element listed");
+        </script>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-28.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-28.htm
new file mode 100644
index 0000000..a0b7ef7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-28.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html><head>
+        <title>getElementsByClassName</title>
+        <meta content="generic element listed" name="description">
+    <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+    <script src="../../../../resources/testharness.js"></script>
+    <script src="../../../../resources/testharnessreport.js"></script>
+</head>
+    <body>
+        <div id="log"></div>
+        <div class="te xt">
+            te xt
+            <div class="te">
+                te; xt
+                <a class="text link" href="#foo">test link #foo</a>
+                <fooU00003Abar class="te xt namespace">te xt namespace
+            </foou00003abar></div>
+            <b class="text">text</b>
+        </div>
+        <div class="xt te">xt te</div>
+        <script type="text/javascript">
+            test(function()
+            {
+                var collection = document.getElementsByClassName("te xt");
+                assert_equals(collection.length, 3);
+                assert_equals(collection[0].parentNode.nodeName, "BODY");
+                assert_equals(collection[1].parentNode.nodeName, "DIV");
+                assert_equals(collection[2].parentNode.nodeName, "BODY");
+            }, "generic element listed");
+        </script>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-29.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-29.htm
new file mode 100644
index 0000000..fbac3f58
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-29.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html><head>
+    <title>getElementsByClassName</title>
+    <meta content="get class from children of element" name="description">
+    <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+    <script src="../../../../resources/testharness.js"></script>
+    <script src="../../../../resources/testharnessreport.js"></script>
+</head>
+    <body>
+        <div id='log'></div>
+        <div>
+            <div>
+                <a class="text link" href="#foo">test link #foo</a>
+            </div>
+            <b class="text">text</b>
+        </div>
+        <table>
+            <caption class="text caption">text caption</caption>
+            <thead>
+                <tr>
+                    <td class="TEXT head">TEXT head</td>
+                </tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td class="td text1">td text1</td>
+                </tr>
+                <tr>
+                    <td class="td text">td text</td>
+                </tr>
+                <tr>
+                    <td class="td te xt">td te xt</td>
+                </tr>
+            </tbody>
+            <tfoot>
+                <tr>
+                    <td class="TEXT foot">TEXT foot</td>
+                </tr>
+            </tfoot>
+        </table>
+        <div class="xt te">xt te</div>
+
+        <script type="text/javascript">
+            test(function()
+            {
+                var collection = document.getElementsByTagName("table")[0].getElementsByClassName("te xt");
+                assert_equals(collection.length, 1);
+                assert_equals(collection[0].parentNode.nodeName, "TR");
+            }, "get class from children of element");
+        </script>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-30.htm b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-30.htm
new file mode 100644
index 0000000..1655126b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/getElementsByClassName-30.htm
@@ -0,0 +1,190 @@
+<!DOCTYPE html>
+<html><head class="foo">
+        <title class="foo">getElementsByClassName</title>
+        <meta class="foo" content="big element listing" name="description">
+        <link class="foo">
+        <base class="foo">
+        <script class="foo"></script>
+        <style class="foo"></style>
+    <script src="../../../../resources/testharness.js"></script>
+    <script src="../../../../resources/testharnessreport.js"></script>
+    <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+</head>
+    <body class="foo">
+    <div id='log'></div>
+        <a class="foo">a</a>
+        <abbr class="foo">abbr</abbr>
+        <acronym class="foo">acronym</acronym>
+        <address class="foo">address</address>
+        <applet class="foo">applet</applet>
+        <b class="foo">b</b>
+        <bdo class="foo">bdo</bdo>
+        <big class="foo">big</big>
+        <blockquote class="foo">blockquote</blockquote>
+        <br class="foo">
+        <button class="foo">button</button>
+        <center class="foo">center</center>
+        <cite class="foo">cite</cite>
+        <code class="foo">code</code>
+        <del class="foo">del</del>
+        <dfn class="foo">dfn</dfn>
+        <dir class="foo">dir
+            <li class="foo">li</li>
+        </dir>
+        <div class="foo">div</div>
+        <dl class="foo">
+            <dt class="foo">
+                </dt><dd class="foo">dd</dd>
+        </dl>
+        <em class="foo">em</em>
+        <font class="foo">font</font>
+        <form class="foo">
+            <label class="foo">label</label>
+            <fieldset class="foo">
+                <legend class="foo">legend</legend>
+            </fieldset>
+        </form>
+        <h1 class="foo">h1</h1>
+        <hr class="foo">
+        <i class="foo">i</i>
+        <iframe class="foo">iframe</iframe>
+        <img class="foo">
+        <input class="foo">
+        <ins class="foo">ins</ins>
+        <kbd class="foo">kbd</kbd>
+        <map class="foo">
+            <area class="foo"></area>
+        </map>
+        <menu class="foo">menu</menu>
+        <noscript class="foo">noscript</noscript>
+        <object class="foo">
+            <param class="foo">
+        </object>
+        <ol class="foo">ol</ol>
+        <p class="foo">p</p>
+        <pre class="foo">pre</pre>
+        <q class="foo">q</q>
+        <s class="foo">s</s>
+        <samp class="foo">samp</samp>
+        <select class="foo">
+            <optgroup class="foo">optgroup</optgroup>
+            <option class="foo">option</option>
+        </select>
+        <small class="foo">small</small>
+        <span class="foo">span</span>
+        <strike class="foo">strike</strike>
+        <strong class="foo">strong</strong>
+        <sub class="foo">sub</sub>
+        <sup class="foo">sup</sup>
+        colgroup<table class="foo">
+            <caption class="foo">caption</caption>
+            <colgroup><col class="foo">
+            </colgroup><colgroup class="foo"></colgroup>
+            <thead class="foo">
+                <tr><th class="foo">th</th>
+            </tr></thead>
+            <tbody class="foo">
+                <tr class="foo">
+                    <td class="foo">td</td>
+                </tr>
+            </tbody>
+            <tfoot class="foo"></tfoot>
+        </table>
+        <textarea class="foo">textarea</textarea>
+        <tt class="foo">tt</tt>
+        <u class="foo">u</u>
+        <ul class="foo">ul</ul>
+        <var class="foo">var</var>
+        <script type="text/javascript">
+    test(function ()
+          {
+           var arrElements = [
+                "HEAD",
+                "TITLE",
+                "META",
+                "LINK",
+                "BASE",
+                "SCRIPT",
+                "STYLE",
+                "BODY",
+                "A",
+                "ABBR",
+                "ACRONYM",
+                "ADDRESS",
+                "APPLET",
+                "B",
+                "BDO",
+                "BIG",
+                "BLOCKQUOTE",
+                "BR",
+                "BUTTON",
+                "CENTER",
+                "CITE",
+                "CODE",
+                "DEL",
+                "DFN",
+                "DIR",
+                "LI",
+                "DIV",
+                "DL",
+                "DT",
+                "DD",
+                "EM",
+                "FONT",
+                "FORM",
+                "LABEL",
+                "FIELDSET",
+                "LEGEND",
+                "H1",
+                "HR",
+                "I",
+                "IFRAME",
+                "IMG",
+                "INPUT",
+                "INS",
+                "KBD",
+                "MAP",
+                "AREA",
+                "MENU",
+                "NOSCRIPT",
+                "OBJECT",
+                "PARAM",
+                "OL",
+                "P",
+                "PRE",
+                "Q",
+                "S",
+                "SAMP",
+                "SELECT",
+                "OPTGROUP",
+                "OPTION",
+                "SMALL",
+                "SPAN",
+                "STRIKE",
+                "STRONG",
+                "SUB",
+                "SUP",
+                "TABLE",
+                "CAPTION",
+                "COL",
+                "COLGROUP",
+                "THEAD",
+                "TH",
+                "TBODY",
+                "TR",
+                "TD",
+                "TFOOT",
+                "TEXTAREA",
+                "TT",
+                "U",
+                "UL",
+                "VAR"];
+
+                var collection = document.getElementsByClassName("foo");
+                for (var x = 0; x < collection.length; x++)
+                {
+                    assert_equals(collection[x].nodeName, arrElements[x]);
+                }
+}, "big element listing");
+        </script>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/mutationobservers.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/mutationobservers.js
new file mode 100644
index 0000000..772f280b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/mutationobservers.js
@@ -0,0 +1,76 @@
+// Compares a mutation record to a predefined one
+// mutationToCheck is a mutation record from the user agent
+// expectedRecord is a mutation record minted by the test
+//    for expectedRecord, if properties are ommitted, they get default ones
+function checkRecords(target, mutationToCheck, expectedRecord) {
+  var mr1;
+  var mr2;
+
+
+  function checkField(property, isArray) {
+    var field = mr2[property];
+    if (isArray === undefined) {
+      isArray = false;
+    }
+    if (field instanceof Function) {
+      field = field();
+    } else if (field === undefined) {
+      if (isArray) {
+        field = new Array();
+      } else {
+        field = null;
+      }
+    }
+    if (isArray) {
+      assert_array_equals(mr1[property], field, property + " didn't match");
+    } else {
+      assert_equals(mr1[property], field, property + " didn't match");
+    }
+  }
+
+  assert_equals(mutationToCheck.length, expectedRecord.length, "mutation records must match");
+  for (var item = 0; item < mutationToCheck.length; item++) {
+    mr1 = mutationToCheck[item];
+    mr2 = expectedRecord[item];
+
+    if (mr2.target instanceof Function) {
+      assert_equals(mr1.target, mr2.target(), "target node must match");
+    } else if (mr2.target !== undefined) {
+      assert_equals(mr1.target, mr2.target, "target node must match");
+    } else {
+      assert_equals(mr1.target, target, "target node must match");
+    }
+
+    checkField("type");
+    checkField("addedNodes", true);
+    checkField("removedNodes", true);
+    checkField("previousSibling");
+    checkField("nextSibling");
+    checkField("attributeName");
+    checkField("attributeNamespace");
+    checkField("oldValue");
+  };
+}
+
+function runMutationTest(node, mutationObserverOptions, mutationRecordSequence, mutationFunction, description, target) {
+  var test = async_test(description);
+
+
+  function moc(mrl, obs) {
+    test.step(
+      function () {
+            if (target === undefined) target = node;
+            checkRecords(target, mrl, mutationRecordSequence);
+        test.done();
+      }
+     );
+  }
+
+  test.step(
+    function () {
+      (new MutationObserver(moc)).observe(node, mutationObserverOptions);
+      mutationFunction();
+    }
+  );
+  return mutationRecordSequence.length
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/prepend-on-Document-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/prepend-on-Document-expected.txt
new file mode 100644
index 0000000..39e18e34
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/prepend-on-Document-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+FAIL Document.prepend() without any argument, on a Document having no child. parent.prepend is not a function
+FAIL Document.prepend() with only one element as an argument, on a Document having no child. parent.prepend is not a function
+FAIL Document.append() with only one element as an argument, on a Document having one child. assert_throws: function "function () { parent.prepend(y); }" threw object "TypeError: parent.prepend is not a function" that is not a DOMException HierarchyRequestError: property "code" is equal to undefined, expected 3
+FAIL Document.prepend() with text as an argument, on a Document having no child. assert_throws: function "function () { parent.prepend('text'); }" threw object "TypeError: parent.prepend is not a function" that is not a DOMException HierarchyRequestError: property "code" is equal to undefined, expected 3
+FAIL Document.prepend() with two elements as the argument, on a Document having no child. assert_throws: function "function () { parent.prepend(x, y); }" threw object "TypeError: parent.prepend is not a function" that is not a DOMException HierarchyRequestError: property "code" is equal to undefined, expected 3
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/prepend-on-Document.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/prepend-on-Document.html
new file mode 100644
index 0000000..8c725e1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/prepend-on-Document.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>DocumentType.prepend</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-parentnode-prepend">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script>
+
+function test_prepend_on_Document() {
+
+    var node = document.implementation.createDocument(null, null);
+    test(function() {
+        var parent = node.cloneNode();
+        parent.prepend();
+        assert_array_equals(parent.childNodes, []);
+    }, 'Document.prepend() without any argument, on a Document having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        var x = document.createElement('x');
+        parent.prepend(x);
+        assert_array_equals(parent.childNodes, [x]);
+    }, 'Document.prepend() with only one element as an argument, on a Document having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        parent.appendChild(x);
+        assert_throws('HierarchyRequestError', function() { parent.prepend(y); });
+        assert_array_equals(parent.childNodes, [x]);
+    }, 'Document.append() with only one element as an argument, on a Document having one child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        assert_throws('HierarchyRequestError', function() { parent.prepend('text'); });
+        assert_array_equals(parent.childNodes, []);
+    }, 'Document.prepend() with text as an argument, on a Document having no child.');
+
+    test(function() {
+        var parent = node.cloneNode();
+        var x = document.createElement('x');
+        var y = document.createElement('y');
+        assert_throws('HierarchyRequestError', function() { parent.prepend(x, y); });
+        assert_array_equals(parent.childNodes, []);
+    }, 'Document.prepend() with two elements as the argument, on a Document having no child.');
+
+}
+
+test_prepend_on_Document();
+
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/productions.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/productions.js
new file mode 100644
index 0000000..2b99590
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/productions.js
@@ -0,0 +1,3 @@
+var invalid_names = ["", "invalid^Name", "\\", "'", '"', "0", "0:a"] // XXX
+var valid_names = ["x", ":", "a:0"]
+var invalid_qnames = [":a", "b:", "x:y:z"] // XXX
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/selectors.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/selectors.js
new file mode 100644
index 0000000..c3e2d909
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/selectors.js
@@ -0,0 +1,717 @@
+// Bit-mapped flags to indicate which tests the selector is suitable for
+var TEST_QSA              = 0x01; // querySelector() and querySelectorAll() tests
+var TEST_FIND             = 0x04; // find() and findAll() tests, may be unsuitable for querySelector[All]
+var TEST_MATCH            = 0x10; // matches() tests
+
+/*
+ * All of these invalid selectors should result in a SyntaxError being thrown by the APIs.
+ *
+ *   name:     A descriptive name of the selector being tested
+ *   selector: The selector to test
+ */
+var invalidSelectors = [
+  {name: "Empty String",                 selector: ""},
+  {name: "Invalid character",            selector: "["},
+  {name: "Invalid character",            selector: "]"},
+  {name: "Invalid character",            selector: "("},
+  {name: "Invalid character",            selector: ")"},
+  {name: "Invalid character",            selector: "{"},
+  {name: "Invalid character",            selector: "}"},
+  {name: "Invalid character",            selector: "<"},
+  {name: "Invalid character",            selector: ">"},
+  {name: "Invalid ID",                   selector: "#"},
+  {name: "Invalid group of selectors",   selector: "div,"},
+  {name: "Invalid class",                selector: "."},
+  {name: "Invalid class",                selector: ".5cm"},
+  {name: "Invalid class",                selector: "..test"},
+  {name: "Invalid class",                selector: ".foo..quux"},
+  {name: "Invalid class",                selector: ".bar."},
+  {name: "Invalid combinator",           selector: "div & address, p"},
+  {name: "Invalid combinator",           selector: "div >> address, p"},
+  {name: "Invalid combinator",           selector: "div ++ address, p"},
+  {name: "Invalid combinator",           selector: "div ~~ address, p"},
+  {name: "Invalid [att=value] selector", selector: "[*=test]"},
+  {name: "Invalid [att=value] selector", selector: "[*|*=test]"},
+  {name: "Invalid [att=value] selector", selector: "[class= space unquoted ]"},
+  {name: "Unknown pseudo-class",         selector: "div:example"},
+  {name: "Unknown pseudo-class",         selector: ":example"},
+  {name: "Unknown pseudo-element",       selector: "div::example"},
+  {name: "Unknown pseudo-element",       selector: "::example"},
+  {name: "Invalid pseudo-element",       selector: ":::before"},
+  {name: "Undeclared namespace",         selector: "ns|div"},
+  {name: "Undeclared namespace",         selector: ":not(ns|div)"},
+  {name: "Invalid namespace",            selector: "^|div"},
+  {name: "Invalid namespace",            selector: "$|div"}
+];
+
+/*
+ * All of these should be valid selectors, expected to match zero or more elements in the document.
+ * None should throw any errors.
+ *
+ *   name:     A descriptive name of the selector being tested
+ *   selector: The selector to test
+ *   expect:   A list of IDs of the elements expected to be matched. List must be given in tree order.
+ *   exclude:  An array of contexts to exclude from testing. The valid values are:
+ *             ["document", "element", "fragment", "detached", "html", "xhtml"]
+ *             The "html" and "xhtml" values represent the type of document being queried. These are useful
+ *             for tests that are affected by differences between HTML and XML, such as case sensitivity.
+ *   level:    An integer indicating the CSS or Selectors level in which the selector being tested was introduced.
+ *   testType: A bit-mapped flag indicating the type of test.
+ *
+ * Note: Interactive pseudo-classes (:active :hover and :focus) have not been tested in this test suite.
+ */
+var validSelectors = [
+  // Type Selector
+  {name: "Type selector, matching html element", selector: "html", expect: ["html"],          exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Type selector, matching html element", selector: "html", expect: [] /*no matches*/, exclude: ["document"],                        level: 1, testType: TEST_QSA},
+  {name: "Type selector, matching body element", selector: "body", expect: ["body"],          exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Type selector, matching body element", selector: "body", expect: [] /*no matches*/, exclude: ["document"],                        level: 1, testType: TEST_QSA},
+
+  // Universal Selector
+  // Testing "*" for entire an entire context node is handled separately.
+  {name: "Universal selector, matching all children of element with specified ID",       selector: "#universal>*",   expect: ["universal-p1", "universal-hr1", "universal-pre1", "universal-p2", "universal-address1"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Universal selector, matching all grandchildren of element with specified ID",  selector: "#universal>*>*", expect: ["universal-code1", "universal-span1", "universal-a1", "universal-code2"],                 level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Universal selector, matching all children of empty element with specified ID", selector: "#empty>*",       expect: [] /*no matches*/,                                                                         level: 2, testType: TEST_QSA},
+  {name: "Universal selector, matching all descendants of element with specified ID",    selector: "#universal *",   expect: ["universal-p1", "universal-code1", "universal-hr1", "universal-pre1", "universal-span1", "universal-p2", "universal-a1", "universal-address1", "universal-code2", "universal-a2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+
+  // Attribute Selectors
+  // - presence                  [att]
+  {name: "Attribute presence selector, matching align attribute with value",                    selector: ".attr-presence-div1[align]",                             expect: ["attr-presence-div1"],                                             level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute presence selector, matching align attribute with empty value",              selector: ".attr-presence-div2[align]",                             expect: ["attr-presence-div2"],                                             level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute presence selector, matching title attribute, case insensitivity",           selector: "#attr-presence [TiTlE]",                                 expect: ["attr-presence-a1", "attr-presence-span1"], exclude: ["xhtml"],    level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute presence selector, not matching title attribute, case sensitivity",         selector: "#attr-presence [TiTlE]",                                 expect: [],                                          exclude: ["html"],     level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute presence selector, matching custom data-* attribute",                       selector: "[data-attr-presence]",                                   expect: ["attr-presence-pre1", "attr-presence-blockquote1"],                level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute presence selector, not matching attribute with similar name",               selector: ".attr-presence-div3[align], .attr-presence-div4[align]", expect: [] /*no matches*/,                                                  level: 2, testType: TEST_QSA},
+  {name: "Attribute presence selector, matching attribute with non-ASCII characters",           selector: "ul[data-中文]",                                            expect: ["attr-presence-ul1"],                                              level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute presence selector, not matching default option without selected attribute", selector: "#attr-presence-select1 option[selected]",                expect: [] /* no matches */,                                                level: 2, testType: TEST_QSA},
+  {name: "Attribute presence selector, matching option with selected attribute",                selector: "#attr-presence-select2 option[selected]",                expect: ["attr-presence-select2-option4"],                                  level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute presence selector, matching multiple options with selected attributes",     selector: "#attr-presence-select3 option[selected]",                expect: ["attr-presence-select3-option2", "attr-presence-select3-option3"], level: 2, testType: TEST_QSA | TEST_MATCH},
+
+  // - value                     [att=val]
+  {name: "Attribute value selector, matching align attribute with value",                                    selector: "#attr-value [align=\"center\"]",                                     expect: ["attr-value-div1"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute value selector, matching align attribute with empty value",                              selector: "#attr-value [align=\"\"]",                                           expect: ["attr-value-div2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute value selector, not matching align attribute with partial value",                        selector: "#attr-value [align=\"c\"]",                                          expect: [] /*no matches*/,   level: 2, testType: TEST_QSA},
+  {name: "Attribute value selector, not matching align attribute with incorrect value",                      selector: "#attr-value [align=\"centera\"]",                                    expect: [] /*no matches*/,   level: 2, testType: TEST_QSA},
+  {name: "Attribute value selector, matching custom data-* attribute with unicode escaped value",            selector: "[data-attr-value=\"\\e9\"]",                                         expect: ["attr-value-div3"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute value selector, matching custom data-* attribute with escaped character",                selector: "[data-attr-value\_foo=\"\\e9\"]",                                    expect: ["attr-value-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute value selector with single-quoted value, matching multiple inputs with type attributes", selector: "#attr-value input[type='hidden'],#attr-value input[type='radio']",   expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute value selector with double-quoted value, matching multiple inputs with type attributes", selector: "#attr-value input[type=\"hidden\"],#attr-value input[type='radio']", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute value selector with unquoted value, matching multiple inputs with type attributes",      selector: "#attr-value input[type=hidden],#attr-value input[type=radio]",       expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute value selector, matching attribute with value using non-ASCII characters",               selector: "[data-attr-value=中文]",                                               expect: ["attr-value-div5"], level: 2, testType: TEST_QSA | TEST_MATCH},
+
+  // - whitespace-separated list [att~=val]
+  {name: "Attribute whitespace-separated list selector, matching class attribute with value",                                  selector: "#attr-whitespace [class~=\"div1\"]",                                        expect: ["attr-whitespace-div1"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute whitespace-separated list selector, not matching class attribute with empty value",                        selector: "#attr-whitespace [class~=\"\"]",                                            expect: [] /*no matches*/ ,       level: 2, testType: TEST_QSA},
+  {name: "Attribute whitespace-separated list selector, not matching class attribute with partial value",                      selector: "[data-attr-whitespace~=\"div\"]",                                           expect: [] /*no matches*/ ,       level: 2, testType: TEST_QSA},
+  {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value",          selector: "[data-attr-whitespace~=\"\\0000e9\"]",                                      expect: ["attr-whitespace-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character",              selector: "[data-attr-whitespace\_foo~=\"\\e9\"]",                                     expect: ["attr-whitespace-div5"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes", selector: "#attr-whitespace a[rel~='bookmark'],  #attr-whitespace a[rel~='nofollow']", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes", selector: "#attr-whitespace a[rel~=\"bookmark\"],#attr-whitespace a[rel~='nofollow']", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes",      selector: "#attr-whitespace a[rel~=bookmark],    #attr-whitespace a[rel~=nofollow]",   expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute whitespace-separated list selector with double-quoted value, not matching value with space",               selector: "#attr-whitespace a[rel~=\"book mark\"]",                                    expect: [] /* no matches */,      level: 2, testType: TEST_QSA},
+  {name: "Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters",       selector: "#attr-whitespace [title~=中文]",                                              expect: ["attr-whitespace-p1"],   level: 2, testType: TEST_QSA | TEST_MATCH},
+
+  // - hyphen-separated list     [att|=val]
+  {name: "Attribute hyphen-separated list selector, not matching unspecified lang attribute",    selector: "#attr-hyphen-div1[lang|=\"en\"]",    expect: [] /*no matches*/,    level: 2, testType: TEST_QSA},
+  {name: "Attribute hyphen-separated list selector, matching lang attribute with exact value",   selector: "#attr-hyphen-div2[lang|=\"fr\"]",    expect: ["attr-hyphen-div2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute hyphen-separated list selector, matching lang attribute with partial value", selector: "#attr-hyphen-div3[lang|=\"en\"]",    expect: ["attr-hyphen-div3"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute hyphen-separated list selector, not matching incorrect value",               selector: "#attr-hyphen-div4[lang|=\"es-AR\"]", expect: [] /*no matches*/,    level: 2, testType: TEST_QSA},
+
+  // - substring begins-with     [att^=val] (Level 3)
+  {name: "Attribute begins with selector, matching href attributes beginning with specified substring",                             selector: "#attr-begins a[href^=\"http://www\"]", expect: ["attr-begins-a1", "attr-begins-a3"],     level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute begins with selector, matching lang attributes beginning with specified substring, ",                           selector: "#attr-begins [lang^=\"en-\"]",         expect: ["attr-begins-div2", "attr-begins-div4"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute begins with selector, not matching class attribute not beginning with specified substring",                     selector: "#attr-begins [class^=apple]",          expect: [] /*no matches*/,                        level: 3, testType: TEST_QSA},
+  {name: "Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring",    selector: "#attr-begins [class^=' apple']",       expect: ["attr-begins-p1"],                       level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring",    selector: "#attr-begins [class^=\" apple\"]",     expect: ["attr-begins-p1"],                       level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring", selector: "#attr-begins [class^= apple]",         expect: [] /*no matches*/,                        level: 3, testType: TEST_QSA},
+
+  // - substring ends-with       [att$=val] (Level 3)
+  {name: "Attribute ends with selector, matching href attributes ending with specified substring",                             selector: "#attr-ends a[href$=\".org\"]",   expect: ["attr-ends-a1", "attr-ends-a3"],     level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute ends with selector, matching lang attributes ending with specified substring, ",                           selector: "#attr-ends [lang$=\"-CH\"]",     expect: ["attr-ends-div2", "attr-ends-div4"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute ends with selector, not matching class attribute not ending with specified substring",                     selector: "#attr-ends [class$=apple]",      expect: [] /*no matches*/,                    level: 3, testType: TEST_QSA},
+  {name: "Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring",    selector: "#attr-ends [class$='apple ']",   expect: ["attr-ends-p1"],                     level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring",    selector: "#attr-ends [class$=\"apple \"]", expect: ["attr-ends-p1"],                     level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring", selector: "#attr-ends [class$=apple ]",     expect: [] /*no matches*/,                    level: 3, testType: TEST_QSA},
+
+  // - substring contains        [att*=val] (Level 3)
+  {name: "Attribute contains selector, matching href attributes beginning with specified substring",                          selector: "#attr-contains a[href*=\"http://www\"]",     expect: ["attr-contains-a1", "attr-contains-a3"],     level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute contains selector, matching href attributes ending with specified substring",                             selector: "#attr-contains a[href*=\".org\"]",           expect: ["attr-contains-a1", "attr-contains-a2"],     level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute contains selector, matching href attributes containing specified substring",                              selector: "#attr-contains a[href*=\".example.\"]",      expect: ["attr-contains-a1", "attr-contains-a3"],     level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute contains selector, matching lang attributes beginning with specified substring, ",                        selector: "#attr-contains [lang*=\"en-\"]",             expect: ["attr-contains-div2", "attr-contains-div6"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute contains selector, matching lang attributes ending with specified substring, ",                           selector: "#attr-contains [lang*=\"-CH\"]",             expect: ["attr-contains-div3", "attr-contains-div5"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring", selector: "#attr-contains [class*=' apple']",           expect: ["attr-contains-p1"],                         level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute contains selector with single-quoted value, matching class attribute ending with specified substring",    selector: "#attr-contains [class*='orange ']",          expect: ["attr-contains-p1"],                         level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute contains selector with single-quoted value, matching class attribute containing specified substring",     selector: "#attr-contains [class*='ple banana ora']",   expect: ["attr-contains-p1"],                         level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring", selector: "#attr-contains [class*=\" apple\"]",         expect: ["attr-contains-p1"],                         level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute contains selector with double-quoted value, matching class attribute ending with specified substring",    selector: "#attr-contains [class*=\"orange \"]",        expect: ["attr-contains-p1"],                         level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute contains selector with double-quoted value, matching class attribute containing specified substring",     selector: "#attr-contains [class*=\"ple banana ora\"]", expect: ["attr-contains-p1"],                         level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute contains selector with unquoted value, matching class attribute beginning with specified substring",      selector: "#attr-contains [class*= apple]",             expect: ["attr-contains-p1"],                         level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute contains selector with unquoted value, matching class attribute ending with specified substring",         selector: "#attr-contains [class*=orange ]",            expect: ["attr-contains-p1"],                         level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "Attribute contains selector with unquoted value, matching class attribute containing specified substring",          selector: "#attr-contains [class*= banana ]",           expect: ["attr-contains-p1"],                         level: 3, testType: TEST_QSA | TEST_MATCH},
+
+  // Pseudo-classes
+  // - :root                 (Level 3)
+  {name: ":root pseudo-class selector, matching document root element",      selector: ":root", expect: ["html"],          exclude: ["element", "fragment", "detached"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":root pseudo-class selector, not matching document root element",  selector: ":root", expect: [] /*no matches*/, exclude: ["document"],                        level: 3, testType: TEST_QSA},
+
+  // - :nth-child(n)         (Level 3)
+  // XXX write descriptions
+  {name: ":nth-child selector, matching the third child element",                              selector: "#pseudo-nth-table1 :nth-child(3)", expect: ["pseudo-nth-td3", "pseudo-nth-td9", "pseudo-nth-tr3", "pseudo-nth-td15"],                    level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":nth-child selector, matching every third child element",                            selector: "#pseudo-nth li:nth-child(3n)",     expect: ["pseudo-nth-li3", "pseudo-nth-li6", "pseudo-nth-li9", "pseudo-nth-li12"],                    level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":nth-child selector, matching every second child element, starting from the fourth", selector: "#pseudo-nth li:nth-child(2n+4)",   expect: ["pseudo-nth-li4", "pseudo-nth-li6", "pseudo-nth-li8", "pseudo-nth-li10", "pseudo-nth-li12"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":nth-child selector, matching every fourth child element, starting from the third",  selector: "#pseudo-nth-p1 :nth-child(4n-1)",  expect: ["pseudo-nth-em2", "pseudo-nth-span3"],                                                       level: 3, testType: TEST_QSA | TEST_MATCH},
+
+  // - :nth-last-child       (Level 3)
+  {name: ":nth-last-child selector, matching the third last child element",                                           selector: "#pseudo-nth-table1 :nth-last-child(3)", expect: ["pseudo-nth-tr1", "pseudo-nth-td4", "pseudo-nth-td10", "pseudo-nth-td16"],                 level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":nth-last-child selector, matching every third child element from the end",                                 selector: "#pseudo-nth li:nth-last-child(3n)",     expect: ["pseudo-nth-li1", "pseudo-nth-li4", "pseudo-nth-li7", "pseudo-nth-li10"],                  level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":nth-last-child selector, matching every second child element from the end, starting from the fourth last", selector: "#pseudo-nth li:nth-last-child(2n+4)",   expect: ["pseudo-nth-li1", "pseudo-nth-li3", "pseudo-nth-li5", "pseudo-nth-li7", "pseudo-nth-li9"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":nth-last-child selector, matching every fourth element from the end, starting from the third last",        selector: "#pseudo-nth-p1 :nth-last-child(4n-1)",  expect: ["pseudo-nth-span2", "pseudo-nth-span4"],                                                   level: 3, testType: TEST_QSA | TEST_MATCH},
+
+  // - :nth-of-type(n)       (Level 3)
+  {name: ":nth-of-type selector, matching the third em element",                                        selector: "#pseudo-nth-p1 em:nth-of-type(3)",      expect: ["pseudo-nth-em3"],                                                                                 level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":nth-of-type selector, matching every second element of their type",                          selector: "#pseudo-nth-p1 :nth-of-type(2n)",       expect: ["pseudo-nth-em2", "pseudo-nth-span2", "pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":nth-of-type selector, matching every second elemetn of their type, starting from the first", selector: "#pseudo-nth-p1 span:nth-of-type(2n-1)", expect: ["pseudo-nth-span1", "pseudo-nth-span3"],                                                           level: 3, testType: TEST_QSA | TEST_MATCH},
+
+  // - :nth-last-of-type(n)  (Level 3)
+  {name: ":nth-last-of-type selector, matching the thrid last em element", selector: "#pseudo-nth-p1 em:nth-last-of-type(3)",      expect: ["pseudo-nth-em2"],                                                                                 level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":nth-last-of-type selector, matching every second last element of their type", selector: "#pseudo-nth-p1 :nth-last-of-type(2n)",       expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1", "pseudo-nth-em3", "pseudo-nth-span3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":nth-last-of-type selector, matching every second last element of their type, starting from the last", selector: "#pseudo-nth-p1 span:nth-last-of-type(2n-1)", expect: ["pseudo-nth-span2", "pseudo-nth-span4"],                                                           level: 3, testType: TEST_QSA | TEST_MATCH},
+
+  // - :first-of-type        (Level 3)
+  {name: ":first-of-type selector, matching the first em element", selector: "#pseudo-nth-p1 em:first-of-type",      expect: ["pseudo-nth-em1"],                                           level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":first-of-type selector, matching the first of every type of element", selector: "#pseudo-nth-p1 :first-of-type",        expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":first-of-type selector, matching the first td element in each table row", selector: "#pseudo-nth-table1 tr :first-of-type", expect: ["pseudo-nth-td1", "pseudo-nth-td7", "pseudo-nth-td13"],      level: 3, testType: TEST_QSA | TEST_MATCH},
+
+  // - :last-of-type         (Level 3)
+  {name: ":last-of-type selector, matching the last em elemnet", selector: "#pseudo-nth-p1 em:last-of-type",      expect: ["pseudo-nth-em4"],                                           level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":last-of-type selector, matching the last of every type of element", selector: "#pseudo-nth-p1 :last-of-type",        expect: ["pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":last-of-type selector, matching the last td element in each table row", selector: "#pseudo-nth-table1 tr :last-of-type", expect: ["pseudo-nth-td6", "pseudo-nth-td12", "pseudo-nth-td18"],     level: 3, testType: TEST_QSA | TEST_MATCH},
+
+  // - :first-child
+  {name: ":first-child pseudo-class selector, matching first child div element",          selector: "#pseudo-first-child div:first-child",                                        expect: ["pseudo-first-child-div1"],                                                          level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: ":first-child pseudo-class selector, doesn't match non-first-child elements",    selector: ".pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child", expect: [] /*no matches*/,                                                                    level: 2, testType: TEST_QSA},
+  {name: ":first-child pseudo-class selector, matching first-child of multiple elements", selector: "#pseudo-first-child span:first-child",                                       expect: ["pseudo-first-child-span1", "pseudo-first-child-span3", "pseudo-first-child-span5"], level: 2, testType: TEST_QSA | TEST_MATCH},
+
+  // - :last-child           (Level 3)
+  {name: ":last-child pseudo-class selector, matching last child div element",           selector: "#pseudo-last-child div:last-child",                                       expect: ["pseudo-last-child-div3"],                                                        level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":last-child pseudo-class selector, doesn't match non-last-child elements",     selector: ".pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child", expect: [] /*no matches*/,                                                                 level: 3, testType: TEST_QSA},
+  {name: ":last-child pseudo-class selector, matching first-child of multiple elements", selector: "#pseudo-last-child span:last-child",                                      expect: ["pseudo-last-child-span2", "pseudo-last-child-span4", "pseudo-last-child-span6"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+  // - :only-child           (Level 3)
+  {name: ":pseudo-only-child pseudo-class selector, matching all only-child elements", selector: "#pseudo-only :only-child", expect: ["pseudo-only-span1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":pseudo-only-child pseudo-class selector, matching only-child em elements",  selector: "#pseudo-only em:only-child", expect: [] /*no matches*/,   level: 3, testType: TEST_QSA},
+
+  // - :only-of-type         (Level 3)
+  {name: ":pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type", selector: "#pseudo-only :only-of-type", expect: ["pseudo-only-span1", "pseudo-only-em1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type",  selector: "#pseudo-only em:only-of-type", expect: ["pseudo-only-em1"],                    level: 3, testType: TEST_QSA | TEST_MATCH},
+
+  // - :empty                (Level 3)
+  {name: ":empty pseudo-class selector, matching empty p elements",   selector: "#pseudo-empty p:empty", expect: ["pseudo-empty-p1", "pseudo-empty-p2"],                       level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":empty pseudo-class selector, matching all empty elements", selector: "#pseudo-empty :empty",  expect: ["pseudo-empty-p1", "pseudo-empty-p2", "pseudo-empty-span1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+  // - :link and :visited
+  // Implementations may treat all visited links as unvisited, so these cannot be tested separately.
+  // The only guarantee is that ":link,:visited" matches the set of all visited and unvisited links and that they are individually mutually exclusive sets.
+  {name: ":link and :visited pseudo-class selectors, matching a and area elements with href attributes",        selector: "#pseudo-link :link, #pseudo-link :visited", expect: ["pseudo-link-a1", "pseudo-link-a2", "pseudo-link-area1"],                                level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: ":link and :visited pseudo-class selectors, matching link elements with href attributes",              selector: "#head :link, #head :visited",               expect: ["pseudo-link-link1", "pseudo-link-link2"], exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: ":link and :visited pseudo-class selectors, not matching link elements with href attributes",          selector: "#head :link, #head :visited",               expect: [] /*no matches*/,                          exclude: ["document"],                        level: 1, testType: TEST_QSA},
+  {name: ":link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing", selector: ":link:visited",                             expect: [] /*no matches*/,                          exclude: ["document"],                        level: 1, testType: TEST_QSA},
+
+  // - :target               (Level 3)
+  {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", expect: [] /*no matches*/, exclude: ["document", "element"],  level: 3, testType: TEST_QSA},
+  {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", expect: ["target"],        exclude: ["fragment", "detached"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+  // - :lang()
+  {name: ":lang pseudo-class selector, matching inherited language",                     selector: "#pseudo-lang-div1:lang(en)",    expect: ["pseudo-lang-div1"], exclude: ["detached", "fragment"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: ":lang pseudo-class selector, not matching element with no inherited language", selector: "#pseudo-lang-div1:lang(en)",    expect: [] /*no matches*/,    exclude: ["document", "element"],  level: 2, testType: TEST_QSA},
+  {name: ":lang pseudo-class selector, matching specified language with exact value",    selector: "#pseudo-lang-div2:lang(fr)",    expect: ["pseudo-lang-div2"],                                    level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: ":lang pseudo-class selector, matching specified language with partial value",  selector: "#pseudo-lang-div3:lang(en)",    expect: ["pseudo-lang-div3"],                                    level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: ":lang pseudo-class selector, not matching incorrect language",                 selector: "#pseudo-lang-div4:lang(es-AR)", expect: [] /*no matches*/,                                       level: 2, testType: TEST_QSA},
+
+  // - :enabled              (Level 3)
+  {name: ":enabled pseudo-class selector, matching all enabled form controls",  selector: "#pseudo-ui :enabled",  expect: ["pseudo-ui-input1", "pseudo-ui-input2", "pseudo-ui-input3", "pseudo-ui-input4", "pseudo-ui-input5", "pseudo-ui-input6",
+                                                                                                                           "pseudo-ui-input7", "pseudo-ui-input8", "pseudo-ui-input9", "pseudo-ui-textarea1", "pseudo-ui-button1"],    level: 3, testType: TEST_QSA | TEST_MATCH},
+
+  // - :disabled             (Level 3)
+  {name: ":enabled pseudo-class selector, matching all disabled form controls", selector: "#pseudo-ui :disabled", expect: ["pseudo-ui-input10", "pseudo-ui-input11", "pseudo-ui-input12", "pseudo-ui-input13", "pseudo-ui-input14", "pseudo-ui-input15",
+                                                                                                                           "pseudo-ui-input16", "pseudo-ui-input17", "pseudo-ui-input18", "pseudo-ui-textarea2", "pseudo-ui-button2"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+  // - :checked              (Level 3)
+  {name: ":checked pseudo-class selector, matching checked radio buttons and checkboxes", selector: "#pseudo-ui :checked", expect: ["pseudo-ui-input4", "pseudo-ui-input6", "pseudo-ui-input13", "pseudo-ui-input15"],  level: 3, testType: TEST_QSA | TEST_MATCH},
+
+  // - :not(s)               (Level 3)
+  {name: ":not pseudo-class selector, matching ", selector: "#not>:not(div)",   expect: ["not-p1", "not-p2", "not-p3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":not pseudo-class selector, matching ", selector: "#not * :not(:first-child)",   expect: ["not-em1", "not-em2", "not-em3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: ":not pseudo-class selector, matching nothing", selector: ":not(*)",   expect: [] /* no matches */, level: 3, testType: TEST_QSA},
+  {name: ":not pseudo-class selector, matching nothing", selector: ":not(*|*)", expect: [] /* no matches */, level: 3, testType: TEST_QSA},
+
+  // Pseudo-elements
+  // - ::first-line
+  {name: ":first-line pseudo-element (one-colon syntax) selector, not matching any elements",    selector: "#pseudo-element:first-line",    expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+  {name: "::first-line pseudo-element (two-colon syntax) selector, not matching any elements",   selector: "#pseudo-element::first-line",   expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+
+  // - ::first-letter
+  {name: ":first-letter pseudo-element (one-colon syntax) selector, not matching any elements",  selector: "#pseudo-element:first-letter",  expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+  {name: "::first-letter pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::first-letter", expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+
+  // - ::before
+  {name: ":before pseudo-element (one-colon syntax) selector, not matching any elements",        selector: "#pseudo-element:before",        expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+  {name: "::before pseudo-element (two-colon syntax) selector, not matching any elements",       selector: "#pseudo-element::before",       expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+
+  // - ::after
+  {name: ":after pseudo-element (one-colon syntax) selector, not matching any elements",         selector: "#pseudo-element:after",         expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+  {name: "::after pseudo-element (two-colon syntax) selector, not matching any elements",        selector: "#pseudo-element::after",        expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+
+  // Class Selectors
+  {name: "Class selector, matching element with specified class",                                           selector: ".class-p",                expect: ["class-p1","class-p2", "class-p3"],                                              level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Class selector, chained, matching only elements with all specified classes",                      selector: "#class .apple.orange.banana",    expect: ["class-div1", "class-div2", "class-p4", "class-div3", "class-p6", "class-div4"], level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Class Selector, chained, with type selector",                                                     selector: "div.apple.banana.orange", expect: ["class-div1", "class-div2", "class-div3", "class-div4"],                         level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Class selector, matching element with class value using non-ASCII characters (1)",                selector: ".\u53F0\u5317Ta\u0301ibe\u030Ci",             expect: ["class-span1"],               level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Class selector, matching multiple elements with class value using non-ASCII characters",          selector: ".\u53F0\u5317",                     expect: ["class-span1","class-span2"], level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Class selector, chained, matching element with multiple class values using non-ASCII characters (1)", selector: ".\u53F0\u5317Ta\u0301ibe\u030Ci.\u53F0\u5317",          expect: ["class-span1"],               level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Class selector, matching element with class with escaped character",                              selector: ".foo\\:bar",              expect: ["class-span3"],               level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Class selector, matching element with class with escaped character",                              selector: ".test\\.foo\\[5\\]bar",   expect: ["class-span4"],               level: 1, testType: TEST_QSA | TEST_MATCH},
+
+  // ID Selectors
+  {name: "ID selector, matching element with specified id",           selector: "#id #id-div1",              expect: ["id-div1"],            level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "ID selector, chained, matching element with specified id",  selector: "#id-div1, #id-div1",        expect: ["id-div1"],            level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "ID selector, chained, matching element with specified id",  selector: "#id-div1, #id-div2",        expect: ["id-div1", "id-div2"], level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "ID Selector, chained, with type selector",                  selector: "div#id-div1, div#id-div2",  expect: ["id-div1", "id-div2"], level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "ID selector, not matching non-existent descendant",         selector: "#id #none",                 expect: [] /*no matches*/,      level: 1, testType: TEST_QSA},
+  {name: "ID selector, not matching non-existent ancestor",           selector: "#none #id-div1",            expect: [] /*no matches*/,      level: 1, testType: TEST_QSA},
+  {name: "ID selector, matching multiple elements with duplicate id", selector: "#id-li-duplicate",          expect: ["id-li-duplicate", "id-li-duplicate", "id-li-duplicate", "id-li-duplicate"], level: 1, testType: TEST_QSA | TEST_MATCH},
+
+  {name: "ID selector, matching id value using non-ASCII characters (1)",    selector: "#\u53F0\u5317Ta\u0301ibe\u030Ci",           expect: ["\u53F0\u5317Ta\u0301ibe\u030Ci"],       level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "ID selector, matching id value using non-ASCII characters (2)",    selector: "#\u53F0\u5317",                   expect: ["\u53F0\u5317"],               level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "ID selector, matching id values using non-ASCII characters (1)", selector: "#\u53F0\u5317Ta\u0301ibe\u030Ci, #\u53F0\u5317",      expect: ["\u53F0\u5317Ta\u0301ibe\u030Ci", "\u53F0\u5317"], level: 1, testType: TEST_QSA | TEST_MATCH},
+
+  // XXX runMatchesTest() in level2-lib.js can't handle this because obtaining the expected nodes requires escaping characters when generating the selector from 'expect' values
+  {name: "ID selector, matching element with id with escaped character", selector: "#\\#foo\\:bar",         expect: ["#foo:bar"],         level: 1, testType: TEST_QSA},
+  {name: "ID selector, matching element with id with escaped character", selector: "#test\\.foo\\[5\\]bar", expect: ["test.foo[5]bar"],   level: 1, testType: TEST_QSA},
+
+  // Namespaces
+  // XXX runMatchesTest() in level2-lib.js can't handle these because non-HTML elements don't have a recognised id
+  {name: "Namespace selector, matching element with any namespace",        selector: "#any-namespace *|div", expect: ["any-namespace-div1", "any-namespace-div2", "any-namespace-div3", "any-namespace-div4"], level: 3, testType: TEST_QSA},
+  {name: "Namespace selector, matching div elements in no namespace only", selector: "#no-namespace |div",   expect: ["no-namespace-div3"], level: 3, testType: TEST_QSA},
+  {name: "Namespace selector, matching any elements in no namespace only", selector: "#no-namespace |*",     expect: ["no-namespace-div3"], level: 3, testType: TEST_QSA},
+
+  // Combinators
+  // - Descendant combinator ' '
+  {name: "Descendant combinator, matching element that is a descendant of an element with id",                 selector: "#descendant div",                   expect: ["descendant-div1", "descendant-div2", "descendant-div3", "descendant-div4"], level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Descendant combinator, matching element with id that is a descendant of an element",                 selector: "body #descendant-div1",             expect: ["descendant-div1"], exclude: ["detached", "fragment"], level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Descendant combinator, matching element with id that is a descendant of an element",                 selector: "div #descendant-div1",              expect: ["descendant-div1"],                                    level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Descendant combinator, matching element with id that is a descendant of an element with id",         selector: "#descendant #descendant-div2",      expect: ["descendant-div2"],                                    level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Descendant combinator, matching element with class that is a descendant of an element with id",      selector: "#descendant .descendant-div2",      expect: ["descendant-div2"],                                    level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Descendant combinator, matching element with class that is a descendant of an element with class",   selector: ".descendant-div1 .descendant-div3", expect: ["descendant-div3"],                                    level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Descendant combinator, not matching element with id that is not a descendant of an element with id", selector: "#descendant-div1 #descendant-div4", expect: [] /*no matches*/,                                      level: 1, testType: TEST_QSA},
+  {name: "Descendant combinator, whitespace characters",                                                       selector: "#descendant\t\r\n#descendant-div2", expect: ["descendant-div2"],                                    level: 1, testType: TEST_QSA | TEST_MATCH},
+
+  // - Child combinator '>'
+  {name: "Child combinator, matching element that is a child of an element with id",                       selector: "#child>div",                          expect: ["child-div1", "child-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Child combinator, matching element with id that is a child of an element",                       selector: "div>#child-div1",                     expect: ["child-div1"],               level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Child combinator, matching element with id that is a child of an element with id",               selector: "#child>#child-div1",                  expect: ["child-div1"],               level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Child combinator, matching element with id that is a child of an element with class",            selector: "#child-div1>.child-div2",             expect: ["child-div2"],               level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Child combinator, matching element with class that is a child of an element with class",         selector: ".child-div1>.child-div2",             expect: ["child-div2"],               level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Child combinator, not matching element with id that is not a child of an element with id",       selector: "#child>#child-div3",                  expect: [] /*no matches*/,            level: 2, testType: TEST_QSA},
+  {name: "Child combinator, not matching element with id that is not a child of an element with class",    selector: "#child-div1>.child-div3",             expect: [] /*no matches*/,            level: 2, testType: TEST_QSA},
+  {name: "Child combinator, not matching element with class that is not a child of an element with class", selector: ".child-div1>.child-div3",             expect: [] /*no matches*/,            level: 2, testType: TEST_QSA},
+  {name: "Child combinator, surrounded by whitespace",                                                     selector: "#child-div1\t\r\n>\t\r\n#child-div2", expect: ["child-div2"],               level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Child combinator, whitespace after",                                                             selector: "#child-div1>\t\r\n#child-div2",       expect: ["child-div2"],               level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Child combinator, whitespace before",                                                            selector: "#child-div1\t\r\n>#child-div2",       expect: ["child-div2"],               level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Child combinator, no whitespace",                                                                selector: "#child-div1>#child-div2",             expect: ["child-div2"],               level: 2, testType: TEST_QSA | TEST_MATCH},
+
+  // - Adjacent sibling combinator '+'
+  {name: "Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id",                 selector: "#adjacent-div2+div",                                         expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element",                 selector: "div+#adjacent-div4",                                         expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id",         selector: "#adjacent-div2+#adjacent-div4",                              expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id",      selector: "#adjacent-div2+.adjacent-div4",                              expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class",   selector: ".adjacent-div2+.adjacent-div4",                              expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element",                    selector: "#adjacent div+p",                                            expect: ["adjacent-p2"],   level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id", selector: "#adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+  {name: "Adjacent sibling combinator, surrounded by whitespace",                                                           selector: "#adjacent-p2\t\r\n+\t\r\n#adjacent-p3",                      expect: ["adjacent-p3"],   level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Adjacent sibling combinator, whitespace after",                                                                   selector: "#adjacent-p2+\t\r\n#adjacent-p3",                            expect: ["adjacent-p3"],   level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Adjacent sibling combinator, whitespace before",                                                                  selector: "#adjacent-p2\t\r\n+#adjacent-p3",                            expect: ["adjacent-p3"],   level: 2, testType: TEST_QSA | TEST_MATCH},
+  {name: "Adjacent sibling combinator, no whitespace",                                                                      selector: "#adjacent-p2+#adjacent-p3",                                  expect: ["adjacent-p3"],   level: 2, testType: TEST_QSA | TEST_MATCH},
+
+  // - General sibling combinator ~ (Level 3)
+  {name: "General sibling combinator, matching element that is a sibling of an element with id",                    selector: "#sibling-div2~div",                                        expect: ["sibling-div4", "sibling-div6"], level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "General sibling combinator, matching element with id that is a sibling of an element",                    selector: "div~#sibling-div4",                                        expect: ["sibling-div4"],                 level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "General sibling combinator, matching element with id that is a sibling of an element with id",            selector: "#sibling-div2~#sibling-div4",                              expect: ["sibling-div4"],                 level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "General sibling combinator, matching element with class that is a sibling of an element with id",         selector: "#sibling-div2~.sibling-div",                               expect: ["sibling-div4", "sibling-div6"],                 level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "General sibling combinator, matching p element that is a sibling of a div element",                       selector: "#sibling div~p",                                           expect: ["sibling-p2", "sibling-p3"],                   level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "General sibling combinator, not matching element with id that is not a sibling after a p element",        selector: "#sibling>p~div",                                           expect: [] /*no matches*/,                level: 3, testType: TEST_QSA},
+  {name: "General sibling combinator, not matching element with id that is not a sibling after an element with id", selector: "#sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1", expect: [] /*no matches*/,                level: 3, testType: TEST_QSA},
+  {name: "General sibling combinator, surrounded by whitespace",                                                    selector: "#sibling-p2\t\r\n~\t\r\n#sibling-p3",                      expect: ["sibling-p3"],                   level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "General sibling combinator, whitespace after",                                                            selector: "#sibling-p2~\t\r\n#sibling-p3",                            expect: ["sibling-p3"],                   level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "General sibling combinator, whitespace before",                                                           selector: "#sibling-p2\t\r\n~#sibling-p3",                            expect: ["sibling-p3"],                   level: 3, testType: TEST_QSA | TEST_MATCH},
+  {name: "General sibling combinator, no whitespace",                                                               selector: "#sibling-p2~#sibling-p3",                                  expect: ["sibling-p3"],                   level: 3, testType: TEST_QSA | TEST_MATCH},
+
+  // Group of selectors (comma)
+  {name: "Syntax, group of selectors separator, surrounded by whitespace", selector: "#group em\t\r \n,\t\r \n#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Syntax, group of selectors separator, whitespace after",         selector: "#group em,\t\r\n#group strong",         expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Syntax, group of selectors separator, whitespace before",        selector: "#group em\t\r\n,#group strong",         expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH},
+  {name: "Syntax, group of selectors separator, no whitespace",            selector: "#group em,#group strong",               expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH},
+];
+
+
+/*
+ * These selectors are intended to be used with the find(), findAll() and matches() methods.  Expected results
+ * should be determined under the assumption that :scope will be prepended to the selector where appropriate,
+ * in accordance with the specification.
+ *
+ * All of these should be valid relative selectors, expected to match zero or more elements in the document.
+ * None should throw any errors.
+ *
+ *   name:      A descriptive name of the selector being tested
+ *
+ *   selector:  The selector to test
+ *
+ *   ctx:       A selector to obtain the context object to use for tests invoking context.find(),
+ *              and to use as a single reference node for tests invoking document.find().
+ *              Note: context = root.querySelector(ctx);
+ *
+ *   ref:       A selector to obtain the reference nodes to be used for the selector.
+ *              Note: If root is the document or an in-document element:
+ *                      refNodes = document.querySelectorAll(ref);
+ *                    Otherwise, if root is a fragment or detached element:
+ *                      refNodes = root.querySelectorAll(ref);
+ *
+ *   expect:    A list of IDs of the elements expected to be matched. List must be given in tree order.
+ *
+ *   unexpected: A list of IDs of some elements that are not expected to match the given selector.
+ *               This is used to verify that unexpected.matches(selector, refNode) does not match.
+ *
+ *   exclude:   An array of contexts to exclude from testing. The valid values are:
+ *              ["document", "element", "fragment", "detached", "html", "xhtml"]
+ *              The "html" and "xhtml" values represent the type of document being queried. These are useful
+ *              for tests that are affected by differences between HTML and XML, such as case sensitivity.
+ *
+ *   level:     An integer indicating the CSS or Selectors level in which the selector being tested was introduced.
+ *
+ *   testType:  A bit-mapped flag indicating the type of test.
+ *
+ * The test function for these tests accepts a specified root node, on which the methods will be invoked during the tests.
+ *
+ * Based on whether either 'context' or 'refNodes', or both, are specified the tests will execute the following methods:
+ *
+ * Where testType is TEST_FIND:
+ *
+ * context.findAll(selector, refNodes)
+ * context.findAll(selector)        // Only if refNodes is not specified
+ * root.findAll(selector, context)  // Only if refNodes is not specified
+ * root.findAll(selector, refNodes) // Only if context is not specified
+ * root.findAll(selector)           // Only if neither context nor refNodes is specified
+ *
+ * Where testType is TEST_QSA
+ *
+ * context.querySelectorAll(selector)
+ * root.querySelectorAll(selector)  // Only if neither context nor refNodes is specified
+ *
+ * Equivalent tests will be run for .find() as well.
+ * Note: Do not specify a testType of TEST_QSA where either implied :scope or explicit refNodes
+ * are required.
+ *
+ * Where testType is TEST_MATCH:
+ * For each expected result given, within the specified root:
+ *
+ * expect.matches(selector, context)    // Only where refNodes is not specified
+ * expect.matches(selector, refNodes)
+ * expect.matches(selector)             // Only if neither context nor refNodes is specified
+ *
+ * The tests involving refNodes for both find(), findAll() and matches() will each be run by passing the
+ * collection as a NodeList, an Array and, if there is only a single element, an Element node.
+ *
+ * Note: Interactive pseudo-classes (:active :hover and :focus) have not been tested in this test suite.
+ */
+
+var scopedSelectors = [
+  //{name: "", selector: "", ctx: "", ref: "", expect: [], level: 1, testType: TEST_FIND | TEST_MATCH},
+
+  // Universal Selector
+  {name: "Universal selector, matching all children of the specified reference element",       selector: ">*",   ctx: "#universal", expect: ["universal-p1", "universal-hr1", "universal-pre1", "universal-p2", "universal-address1"], unexpected: ["universal", "empty"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Universal selector, matching all grandchildren of the specified reference element",  selector: ">*>*", ctx: "#universal", expect: ["universal-code1", "universal-span1", "universal-a1", "universal-code2"],                 unexpected: ["universal", "empty"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Universal selector, matching all children of the specified empty reference element", selector: ">*",   ctx: "#empty",     expect: [] /*no matches*/,                                                                         unexpected: ["universal", "empty"], level: 2, testType: TEST_QSA},
+  {name: "Universal selector, matching all descendants of the specified reference element",    selector: "*",    ctx: "#universal", expect: ["universal-p1", "universal-code1", "universal-hr1", "universal-pre1", "universal-span1",
+                                                                                                                                             "universal-p2", "universal-a1", "universal-address1", "universal-code2", "universal-a2"], unexpected: ["universal", "empty"], level: 2, testType: TEST_FIND | TEST_MATCH},
+
+  // Attribute Selectors
+  // - presence                  [att]
+  {name: "Attribute presence selector, matching align attribute with value",                    selector: ".attr-presence-div1[align]",                             ctx: "#attr-presence", expect: ["attr-presence-div1"],                                             level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute presence selector, matching align attribute with empty value",              selector: ".attr-presence-div2[align]",                             ctx: "#attr-presence", expect: ["attr-presence-div2"],                                             level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute presence selector, matching title attribute, case insensitivity",           selector: "[TiTlE]",                                                ctx: "#attr-presence", expect: ["attr-presence-a1", "attr-presence-span1"], exclude: ["xhtml"],    level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute presence selector, not matching title attribute, case sensitivity",         selector: "[TiTlE]",                                                ctx: "#attr-presence", expect: [],                                          exclude: ["html"],     level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute presence selector, matching custom data-* attribute",                       selector: "[data-attr-presence]",                                   ctx: "#attr-presence", expect: ["attr-presence-pre1", "attr-presence-blockquote1"],                level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute presence selector, not matching attribute with similar name",               selector: ".attr-presence-div3[align], .attr-presence-div4[align]", ctx: "#attr-presence", expect: [] /*no matches*/,                                                  level: 2, testType: TEST_FIND},
+  {name: "Attribute presence selector, matching attribute with non-ASCII characters",           selector: "ul[data-中文]",                                            ctx: "#attr-presence", expect: ["attr-presence-ul1"],                                              level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute presence selector, not matching default option without selected attribute", selector: "#attr-presence-select1 option[selected]",                ctx: "#attr-presence", expect: [] /* no matches */,                                                level: 2, testType: TEST_FIND},
+  {name: "Attribute presence selector, matching option with selected attribute",                selector: "#attr-presence-select2 option[selected]",                ctx: "#attr-presence", expect: ["attr-presence-select2-option4"],                                  level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute presence selector, matching multiple options with selected attributes",     selector: "#attr-presence-select3 option[selected]",                ctx: "#attr-presence", expect: ["attr-presence-select3-option2", "attr-presence-select3-option3"], level: 2, testType: TEST_FIND | TEST_MATCH},
+
+  // - value                     [att=val]
+  {name: "Attribute value selector, matching align attribute with value",                                    selector: "[align=\"center\"]",                                     ctx: "#attr-value", expect: ["attr-value-div1"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute value selector, matching align attribute with empty value",                              selector: "[align=\"\"]",                                           ctx: "#attr-value", expect: ["attr-value-div2"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute value selector, not matching align attribute with partial value",                        selector: "[align=\"c\"]",                                          ctx: "#attr-value", expect: [] /*no matches*/,   level: 2, testType: TEST_FIND},
+  {name: "Attribute value selector, not matching align attribute with incorrect value",                      selector: "[align=\"centera\"]",                                    ctx: "#attr-value", expect: [] /*no matches*/,   level: 2, testType: TEST_FIND},
+  {name: "Attribute value selector, matching custom data-* attribute with unicode escaped value",            selector: "[data-attr-value=\"\\e9\"]",                             ctx: "#attr-value", expect: ["attr-value-div3"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute value selector, matching custom data-* attribute with escaped character",                selector: "[data-attr-value\_foo=\"\\e9\"]",                        ctx: "#attr-value", expect: ["attr-value-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute value selector with single-quoted value, matching multiple inputs with type attributes", selector: "input[type='hidden'],#attr-value input[type='radio']",   ctx: "#attr-value", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute value selector with double-quoted value, matching multiple inputs with type attributes", selector: "input[type=\"hidden\"],#attr-value input[type='radio']", ctx: "#attr-value", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute value selector with unquoted value, matching multiple inputs with type attributes",      selector: "input[type=hidden],#attr-value input[type=radio]",       ctx: "#attr-value", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute value selector, matching attribute with value using non-ASCII characters",               selector: "[data-attr-value=中文]",                                   ctx: "#attr-value", expect: ["attr-value-div5"], level: 2, testType: TEST_FIND | TEST_MATCH},
+
+  // - whitespace-separated list [att~=val]
+  {name: "Attribute whitespace-separated list selector, matching class attribute with value",                                  selector: "[class~=\"div1\"]",                                        ctx: "#attr-whitespace", expect: ["attr-whitespace-div1"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute whitespace-separated list selector, not matching class attribute with empty value",                        selector: "[class~=\"\"]",                                            ctx: "#attr-whitespace", expect: [] /*no matches*/ ,       level: 2, testType: TEST_FIND},
+  {name: "Attribute whitespace-separated list selector, not matching class attribute with partial value",                      selector: "[data-attr-whitespace~=\"div\"]",                                           ctx: "#attr-whitespace", expect: [] /*no matches*/ ,       level: 2, testType: TEST_FIND},
+  {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value",          selector: "[data-attr-whitespace~=\"\\0000e9\"]",                                      ctx: "#attr-whitespace", expect: ["attr-whitespace-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character",              selector: "[data-attr-whitespace\_foo~=\"\\e9\"]",                                     ctx: "#attr-whitespace", expect: ["attr-whitespace-div5"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes", selector: "a[rel~='bookmark'],  #attr-whitespace a[rel~='nofollow']", ctx: "#attr-whitespace", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes", selector: "a[rel~=\"bookmark\"],#attr-whitespace a[rel~='nofollow']", ctx: "#attr-whitespace", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes",      selector: "a[rel~=bookmark],    #attr-whitespace a[rel~=nofollow]",   ctx: "#attr-whitespace", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute whitespace-separated list selector with double-quoted value, not matching value with space",               selector: "a[rel~=\"book mark\"]",                                    ctx: "#attr-whitespace", expect: [] /* no matches */,      level: 2, testType: TEST_FIND},
+  {name: "Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters",       selector: "[title~=中文]",                                              ctx: "#attr-whitespace", expect: ["attr-whitespace-p1"],   level: 2, testType: TEST_FIND | TEST_MATCH},
+
+  // - hyphen-separated list     [att|=val]
+  {name: "Attribute hyphen-separated list selector, not matching unspecified lang attribute",    selector: "#attr-hyphen-div1[lang|=\"en\"]",    ctx: "#attr-hyphen", expect: [] /*no matches*/,    level: 2, testType: TEST_FIND},
+  {name: "Attribute hyphen-separated list selector, matching lang attribute with exact value",   selector: "#attr-hyphen-div2[lang|=\"fr\"]",    ctx: "#attr-hyphen", expect: ["attr-hyphen-div2"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute hyphen-separated list selector, matching lang attribute with partial value", selector: "#attr-hyphen-div3[lang|=\"en\"]",    ctx: "#attr-hyphen", expect: ["attr-hyphen-div3"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute hyphen-separated list selector, not matching incorrect value",               selector: "#attr-hyphen-div4[lang|=\"es-AR\"]", ctx: "#attr-hyphen", expect: [] /*no matches*/,    level: 2, testType: TEST_FIND},
+
+  // - substring begins-with     [att^=val] (Level 3)
+  {name: "Attribute begins with selector, matching href attributes beginning with specified substring",                             selector: "a[href^=\"http://www\"]", ctx: "#attr-begins", expect: ["attr-begins-a1", "attr-begins-a3"],     level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute begins with selector, matching lang attributes beginning with specified substring, ",                           selector: "[lang^=\"en-\"]",         ctx: "#attr-begins", expect: ["attr-begins-div2", "attr-begins-div4"], level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute begins with selector, not matching class attribute not beginning with specified substring",                     selector: "[class^=apple]",          ctx: "#attr-begins", expect: [] /*no matches*/,                        level: 3, testType: TEST_FIND},
+  {name: "Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring",    selector: "[class^=' apple']",       ctx: "#attr-begins", expect: ["attr-begins-p1"],                       level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring",    selector: "[class^=\" apple\"]",     ctx: "#attr-begins", expect: ["attr-begins-p1"],                       level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring", selector: "[class^= apple]",         ctx: "#attr-begins", expect: [] /*no matches*/,                        level: 3, testType: TEST_FIND},
+
+  // - substring ends-with       [att$=val] (Level 3)
+  {name: "Attribute ends with selector, matching href attributes ending with specified substring",                             selector: "a[href$=\".org\"]",   ctx: "#attr-ends", expect: ["attr-ends-a1", "attr-ends-a3"],     level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute ends with selector, matching lang attributes ending with specified substring, ",                           selector: "[lang$=\"-CH\"]",     ctx: "#attr-ends", expect: ["attr-ends-div2", "attr-ends-div4"], level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute ends with selector, not matching class attribute not ending with specified substring",                     selector: "[class$=apple]",      ctx: "#attr-ends", expect: [] /*no matches*/,                    level: 3, testType: TEST_FIND},
+  {name: "Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring",    selector: "[class$='apple ']",   ctx: "#attr-ends", expect: ["attr-ends-p1"],                     level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring",    selector: "[class$=\"apple \"]", ctx: "#attr-ends", expect: ["attr-ends-p1"],                     level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring", selector: "[class$=apple ]",     ctx: "#attr-ends", expect: [] /*no matches*/,                    level: 3, testType: TEST_FIND},
+
+  // - substring contains        [att*=val] (Level 3)
+  {name: "Attribute contains selector, matching href attributes beginning with specified substring",                          selector: "a[href*=\"http://www\"]",     ctx: "#attr-contains", expect: ["attr-contains-a1", "attr-contains-a3"],     level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute contains selector, matching href attributes ending with specified substring",                             selector: "a[href*=\".org\"]",           ctx: "#attr-contains", expect: ["attr-contains-a1", "attr-contains-a2"],     level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute contains selector, matching href attributes containing specified substring",                              selector: "a[href*=\".example.\"]",      ctx: "#attr-contains", expect: ["attr-contains-a1", "attr-contains-a3"],     level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute contains selector, matching lang attributes beginning with specified substring, ",                        selector: "[lang*=\"en-\"]",             ctx: "#attr-contains", expect: ["attr-contains-div2", "attr-contains-div6"], level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute contains selector, matching lang attributes ending with specified substring, ",                           selector: "[lang*=\"-CH\"]",             ctx: "#attr-contains", expect: ["attr-contains-div3", "attr-contains-div5"], level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring", selector: "[class*=' apple']",           ctx: "#attr-contains", expect: ["attr-contains-p1"],                         level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute contains selector with single-quoted value, matching class attribute ending with specified substring",    selector: "[class*='orange ']",          ctx: "#attr-contains", expect: ["attr-contains-p1"],                         level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute contains selector with single-quoted value, matching class attribute containing specified substring",     selector: "[class*='ple banana ora']",   ctx: "#attr-contains", expect: ["attr-contains-p1"],                         level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring", selector: "[class*=\" apple\"]",         ctx: "#attr-contains", expect: ["attr-contains-p1"],                         level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute contains selector with double-quoted value, matching class attribute ending with specified substring",    selector: "[class*=\"orange \"]",        ctx: "#attr-contains", expect: ["attr-contains-p1"],                         level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute contains selector with double-quoted value, matching class attribute containing specified substring",     selector: "[class*=\"ple banana ora\"]", ctx: "#attr-contains", expect: ["attr-contains-p1"],                         level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute contains selector with unquoted value, matching class attribute beginning with specified substring",      selector: "[class*= apple]",             ctx: "#attr-contains", expect: ["attr-contains-p1"],                         level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute contains selector with unquoted value, matching class attribute ending with specified substring",         selector: "[class*=orange ]",            ctx: "#attr-contains", expect: ["attr-contains-p1"],                         level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "Attribute contains selector with unquoted value, matching class attribute containing specified substring",          selector: "[class*= banana ]",           ctx: "#attr-contains", expect: ["attr-contains-p1"],                         level: 3, testType: TEST_FIND | TEST_MATCH},
+
+  // Pseudo-classes
+  // - :root                 (Level 3)
+  {name: ":root pseudo-class selector, matching document root element",      selector: ":root",               expect: ["html"],          exclude: ["element", "fragment", "detached"], level: 3, testType: TEST_FIND},
+  {name: ":root pseudo-class selector, not matching document root element",  selector: ":root",               expect: [] /*no matches*/, exclude: ["document"],                        level: 3, testType: TEST_FIND},
+  {name: ":root pseudo-class selector, not matching document root element",  selector: ":root", ctx: "#html", expect: [] /*no matches*/, exclude: ["fragment", "detached"],            level: 3, testType: TEST_FIND},
+
+  // - :nth-child(n)         (Level 3)
+  {name: ":nth-child selector, matching the third child element",                              selector: ":nth-child(3)",      ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-td3", "pseudo-nth-td9", "pseudo-nth-tr3", "pseudo-nth-td15"],             level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":nth-child selector, matching every third child element",                            selector: "li:nth-child(3n)",   ctx: "#pseudo-nth", expect: ["pseudo-nth-li3", "pseudo-nth-li6", "pseudo-nth-li9", "pseudo-nth-li12"],                    level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":nth-child selector, matching every second child element, starting from the fourth", selector: "li:nth-child(2n+4)", ctx: "#pseudo-nth", expect: ["pseudo-nth-li4", "pseudo-nth-li6", "pseudo-nth-li8", "pseudo-nth-li10", "pseudo-nth-li12"], level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":nth-child selector, matching every fourth child element, starting from the third",  selector: ":nth-child(4n-1)",   ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em2", "pseudo-nth-span3"],                                                    level: 3, testType: TEST_FIND | TEST_MATCH},
+
+  // - :nth-last-child       (Level 3)
+  {name: ":nth-last-child selector, matching the third last child element",                                           selector: ":nth-last-child(3)",      ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-tr1", "pseudo-nth-td4", "pseudo-nth-td10", "pseudo-nth-td16"],         level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":nth-last-child selector, matching every third child element from the end",                                 selector: "li:nth-last-child(3n)",   ctx: "pseudo-nth", expect: ["pseudo-nth-li1", "pseudo-nth-li4", "pseudo-nth-li7", "pseudo-nth-li10"],                  level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":nth-last-child selector, matching every second child element from the end, starting from the fourth last", selector: "li:nth-last-child(2n+4)", ctx: "pseudo-nth", expect: ["pseudo-nth-li1", "pseudo-nth-li3", "pseudo-nth-li5", "pseudo-nth-li7", "pseudo-nth-li9"], level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":nth-last-child selector, matching every fourth element from the end, starting from the third last",        selector: ":nth-last-child(4n-1)",   ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span2", "pseudo-nth-span4"],                                               level: 3, testType: TEST_FIND | TEST_MATCH},
+
+  // - :nth-of-type(n)       (Level 3)
+  {name: ":nth-of-type selector, matching the third em element",                                        selector: "em:nth-of-type(3)",      ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em3"],                                                                                 level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":nth-of-type selector, matching every second element of their type",                          selector: ":nth-of-type(2n)",       ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em2", "pseudo-nth-span2", "pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":nth-of-type selector, matching every second elemetn of their type, starting from the first", selector: "span:nth-of-type(2n-1)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span1", "pseudo-nth-span3"],                                                           level: 3, testType: TEST_FIND | TEST_MATCH},
+
+  // - :nth-last-of-type(n)  (Level 3)
+  {name: ":nth-last-of-type selector, matching the thrid last em element",                                       selector: "em:nth-last-of-type(3)",      ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em2"],                                                                                 level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":nth-last-of-type selector, matching every second last element of their type",                         selector: ":nth-last-of-type(2n)",       ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1", "pseudo-nth-em3", "pseudo-nth-span3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":nth-last-of-type selector, matching every second last element of their type, starting from the last", selector: "span:nth-last-of-type(2n-1)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span2", "pseudo-nth-span4"],                                                           level: 3, testType: TEST_FIND | TEST_MATCH},
+
+  // - :first-of-type        (Level 3)
+  {name: ":first-of-type selector, matching the first em element",                   selector: "em:first-of-type",  ctx: "#pseudo-nth-p1",     expect: ["pseudo-nth-em1"],                                           level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":first-of-type selector, matching the first of every type of element",     selector: ":first-of-type",    ctx: "#pseudo-nth-p1",     expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":first-of-type selector, matching the first td element in each table row", selector: "tr :first-of-type", ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-td1", "pseudo-nth-td7", "pseudo-nth-td13"],      level: 3, testType: TEST_FIND | TEST_MATCH},
+
+  // - :last-of-type         (Level 3)
+  {name: ":last-of-type selector, matching the last em elemnet",                     selector: "em:last-of-type",   ctx: "#pseudo-nth-p1",     expect: ["pseudo-nth-em4"],                                           level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":last-of-type selector, matching the last of every type of element",       selector: ":last-of-type",     ctx: "#pseudo-nth-p1",     expect: ["pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":last-of-type selector, matching the last td element in each table row",   selector: "tr :last-of-type",  ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-td6", "pseudo-nth-td12", "pseudo-nth-td18"],     level: 3, testType: TEST_FIND | TEST_MATCH},
+
+  // - :first-child
+  {name: ":first-child pseudo-class selector, matching first child div element",          selector: "div:first-child",                                                            ctx: "#pseudo-first-child", expect: ["pseudo-first-child-div1"],                                                          level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: ":first-child pseudo-class selector, doesn't match non-first-child elements",    selector: ".pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child", ctx: "#pseudo-first-child", expect: [] /*no matches*/,                                                                    level: 2, testType: TEST_FIND},
+  {name: ":first-child pseudo-class selector, matching first-child of multiple elements", selector: "span:first-child",                                                           ctx: "#pseudo-first-child", expect: ["pseudo-first-child-span1", "pseudo-first-child-span3", "pseudo-first-child-span5"], level: 2, testType: TEST_FIND | TEST_MATCH},
+
+  // - :last-child           (Level 3)
+  {name: ":last-child pseudo-class selector, matching last child div element",           selector: "div:last-child",                                                          ctx: "#pseudo-last-child", expect: ["pseudo-last-child-div3"],                                                        level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":last-child pseudo-class selector, doesn't match non-last-child elements",     selector: ".pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child", ctx: "#pseudo-last-child", expect: [] /*no matches*/,                                                                 level: 3, testType: TEST_FIND},
+  {name: ":last-child pseudo-class selector, matching first-child of multiple elements", selector: "span:last-child",                                                         ctx: "#pseudo-last-child", expect: ["pseudo-last-child-span2", "pseudo-last-child-span4", "pseudo-last-child-span6"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+  // - :only-child           (Level 3)
+  {name: ":pseudo-only-child pseudo-class selector, matching all only-child elements", selector: ":only-child",   ctx: "#pseudo-only", expect: ["pseudo-only-span1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":pseudo-only-child pseudo-class selector, matching only-child em elements",  selector: "em:only-child", ctx: "#pseudo-only", expect: [] /*no matches*/,     level: 3, testType: TEST_FIND},
+
+  // - :only-of-type         (Level 3)
+  {name: ":pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type", selector: " :only-of-type",   ctx: "#pseudo-only", expect: ["pseudo-only-span1", "pseudo-only-em1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type",  selector: " em:only-of-type", ctx: "#pseudo-only", expect: ["pseudo-only-em1"],                    level: 3, testType: TEST_FIND | TEST_MATCH},
+
+  // - :empty                (Level 3)
+  {name: ":empty pseudo-class selector, matching empty p elements",   selector: "p:empty", ctx: "#pseudo-empty", expect: ["pseudo-empty-p1", "pseudo-empty-p2"],                       level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":empty pseudo-class selector, matching all empty elements", selector: ":empty",  ctx: "#pseudo-empty", expect: ["pseudo-empty-p1", "pseudo-empty-p2", "pseudo-empty-span1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+  // - :link and :visited
+  // Implementations may treat all visited links as unvisited, so these cannot be tested separately.
+  // The only guarantee is that ":link,:visited" matches the set of all visited and unvisited links and that they are individually mutually exclusive sets.
+  {name: ":link and :visited pseudo-class selectors, matching a and area elements with href attributes",        selector: " :link, #pseudo-link :visited", ctx: "#pseudo-link", expect: ["pseudo-link-a1", "pseudo-link-a2", "pseudo-link-area1"],                                level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: ":link and :visited pseudo-class selectors, matching link elements with href attributes",              selector: " :link, #head :visited",        ctx: "#head",        expect: ["pseudo-link-link1", "pseudo-link-link2"], exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: ":link and :visited pseudo-class selectors, not matching link elements with href attributes",          selector: " :link, #head :visited",        ctx: "#head",        expect: [] /*no matches*/,                          exclude: ["document"],                        level: 1, testType: TEST_FIND},
+  {name: ":link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing", selector: ":link:visited",                 ctx: "#html",        expect: [] /*no matches*/,                          exclude: ["document"],                        level: 1, testType: TEST_FIND},
+
+// XXX Figure out context or refNodes for this
+  // - :target               (Level 3)
+  {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", ctx: "", expect: [] /*no matches*/, exclude: ["document", "element"],  level: 3, testType: TEST_FIND},
+  {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", ctx: "", expect: ["target"],        exclude: ["fragment", "detached"], level: 3, testType: TEST_FIND},
+
+// XXX Fix ctx in tests below
+
+  // - :lang()
+  {name: ":lang pseudo-class selector, matching inherited language (1)",                     selector: "#pseudo-lang-div1:lang(en)",    ctx: "", expect: ["pseudo-lang-div1"], exclude: ["detached", "fragment"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: ":lang pseudo-class selector, not matching element with no inherited language", selector: "#pseudo-lang-div1:lang(en)",    ctx: "", expect: [] /*no matches*/,    exclude: ["document", "element"],  level: 2, testType: TEST_FIND},
+  {name: ":lang pseudo-class selector, matching specified language with exact value (1)",    selector: "#pseudo-lang-div2:lang(fr)",    ctx: "", expect: ["pseudo-lang-div2"],                                    level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: ":lang pseudo-class selector, matching specified language with partial value (1)",  selector: "#pseudo-lang-div3:lang(en)",    ctx: "", expect: ["pseudo-lang-div3"],                                    level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: ":lang pseudo-class selector, not matching incorrect language",                 selector: "#pseudo-lang-div4:lang(es-AR)", ctx: "", expect: [] /*no matches*/,                                       level: 2, testType: TEST_FIND},
+
+  // - :enabled              (Level 3)
+  {name: ":enabled pseudo-class selector, matching all enabled form controls (1)",  selector: "#pseudo-ui :enabled",  ctx: "", expect: ["pseudo-ui-input1", "pseudo-ui-input2", "pseudo-ui-input3", "pseudo-ui-input4", "pseudo-ui-input5", "pseudo-ui-input6",
+                                                                                                                           "pseudo-ui-input7", "pseudo-ui-input8", "pseudo-ui-input9", "pseudo-ui-textarea1", "pseudo-ui-button1"],    level: 3, testType: TEST_FIND | TEST_MATCH},
+
+  // - :disabled             (Level 3)
+  {name: ":enabled pseudo-class selector, matching all disabled form controls (1)", selector: "#pseudo-ui :disabled", ctx: "", expect: ["pseudo-ui-input10", "pseudo-ui-input11", "pseudo-ui-input12", "pseudo-ui-input13", "pseudo-ui-input14", "pseudo-ui-input15",
+                                                                                                                           "pseudo-ui-input16", "pseudo-ui-input17", "pseudo-ui-input18", "pseudo-ui-textarea2", "pseudo-ui-button2"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+  // - :checked              (Level 3)
+  {name: ":checked pseudo-class selector, matching checked radio buttons and checkboxes (1)", selector: "#pseudo-ui :checked", ctx: "", expect: ["pseudo-ui-input4", "pseudo-ui-input6", "pseudo-ui-input13", "pseudo-ui-input15"],  level: 3, testType: TEST_FIND | TEST_MATCH},
+
+  // - :not(s)               (Level 3)
+  {name: ":not pseudo-class selector, matching (1)", selector: "#not>:not(div)",   ctx: "", expect: ["not-p1", "not-p2", "not-p3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":not pseudo-class selector, matching (1)", selector: "#not * :not(:first-child)",   ctx: "", expect: ["not-em1", "not-em2", "not-em3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: ":not pseudo-class selector, matching nothing", selector: ":not(*)",   ctx: "", expect: [] /* no matches */, level: 3, testType: TEST_FIND},
+  {name: ":not pseudo-class selector, matching nothing", selector: ":not(*|*)", ctx: "", expect: [] /* no matches */, level: 3, testType: TEST_FIND},
+
+  // Pseudo-elements
+  // - ::first-line
+  {name: ":first-line pseudo-element (one-colon syntax) selector, not matching any elements",    selector: "#pseudo-element:first-line",    ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+  {name: "::first-line pseudo-element (two-colon syntax) selector, not matching any elements",   selector: "#pseudo-element::first-line",   ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+
+  // - ::first-letter
+  {name: ":first-letter pseudo-element (one-colon syntax) selector, not matching any elements",  selector: "#pseudo-element:first-letter",  ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+  {name: "::first-letter pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::first-letter", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+
+  // - ::before
+  {name: ":before pseudo-element (one-colon syntax) selector, not matching any elements",        selector: "#pseudo-element:before",        ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+  {name: "::before pseudo-element (two-colon syntax) selector, not matching any elements",       selector: "#pseudo-element::before",       ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+
+  // - ::after
+  {name: ":after pseudo-element (one-colon syntax) selector, not matching any elements",         selector: "#pseudo-element:after",         ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+  {name: "::after pseudo-element (two-colon syntax) selector, not matching any elements",        selector: "#pseudo-element::after",        ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+
+  // Class Selectors
+  {name: "Class selector, matching element with specified class (1)",                                           selector: ".class-p",                ctx: "", expect: ["class-p1","class-p2", "class-p3"],                                              level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Class selector, chained, matching only elements with all specified classes (1)",                      selector: "#class .apple.orange.banana",    ctx: "", expect: ["class-div1", "class-div2", "class-p4", "class-div3", "class-p6", "class-div4"], level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Class Selector, chained, with type selector (1)",                                                     selector: "div.apple.banana.orange", ctx: "", expect: ["class-div1", "class-div2", "class-div3", "class-div4"],                         level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Class selector, matching element with class value using non-ASCII characters (2)",                    selector: ".\u53F0\u5317Ta\u0301ibe\u030Ci",             ctx: "", expect: ["class-span1"],               level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Class selector, matching multiple elements with class value using non-ASCII characters (1)",          selector: ".\u53F0\u5317",                     ctx: "", expect: ["class-span1","class-span2"], level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Class selector, chained, matching element with multiple class values using non-ASCII characters (2)", selector: ".\u53F0\u5317Ta\u0301ibe\u030Ci.\u53F0\u5317",          ctx: "", expect: ["class-span1"],               level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Class selector, matching element with class with escaped character (1)",                              selector: ".foo\\:bar",              ctx: "", expect: ["class-span3"],               level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Class selector, matching element with class with escaped character (1)",                              selector: ".test\\.foo\\[5\\]bar",   ctx: "", expect: ["class-span4"],               level: 1, testType: TEST_FIND | TEST_MATCH},
+
+  // ID Selectors
+  {name: "ID selector, matching element with specified id (1)",           selector: "#id #id-div1",              ctx: "", expect: ["id-div1"],            level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "ID selector, chained, matching element with specified id (1)",  selector: "#id-div1, #id-div1",        ctx: "", expect: ["id-div1"],            level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "ID selector, chained, matching element with specified id (1)",  selector: "#id-div1, #id-div2",        ctx: "", expect: ["id-div1", "id-div2"], level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "ID Selector, chained, with type selector (1)",                  selector: "div#id-div1, div#id-div2",  ctx: "", expect: ["id-div1", "id-div2"], level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "ID selector, not matching non-existent descendant",         selector: "#id #none",                 ctx: "", expect: [] /*no matches*/,      level: 1, testType: TEST_FIND},
+  {name: "ID selector, not matching non-existent ancestor",           selector: "#none #id-div1",            ctx: "", expect: [] /*no matches*/,      level: 1, testType: TEST_FIND},
+  {name: "ID selector, matching multiple elements with duplicate id (1)", selector: "#id-li-duplicate",          ctx: "", expect: ["id-li-duplicate", "id-li-duplicate", "id-li-duplicate", "id-li-duplicate"], level: 1, testType: TEST_FIND | TEST_MATCH},
+
+  {name: "ID selector, matching id value using non-ASCII characters (3)",    selector: "#\u53F0\u5317Ta\u0301ibe\u030Ci",           ctx: "", expect: ["\u53F0\u5317Ta\u0301ibe\u030Ci"],       level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "ID selector, matching id value using non-ASCII characters (4)",    selector: "#\u53F0\u5317",                   ctx: "", expect: ["\u53F0\u5317"],               level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "ID selector, matching id values using non-ASCII characters (2)",   selector: "#\u53F0\u5317Ta\u0301ibe\u030Ci, #\u53F0\u5317",      ctx: "", expect: ["\u53F0\u5317Ta\u0301ibe\u030Ci", "\u53F0\u5317"], level: 1, testType: TEST_FIND | TEST_MATCH},
+
+  // XXX runMatchesTest() in level2-lib.js can't handle this because obtaining the expected nodes requires escaping characters when generating the selector from 'expect' values
+  {name: "ID selector, matching element with id with escaped character", selector: "#\\#foo\\:bar",         ctx: "", expect: ["#foo:bar"],         level: 1, testType: TEST_FIND},
+  {name: "ID selector, matching element with id with escaped character", selector: "#test\\.foo\\[5\\]bar", ctx: "", expect: ["test.foo[5]bar"],   level: 1, testType: TEST_FIND},
+
+  // Namespaces
+  // XXX runMatchesTest() in level2-lib.js can't handle these because non-HTML elements don't have a recognised id
+  {name: "Namespace selector, matching element with any namespace",        selector: "#any-namespace *|div", ctx: "", expect: ["any-namespace-div1", "any-namespace-div2", "any-namespace-div3", "any-namespace-div4"], level: 3, testType: TEST_FIND},
+  {name: "Namespace selector, matching div elements in no namespace only", selector: "#no-namespace |div",   ctx: "", expect: ["no-namespace-div3"], level: 3, testType: TEST_FIND},
+  {name: "Namespace selector, matching any elements in no namespace only", selector: "#no-namespace |*",     ctx: "", expect: ["no-namespace-div3"], level: 3, testType: TEST_FIND},
+
+  // Combinators
+  // - Descendant combinator ' '
+  {name: "Descendant combinator, matching element that is a descendant of an element with id (1)",                 selector: "#descendant div",                   ctx: "", expect: ["descendant-div1", "descendant-div2", "descendant-div3", "descendant-div4"], level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Descendant combinator, matching element with id that is a descendant of an element (1)",                 selector: "body #descendant-div1",             ctx: "", expect: ["descendant-div1"], exclude: ["detached", "fragment"], level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Descendant combinator, matching element with id that is a descendant of an element (1)",                 selector: "div #descendant-div1",              ctx: "", expect: ["descendant-div1"],                                    level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Descendant combinator, matching element with id that is a descendant of an element with id (1)",         selector: "#descendant #descendant-div2",      ctx: "", expect: ["descendant-div2"],                                    level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Descendant combinator, matching element with class that is a descendant of an element with id (1)",      selector: "#descendant .descendant-div2",      ctx: "", expect: ["descendant-div2"],                                    level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Descendant combinator, matching element with class that is a descendant of an element with class (1)",   selector: ".descendant-div1 .descendant-div3", ctx: "", expect: ["descendant-div3"],                                    level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Descendant combinator, not matching element with id that is not a descendant of an element with id", selector: "#descendant-div1 #descendant-div4", ctx: "", expect: [] /*no matches*/,                                      level: 1, testType: TEST_FIND},
+  {name: "Descendant combinator, whitespace characters (1)",                                                       selector: "#descendant\t\r\n#descendant-div2", ctx: "", expect: ["descendant-div2"],                                    level: 1, testType: TEST_FIND | TEST_MATCH},
+
+  // - Child combinator '>'
+  {name: "Child combinator, matching element that is a child of an element with id (1)",                       selector: "#child>div",                          ctx: "", expect: ["child-div1", "child-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Child combinator, matching element with id that is a child of an element (1)",                       selector: "div>#child-div1",                     ctx: "", expect: ["child-div1"],               level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Child combinator, matching element with id that is a child of an element with id (1)",               selector: "#child>#child-div1",                  ctx: "", expect: ["child-div1"],               level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Child combinator, matching element with id that is a child of an element with class (1)",            selector: "#child-div1>.child-div2",             ctx: "", expect: ["child-div2"],               level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Child combinator, matching element with class that is a child of an element with class (1)",         selector: ".child-div1>.child-div2",             ctx: "", expect: ["child-div2"],               level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Child combinator, not matching element with id that is not a child of an element with id",       selector: "#child>#child-div3",                  ctx: "", expect: [] /*no matches*/,            level: 2, testType: TEST_FIND},
+  {name: "Child combinator, not matching element with id that is not a child of an element with class",    selector: "#child-div1>.child-div3",             ctx: "", expect: [] /*no matches*/,            level: 2, testType: TEST_FIND},
+  {name: "Child combinator, not matching element with class that is not a child of an element with class", selector: ".child-div1>.child-div3",             ctx: "", expect: [] /*no matches*/,            level: 2, testType: TEST_FIND},
+  {name: "Child combinator, surrounded by whitespace (1)",                                                     selector: "#child-div1\t\r\n>\t\r\n#child-div2", ctx: "", expect: ["child-div2"],               level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Child combinator, whitespace after (1)",                                                             selector: "#child-div1>\t\r\n#child-div2",       ctx: "", expect: ["child-div2"],               level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Child combinator, whitespace before (1)",                                                            selector: "#child-div1\t\r\n>#child-div2",       ctx: "", expect: ["child-div2"],               level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Child combinator, no whitespace (1)",                                                                selector: "#child-div1>#child-div2",             ctx: "", expect: ["child-div2"],               level: 2, testType: TEST_FIND | TEST_MATCH},
+
+  // - Adjacent sibling combinator '+'
+  {name: "Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id (1)",                 selector: "#adjacent-div2+div",                                         ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element (1)",                 selector: "div+#adjacent-div4",                                         ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id (1)",         selector: "#adjacent-div2+#adjacent-div4",                              ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id (1)",      selector: "#adjacent-div2+.adjacent-div4",                              ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class (1)",   selector: ".adjacent-div2+.adjacent-div4",                              ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element (1)",                    selector: "#adjacent div+p",                                            ctx: "", expect: ["adjacent-p2"],   level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id", selector: "#adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+  {name: "Adjacent sibling combinator, surrounded by whitespace (1)",                                                           selector: "#adjacent-p2\t\r\n+\t\r\n#adjacent-p3",                      ctx: "", expect: ["adjacent-p3"],   level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Adjacent sibling combinator, whitespace after (1)",                                                                   selector: "#adjacent-p2+\t\r\n#adjacent-p3",                            ctx: "", expect: ["adjacent-p3"],   level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Adjacent sibling combinator, whitespace before (1)",                                                                  selector: "#adjacent-p2\t\r\n+#adjacent-p3",                            ctx: "", expect: ["adjacent-p3"],   level: 2, testType: TEST_FIND | TEST_MATCH},
+  {name: "Adjacent sibling combinator, no whitespace (1)",                                                                      selector: "#adjacent-p2+#adjacent-p3",                                  ctx: "", expect: ["adjacent-p3"],   level: 2, testType: TEST_FIND | TEST_MATCH},
+
+  // - General sibling combinator ~ (Level 3)
+  {name: "General sibling combinator, matching element that is a sibling of an element with id (1)",                    selector: "#sibling-div2~div",                                        ctx: "", expect: ["sibling-div4", "sibling-div6"], level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "General sibling combinator, matching element with id that is a sibling of an element (1)",                    selector: "div~#sibling-div4",                                        ctx: "", expect: ["sibling-div4"],                 level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "General sibling combinator, matching element with id that is a sibling of an element with id (1)",            selector: "#sibling-div2~#sibling-div4",                              ctx: "", expect: ["sibling-div4"],                 level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "General sibling combinator, matching element with class that is a sibling of an element with id (1)",         selector: "#sibling-div2~.sibling-div",                               ctx: "", expect: ["sibling-div4", "sibling-div6"],                 level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "General sibling combinator, matching p element that is a sibling of a div element (1)",                       selector: "#sibling div~p",                                           ctx: "", expect: ["sibling-p2", "sibling-p3"],                   level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "General sibling combinator, not matching element with id that is not a sibling after a p element (1)",        selector: "#sibling>p~div",                                           ctx: "", expect: [] /*no matches*/,                level: 3, testType: TEST_FIND},
+  {name: "General sibling combinator, not matching element with id that is not a sibling after an element with id", selector: "#sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1", ctx: "", expect: [] /*no matches*/,                level: 3, testType: TEST_FIND},
+  {name: "General sibling combinator, surrounded by whitespace (1)",                                                    selector: "#sibling-p2\t\r\n~\t\r\n#sibling-p3",                      ctx: "", expect: ["sibling-p3"],                   level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "General sibling combinator, whitespace after (1)",                                                            selector: "#sibling-p2~\t\r\n#sibling-p3",                            ctx: "", expect: ["sibling-p3"],                   level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "General sibling combinator, whitespace before (1)",                                                           selector: "#sibling-p2\t\r\n~#sibling-p3",                            ctx: "", expect: ["sibling-p3"],                   level: 3, testType: TEST_FIND | TEST_MATCH},
+  {name: "General sibling combinator, no whitespace (1)",                                                               selector: "#sibling-p2~#sibling-p3",                                  ctx: "", expect: ["sibling-p3"],                   level: 3, testType: TEST_FIND | TEST_MATCH},
+
+  // Group of selectors (comma)
+  {name: "Syntax, group of selectors separator, surrounded by whitespace (1)", selector: "#group em\t\r \n,\t\r \n#group strong", ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Syntax, group of selectors separator, whitespace after (1)",         selector: "#group em,\t\r\n#group strong",         ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Syntax, group of selectors separator, whitespace before (1)",        selector: "#group em\t\r\n,#group strong",         ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH},
+  {name: "Syntax, group of selectors separator, no whitespace (1)",            selector: "#group em,#group strong",               ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH},
+];
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-attributes.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-attributes.html
new file mode 100644
index 0000000..529a69099
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-attributes.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Range attributes</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<meta name=timeout content=long>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+  var r = document.createRange();
+  assert_equals(r.startContainer, document)
+  assert_equals(r.endContainer, document)
+  assert_equals(r.startOffset, 0)
+  assert_equals(r.endOffset, 0)
+  assert_true(r.collapsed)
+  r.detach()
+  assert_equals(r.startContainer, document)
+  assert_equals(r.endContainer, document)
+  assert_equals(r.startOffset, 0)
+  assert_equals(r.endOffset, 0)
+  assert_true(r.collapsed)
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-cloneRange.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-cloneRange.html
new file mode 100644
index 0000000..571f87e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-cloneRange.html
@@ -0,0 +1,112 @@
+<!doctype html>
+<title>Range.cloneRange() and document.createRange() tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+function testCloneRange(rangeEndpoints) {
+  var range;
+  if (rangeEndpoints == "detached") {
+    range = document.createRange();
+    range.detach();
+    var clonedRange = range.cloneRange();
+    assert_equals(clonedRange.startContainer, range.startContainer,
+      "startContainers must be equal after cloneRange()");
+    assert_equals(clonedRange.startOffset, range.startOffset,
+      "startOffsets must be equal after cloneRange()");
+    assert_equals(clonedRange.endContainer, range.endContainer,
+      "endContainers must be equal after cloneRange()");
+    assert_equals(clonedRange.endOffset, range.endOffset,
+      "endOffsets must be equal after cloneRange()");
+    return;
+  }
+
+  // Have to account for Ranges involving Documents!  We could just create
+  // the Range from the current document unconditionally, but some browsers
+  // (WebKit) don't implement setStart() and setEnd() per spec and will throw
+  // spurious exceptions at the time of this writing.  No need to mask other
+  // bugs.
+  var ownerDoc = rangeEndpoints[0].nodeType == Node.DOCUMENT_NODE
+    ? rangeEndpoints[0]
+    : rangeEndpoints[0].ownerDocument;
+  range = ownerDoc.createRange();
+  // Here we throw in some createRange() tests, because why not.  Have to
+  // test it someplace.
+  assert_equals(range.startContainer, ownerDoc,
+    "doc.createRange() must create Range whose startContainer is doc");
+  assert_equals(range.endContainer, ownerDoc,
+    "doc.createRange() must create Range whose endContainer is doc");
+  assert_equals(range.startOffset, 0,
+    "doc.createRange() must create Range whose startOffset is 0");
+  assert_equals(range.endOffset, 0,
+    "doc.createRange() must create Range whose endOffset is 0");
+
+  range.setStart(rangeEndpoints[0], rangeEndpoints[1]);
+  range.setEnd(rangeEndpoints[2], rangeEndpoints[3]);
+
+  // Make sure we bail out now if setStart or setEnd are buggy, so it doesn't
+  // create misleading failures later.
+  assert_equals(range.startContainer, rangeEndpoints[0],
+    "Sanity check on setStart()");
+  assert_equals(range.startOffset, rangeEndpoints[1],
+    "Sanity check on setStart()");
+  assert_equals(range.endContainer, rangeEndpoints[2],
+    "Sanity check on setEnd()");
+  assert_equals(range.endOffset, rangeEndpoints[3],
+    "Sanity check on setEnd()");
+
+  var clonedRange = range.cloneRange();
+
+  assert_equals(clonedRange.startContainer, range.startContainer,
+    "startContainers must be equal after cloneRange()");
+  assert_equals(clonedRange.startOffset, range.startOffset,
+    "startOffsets must be equal after cloneRange()");
+  assert_equals(clonedRange.endContainer, range.endContainer,
+    "endContainers must be equal after cloneRange()");
+  assert_equals(clonedRange.endOffset, range.endOffset,
+    "endOffsets must be equal after cloneRange()");
+
+  // Make sure that modifying one doesn't affect the other.
+  var testNode1 = ownerDoc.createTextNode("testing");
+  var testNode2 = ownerDoc.createTextNode("testing with different length");
+
+  range.setStart(testNode1, 1);
+  range.setEnd(testNode1, 2);
+  assert_equals(clonedRange.startContainer, rangeEndpoints[0],
+    "Modifying a Range must not modify its clone's startContainer");
+  assert_equals(clonedRange.startOffset, rangeEndpoints[1],
+    "Modifying a Range must not modify its clone's startOffset");
+  assert_equals(clonedRange.endContainer, rangeEndpoints[2],
+    "Modifying a Range must not modify its clone's endContainer");
+  assert_equals(clonedRange.endOffset, rangeEndpoints[3],
+    "Modifying a Range must not modify its clone's endOffset");
+
+  clonedRange.setStart(testNode2, 3);
+  clonedRange.setStart(testNode2, 4);
+
+  assert_equals(range.startContainer, testNode1,
+    "Modifying a clone must not modify the original Range's startContainer");
+  assert_equals(range.startOffset, 1,
+    "Modifying a clone must not modify the original Range's startOffset");
+  assert_equals(range.endContainer, testNode1,
+    "Modifying a clone must not modify the original Range's endContainer");
+  assert_equals(range.endOffset, 2,
+    "Modifying a clone must not modify the original Range's endOffset");
+}
+
+var tests = [];
+for (var i = 0; i < testRanges.length; i++) {
+  tests.push([
+    "Range " + i + " " + testRanges[i],
+    eval(testRanges[i])
+  ]);
+}
+generate_tests(testCloneRange, tests);
+
+testDiv.style.display = "none";
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-collapse.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-collapse.html
new file mode 100644
index 0000000..6678fb29
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-collapse.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<title>Range.collapse() and .collapsed tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+function testCollapse(rangeEndpoints, toStart) {
+  var range;
+  if (rangeEndpoints == "detached") {
+    range = document.createRange();
+    range.detach(); // should be a no-op and therefore the following should not throw
+    range.collapse(toStart);
+    assert_equals(true, range.collapsed);
+  }
+
+  // Have to account for Ranges involving Documents!
+  var ownerDoc = rangeEndpoints[0].nodeType == Node.DOCUMENT_NODE
+    ? rangeEndpoints[0]
+    : rangeEndpoints[0].ownerDocument;
+  range = ownerDoc.createRange();
+  range.setStart(rangeEndpoints[0], rangeEndpoints[1]);
+  range.setEnd(rangeEndpoints[2], rangeEndpoints[3]);
+
+  var expectedContainer = toStart ? range.startContainer : range.endContainer;
+  var expectedOffset = toStart ? range.startOffset : range.endOffset;
+
+  assert_equals(range.collapsed, range.startContainer == range.endContainer
+    && range.startOffset == range.endOffset,
+    "collapsed must be true if and only if the start and end are equal");
+
+  if (toStart === undefined) {
+    range.collapse();
+  } else {
+    range.collapse(toStart);
+  }
+
+  assert_equals(range.startContainer, expectedContainer,
+    "Wrong startContainer");
+  assert_equals(range.endContainer, expectedContainer,
+    "Wrong endContainer");
+  assert_equals(range.startOffset, expectedOffset,
+    "Wrong startOffset");
+  assert_equals(range.endOffset, expectedOffset,
+    "Wrong endOffset");
+  assert_true(range.collapsed,
+    ".collapsed must be set after .collapsed()");
+}
+
+var tests = [];
+for (var i = 0; i < testRanges.length; i++) {
+  tests.push([
+    "Range " + i + " " + testRanges[i] + ", toStart true",
+    eval(testRanges[i]),
+    true
+  ]);
+  tests.push([
+    "Range " + i + " " + testRanges[i] + ", toStart false",
+    eval(testRanges[i]),
+    false
+  ]);
+  tests.push([
+    "Range " + i + " " + testRanges[i] + ", toStart omitted",
+    eval(testRanges[i]),
+    undefined
+  ]);
+}
+generate_tests(testCollapse, tests);
+
+testDiv.style.display = "none";
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-commonAncestorContainer-2.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-commonAncestorContainer-2.html
new file mode 100644
index 0000000..7d701b0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-commonAncestorContainer-2.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>Range.commonAncestorContainer</title>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+  var range = document.createRange();
+  range.detach();
+  assert_equals(range.commonAncestorContainer, document);
+}, "Detached Range")
+test(function() {
+  var df = document.createDocumentFragment();
+  var foo = df.appendChild(document.createElement("foo"));
+  foo.appendChild(document.createTextNode("Foo"));
+  var bar = df.appendChild(document.createElement("bar"));
+  bar.appendChild(document.createComment("Bar"));
+  [
+    // start node, start offset, end node, end offset, expected cAC
+    [foo, 0, bar, 0, df],
+    [foo, 0, foo.firstChild, 3, foo],
+    [foo.firstChild, 0, bar, 0, df],
+    [foo.firstChild, 3, bar.firstChild, 2, df]
+  ].forEach(function(t) {
+    test(function() {
+      var range = document.createRange();
+      range.setStart(t[0], t[1]);
+      range.setEnd(t[2], t[3]);
+      assert_equals(range.commonAncestorContainer, t[4]);
+    })
+  });
+}, "Normal Ranges")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-commonAncestorContainer.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-commonAncestorContainer.html
new file mode 100644
index 0000000..3db1433e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-commonAncestorContainer.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<title>Range.commonAncestorContainer tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+testRanges.unshift("[detached]");
+
+for (var i = 0; i < testRanges.length; i++) {
+  test(function() {
+    var range;
+    if (i == 0) {
+      range = document.createRange();
+      range.detach();
+    } else {
+      range = rangeFromEndpoints(eval(testRanges[i]));
+    }
+
+    // "Let container be start node."
+    var container = range.startContainer;
+
+    // "While container is not an inclusive ancestor of end node, let
+    // container be container's parent."
+    while (container != range.endContainer
+    && !isAncestor(container, range.endContainer)) {
+      container = container.parentNode;
+    }
+
+    // "Return container."
+    assert_equals(range.commonAncestorContainer, container);
+  }, i + ": range " + testRanges[i]);
+}
+
+testDiv.style.display = "none";
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-comparePoint-2.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-comparePoint-2.html
new file mode 100644
index 0000000..1dc4870
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-comparePoint-2.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Range.comparePoint</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<meta name=timeout content=long>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+  var r = document.createRange();
+  r.detach()
+  assert_equals(r.comparePoint(document.body, 0), 1)
+})
+test(function() {
+  var r = document.createRange();
+  assert_throws(new TypeError(), function() { r.comparePoint(null, 0) })
+})
+test(function() {
+  var doc = document.implementation.createHTMLDocument("tralala")
+  var r = document.createRange();
+  assert_throws("WRONG_DOCUMENT_ERR", function() { r.comparePoint(doc.body, 0) })
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-constructor.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-constructor.html
new file mode 100644
index 0000000..255f34a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-constructor.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>Range constructor test</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<div id=log></div>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<script>
+"use strict";
+
+test(function() {
+    var range = new Range();
+    assert_equals(range.startContainer, document, "startContainer");
+    assert_equals(range.endContainer, document, "endContainer");
+    assert_equals(range.startOffset, 0, "startOffset");
+    assert_equals(range.endOffset, 0, "endOffset");
+    assert_true(range.collapsed, "collapsed");
+    assert_equals(range.commonAncestorContainer, document,
+                  "commonAncestorContainer");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-detach.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-detach.html
new file mode 100644
index 0000000..0e0ceeb2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-detach.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title>Range.detach</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<meta name=timeout content=long>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+  var r = document.createRange();
+  r.detach()
+  r.detach()
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-intersectsNode-binding.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-intersectsNode-binding.html
new file mode 100644
index 0000000..1d4de89
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-intersectsNode-binding.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>Range.intersectsNode</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<meta name=timeout content=long>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+  var r = document.createRange();
+  assert_throws(new TypeError(), function() { r.intersectsNode(); });
+  assert_throws(new TypeError(), function() { r.intersectsNode(null); });
+  assert_throws(new TypeError(), function() { r.intersectsNode(undefined); });
+  assert_throws(new TypeError(), function() { r.intersectsNode(42); });
+  assert_throws(new TypeError(), function() { r.intersectsNode("foo"); });
+  assert_throws(new TypeError(), function() { r.intersectsNode({}); });
+  r.detach();
+  assert_throws(new TypeError(), function() { r.intersectsNode(); });
+  assert_throws(new TypeError(), function() { r.intersectsNode(null); });
+  assert_throws(new TypeError(), function() { r.intersectsNode(undefined); });
+  assert_throws(new TypeError(), function() { r.intersectsNode(42); });
+  assert_throws(new TypeError(), function() { r.intersectsNode("foo"); });
+  assert_throws(new TypeError(), function() { r.intersectsNode({}); });
+}, "Calling intersectsNode without an argument or with an invalid argument should throw a TypeError.")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-intersectsNode.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-intersectsNode.html
new file mode 100644
index 0000000..7745088
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-intersectsNode.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<title>Range.intersectsNode() tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+// Will be filled in on the first run for that range
+var testRangesCached = [];
+
+for (var i = 0; i < testNodes.length; i++) {
+  var node = eval(testNodes[i]);
+
+  for (var j = 0; j < testRanges.length; j++) {
+    test(function() {
+      if (testRangesCached[j] === undefined) {
+        try {
+          testRangesCached[j] = rangeFromEndpoints(eval(testRanges[i]));
+        } catch(e) {
+          testRangesCached[j] = null;
+        }
+      }
+      assert_not_equals(testRangesCached[j], null,
+        "Setting up the range failed");
+
+      var range = testRangesCached[j].cloneRange();
+
+      // "If node's root is different from the context object's root,
+      // return false and terminate these steps."
+      if (furthestAncestor(node) !== furthestAncestor(range.startContainer)) {
+        assert_equals(range.intersectsNode(node), false,
+          "Must return false if node and range have different roots");
+        return;
+      }
+
+      // "Let parent be node's parent."
+      var parent_ = node.parentNode;
+
+      // "If parent is null, return true and terminate these steps."
+      if (!parent_) {
+        assert_equals(range.intersectsNode(node), true,
+          "Must return true if node's parent is null");
+        return;
+      }
+
+      // "Let offset be node's index."
+      var offset = indexOf(node);
+
+      // "If (parent, offset) is before end and (parent, offset + 1) is
+      // after start, return true and terminate these steps."
+      if (getPosition(parent_, offset, range.endContainer, range.endOffset) === "before"
+      && getPosition(parent_, offset + 1, range.startContainer, range.startOffset) === "after") {
+        assert_equals(range.intersectsNode(node), true,
+          "Must return true if (parent, offset) is before range end and (parent, offset + 1) is after range start");
+        return;
+      }
+
+      // "Return false."
+      assert_equals(range.intersectsNode(node), false,
+        "Must return false if (parent, offset) is not before range end or (parent, offset + 1) is not after range start");
+    }, "Node " + i + " " + testNodes[i] + ", range " + j + " " + testRanges[j]);
+  }
+}
+
+testDiv.style.display = "none";
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-selectNode.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-selectNode.html
new file mode 100644
index 0000000..0fbb857d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/ranges/Range-selectNode.html
@@ -0,0 +1,99 @@
+<!doctype html>
+<title>Range.selectNode() and .selectNodeContents() tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+function testSelectNode(range, node) {
+    try {
+        range.collapsed;
+    } catch (e) {
+        // Range is detached
+        assert_throws("INVALID_STATE_ERR", function () {
+            range.selectNode(node);
+        }, "selectNode() on a detached node must throw INVALID_STATE_ERR");
+        assert_throws("INVALID_STATE_ERR", function () {
+            range.selectNodeContents(node);
+        }, "selectNodeContents() on a detached node must throw INVALID_STATE_ERR");
+        return;
+    }
+
+    if (!node.parentNode) {
+        assert_throws("INVALID_NODE_TYPE_ERR", function() {
+            range.selectNode(node);
+        }, "selectNode() on a node with no parent must throw INVALID_NODE_TYPE_ERR");
+    } else {
+        var index = 0;
+        while (node.parentNode.childNodes[index] != node) {
+            index++;
+        }
+
+        range.selectNode(node);
+        assert_equals(range.startContainer, node.parentNode,
+            "After selectNode(), startContainer must equal parent node");
+        assert_equals(range.endContainer, node.parentNode,
+            "After selectNode(), endContainer must equal parent node");
+        assert_equals(range.startOffset, index,
+            "After selectNode(), startOffset must be index of node in parent (" + index + ")");
+        assert_equals(range.endOffset, index + 1,
+            "After selectNode(), endOffset must be one plus index of node in parent (" + (index + 1) + ")");
+    }
+
+    if (node.nodeType == Node.DOCUMENT_TYPE_NODE) {
+        assert_throws("INVALID_NODE_TYPE_ERR", function () {
+            range.selectNodeContents(node);
+        }, "selectNodeContents() on a doctype must throw INVALID_NODE_TYPE_ERR");
+    } else {
+        range.selectNodeContents(node);
+        assert_equals(range.startContainer, node,
+            "After selectNodeContents(), startContainer must equal node");
+        assert_equals(range.endContainer, node,
+            "After selectNodeContents(), endContainer must equal node");
+        assert_equals(range.startOffset, 0,
+            "After selectNodeContents(), startOffset must equal 0");
+        var len = nodeLength(node);
+        assert_equals(range.endOffset, len,
+            "After selectNodeContents(), endOffset must equal node length (" + len + ")");
+    }
+}
+
+var range = document.createRange();
+var foreignRange = foreignDoc.createRange();
+var xmlRange = xmlDoc.createRange();
+var detachedRange = document.createRange();
+detachedRange.detach();
+var tests = [];
+function testTree(root, marker) {
+    if (root.nodeType == Node.ELEMENT_NODE && root.id == "log") {
+        // This is being modified during the tests, so let's not test it.
+        return;
+    }
+    tests.push([marker + root.nodeName.toLowerCase() + " node, current doc's range, type " + root.nodeType, range, root]);
+    tests.push([marker + root.nodeName.toLowerCase() + " node, foreign doc's range, type " + root.nodeType, foreignRange, root]);
+    tests.push([marker + root.nodeName.toLowerCase() + " node, XML doc's range, type " + root.nodeType, xmlRange, root]);
+    tests.push([marker + root.nodeName.toLowerCase() + " node, detached range, type " + root.nodeType, detachedRange, root]);
+    for (var i = 0; i < root.childNodes.length; i++) {
+        testTree(root.childNodes[i], "**" + marker);
+    }
+}
+testTree(document, " current doc: ");
+testTree(foreignDoc, " foreign doc: ");
+testTree(detachedDiv, " detached div in current doc: ");
+
+var otherTests = [xmlDoc, xmlElement, detachedTextNode, foreignTextNode,
+xmlTextNode, processingInstruction, comment, foreignComment, xmlComment,
+docfrag, foreignDocfrag, xmlDocfrag];
+
+for (var i = 0; i < otherTests.length; i++) {
+    testTree(otherTests[i], " ");
+}
+
+generate_tests(testSelectNode, tests);
+
+testDiv.style.display = "none";
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/NodeFilter-constants.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/NodeFilter-constants.html
new file mode 100644
index 0000000..b82f7e6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/NodeFilter-constants.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<title>NodeFilter constants</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="../constants.js"></script>
+<div id="log"></div>
+<script>
+var objects;
+setup(function() {
+  objects = [
+    [NodeFilter, "NodeFilter interface object"],
+  ]
+})
+testConstants(objects, [
+  ["FILTER_ACCEPT", 1],
+  ["FILTER_REJECT", 2],
+  ["FILTER_SKIP", 3]
+], "acceptNode")
+testConstants(objects, [
+  ["SHOW_ALL", 0xFFFFFFFF],
+  ["SHOW_ELEMENT", 0x1],
+  ["SHOW_ATTRIBUTE", 0x2],
+  ["SHOW_TEXT", 0x4],
+  ["SHOW_CDATA_SECTION", 0x8],
+  ["SHOW_ENTITY_REFERENCE", 0x10],
+  ["SHOW_ENTITY", 0x20],
+  ["SHOW_PROCESSING_INSTRUCTION", 0x40],
+  ["SHOW_COMMENT", 0x80],
+  ["SHOW_DOCUMENT", 0x100],
+  ["SHOW_DOCUMENT_TYPE", 0x200],
+  ["SHOW_DOCUMENT_FRAGMENT", 0x400],
+  ["SHOW_NOTATION", 0x800]
+], "whatToShow")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/NodeIterator-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/NodeIterator-expected.txt
new file mode 100644
index 0000000..46595c8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/NodeIterator-expected.txt
@@ -0,0 +1,748 @@
+This is a testharness.js-based test.
+PASS detach() should be a no-op 
+PASS createNodeIterator() parameter defaults 
+PASS createNodeIterator() with null as arguments 
+PASS createNodeIterator() with undefined as arguments 
+PASS Propagate exception from filter function 
+PASS document.createNodeIterator(paras[0], 0, null) 
+FAIL document.createNodeIterator(paras[0], 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0], 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0], 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[0], 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(paras[0], 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0], 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0], 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[0], NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(paras[0], NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0], NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0], NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[0], NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(paras[0], NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0], NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0], NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[0], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(paras[0], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[0].firstChild, 0, null) 
+FAIL document.createNodeIterator(paras[0].firstChild, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0].firstChild, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0].firstChild, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[0].firstChild, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(paras[0].firstChild, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0].firstChild, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0].firstChild, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[0].firstChild, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(paras[0].firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0].firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0].firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[0].firstChild, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(paras[0].firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0].firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0].firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[0].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(paras[0].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[0].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[1].firstChild, 0, null) 
+FAIL document.createNodeIterator(paras[1].firstChild, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1].firstChild, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1].firstChild, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[1].firstChild, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(paras[1].firstChild, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1].firstChild, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1].firstChild, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[1].firstChild, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(paras[1].firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1].firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1].firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[1].firstChild, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(paras[1].firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1].firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1].firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[1].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(paras[1].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignPara1, 0, null) 
+FAIL document.createNodeIterator(foreignPara1, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignPara1, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(foreignPara1, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignPara1, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(foreignPara1, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignPara1, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(foreignPara1, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(foreignPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignPara1.firstChild, 0, null) 
+FAIL document.createNodeIterator(foreignPara1.firstChild, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1.firstChild, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1.firstChild, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignPara1.firstChild, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(foreignPara1.firstChild, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1.firstChild, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1.firstChild, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(foreignPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara1, 0, null) 
+FAIL document.createNodeIterator(detachedPara1, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara1, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(detachedPara1, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara1, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(detachedPara1, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara1, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(detachedPara1, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(detachedPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara1.firstChild, 0, null) 
+FAIL document.createNodeIterator(detachedPara1.firstChild, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1.firstChild, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1.firstChild, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara1.firstChild, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(detachedPara1.firstChild, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1.firstChild, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1.firstChild, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(detachedPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(document, 0, null) 
+FAIL document.createNodeIterator(document, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(document, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(document, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(document, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(document, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(document, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(document, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(document, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(document, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(document, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(document, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedDiv, 0, null) 
+FAIL document.createNodeIterator(detachedDiv, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedDiv, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedDiv, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedDiv, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(detachedDiv, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedDiv, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedDiv, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedDiv, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(detachedDiv, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedDiv, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedDiv, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedDiv, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(detachedDiv, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedDiv, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedDiv, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(detachedDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignDoc, 0, null) 
+FAIL document.createNodeIterator(foreignDoc, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoc, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoc, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignDoc, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(foreignDoc, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoc, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoc, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignDoc, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(foreignDoc, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoc, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoc, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignDoc, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(foreignDoc, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoc, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoc, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(foreignDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignPara2, 0, null) 
+FAIL document.createNodeIterator(foreignPara2, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara2, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara2, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignPara2, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(foreignPara2, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara2, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara2, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignPara2, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(foreignPara2, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara2, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara2, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignPara2, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(foreignPara2, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara2, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara2, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(foreignPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlDoc, 0, null) 
+FAIL document.createNodeIterator(xmlDoc, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoc, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoc, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlDoc, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(xmlDoc, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoc, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoc, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlDoc, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(xmlDoc, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoc, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoc, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlDoc, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(xmlDoc, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoc, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoc, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(xmlDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlElement, 0, null) 
+FAIL document.createNodeIterator(xmlElement, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlElement, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlElement, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlElement, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(xmlElement, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlElement, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlElement, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlElement, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(xmlElement, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlElement, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlElement, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlElement, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(xmlElement, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlElement, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlElement, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(xmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedTextNode, 0, null) 
+FAIL document.createNodeIterator(detachedTextNode, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedTextNode, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedTextNode, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedTextNode, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(detachedTextNode, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedTextNode, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedTextNode, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedTextNode, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(detachedTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedTextNode, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(detachedTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(detachedTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignTextNode, 0, null) 
+FAIL document.createNodeIterator(foreignTextNode, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignTextNode, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignTextNode, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignTextNode, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(foreignTextNode, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignTextNode, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignTextNode, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignTextNode, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(foreignTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignTextNode, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(foreignTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(foreignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(processingInstruction, 0, null) 
+FAIL document.createNodeIterator(processingInstruction, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(processingInstruction, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(processingInstruction, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(processingInstruction, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(processingInstruction, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(processingInstruction, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(processingInstruction, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(processingInstruction, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(processingInstruction, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(processingInstruction, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(processingInstruction, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(processingInstruction, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(processingInstruction, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(processingInstruction, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(processingInstruction, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(processingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(processingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(processingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(processingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedProcessingInstruction, 0, null) 
+FAIL document.createNodeIterator(detachedProcessingInstruction, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedProcessingInstruction, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedProcessingInstruction, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedProcessingInstruction, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(detachedProcessingInstruction, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedProcessingInstruction, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedProcessingInstruction, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedProcessingInstruction, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(detachedProcessingInstruction, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedProcessingInstruction, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedProcessingInstruction, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(comment, 0, null) 
+FAIL document.createNodeIterator(comment, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(comment, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(comment, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(comment, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(comment, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(comment, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(comment, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(comment, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(comment, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(comment, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(comment, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(comment, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(comment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(comment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(comment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(comment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(comment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(comment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(comment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedComment, 0, null) 
+FAIL document.createNodeIterator(detachedComment, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedComment, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedComment, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedComment, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(detachedComment, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedComment, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedComment, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedComment, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(detachedComment, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedComment, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedComment, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedComment, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(detachedComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(detachedComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(docfrag, 0, null) 
+FAIL document.createNodeIterator(docfrag, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(docfrag, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(docfrag, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(docfrag, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(docfrag, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(docfrag, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(docfrag, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(docfrag, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(docfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(docfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(docfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(docfrag, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(docfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(docfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(docfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(docfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(docfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(docfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(docfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(doctype, 0, null) 
+FAIL document.createNodeIterator(doctype, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(doctype, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(doctype, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(doctype, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(doctype, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(doctype, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(doctype, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(doctype, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(doctype, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(doctype, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(doctype, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(doctype, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(doctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(doctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(doctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(doctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(doctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(doctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(doctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignDoctype, 0, null) 
+FAIL document.createNodeIterator(foreignDoctype, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoctype, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoctype, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignDoctype, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(foreignDoctype, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoctype, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoctype, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignDoctype, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(foreignDoctype, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoctype, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoctype, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignDoctype, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(foreignDoctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(foreignDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[1], 0, null) 
+FAIL document.createNodeIterator(paras[1], 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1], 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1], 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[1], 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(paras[1], 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1], 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1], 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[1], NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(paras[1], NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1], NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1], NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[1], NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(paras[1], NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1], NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1], NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(paras[1], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(paras[1], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(paras[1], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara2, 0, null) 
+FAIL document.createNodeIterator(detachedPara2, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara2, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(detachedPara2, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara2, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(detachedPara2, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara2, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(detachedPara2, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(detachedPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara2.firstChild, 0, null) 
+FAIL document.createNodeIterator(detachedPara2.firstChild, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2.firstChild, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2.firstChild, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara2.firstChild, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(detachedPara2.firstChild, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2.firstChild, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2.firstChild, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara2.firstChild, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(detachedPara2.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(testDiv, 0, null) 
+FAIL document.createNodeIterator(testDiv, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(testDiv, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(testDiv, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(testDiv, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(testDiv, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(testDiv, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(testDiv, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(testDiv, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(testDiv, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(testDiv, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(testDiv, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(testDiv, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(testDiv, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(testDiv, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(testDiv, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(testDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(testDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(testDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(testDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedXmlElement, 0, null) 
+FAIL document.createNodeIterator(detachedXmlElement, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlElement, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlElement, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedXmlElement, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(detachedXmlElement, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlElement, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlElement, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedXmlElement, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(detachedXmlElement, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlElement, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlElement, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedXmlElement, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(detachedXmlElement, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlElement, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlElement, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedXmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(detachedXmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedForeignTextNode, 0, null) 
+FAIL document.createNodeIterator(detachedForeignTextNode, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignTextNode, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignTextNode, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedForeignTextNode, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(detachedForeignTextNode, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignTextNode, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignTextNode, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedForeignTextNode, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(detachedForeignTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlTextNode, 0, null) 
+FAIL document.createNodeIterator(xmlTextNode, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlTextNode, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlTextNode, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlTextNode, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(xmlTextNode, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlTextNode, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlTextNode, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlTextNode, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(xmlTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlTextNode, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(xmlTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(xmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedXmlTextNode, 0, null) 
+FAIL document.createNodeIterator(detachedXmlTextNode, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlTextNode, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlTextNode, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedXmlTextNode, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(detachedXmlTextNode, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlTextNode, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlTextNode, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedXmlTextNode, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(detachedXmlTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlComment, 0, null) 
+FAIL document.createNodeIterator(xmlComment, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlComment, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlComment, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlComment, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(xmlComment, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlComment, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlComment, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlComment, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(xmlComment, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlComment, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlComment, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlComment, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(xmlComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(xmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignComment, 0, null) 
+FAIL document.createNodeIterator(foreignComment, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignComment, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignComment, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignComment, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(foreignComment, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignComment, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignComment, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignComment, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(foreignComment, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignComment, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignComment, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignComment, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(foreignComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(foreignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedForeignComment, 0, null) 
+FAIL document.createNodeIterator(detachedForeignComment, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignComment, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignComment, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedForeignComment, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(detachedForeignComment, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignComment, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignComment, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedForeignComment, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(detachedForeignComment, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignComment, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignComment, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedForeignComment, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(detachedForeignComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedForeignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(detachedForeignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedForeignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedXmlComment, 0, null) 
+FAIL document.createNodeIterator(detachedXmlComment, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlComment, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlComment, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedXmlComment, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(detachedXmlComment, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlComment, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlComment, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedXmlComment, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(detachedXmlComment, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlComment, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlComment, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedXmlComment, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(detachedXmlComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(detachedXmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(detachedXmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(detachedXmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignDocfrag, 0, null) 
+FAIL document.createNodeIterator(foreignDocfrag, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDocfrag, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDocfrag, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignDocfrag, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(foreignDocfrag, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDocfrag, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDocfrag, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignDocfrag, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(foreignDocfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDocfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDocfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignDocfrag, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(foreignDocfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDocfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDocfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(foreignDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(foreignDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(foreignDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlDocfrag, 0, null) 
+FAIL document.createNodeIterator(xmlDocfrag, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDocfrag, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDocfrag, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlDocfrag, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(xmlDocfrag, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDocfrag, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDocfrag, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlDocfrag, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(xmlDocfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDocfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDocfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlDocfrag, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(xmlDocfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDocfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDocfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(xmlDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlDoctype, 0, null) 
+FAIL document.createNodeIterator(xmlDoctype, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoctype, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoctype, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlDoctype, 0xFFFFFFFF, null) 
+FAIL document.createNodeIterator(xmlDoctype, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoctype, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoctype, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlDoctype, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createNodeIterator(xmlDoctype, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoctype, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoctype, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlDoctype, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createNodeIterator(xmlDoctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createNodeIterator(xmlDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createNodeIterator(xmlDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createNodeIterator(xmlDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/NodeIterator-removal.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/NodeIterator-removal.html
new file mode 100644
index 0000000..f752461
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/NodeIterator-removal.html
@@ -0,0 +1,100 @@
+<!doctype html>
+<title>NodeIterator removal tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+for (var i = 0; i < testNodes.length; i++) {
+  var node = eval(testNodes[i]);
+  if (!node.parentNode) {
+    // Nothing to test
+    continue;
+  }
+  test(function() {
+    var iters = [];
+    var descs = [];
+    var expectedReferenceNodes = [];
+    var expectedPointers = [];
+
+    for (var j = 0; j < testNodes.length; j++) {
+      var root = eval(testNodes[j]);
+      // Add all distinct iterators with this root, calling nextNode()
+      // repeatedly until it winds up with the same iterator.
+      for (var k = 0; ; k++) {
+        var iter = document.createNodeIterator(root);
+        for (var l = 0; l < k; l++) {
+          iter.nextNode();
+        }
+        if (k && iter.referenceNode == iters[iters.length - 1].referenceNode
+            && iter.pointerBeforeReferenceNode
+               == iters[iters.length - 1].pointerBeforeReferenceNode) {
+          break;
+        } else {
+          iters.push(iter);
+          descs.push("document.createNodeIterator(" + testNodes[j]
+            + ") advanced " + k + " times");
+          expectedReferenceNodes.push(iter.referenceNode);
+          expectedPointers.push(iter.pointerBeforeReferenceNode);
+
+          var idx = iters.length - 1;
+
+          // "If the node is root or is not an inclusive ancestor of the
+          // referenceNode attribute value, terminate these steps."
+          //
+          // We also have to rule out the case where node is an ancestor of
+          // root, which is implicitly handled by the spec since such a node
+          // was not part of the iterator collection to start with.
+          if (isInclusiveAncestor(node, root)
+              || !isInclusiveAncestor(node, iter.referenceNode)) {
+            continue;
+          }
+
+          // "If the pointerBeforeReferenceNode attribute value is false, set
+          // the referenceNode attribute to the first node preceding the node
+          // that is being removed, and terminate these steps."
+          if (!iter.pointerBeforeReferenceNode) {
+            expectedReferenceNodes[idx] = previousNode(node);
+            continue;
+          }
+
+          // "If there is a node following the last inclusive descendant of the
+          // node that is being removed, set the referenceNode attribute to the
+          // first such node, and terminate these steps."
+          var next = nextNodeDescendants(node);
+          if (next) {
+            expectedReferenceNodes[idx] = next;
+            continue;
+          }
+
+          // "Set the referenceNode attribute to the first node preceding the
+          // node that is being removed and set the pointerBeforeReferenceNode
+          // attribute to false."
+          expectedReferenceNodes[idx] = previousNode(node);
+          expectedPointers[idx] = false;
+        }
+      }
+    }
+
+    var oldParent = node.parentNode;
+    var oldSibling = node.nextSibling;
+    oldParent.removeChild(node);
+
+    for (var j = 0; j < iters.length; j++) {
+      var iter = iters[j];
+      assert_equals(iter.referenceNode, expectedReferenceNodes[j],
+                    ".referenceNode of " + descs[j]);
+      assert_equals(iter.pointerBeforeReferenceNode, expectedPointers[j],
+                    ".pointerBeforeReferenceNode of " + descs[j]);
+    }
+
+    oldParent.insertBefore(node, oldSibling);
+  }, "Test removing node " + testNodes[i]);
+}
+
+testDiv.style.display = "none";
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/NodeIterator.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/NodeIterator.html
new file mode 100644
index 0000000..544a63b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/NodeIterator.html
@@ -0,0 +1,202 @@
+<!doctype html>
+<title>NodeIterator tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+function check_iter(iter, root, whatToShowValue) {
+    whatToShowValue = whatToShowValue === undefined ? 0xFFFFFFFF : whatToShowValue;
+
+    assert_equals(iter.toString(), '[object NodeIterator]', 'toString');
+    assert_equals(iter.root, root, 'root');
+    assert_equals(iter.whatToShow, whatToShowValue, 'whatToShow');
+    assert_equals(iter.filter, null, 'filter');
+    assert_equals(iter.referenceNode, root, 'referenceNode');
+    assert_equals(iter.pointerBeforeReferenceNode, true, 'pointerBeforeReferenceNode');
+    assert_readonly(iter, 'root');
+    assert_readonly(iter, 'whatToShow');
+    assert_readonly(iter, 'filter');
+    assert_readonly(iter, 'referenceNode');
+    assert_readonly(iter, 'pointerBeforeReferenceNode');
+}
+
+test(function() {
+  var iter = document.createNodeIterator(document);
+  iter.detach();
+  iter.detach();
+}, "detach() should be a no-op");
+
+test(function() {
+  var iter = document.createNodeIterator(document);
+  check_iter(iter, document);
+}, "createNodeIterator() parameter defaults");
+
+test(function() {
+  var iter = document.createNodeIterator(document, null, null);
+  check_iter(iter, document, 0);
+}, "createNodeIterator() with null as arguments");
+
+test(function() {
+  var iter = document.createNodeIterator(document, undefined, undefined);
+  check_iter(iter, document);
+}, "createNodeIterator() with undefined as arguments");
+
+test(function() {
+  var iter = document.createNodeIterator(document, NodeFilter.SHOW_ALL,
+                                        function() { throw {name: "failed"} });
+  assert_throws({name: "failed"}, function() { iter.nextNode() });
+}, "Propagate exception from filter function");
+
+function testIterator(root, whatToShow, filter) {
+  var iter = document.createNodeIterator(root, whatToShow, filter);
+
+  assert_equals(iter.root, root, ".root");
+  assert_equals(iter.referenceNode, root, "Initial .referenceNode");
+  assert_equals(iter.pointerBeforeReferenceNode, true,
+                ".pointerBeforeReferenceNode");
+  assert_equals(iter.whatToShow, whatToShow, ".whatToShow");
+  assert_equals(iter.filter, filter, ".filter");
+
+  var expectedReferenceNode = root;
+  var expectedBeforeNode = true;
+  // "Let node be the value of the referenceNode attribute."
+  var node = root;
+  // "Let before node be the value of the pointerBeforeReferenceNode
+  // attribute."
+  var beforeNode = true;
+  var i = 1;
+  // Each loop iteration runs nextNode() once.
+  while (node) {
+    do {
+      if (!beforeNode) {
+        // "If before node is false, let node be the first node following node
+        // in the iterator collection. If there is no such node return null."
+        node = nextNode(node);
+        if (!isInclusiveDescendant(node, root)) {
+          node = null;
+          break;
+        }
+      } else {
+        // "If before node is true, set it to false."
+        beforeNode = false;
+      }
+      // "Filter node and let result be the return value.
+      //
+      // "If result is FILTER_ACCEPT, go to the next step in the overall set of
+      // steps.
+      //
+      // "Otherwise, run these substeps again."
+      if (!((1 << (node.nodeType - 1)) & whatToShow)
+          || (filter && filter(node) != NodeFilter.FILTER_ACCEPT)) {
+        continue;
+      }
+
+      // "Set the referenceNode attribute to node, set the
+      // pointerBeforeReferenceNode attribute to before node, and return node."
+      expectedReferenceNode = node;
+      expectedBeforeNode = beforeNode;
+
+      break;
+    } while (true);
+
+    assert_equals(iter.nextNode(), node, ".nextNode() " + i + " time(s)");
+    assert_equals(iter.referenceNode, expectedReferenceNode,
+                  ".referenceNode after nextNode() " + i + " time(s)");
+    assert_equals(iter.pointerBeforeReferenceNode, expectedBeforeNode,
+             ".pointerBeforeReferenceNode after nextNode() " + i + " time(s)");
+
+    i++;
+  }
+
+  // Same but for previousNode() (mostly copy-pasted, oh well)
+  var iter = document.createNodeIterator(root, whatToShow, filter);
+
+  var expectedReferenceNode = root;
+  var expectedBeforeNode = true;
+  // "Let node be the value of the referenceNode attribute."
+  var node = root;
+  // "Let before node be the value of the pointerBeforeReferenceNode
+  // attribute."
+  var beforeNode = true;
+  var i = 1;
+  // Each loop iteration runs previousNode() once.
+  while (node) {
+    do {
+      if (beforeNode) {
+        // "If before node is true, let node be the first node preceding node
+        // in the iterator collection. If there is no such node return null."
+        node = previousNode(node);
+        if (!isInclusiveDescendant(node, root)) {
+          node = null;
+          break;
+        }
+      } else {
+        // "If before node is false, set it to true."
+        beforeNode = true;
+      }
+      // "Filter node and let result be the return value.
+      //
+      // "If result is FILTER_ACCEPT, go to the next step in the overall set of
+      // steps.
+      //
+      // "Otherwise, run these substeps again."
+      if (!((1 << (node.nodeType - 1)) & whatToShow)
+          || (filter && filter(node) != NodeFilter.FILTER_ACCEPT)) {
+        continue;
+      }
+
+      // "Set the referenceNode attribute to node, set the
+      // pointerBeforeReferenceNode attribute to before node, and return node."
+      expectedReferenceNode = node;
+      expectedBeforeNode = beforeNode;
+
+      break;
+    } while (true);
+
+    assert_equals(iter.previousNode(), node, ".previousNode() " + i + " time(s)");
+    assert_equals(iter.referenceNode, expectedReferenceNode,
+                  ".referenceNode after previousNode() " + i + " time(s)");
+    assert_equals(iter.pointerBeforeReferenceNode, expectedBeforeNode,
+         ".pointerBeforeReferenceNode after previousNode() " + i + " time(s)");
+
+    i++;
+  }
+}
+
+var whatToShows = [
+  "0",
+  "0xFFFFFFFF",
+  "NodeFilter.SHOW_ELEMENT",
+  "NodeFilter.SHOW_ATTRIBUTE",
+  "NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT",
+];
+
+var callbacks = [
+  "null",
+  "(function(node) { return true })",
+  "(function(node) { return false })",
+  "(function(node) { return node.nodeName[0] == '#' })",
+];
+
+var tests = [];
+for (var i = 0; i < testNodes.length; i++) {
+  for (var j = 0; j < whatToShows.length; j++) {
+    for (var k = 0; k < callbacks.length; k++) {
+      tests.push([
+        "document.createNodeIterator(" + testNodes[i]
+          + ", " + whatToShows[j] + ", " + callbacks[k] + ")",
+        eval(testNodes[i]), eval(whatToShows[j]), eval(callbacks[k])
+      ]);
+    }
+  }
+}
+
+generate_tests(testIterator, tests);
+
+testDiv.style.display = "none";
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-acceptNode-filter.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-acceptNode-filter.html
new file mode 100644
index 0000000..c423810f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-acceptNode-filter.html
@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<html>
+<!-- 
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/acceptNode-filter.js
+ -->
+<head>
+<title>TreeWalker: acceptNode-filter</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>Test JS objects as NodeFilters</p>
+<script>
+var testElement;
+setup(function() {
+    testElement = document.createElement("div");
+    testElement.id = 'root';
+    //testElement.innerHTML='<div id="A1"><div id="B1"></div><div id="B2"></div></div>';
+
+    // XXX for Servo, build the tree without using innerHTML
+    var a1 = document.createElement("div");
+    a1.id = "A1";
+    var b1 = document.createElement("div");
+    b1.id = "B1";
+    var b2 = document.createElement("div");
+    b2.id = "B2";
+    testElement.appendChild(a1);
+    a1.appendChild(b1);
+    a1.appendChild(b2);
+});
+
+test(function()
+{
+    function filter(node)
+    {
+        if (node.id == "B1")
+            return NodeFilter.FILTER_SKIP;
+        return NodeFilter.FILTER_ACCEPT;
+    }
+
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter);
+    assert_node(walker.currentNode, { type: Element, id: 'root' });
+    assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+    assert_node(walker.currentNode, { type: Element, id: 'A1' });
+    assert_node(walker.nextNode(), { type: Element, id: 'B2' });
+    assert_node(walker.currentNode, { type: Element, id: 'B2' });
+}, 'Testing with raw function filter');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, {
+        acceptNode : function(node) {
+            if (node.id == "B1")
+                return NodeFilter.FILTER_SKIP;
+            return NodeFilter.FILTER_ACCEPT;
+        }
+    });
+    assert_node(walker.currentNode, { type: Element, id: 'root' });
+    assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+    assert_node(walker.currentNode, { type: Element, id: 'A1' });
+    assert_node(walker.nextNode(), { type: Element, id: 'B2' });
+    assert_node(walker.currentNode, { type: Element, id: 'B2' });
+}, 'Testing with object filter');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, null);
+    assert_node(walker.currentNode, { type: Element, id: 'root' });
+    assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+    assert_node(walker.currentNode, { type: Element, id: 'A1' });
+    assert_node(walker.nextNode(), { type: Element, id: 'B1' });
+    assert_node(walker.currentNode, { type: Element, id: 'B1' });
+}, 'Testing with null filter');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, undefined);
+    assert_node(walker.currentNode, { type: Element, id: 'root' });
+    assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+    assert_node(walker.currentNode, { type: Element, id: 'A1' });
+    assert_node(walker.nextNode(), { type: Element, id: 'B1' });
+    assert_node(walker.currentNode, { type: Element, id: 'B1' });
+}, 'Testing with undefined filter');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, {});
+    assert_throws(new TypeError(), function () { walker.firstChild(); });
+    assert_node(walker.currentNode, { type: Element, id: 'root' });
+    assert_throws(new TypeError(), function () { walker.nextNode(); });
+    assert_node(walker.currentNode, { type: Element, id: 'root' });
+}, 'Testing with object lacking acceptNode property');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, { acceptNode: "foo" });
+    assert_throws(new TypeError(), function () { walker.firstChild(); });
+    assert_node(walker.currentNode, { type: Element, id: 'root' });
+    assert_throws(new TypeError(), function () { walker.nextNode(); });
+    assert_node(walker.currentNode, { type: Element, id: 'root' });
+}, 'Testing with object with non-function acceptNode property');
+
+test(function()
+{
+    var filter = function() { return NodeFilter.FILTER_ACCEPT; };
+    filter.acceptNode = function(node) { return NodeFilter.FILTER_SKIP; };
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter);
+    assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+    assert_node(walker.nextNode(), { type: Element, id: 'B1' });
+}, 'Testing with function having acceptNode function');
+
+test(function()
+{
+    var filter = {
+        acceptNode: function(node) {
+            return NodeFilter.FILTER_ACCEPT;
+        }
+    };
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter);
+    assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+}, 'Testing acceptNode callee');
+
+test(function()
+{
+    var test_error = { name: "test" };
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT,
+                                           function(node) {
+                                               throw test_error;
+                                           });
+    assert_throws(test_error, function () { walker.firstChild(); });
+    assert_node(walker.currentNode, { type: Element, id: 'root' });
+    assert_throws(test_error, function () { walker.nextNode(); });
+    assert_node(walker.currentNode, { type: Element, id: 'root' });
+}, 'Testing with filter function that throws');
+
+test(function()
+{
+    var test_error = { name: "test" };
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT,
+                                           {
+                                               acceptNode : function(node) {
+                                                   throw test_error;
+                                               }
+                                           });
+    assert_throws(test_error, function () { walker.firstChild(); });
+    assert_node(walker.currentNode, { type: Element, id: 'root' });
+    assert_throws(test_error, function () { walker.nextNode(); });
+    assert_node(walker.currentNode, { type: Element, id: 'root' });
+}, 'Testing with filter object that throws');
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-basic.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-basic.html
new file mode 100644
index 0000000..501c2e7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-basic.html
@@ -0,0 +1,155 @@
+<!DOCTYPE html>
+<html>
+<!-- 
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/TreeWalker-basic.html
+ -->
+<head>
+<title>TreeWalker: Basic test</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>This test checks the basic functionality of TreeWalker.</p>
+<script>
+function createSampleDOM()
+{
+    // Tree structure:
+    //             #a
+    //             |
+    //        +----+----+
+    //        |         |
+    //       "b"        #c
+    //                  |
+    //             +----+----+
+    //             |         |
+    //            #d      <!--j-->
+    //             |
+    //        +----+----+
+    //        |    |    |
+    //       "e"  #f   "i"
+    //             |
+    //          +--+--+
+    //          |     |
+    //         "g" <!--h-->
+    var div = document.createElement('div');
+    div.id = 'a';
+    // div.innerHTML = 'b<div id="c"><div id="d">e<span id="f">g<!--h--></span>i</div><!--j--></div>';
+
+    div.appendChild(document.createTextNode("b"));
+
+    var c = document.createElement("div");
+    c.id = 'c';
+    div.appendChild(c);
+
+    var d = document.createElement("div");
+    d.id = 'd';
+    c.appendChild(d);
+
+    var e = document.createTextNode("e");
+    d.appendChild(e);
+
+    var f = document.createElement("span");
+    f.id = 'f';
+    d.appendChild(f);
+
+    var g = document.createTextNode("g");
+    f.appendChild(g);
+
+    var h = document.createComment("h");
+    f.appendChild(h);
+
+    var i = document.createTextNode("i");
+    d.appendChild(i);
+
+    var j = document.createComment("j");
+    c.appendChild(j);
+
+    return div;
+}
+
+function check_walker(walker, root, whatToShowValue)
+{
+    whatToShowValue = whatToShowValue === undefined ? 0xFFFFFFFF : whatToShowValue;
+
+    assert_equals(walker.toString(), '[object TreeWalker]', 'toString');
+    assert_equals(walker.root, root, 'root');
+    assert_equals(walker.whatToShow, whatToShowValue, 'whatToShow');
+    assert_equals(walker.filter, null, 'filter');
+    assert_equals(walker.currentNode, root, 'currentNode');
+    assert_readonly(walker, 'root');
+    assert_readonly(walker, 'whatToShow');
+    assert_readonly(walker, 'filter');
+}
+
+test(function ()
+{
+    var root = createSampleDOM();
+    var walker = document.createTreeWalker(root);
+    check_walker(walker, root);
+}, 'Construct a TreeWalker by document.createTreeWalker(root).');
+
+test(function ()
+{
+    var root = createSampleDOM();
+    var walker = document.createTreeWalker(root, null, null);
+    check_walker(walker, root, 0);
+}, 'Construct a TreeWalker by document.createTreeWalker(root, null, null).');
+
+test(function ()
+{
+    var root = createSampleDOM();
+    var walker = document.createTreeWalker(root, undefined, undefined);
+    check_walker(walker, root);
+}, 'Construct a TreeWalker by document.createTreeWalker(root, undefined, undefined).');
+
+test(function ()
+{
+    assert_throws(new TypeError(), function () { document.createTreeWalker(); });
+    assert_throws(new TypeError(), function () { document.createTreeWalker(null); });
+    assert_throws(new TypeError(), function () { document.createTreeWalker(undefined); });
+    assert_throws(new TypeError(), function () { document.createTreeWalker(new Object()); });
+    assert_throws(new TypeError(), function () { document.createTreeWalker(1); });
+}, 'Give an invalid root node to document.createTreeWalker().');
+
+test(function ()
+{
+    var root = createSampleDOM();
+    var walker = document.createTreeWalker(root);
+    var f = root.lastChild.firstChild.childNodes[1];  // An element node: div#f.
+
+    assert_node(walker.currentNode, { type: Element, id: 'a' });
+    assert_equals(walker.parentNode(), null);
+    assert_node(walker.currentNode, { type: Element, id: 'a' });
+    assert_node(walker.firstChild(), { type: Text, nodeValue: 'b' });
+    assert_node(walker.currentNode, { type: Text, nodeValue: 'b' });
+    assert_node(walker.nextSibling(), { type: Element, id: 'c' });
+    assert_node(walker.currentNode, { type: Element, id: 'c' });
+    assert_node(walker.lastChild(), { type: Comment, nodeValue: 'j' });
+    assert_node(walker.currentNode, { type: Comment, nodeValue: 'j' });
+    assert_node(walker.previousSibling(), { type: Element, id: 'd' });
+    assert_node(walker.currentNode, { type: Element, id: 'd' });
+    assert_node(walker.nextNode(), { type: Text, nodeValue: 'e' });
+    assert_node(walker.currentNode, { type: Text, nodeValue: 'e' });
+    assert_node(walker.parentNode(), { type: Element, id: 'd' });
+    assert_node(walker.currentNode, { type: Element, id: 'd' });
+    assert_node(walker.previousNode(), { type: Element, id: 'c' });
+    assert_node(walker.currentNode, { type: Element, id: 'c' });
+    assert_equals(walker.nextSibling(), null);
+    assert_node(walker.currentNode, { type: Element, id: 'c' });
+    walker.currentNode = f;
+    assert_equals(walker.currentNode, f);
+}, 'Walk over nodes.');
+
+test(function() {
+    var treeWalker = document.createTreeWalker(document.body, 42, null);
+    assert_equals(treeWalker.root, document.body);
+    assert_equals(treeWalker.currentNode, document.body);
+    assert_equals(treeWalker.whatToShow, 42);
+    assert_equals(treeWalker.filter, null);
+}, "Optional arguments to createTreeWalker should be optional (3 passed, null).");
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-currentNode.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-currentNode.html
new file mode 100644
index 0000000..98829e6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-currentNode.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<!-- 
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/resources/TreeWalker-currentNode.js
+ -->
+<head>
+<title>TreeWalker: currentNode</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<div id='parent'>
+<div id='subTree'><p>Lorem ipsum <span>dolor <b>sit</b> amet</span>, consectetur <i>adipisicing</i> elit, sed do eiusmod <tt>tempor <b><i>incididunt ut</i> labore</b> et dolore magna</tt> aliqua.</p></div>
+</div>
+<p>Test TreeWalker currentNode functionality</p>
+<script>
+// var subTree = document.createElement('div');
+// subTree.innerHTML = "<p>Lorem ipsum <span>dolor <b>sit</b> amet</span>, consectetur <i>adipisicing</i> elit, sed do eiusmod <tt>tempor <b><i>incididunt ut</i> labore</b> et dolore magna</tt> aliqua.</p>"
+// document.body.appendChild(subTree);
+var subTree = document.getElementById("subTree");
+
+var all = function(node) { return true; }
+
+test(function()
+{
+    var w = document.createTreeWalker(subTree, NodeFilter.SHOW_ELEMENT, all);
+    assert_node(w.currentNode, { type: Element, id: 'subTree' });
+    assert_equals(w.parentNode(), null);
+    assert_node(w.currentNode, { type: Element, id: 'subTree' });
+}, "Test that TreeWalker.parent() doesn't set the currentNode to a node not under the root.");
+
+test(function()
+{
+    var w = document.createTreeWalker(subTree,
+                                      NodeFilter.SHOW_ELEMENT
+                                      | NodeFilter.SHOW_COMMENT,
+                                      all);
+    w.currentNode = document.documentElement;
+    assert_equals(w.parentNode(), null);
+    assert_equals(w.currentNode, document.documentElement);
+    w.currentNode = document.documentElement;
+    assert_equals(w.nextNode(), document.documentElement.firstChild);
+    assert_equals(w.currentNode, document.documentElement.firstChild);
+    w.currentNode = document.documentElement;
+    assert_equals(w.previousNode(), null);
+    assert_equals(w.currentNode, document.documentElement);
+    w.currentNode = document.documentElement;
+    assert_equals(w.firstChild(), document.documentElement.firstChild);
+    assert_equals(w.currentNode, document.documentElement.firstChild);
+    w.currentNode = document.documentElement;
+    assert_equals(w.lastChild(), document.documentElement.lastChild);
+    assert_equals(w.currentNode, document.documentElement.lastChild);
+    w.currentNode = document.documentElement;
+    assert_equals(w.nextSibling(), null);
+    assert_equals(w.currentNode, document.documentElement);
+    w.currentNode = document.documentElement;
+    assert_equals(w.previousSibling(), null);
+    assert_equals(w.currentNode, document.documentElement);
+}, "Test that we handle setting the currentNode to arbitrary nodes not under the root element.");
+
+test(function()
+{
+    var w = document.createTreeWalker(subTree, NodeFilter.SHOW_ELEMENT, all);
+    w.currentNode = subTree.previousSibling;
+    assert_equals(w.nextNode(), subTree);
+    w.currentNode = document.getElementById("parent");
+    assert_equals(w.firstChild(), subTree);
+}, "Test how we handle the case when the traversed to node is within the root, but the currentElement is not.");
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-expected.txt
new file mode 100644
index 0000000..3c4f2e1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-expected.txt
@@ -0,0 +1,743 @@
+This is a testharness.js-based test.
+PASS document.createTreeWalker(paras[0], 0, null) 
+FAIL document.createTreeWalker(paras[0], 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0], 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0], 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[0], 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(paras[0], 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0], 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0], 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[0], NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(paras[0], NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0], NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0], NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[0], NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(paras[0], NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0], NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0], NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[0], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(paras[0], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[0].firstChild, 0, null) 
+FAIL document.createTreeWalker(paras[0].firstChild, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0].firstChild, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0].firstChild, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[0].firstChild, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(paras[0].firstChild, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0].firstChild, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0].firstChild, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[0].firstChild, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(paras[0].firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0].firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0].firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[0].firstChild, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(paras[0].firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0].firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0].firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[0].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(paras[0].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[0].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[1].firstChild, 0, null) 
+FAIL document.createTreeWalker(paras[1].firstChild, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1].firstChild, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1].firstChild, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[1].firstChild, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(paras[1].firstChild, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1].firstChild, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1].firstChild, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[1].firstChild, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(paras[1].firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1].firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1].firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[1].firstChild, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(paras[1].firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1].firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1].firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[1].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(paras[1].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1].firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignPara1, 0, null) 
+FAIL document.createTreeWalker(foreignPara1, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignPara1, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(foreignPara1, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignPara1, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(foreignPara1, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignPara1, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(foreignPara1, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(foreignPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignPara1.firstChild, 0, null) 
+FAIL document.createTreeWalker(foreignPara1.firstChild, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1.firstChild, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1.firstChild, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignPara1.firstChild, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(foreignPara1.firstChild, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1.firstChild, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1.firstChild, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(foreignPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara1, 0, null) 
+FAIL document.createTreeWalker(detachedPara1, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara1, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(detachedPara1, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara1, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(detachedPara1, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara1, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(detachedPara1, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(detachedPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara1.firstChild, 0, null) 
+FAIL document.createTreeWalker(detachedPara1.firstChild, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1.firstChild, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1.firstChild, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara1.firstChild, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(detachedPara1.firstChild, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1.firstChild, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1.firstChild, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(detachedPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara1.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(document, 0, null) 
+FAIL document.createTreeWalker(document, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(document, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(document, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(document, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(document, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(document, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(document, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(document, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(document, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(document, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(document, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(document, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(document, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(document, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(document, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(document, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(document, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(document, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(document, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedDiv, 0, null) 
+FAIL document.createTreeWalker(detachedDiv, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedDiv, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedDiv, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedDiv, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(detachedDiv, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedDiv, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedDiv, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedDiv, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(detachedDiv, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedDiv, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedDiv, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedDiv, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(detachedDiv, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedDiv, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedDiv, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(detachedDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignDoc, 0, null) 
+FAIL document.createTreeWalker(foreignDoc, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoc, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoc, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignDoc, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(foreignDoc, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoc, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoc, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignDoc, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(foreignDoc, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoc, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoc, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignDoc, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(foreignDoc, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoc, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoc, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(foreignDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignPara2, 0, null) 
+FAIL document.createTreeWalker(foreignPara2, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara2, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara2, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignPara2, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(foreignPara2, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara2, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara2, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignPara2, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(foreignPara2, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara2, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara2, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignPara2, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(foreignPara2, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara2, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara2, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(foreignPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlDoc, 0, null) 
+FAIL document.createTreeWalker(xmlDoc, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoc, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoc, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlDoc, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(xmlDoc, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoc, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoc, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlDoc, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(xmlDoc, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoc, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoc, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlDoc, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(xmlDoc, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoc, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoc, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(xmlDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoc, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlElement, 0, null) 
+FAIL document.createTreeWalker(xmlElement, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlElement, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlElement, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlElement, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(xmlElement, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlElement, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlElement, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlElement, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(xmlElement, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlElement, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlElement, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlElement, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(xmlElement, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlElement, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlElement, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(xmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedTextNode, 0, null) 
+FAIL document.createTreeWalker(detachedTextNode, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedTextNode, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedTextNode, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedTextNode, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(detachedTextNode, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedTextNode, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedTextNode, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedTextNode, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(detachedTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedTextNode, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(detachedTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(detachedTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignTextNode, 0, null) 
+FAIL document.createTreeWalker(foreignTextNode, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignTextNode, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignTextNode, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignTextNode, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(foreignTextNode, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignTextNode, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignTextNode, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignTextNode, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(foreignTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignTextNode, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(foreignTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(foreignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(processingInstruction, 0, null) 
+FAIL document.createTreeWalker(processingInstruction, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(processingInstruction, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(processingInstruction, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(processingInstruction, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(processingInstruction, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(processingInstruction, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(processingInstruction, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(processingInstruction, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(processingInstruction, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(processingInstruction, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(processingInstruction, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(processingInstruction, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(processingInstruction, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(processingInstruction, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(processingInstruction, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(processingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(processingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(processingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(processingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedProcessingInstruction, 0, null) 
+FAIL document.createTreeWalker(detachedProcessingInstruction, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedProcessingInstruction, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedProcessingInstruction, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedProcessingInstruction, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(detachedProcessingInstruction, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedProcessingInstruction, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedProcessingInstruction, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedProcessingInstruction, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(detachedProcessingInstruction, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedProcessingInstruction, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedProcessingInstruction, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedProcessingInstruction, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(comment, 0, null) 
+FAIL document.createTreeWalker(comment, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(comment, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(comment, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(comment, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(comment, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(comment, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(comment, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(comment, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(comment, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(comment, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(comment, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(comment, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(comment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(comment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(comment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(comment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(comment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(comment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(comment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedComment, 0, null) 
+FAIL document.createTreeWalker(detachedComment, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedComment, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedComment, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedComment, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(detachedComment, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedComment, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedComment, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedComment, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(detachedComment, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedComment, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedComment, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedComment, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(detachedComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(detachedComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(docfrag, 0, null) 
+FAIL document.createTreeWalker(docfrag, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(docfrag, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(docfrag, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(docfrag, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(docfrag, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(docfrag, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(docfrag, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(docfrag, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(docfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(docfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(docfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(docfrag, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(docfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(docfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(docfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(docfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(docfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(docfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(docfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(doctype, 0, null) 
+FAIL document.createTreeWalker(doctype, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(doctype, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(doctype, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(doctype, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(doctype, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(doctype, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(doctype, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(doctype, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(doctype, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(doctype, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(doctype, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(doctype, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(doctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(doctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(doctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(doctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(doctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(doctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(doctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignDoctype, 0, null) 
+FAIL document.createTreeWalker(foreignDoctype, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoctype, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoctype, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignDoctype, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(foreignDoctype, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoctype, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoctype, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignDoctype, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(foreignDoctype, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoctype, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoctype, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignDoctype, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(foreignDoctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(foreignDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[1], 0, null) 
+FAIL document.createTreeWalker(paras[1], 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1], 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1], 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[1], 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(paras[1], 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1], 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1], 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[1], NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(paras[1], NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1], NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1], NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[1], NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(paras[1], NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1], NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1], NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(paras[1], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(paras[1], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(paras[1], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara2, 0, null) 
+FAIL document.createTreeWalker(detachedPara2, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara2, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(detachedPara2, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara2, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(detachedPara2, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara2, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(detachedPara2, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(detachedPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara2.firstChild, 0, null) 
+FAIL document.createTreeWalker(detachedPara2.firstChild, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2.firstChild, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2.firstChild, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara2.firstChild, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(detachedPara2.firstChild, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2.firstChild, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2.firstChild, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara2.firstChild, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(detachedPara2.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2.firstChild, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedPara2.firstChild, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(testDiv, 0, null) 
+FAIL document.createTreeWalker(testDiv, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(testDiv, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(testDiv, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(testDiv, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(testDiv, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(testDiv, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(testDiv, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(testDiv, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(testDiv, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(testDiv, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(testDiv, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(testDiv, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(testDiv, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(testDiv, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(testDiv, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(testDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(testDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(testDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(testDiv, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedXmlElement, 0, null) 
+FAIL document.createTreeWalker(detachedXmlElement, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlElement, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlElement, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedXmlElement, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(detachedXmlElement, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlElement, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlElement, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedXmlElement, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(detachedXmlElement, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlElement, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlElement, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedXmlElement, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(detachedXmlElement, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlElement, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlElement, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedXmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(detachedXmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlElement, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedForeignTextNode, 0, null) 
+FAIL document.createTreeWalker(detachedForeignTextNode, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignTextNode, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignTextNode, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedForeignTextNode, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(detachedForeignTextNode, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignTextNode, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignTextNode, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedForeignTextNode, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(detachedForeignTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlTextNode, 0, null) 
+FAIL document.createTreeWalker(xmlTextNode, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlTextNode, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlTextNode, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlTextNode, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(xmlTextNode, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlTextNode, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlTextNode, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlTextNode, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(xmlTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlTextNode, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(xmlTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(xmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedXmlTextNode, 0, null) 
+FAIL document.createTreeWalker(detachedXmlTextNode, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlTextNode, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlTextNode, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedXmlTextNode, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(detachedXmlTextNode, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlTextNode, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlTextNode, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedXmlTextNode, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(detachedXmlTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlTextNode, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlTextNode, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlComment, 0, null) 
+FAIL document.createTreeWalker(xmlComment, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlComment, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlComment, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlComment, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(xmlComment, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlComment, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlComment, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlComment, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(xmlComment, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlComment, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlComment, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlComment, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(xmlComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(xmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignComment, 0, null) 
+FAIL document.createTreeWalker(foreignComment, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignComment, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignComment, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignComment, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(foreignComment, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignComment, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignComment, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignComment, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(foreignComment, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignComment, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignComment, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignComment, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(foreignComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(foreignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedForeignComment, 0, null) 
+FAIL document.createTreeWalker(detachedForeignComment, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignComment, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignComment, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedForeignComment, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(detachedForeignComment, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignComment, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignComment, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedForeignComment, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(detachedForeignComment, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignComment, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignComment, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedForeignComment, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(detachedForeignComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedForeignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(detachedForeignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedForeignComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedXmlComment, 0, null) 
+FAIL document.createTreeWalker(detachedXmlComment, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlComment, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlComment, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedXmlComment, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(detachedXmlComment, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlComment, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlComment, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedXmlComment, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(detachedXmlComment, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlComment, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlComment, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedXmlComment, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(detachedXmlComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlComment, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(detachedXmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(detachedXmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(detachedXmlComment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignDocfrag, 0, null) 
+FAIL document.createTreeWalker(foreignDocfrag, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDocfrag, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDocfrag, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignDocfrag, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(foreignDocfrag, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDocfrag, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDocfrag, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignDocfrag, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(foreignDocfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDocfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDocfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignDocfrag, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(foreignDocfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDocfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDocfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(foreignDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(foreignDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(foreignDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlDocfrag, 0, null) 
+FAIL document.createTreeWalker(xmlDocfrag, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDocfrag, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDocfrag, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlDocfrag, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(xmlDocfrag, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDocfrag, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDocfrag, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlDocfrag, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(xmlDocfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDocfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDocfrag, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlDocfrag, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(xmlDocfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDocfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDocfrag, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(xmlDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDocfrag, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlDoctype, 0, null) 
+FAIL document.createTreeWalker(xmlDoctype, 0, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoctype, 0, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoctype, 0, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlDoctype, 0xFFFFFFFF, null) 
+FAIL document.createTreeWalker(xmlDoctype, 0xFFFFFFFF, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoctype, 0xFFFFFFFF, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoctype, 0xFFFFFFFF, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlDoctype, NodeFilter.SHOW_ELEMENT, null) 
+FAIL document.createTreeWalker(xmlDoctype, NodeFilter.SHOW_ELEMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoctype, NodeFilter.SHOW_ELEMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoctype, NodeFilter.SHOW_ELEMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlDoctype, NodeFilter.SHOW_ATTRIBUTE, null) 
+FAIL document.createTreeWalker(xmlDoctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoctype, NodeFilter.SHOW_ATTRIBUTE, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+PASS document.createTreeWalker(xmlDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, null) 
+FAIL document.createTreeWalker(xmlDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return true })) assert_equals: .filter expected (function) function "function (node) { return true }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return false })) assert_equals: .filter expected (function) function "function (node) { return false }" but got (object) object "[object NodeFilter]"
+FAIL document.createTreeWalker(xmlDoctype, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT, (function(node) { return node.nodeName[0] == '#' })) assert_equals: .filter expected (function) function "function (node) { return node.nodeName[0] == '#' }" but got (object) object "[object NodeFilter]"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-previousNodeLastChildReject.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-previousNodeLastChildReject.html
new file mode 100644
index 0000000..d5d426d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-previousNodeLastChildReject.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+<!-- 
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/previousNodeLastChildReject.js
+ -->
+<head>
+<title>TreeWalker: previousNodeLastChildReject</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>Test that previousNode properly respects the filter.</p>
+<script>
+var testElement;
+setup(function() {
+    testElement = document.createElement("div");
+    testElement.id = 'root';
+    // testElement.innerHTML='<div id="A1"><div id="B1"><div id="C1"></div><div id="C2"><div id="D1"></div><div id="D2"></div></div></div><div id="B2"><div id="C3"></div><div id="C4"></div></div></div>';
+    // testElement.innerHTML='
+    // <div id="A1">
+    //   <div id="B1">
+    //     <div id="C1">
+    //     </div>
+    //     <div id="C2">
+    //       <div id="D1">
+    //       </div>
+    //       <div id="D2">
+    //       </div>
+    //     </div>
+    //   </div>
+    //   <div id="B2">
+    //     <div id="C3">
+    //     </div>
+    //     <div id="C4">
+    //     </div>
+    //   </div>
+    // </div>';
+
+    // XXX for Servo, build the tree without using innerHTML
+    var a1 = document.createElement("div"); a1.id = "A1";
+    var b1 = document.createElement("div"); b1.id = "B1";
+    var b2 = document.createElement("div"); b2.id = "B2";
+    var c1 = document.createElement("div"); c1.id = "C1";
+    var c2 = document.createElement("div"); c2.id = "C2";
+    var c3 = document.createElement("div"); c3.id = "C3";
+    var c4 = document.createElement("div"); c4.id = "C4";
+    var d1 = document.createElement("div"); d1.id = "D1";
+    var d2 = document.createElement("div"); d2.id = "D2";
+
+    testElement.appendChild(a1);
+    a1.appendChild(b1);
+    a1.appendChild(b2);
+    b1.appendChild(c1);
+    b1.appendChild(c2);
+    b2.appendChild(c3);
+    b2.appendChild(c4);
+    c2.appendChild(d1);
+    c2.appendChild(d2);
+});
+
+test(function()
+{
+    function filter(node)
+    {
+        if (node.id == "C2")
+            return NodeFilter.FILTER_REJECT;
+        return NodeFilter.FILTER_ACCEPT;
+    }
+
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter);
+    assert_node(walker.currentNode, { type: Element, id: 'root' });
+    assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+    assert_node(walker.currentNode, { type: Element, id: 'A1' });
+    assert_node(walker.nextNode(), { type: Element, id: 'B1' });
+    assert_node(walker.currentNode, { type: Element, id: 'B1' });
+    assert_node(walker.nextNode(), { type: Element, id: 'C1' });
+    assert_node(walker.currentNode, { type: Element, id: 'C1' });
+    assert_node(walker.nextNode(), { type: Element, id: 'B2' });
+    assert_node(walker.currentNode, { type: Element, id: 'B2' });
+    assert_node(walker.previousNode(), { type: Element, id: 'C1' });
+    assert_node(walker.currentNode, { type: Element, id: 'C1' });
+}, 'Test that previousNode properly respects the filter.');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-previousSiblingLastChildSkip.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-previousSiblingLastChildSkip.html
new file mode 100644
index 0000000..0533c39a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-previousSiblingLastChildSkip.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<html>
+<!-- 
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/previousSiblingLastChildSkip.js
+ -->
+<head>
+<title>TreeWalker: previousSiblingLastChildSkip</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>Test that previousSibling properly respects the filter.</p>
+<script>
+var testElement;
+setup(function() {
+    testElement = document.createElement("div");
+    testElement.id = 'root';
+    // testElement.innerHTML='<div id="A1"><div id="B1"><div id="C1"></div><div id="C2"><div id="D1"></div><div id="D2"></div></div></div><div id="B2"><div id="C3"></div><div id="C4"></div></div></div>';
+    // testElement.innerHTML='
+    // <div id="A1">
+    //   <div id="B1">
+    //     <div id="C1">
+    //     </div>
+    //     <div id="C2">
+    //       <div id="D1">
+    //       </div>
+    //       <div id="D2">
+    //       </div>
+    //     </div>
+    //   </div>
+    //   <div id="B2">
+    //     <div id="C3">
+    //     </div>
+    //     <div id="C4">
+    //     </div>
+    //   </div>
+    // </div>';
+
+    // XXX for Servo, build the tree without using innerHTML
+    var a1 = document.createElement("div"); a1.id = "A1";
+    var b1 = document.createElement("div"); b1.id = "B1";
+    var b2 = document.createElement("div"); b2.id = "B2";
+    var c1 = document.createElement("div"); c1.id = "C1";
+    var c2 = document.createElement("div"); c2.id = "C2";
+    var c3 = document.createElement("div"); c3.id = "C3";
+    var c4 = document.createElement("div"); c4.id = "C4";
+    var d1 = document.createElement("div"); d1.id = "D1";
+    var d2 = document.createElement("div"); d2.id = "D2";
+
+    testElement.appendChild(a1);
+    a1.appendChild(b1);
+    a1.appendChild(b2);
+    b1.appendChild(c1);
+    b1.appendChild(c2);
+    b2.appendChild(c3);
+    b2.appendChild(c4);
+    c2.appendChild(d1);
+    c2.appendChild(d2);
+});
+
+test(function()
+{
+    function filter(node)
+    {
+        if (node.id == "B1")
+            return NodeFilter.FILTER_SKIP;
+        return NodeFilter.FILTER_ACCEPT;
+    }
+
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter);
+    assert_node(walker.currentNode, { type: Element, id: 'root' });
+    assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+    assert_node(walker.currentNode, { type: Element, id: 'A1' });
+    assert_node(walker.nextNode(), { type: Element, id: 'C1' });
+    assert_node(walker.currentNode, { type: Element, id: 'C1' });
+    assert_node(walker.nextNode(), { type: Element, id: 'C2' });
+    assert_node(walker.currentNode, { type: Element, id: 'C2' });
+    assert_node(walker.nextNode(), { type: Element, id: 'D1' });
+    assert_node(walker.currentNode, { type: Element, id: 'D1' });
+    assert_node(walker.nextNode(), { type: Element, id: 'D2' });
+    assert_node(walker.currentNode, { type: Element, id: 'D2' });
+    assert_node(walker.nextNode(), { type: Element, id: 'B2' });
+    assert_node(walker.currentNode, { type: Element, id: 'B2' });
+    assert_node(walker.previousSibling(), { type: Element, id: 'C2' });
+    assert_node(walker.currentNode, { type: Element, id: 'C2' });
+}, 'Test that previousSibling properly respects the filter.');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-traversal-reject.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-traversal-reject.html
new file mode 100644
index 0000000..2354da23
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-traversal-reject.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<html>
+<!-- 
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/traversal-reject.js
+ -->
+<head>
+<title>TreeWalker: traversal-reject</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>Test TreeWalker with rejection</p>
+<script>
+var testElement;
+setup(function() {
+    testElement = document.createElement("div");
+    testElement.id = 'root';
+    //testElement.innerHTML='<div id="A1">  <div id="B1">  <div id="C1"></div>  </div>  <div id="B2"></div><div id="B3"></div>  </div>';
+    // <div id="A1">
+    //   <div id="B1">
+    //     <div id="C1"></div>
+    //   </div>
+    //   <div id="B2"></div>
+    //   <div id="B3"></div>
+    // </div>
+
+
+    // XXX for Servo, build the tree without using innerHTML
+    var a1 = document.createElement("div"); a1.id = "A1";
+    var b1 = document.createElement("div"); b1.id = "B1";
+    var b2 = document.createElement("div"); b2.id = "B2";
+    var b3 = document.createElement("div"); b3.id = "B3";
+    var c1 = document.createElement("div"); c1.id = "C1";
+
+    testElement.appendChild(a1);
+    a1.appendChild(b1);
+    a1.appendChild(b2);
+    a1.appendChild(b3);
+    b1.appendChild(c1);
+});
+
+var rejectB1Filter = {
+  acceptNode: function(node) {
+    if (node.id == 'B1')
+      return NodeFilter.FILTER_REJECT;
+
+    return NodeFilter.FILTER_ACCEPT;
+  }
+}
+
+var skipB2Filter = {
+  acceptNode: function(node) {
+    if (node.id == 'B2')
+      return NodeFilter.FILTER_SKIP;
+
+    return NodeFilter.FILTER_ACCEPT;
+  }
+}
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, rejectB1Filter);
+    assert_node(walker.nextNode(), { type: Element, id: 'A1' });
+    assert_node(walker.nextNode(), { type: Element, id: 'B2' });
+    assert_node(walker.nextNode(), { type: Element, id: 'B3' });
+}, 'Testing nextNode');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, rejectB1Filter);
+    assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+    assert_node(walker.firstChild(), { type: Element, id: 'B2' });
+}, 'Testing firstChild');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB2Filter);
+    assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+    assert_node(walker.firstChild(), { type: Element, id: 'B1' });
+    assert_node(walker.nextSibling(), { type: Element, id: 'B3' });
+}, 'Testing nextSibling');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, rejectB1Filter);
+    walker.currentNode = testElement.querySelectorAll('#C1')[0];
+    assert_node(walker.parentNode(), { type: Element, id: 'A1' });
+}, 'Testing parentNode');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB2Filter);
+    walker.currentNode = testElement.querySelectorAll('#B3')[0];
+    assert_node(walker.previousSibling(), { type: Element, id: 'B1' });
+}, 'Testing previousSibling');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, rejectB1Filter);
+    walker.currentNode = testElement.querySelectorAll('#B3')[0];
+    assert_node(walker.previousNode(), { type: Element, id: 'B2' });
+    assert_node(walker.previousNode(), { type: Element, id: 'A1' });
+}, 'Testing previousNode');
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-traversal-skip-most.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-traversal-skip-most.html
new file mode 100644
index 0000000..2fe20d1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-traversal-skip-most.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<!-- 
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/traversal-skip-most.js
+ -->
+<head>
+<title>TreeWalker: traversal-skip-most</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>Test TreeWalker with skipping</p>
+<script>
+var testElement;
+setup(function() {
+    testElement = document.createElement("div");
+    testElement.id = 'root';
+    // testElement.innerHTML='<div id="A1"><div id="B1" class="keep"></div><div id="B2">this text matters</div><div id="B3" class="keep"></div></div>';
+    // <div id="A1">
+    //   <div id="B1" class="keep"></div>
+    //   <div id="B2">this text matters</div>
+    //   <div id="B3" class="keep"></div>
+    // </div>
+
+
+    // XXX for Servo, build the tree without using innerHTML
+    var a1 = document.createElement("div"); a1.id = "A1";
+    var b1 = document.createElement("div"); b1.id = "B1"; b1.className = "keep";
+    var b2 = document.createElement("div"); b2.id = "B2";
+    var b3 = document.createElement("div"); b3.id = "B3"; b3.className = "keep";
+
+    testElement.appendChild(a1);
+    a1.appendChild(b1);
+    a1.appendChild(b2)
+        .appendChild(document.createTextNode("this text matters"));
+    a1.appendChild(b3);
+});
+
+var filter = {
+  acceptNode: function(node) {
+    if (node.className == 'keep')
+      return NodeFilter.FILTER_ACCEPT;
+
+    return NodeFilter.FILTER_SKIP;
+  }
+}
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter);
+    assert_node(walker.firstChild(), { type: Element, id: 'B1' });
+    assert_node(walker.nextSibling(), { type: Element, id: 'B3' });
+}, 'Testing nextSibling');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter);
+    walker.currentNode = testElement.querySelectorAll('#B3')[0];
+    assert_node(walker.previousSibling(), { type: Element, id: 'B1' });
+}, 'Testing previousSibling');
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-traversal-skip.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-traversal-skip.html
new file mode 100644
index 0000000..c38fdb4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-traversal-skip.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<html>
+<!-- 
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/traversal-skip.js
+ -->
+<head>
+<title>TreeWalker: traversal-skip</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>Test TreeWalker with skipping</p>
+<script>
+var testElement;
+setup(function() {
+    testElement = document.createElement("div");
+    testElement.id = 'root';
+    // testElement.innerHTML='<div id="A1">  <div id="B1">  <div id="C1"></div>  </div>  <div id="B2"></div><div id="B3"></div>  </div>';
+    // <div id="A1">
+    //   <div id="B1">
+    //     <div id="C1"></div>
+    //   </div>
+    //   <div id="B2"></div>
+    //   <div id="B3"></div>
+    // </div>
+
+
+    // XXX for Servo, build the tree without using innerHTML
+    var a1 = document.createElement("div"); a1.id = "A1";
+    var b1 = document.createElement("div"); b1.id = "B1";
+    var b2 = document.createElement("div"); b2.id = "B2";
+    var b3 = document.createElement("div"); b3.id = "B3";
+    var c1 = document.createElement("div"); c1.id = "C1";
+
+    testElement.appendChild(a1);
+    a1.appendChild(b1);
+    a1.appendChild(b2);
+    a1.appendChild(b3);
+    b1.appendChild(c1);
+});
+
+var skipB1Filter = {
+  acceptNode: function(node) {
+    if (node.id == 'B1')
+      return NodeFilter.FILTER_SKIP;
+
+    return NodeFilter.FILTER_ACCEPT;
+  }
+}
+
+var skipB2Filter = {
+  acceptNode: function(node) {
+    if (node.id == 'B2')
+      return NodeFilter.FILTER_SKIP;
+
+    return NodeFilter.FILTER_ACCEPT;
+  }
+}
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB1Filter);
+    assert_node(walker.nextNode(), { type: Element, id: 'A1' });
+    assert_node(walker.nextNode(), { type: Element, id: 'C1' });
+    assert_node(walker.nextNode(), { type: Element, id: 'B2' });
+    assert_node(walker.nextNode(), { type: Element, id: 'B3' });
+}, 'Testing nextNode');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB1Filter);
+    assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+    assert_node(walker.firstChild(), { type: Element, id: 'C1' });
+}, 'Testing firstChild');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB2Filter);
+    assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+    assert_node(walker.firstChild(), { type: Element, id: 'B1' });
+    assert_node(walker.nextSibling(), { type: Element, id: 'B3' });
+}, 'Testing nextSibling');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB1Filter);
+    walker.currentNode = testElement.querySelectorAll('#C1')[0];
+    assert_node(walker.parentNode(), { type: Element, id: 'A1' });
+}, 'Testing parentNode');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB2Filter);
+    walker.currentNode = testElement.querySelectorAll('#B3')[0];
+    assert_node(walker.previousSibling(), { type: Element, id: 'B1' });
+}, 'Testing previousSibling');
+
+test(function()
+{
+    var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, skipB1Filter);
+    walker.currentNode = testElement.querySelectorAll('#B3')[0];
+    assert_node(walker.previousNode(), { type: Element, id: 'B2' });
+    assert_node(walker.previousNode(), { type: Element, id: 'C1' });
+    assert_node(walker.previousNode(), { type: Element, id: 'A1' });
+}, 'Testing previousNode');
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-walking-outside-a-tree.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-walking-outside-a-tree.html
new file mode 100644
index 0000000..5b68118a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker-walking-outside-a-tree.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<!-- 
+Test adapted from https://github.com/operasoftware/presto-testo/blob/master/core/standards/acid3/individual/006a.html
+ -->
+<head>
+<title>TreeWalker: walking-outside-a-tree</title>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>[Acid3 - Test 006a] walking outside a tree</p>
+<script>
+test(function () {
+    // test 6: walking outside a tree
+    var doc = document.createElement("div");
+    var head = document.createElement('head');
+    var title = document.createElement('title');
+    var body = document.createElement('body');
+    var p = document.createElement('p');
+    doc.appendChild(head);
+    head.appendChild(title);
+    doc.appendChild(body);
+    body.appendChild(p);
+
+    var w = document.createTreeWalker(body, 0xFFFFFFFF, null);
+    doc.removeChild(body);
+    assert_equals(w.lastChild(), p, "TreeWalker failed after removing the current node from the tree");
+    doc.appendChild(p);
+    assert_equals(w.previousNode(), title, "failed to handle regrafting correctly");
+    p.appendChild(body);
+    assert_equals(w.nextNode(), p, "couldn't retrace steps");
+    assert_equals(w.nextNode(), body, "couldn't step back into root");
+    assert_equals(w.previousNode(), null, "root didn't retake its rootish position");
+}, "walking outside a tree");
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker.html
new file mode 100644
index 0000000..1c9a058
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/TreeWalker.html
@@ -0,0 +1,298 @@
+<!doctype html>
+<title>TreeWalker tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+// TODO .previousNode, .nextNode
+
+function filterNode(node, whatToShow, filter) {
+    // "If active flag is set throw an "InvalidStateError"."
+    // Ignore active flag for these tests, we aren't calling recursively
+    // TODO Test me
+
+    // "Let n be node's nodeType attribute value minus 1."
+    var n = node.nodeType - 1;
+
+    // "If the nth bit (where 0 is the least significant bit) of whatToShow is
+    // not set, return FILTER_SKIP."
+    if (!(whatToShow & (1 << n))) {
+        return NodeFilter.FILTER_SKIP;
+    }
+
+    // "If filter is null, return FILTER_ACCEPT."
+    if (!filter) {
+        return NodeFilter.FILTER_ACCEPT;
+    }
+
+    // "Set the active flag."
+    //
+    // "Let result be the return value of invoking filter."
+    //
+    // "Unset the active flag."
+    //
+    // "If an exception was thrown, re-throw the exception."
+    // TODO Test me
+    //
+    // "Return result."
+    return filter(node);
+}
+
+function testTraverseChildren(type, walker, root, whatToShow, filter) {
+    // TODO We don't test .currentNode other than the root
+    walker.currentNode = root;
+    assert_equals(walker.currentNode, root, "Setting .currentNode");
+
+    var expectedReturn = null;
+    var expectedCurrentNode = root;
+
+    // "To traverse children of type type, run these steps:
+    //
+    // "Let node be the value of the currentNode attribute."
+    var node = walker.currentNode;
+
+    // "Set node to node's first child if type is first, and node's last child
+    // if type is last."
+    node = type == "first" ? node.firstChild : node.lastChild;
+
+    // "Main: While node is not null, run these substeps:"
+    while (node) {
+        // "Filter node and let result be the return value."
+        var result = filterNode(node, whatToShow, filter);
+
+        // "If result is FILTER_ACCEPT, then set the currentNode attribute to
+        // node and return node."
+        if (result == NodeFilter.FILTER_ACCEPT) {
+            expectedCurrentNode = expectedReturn = node;
+            break;
+        }
+
+        // "If result is FILTER_SKIP, run these subsubsteps:"
+        if (result == NodeFilter.FILTER_SKIP) {
+            // "Let child be node's first child if type is first, and node's
+            // last child if type is last."
+            var child = type == "first" ? node.firstChild : node.lastChild;
+
+            // "If child is not null, set node to child and goto Main."
+            if (child) {
+                node = child;
+                continue;
+            }
+        }
+
+        // "While node is not null, run these subsubsteps:"
+        while (node) {
+            // "Let sibling be node's next sibling if type is first, and node's
+            // previous sibling if type is last."
+            var sibling = type == "first" ? node.nextSibling
+                : node.previousSibling;
+
+            // "If sibling is not null, set node to sibling and goto Main."
+            if (sibling) {
+                node = sibling;
+                break;
+            }
+
+            // "Let parent be node's parent."
+            var parent = node.parentNode;
+
+            // "If parent is null, parent is root, or parent is currentNode
+            // attribute's value, return null."
+            if (!parent || parent == root || parent == walker.currentNode) {
+                expectedReturn = node = null;
+                break;
+            } else {
+            // "Otherwise, set node to parent."
+                node = parent;
+            }
+        }
+    }
+
+    if (type == "first") {
+        assert_equals(walker.firstChild(), expectedReturn, ".firstChild()");
+        assert_equals(walker.currentNode, expectedCurrentNode,
+            ".currentNode after .firstChild()");
+    } else {
+        assert_equals(walker.lastChild(), expectedReturn, ".lastChild()");
+        assert_equals(walker.currentNode, expectedCurrentNode,
+        ".currentNode after .lastChild()");
+    }
+}
+
+function testTraverseSiblings(type, walker, root, whatToShow, filter) {
+    // TODO We don't test .currentNode other than the root's first or last child
+    if (!root.firstChild) {
+        // Nothing much to test
+
+        walker.currentNode = root;
+        assert_equals(walker.currentNode, root, "Setting .currentNode");
+
+        if (type == "next") {
+            assert_equals(walker.nextSibling(), null, ".nextSibling()");
+            assert_equals(walker.currentNode, root,
+                ".currentNode after .nextSibling()")
+        } else {
+            assert_equals(walker.previousSibling(), null, ".previousSibling()");
+            assert_equals(walker.currentNode, root,
+                ".currentNode after .previousSibling()")
+        }
+        return;
+    }
+
+    if (type == "next") {
+        walker.currentNode = root.firstChild;
+        assert_equals(walker.currentNode, root.firstChild,
+            "Setting .currentNode");
+    } else {
+        walker.currentNode = root.lastChild;
+        assert_equals(walker.currentNode, root.lastChild,
+            "Setting .currentNode");
+    }
+
+    var expectedReturn = null;
+    var expectedCurrentNode = type == "next" ? root.firstChild : root.lastChild;
+
+    // "To traverse siblings of type type run these steps:"
+    (function() {
+        // "Let node be the value of the currentNode attribute."
+        var node = type == "next" ? root.firstChild : root.lastChild;
+
+        // "If node is root, return null.
+        //
+        // "Run these substeps:
+        do {
+            // "Let sibling be node's next sibling if type is next, and node's
+            // previous sibling if type is previous."
+            var sibling = type == "next" ? node.nextSibling :
+                node.previousSibling;
+
+            // "While sibling is not null, run these subsubsteps:"
+            while (sibling) {
+                // "Set node to sibling."
+                node = sibling;
+
+                // "Filter node and let result be the return value."
+                var result = filterNode(node, whatToShow, filter);
+
+                // "If result is FILTER_ACCEPT, then set the currentNode
+                // attribute to node and return node."
+                if (result == NodeFilter.FILTER_ACCEPT) {
+                    expectedCurrentNode = expectedReturn = node;
+                    return;
+                }
+
+                // "Set sibling to node's first child if type is next, and
+                // node's last child if type is previous."
+                sibling = type == "next" ? node.firstChild : node.lastChild;
+
+                // "If result is FILTER_REJECT or sibling is null, then set
+                // sibling to node's next sibling if type is next, and node's
+                // previous sibling if type is previous."
+                if (result == NodeFilter.FILTER_REJECT || !sibling) {
+                    sibling = type == "next" ? node.nextSibling :
+                        node.previousSibling;
+                }
+            }
+
+            // "Set node to its parent."
+            node = node.parentNode;
+
+            // "If node is null or is root, return null.
+            if (!node || node == root) {
+                return;
+            }
+            // "Filter node and if the return value is FILTER_ACCEPT, then
+            // return null."
+            if (filterNode(node, whatToShow, filter)) {
+                return;
+            }
+
+            // "Run these substeps again."
+        } while (true);
+    })();
+
+    if (type == "next") {
+        assert_equals(walker.nextSibling(), expectedReturn, ".nextSibling()");
+        assert_equals(walker.currentNode, expectedCurrentNode,
+            ".currentNode after .nextSibling()");
+    } else {
+        assert_equals(walker.previousSibling(), expectedReturn, ".previousSibling()");
+        assert_equals(walker.currentNode, expectedCurrentNode,
+            ".currentNode after .previousSibling()");
+    }
+}
+
+function testWalker(root, whatToShow, filter) {
+    var walker = document.createTreeWalker(root, whatToShow, filter);
+
+    assert_equals(walker.root, root, ".root");
+    assert_equals(walker.whatToShow, whatToShow, ".whatToShow");
+    assert_equals(walker.filter, filter, ".filter");
+    assert_equals(walker.currentNode, root, ".currentNode");
+
+    var expectedReturn = null;
+    var expectedCurrentNode = walker.currentNode;
+    // "The parentNode() method must run these steps:"
+    //
+    // "Let node be the value of the currentNode attribute."
+    var node = walker.currentNode;
+
+    // "While node is not null and is not root, run these substeps:"
+    while (node && node != root) {
+        // "Let node be node's parent."
+        node = node.parentNode;
+
+        // "If node is not null and filtering node returns FILTER_ACCEPT, then
+        // set the currentNode attribute to node, return node."
+        if (node && filterNode(node, whatToShow, filter) ==
+        NodeFilter.FILTER_ACCEPT) {
+            expectedCurrentNode = expectedReturn = node;
+        }
+    }
+    assert_equals(walker.parentNode(), expectedReturn, ".parentNode()");
+    assert_equals(walker.currentNode, expectedCurrentNode,
+        ".currentNode after .parentNode()");
+
+    testTraverseChildren("first", walker, root, whatToShow, filter);
+    testTraverseChildren("last", walker, root, whatToShow, filter);
+
+    testTraverseSiblings("next", walker, root, whatToShow, filter);
+    testTraverseSiblings("previous", walker, root, whatToShow, filter);
+}
+
+var whatToShows = [
+    "0",
+    "0xFFFFFFFF",
+    "NodeFilter.SHOW_ELEMENT",
+    "NodeFilter.SHOW_ATTRIBUTE",
+    "NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT",
+];
+
+var callbacks = [
+    "null",
+    "(function(node) { return true })",
+    "(function(node) { return false })",
+    "(function(node) { return node.nodeName[0] == '#' })",
+];
+
+var tests = [];
+for (var i = 0; i < testNodes.length; i++) {
+    for (var j = 0; j < whatToShows.length; j++) {
+        for (var k = 0; k < callbacks.length; k++) {
+            tests.push([
+                "document.createTreeWalker(" + testNodes[i] +
+                    ", " + whatToShows[j] + ", " + callbacks[k] + ")",
+                eval(testNodes[i]), eval(whatToShows[j]), eval(callbacks[k])
+            ]);
+        }
+    }
+}
+generate_tests(testWalker, tests);
+
+testDiv.style.display = "none";
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/traversal-support.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/traversal-support.js
new file mode 100644
index 0000000..0d5d8ad
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/traversal-support.js
@@ -0,0 +1,10 @@
+// |expected| should be an object indicating the expected type of node.
+function assert_node(actual, expected)
+{
+    assert_true(actual instanceof expected.type,
+                'Node type mismatch: actual = ' + actual.nodeType + ', expected = ' + expected.nodeType);
+    if (typeof(expected.id) !== 'undefined')
+        assert_equals(actual.id, expected.id);
+    if (typeof(expected.nodeValue) !== 'undefined')
+        assert_equals(actual.nodeValue, expected.nodeValue);
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/unfinished/TODO b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/unfinished/TODO
new file mode 100644
index 0000000..cecdf98
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/traversal/unfinished/TODO
@@ -0,0 +1 @@
+Check what happens when a NodeFilter turns a number not in the range 1..3
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/editing-test-suite.js b/third_party/WebKit/LayoutTests/inspector/sass/editing-test-suite.js
new file mode 100644
index 0000000..880d38b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sass/editing-test-suite.js
@@ -0,0 +1,128 @@
+var initialize_SassEditingTest = function() {
+
+InspectorTest.runEditingTests = function(cssAST)
+{
+    InspectorTest.runTestSuite([
+        function testSetPropertyName(next)
+        {
+            var clone = cssAST.clone();
+            for (var property of clone.rules[0].properties)
+                property.name.setText("NEW-NAME");
+            InspectorTest.addResult(clone.document.newText());
+            next();
+        },
+
+        function testSetPropertyValue(next)
+        {
+            var clone = cssAST.clone();
+            for (var property of clone.rules[0].properties)
+                property.value.setText("NEW-VALUE");
+            InspectorTest.addResult(clone.document.newText());
+            next();
+        },
+
+        function testDisableProperties(next)
+        {
+            var clone = cssAST.clone();
+            for (var property of clone.rules[0].properties)
+                property.setDisabled(true);
+            InspectorTest.addResult(clone.document.newText());
+            next();
+        },
+
+        function testEnableProperties(next)
+        {
+            var clone = cssAST.clone();
+            for (var property of clone.rules[0].properties)
+                property.setDisabled(false);
+            InspectorTest.addResult(clone.document.newText());
+            next();
+        },
+
+        function testRemoveFirstProperty(next)
+        {
+            var clone = cssAST.clone();
+            clone.rules[0].properties[0].remove();
+            InspectorTest.addResult(clone.document.newText());
+            next();
+        },
+
+        function testRemoveAllProperties(next)
+        {
+            var clone = cssAST.clone();
+            var properties = clone.rules[0].properties;
+            while (properties.length)
+                properties[0].remove();
+            InspectorTest.addResult(clone.document.newText());
+            next();
+        },
+
+        function testInsertFirstProperty(next)
+        {
+            var clone = cssAST.clone();
+            var rule = clone.rules[0];
+            var anchor = rule.properties[0];
+            rule.insertProperty("NEW-NAME", "NEW-VALUE", false, anchor, true);
+            InspectorTest.addResult(clone.document.newText());
+            next();
+        },
+
+        function testInsertLastProperty(next)
+        {
+            var clone = cssAST.clone();
+            var rule = clone.rules[0];
+            var anchor = rule.properties[rule.properties.length - 1];
+            rule.insertProperty("NEW-NAME", "NEW-VALUE", false, anchor, false);
+            InspectorTest.addResult(clone.document.newText());
+            next();
+        },
+
+        function testInsertDisabledProperty(next)
+        {
+            var clone = cssAST.clone();
+            var rule = clone.rules[0];
+            var anchor = rule.properties[1];
+            rule.insertProperty("NEW-NAME", "NEW-VALUE", true, anchor, true);
+            InspectorTest.addResult(clone.document.newText());
+            next();
+        },
+
+        function testInsertMultipleProperties(next)
+        {
+            var clone = cssAST.clone();
+            var rule = clone.rules[0];
+            var anchor = rule.properties[rule.properties.length - 1];
+            rule.insertProperty("TRAILING-4", "VALUE", false, anchor, false);
+            rule.insertProperty("TRAILING-3", "VALUE", false, anchor, false);
+            rule.insertProperty("TRAILING-2", "VALUE", false, anchor, false);
+            rule.insertProperty("TRAILING-1", "VALUE", false, anchor, false);
+            InspectorTest.addResult(clone.document.newText());
+            next();
+        },
+
+        function testAppendAndRemoveLastProperty(next)
+        {
+            var clone = cssAST.clone();
+            var rule = clone.rules[0];
+            var anchor = rule.properties[rule.properties.length - 1];
+            rule.insertProperty("NEW-NAME", "NEW-VALUE", false, anchor, false);
+            anchor.remove();
+            InspectorTest.addResult(clone.document.newText());
+            next();
+        },
+
+        function testComplexChange(next)
+        {
+            var clone = cssAST.clone();
+            var rule = clone.rules[0];
+            var lastProperty = rule.properties[rule.properties.length - 1];
+            rule.insertProperty("NEW-NAME", "NEW-VALUE", false, lastProperty, false);
+            lastProperty.name.setText("CHANGED");
+            rule.properties[0].value.setText("CHANGED");
+            rule.properties[1].setDisabled(true);
+            InspectorTest.addResult(clone.document.newText());
+            next();
+        },
+    ]);
+}
+}
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-bad.css b/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-bad.css
new file mode 100644
index 0000000..db235d1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-bad.css
@@ -0,0 +1,2 @@
+div{RENAMED-PROPERTY:Arial;color:red;margin:10px}div .message{display:flex;align-items:center;justify-content:center}
+/*# sourceMappingURL=test-mapping-bad.css.map */
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-bad.css.map b/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-bad.css.map
new file mode 100644
index 0000000..64e2e27a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-bad.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AAAA,GAAI,CACA,WAAW,CAAE,KAAK,CAClB,KAAK,CAAE,GAAG,CACV,MAAM,CAAE,IAAI,CAEZ,YAAS,CACL,OAAO,CAAE,IAAI,CACb,WAAW,CAAE,MAAM,CACnB,eAAe,CAAE,MAAM",
+"sources": ["test-mapping-bad.scss"],
+"names": [],
+"file": "test-mapping-bad.css"
+}
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-bad.scss b/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-bad.scss
new file mode 100644
index 0000000..ba4be50
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-bad.scss
@@ -0,0 +1,11 @@
+div {
+    font-family: Arial;
+    color: red;
+    margin: 10px;
+
+    .message {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+    }
+}
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-good.css b/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-good.css
new file mode 100644
index 0000000..bd13dec
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-good.css
@@ -0,0 +1,2 @@
+div{font-family:Arial;color:red;margin:10px}div .message{display:flex;align-items:center;justify-content:center}
+/*# sourceMappingURL=test-mapping-good.css.map */
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-good.css.map b/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-good.css.map
new file mode 100644
index 0000000..8e67302
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-good.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AAAA,GAAI,CACA,WAAW,CAAE,KAAK,CAClB,KAAK,CAAE,GAAG,CACV,MAAM,CAAE,IAAI,CAEZ,YAAS,CACL,OAAO,CAAE,IAAI,CACb,WAAW,CAAE,MAAM,CACnB,eAAe,CAAE,MAAM",
+"sources": ["test-mapping-good.scss"],
+"names": [],
+"file": "test-mapping-good.css"
+}
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-good.scss b/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-good.scss
new file mode 100644
index 0000000..ba4be50
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sass/resources/test-mapping-good.scss
@@ -0,0 +1,11 @@
+div {
+    font-family: Arial;
+    color: red;
+    margin: 10px;
+
+    .message {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+    }
+}
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/sass-test.js b/third_party/WebKit/LayoutTests/inspector/sass/sass-test.js
index 0470676b..3714f7480 100644
--- a/third_party/WebKit/LayoutTests/inspector/sass/sass-test.js
+++ b/third_party/WebKit/LayoutTests/inspector/sass/sass-test.js
@@ -2,6 +2,12 @@
 
 InspectorTest.preloadModule("sass");
 
+InspectorTest.loadSourceMap = function(header, callback)
+{
+    var completeSourceMapURL = WebInspector.ParsedURL.completeURL(header.sourceURL, header.sourceMapURL);
+    WebInspector.SourceMap.load(completeSourceMapURL, header.sourceURL, callback);
+}
+
 InspectorTest.dumpAST = function(ast)
 {
     var lines = [String.sprintf("=== AST === %s", ast.document.url)];
@@ -134,6 +140,29 @@
     }
 }
 
+InspectorTest.validateMapping = function(mapping, cssAST, sassModels)
+{
+    InspectorTest.addResult("Mapped CSS: " + mapping._cssToSass.size);
+    InspectorTest.addResult("Mapped SCSS: " + mapping._sassToCss.size);
+    var cssNodes = mapping._cssToSass.keysArray();
+    var staleCSS = 0;
+    var staleSASS = 0;
+    for (var i = 0; i < cssNodes.length; ++i) {
+        var cssNode = cssNodes[i];
+        staleCSS += cssNode.document !== cssAST.document ? 1 : 0;
+        var sassNode = mapping.toSASSNode(cssNode);
+        var sassAST = sassModels.get(sassNode.document.url);
+        staleSASS += sassNode.document !== sassAST.document ? 1 : 0;
+    }
+    if (staleCSS || staleSASS) {
+        InspectorTest.addResult("ERROR: found stale entries");
+        InspectorTest.addResult("   -stale CSS: " + staleCSS);
+        InspectorTest.addResult("   -stale SASS: " + staleSASS);
+    } else {
+        InspectorTest.addResult("No stale entries found.");
+    }
+}
+
 InspectorTest.parseSCSS = function(url, text)
 {
     return self.runtime.instancePromise(WebInspector.TokenizerFactory)
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-1-expected.txt b/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-1-expected.txt
new file mode 100644
index 0000000..647fea6a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-1-expected.txt
@@ -0,0 +1,120 @@
+Verifies AST editing of formatted source.
+
+div {
+    /* This is a regular comment */
+    color: red;
+    /* position: absolute; */
+    display: block
+}
+
+Running: testSetPropertyName
+div {
+    /* This is a regular comment */
+    NEW-NAME: red;
+    /* NEW-NAME: absolute; */
+    NEW-NAME: block
+}
+
+
+Running: testSetPropertyValue
+div {
+    /* This is a regular comment */
+    color:NEW-VALUE;
+    /* position:NEW-VALUE; */
+    display:NEW-VALUE}
+
+
+Running: testDisableProperties
+div {
+    /* This is a regular comment */
+    /* color: red; */
+    /* position: absolute; */
+    /* display: block
+ */}
+
+
+Running: testEnableProperties
+div {
+    /* This is a regular comment */
+    color: red;
+    position: absolute; 
+    display: block
+}
+
+
+Running: testRemoveFirstProperty
+div {
+    /* This is a regular comment */
+    /* position: absolute; */
+    display: block
+}
+
+
+Running: testRemoveAllProperties
+div {
+    /* This is a regular comment */
+    }
+
+
+Running: testInsertFirstProperty
+div {
+    /* This is a regular comment */
+    NEW-NAME: NEW-VALUE;
+    color: red;
+    /* position: absolute; */
+    display: block
+;}
+
+
+Running: testInsertLastProperty
+div {
+    /* This is a regular comment */
+    color: red;
+    /* position: absolute; */
+    display: block
+;
+    NEW-NAME: NEW-VALUE;}
+
+
+Running: testInsertDisabledProperty
+div {
+    /* This is a regular comment */
+    color: red;
+    /* NEW-NAME: NEW-VALUE; */
+    /* position: absolute; */
+    display: block
+;}
+
+
+Running: testInsertMultipleProperties
+div {
+    /* This is a regular comment */
+    color: red;
+    /* position: absolute; */
+    display: block
+;
+    TRAILING-4: VALUE;
+    TRAILING-3: VALUE;
+    TRAILING-2: VALUE;
+    TRAILING-1: VALUE;}
+
+
+Running: testAppendAndRemoveLastProperty
+div {
+    /* This is a regular comment */
+    color: red;
+    /* position: absolute; */
+    ;
+    NEW-NAME: NEW-VALUE;}
+
+
+Running: testComplexChange
+div {
+    /* This is a regular comment */
+    color:CHANGED;
+    /* position: absolute; */
+    CHANGED: block
+;
+    NEW-NAME: NEW-VALUE;}
+
+
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-1.html b/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-1.html
new file mode 100644
index 0000000..4259bbde
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-1.html
@@ -0,0 +1,44 @@
+<html>
+<head>
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="../../http/tests/inspector/elements-test.js"></script>
+<script src="./sass-test.js"></script>
+<script src="./editing-test-suite.js"></script>
+<style>
+pre {
+    font-family: monospace;
+}
+</style>
+<script>
+
+function test()
+{
+    InspectorTest.evaluateInPagePromise("getCSS()")
+        .then(result => InspectorTest.parseCSS("", result.value))
+        .then(ast => InspectorTest.runEditingTests(ast))
+        .catch(console.error.bind(console))
+        .then(InspectorTest.completeTest);
+}
+
+function getCSS()
+{
+    return document.querySelector(".snippet").textContent;
+}
+
+</script>
+</head>
+
+<body onload="runTest()">
+<p>
+Verifies AST editing of formatted source.
+</p>
+<pre class="snippet">
+div {
+    /* This is a regular comment */
+    color: red;
+    /* position: absolute; */
+    display: block
+}
+</pre>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-2-expected.txt b/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-2-expected.txt
new file mode 100644
index 0000000..c64227f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-2-expected.txt
@@ -0,0 +1,49 @@
+Verifies AST editing of minified source.
+
+div{color:red;/*display:block;*/margin:0}
+
+Running: testSetPropertyName
+div{NEW-NAME:red;/*NEW-NAME:block;*/NEW-NAME:0}
+
+Running: testSetPropertyValue
+div{color:NEW-VALUE;/*display:NEW-VALUE;*/margin:NEW-VALUE}
+
+Running: testDisableProperties
+div{/* color:red; *//*display:block;*//* margin:0 */}
+
+Running: testEnableProperties
+div{color:red;display:block;margin:0}
+
+Running: testRemoveFirstProperty
+div{/*display:block;*/margin:0}
+
+Running: testRemoveAllProperties
+div{}
+
+Running: testInsertFirstProperty
+div{NEW-NAME: NEW-VALUE;
+color:red;/*display:block;*/margin:0;}
+
+Running: testInsertLastProperty
+div{color:red;/*display:block;*/margin:0;
+NEW-NAME: NEW-VALUE;}
+
+Running: testInsertDisabledProperty
+div{color:red;/* NEW-NAME: NEW-VALUE; */
+/*display:block;*/margin:0;}
+
+Running: testInsertMultipleProperties
+div{color:red;/*display:block;*/margin:0;
+TRAILING-4: VALUE;
+TRAILING-3: VALUE;
+TRAILING-2: VALUE;
+TRAILING-1: VALUE;}
+
+Running: testAppendAndRemoveLastProperty
+div{color:red;/*display:block;*/;
+NEW-NAME: NEW-VALUE;}
+
+Running: testComplexChange
+div{color:CHANGED;/*display:block;*/CHANGED:0;
+NEW-NAME: NEW-VALUE;}
+
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-2.html b/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-2.html
new file mode 100644
index 0000000..7e3b5e0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-2.html
@@ -0,0 +1,37 @@
+<html>
+<head>
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="../../http/tests/inspector/elements-test.js"></script>
+<script src="./sass-test.js"></script>
+<script src="./editing-test-suite.js"></script>
+<style>
+pre {
+    font-family: monospace;
+}
+</style>
+<script>
+
+function test()
+{
+    InspectorTest.evaluateInPagePromise("getCSS()")
+        .then(result => InspectorTest.parseCSS("", result.value))
+        .then(ast => InspectorTest.runEditingTests(ast))
+        .catch(console.error.bind(console))
+        .then(InspectorTest.completeTest);
+}
+
+function getCSS()
+{
+    return document.querySelector(".snippet").textContent;
+}
+
+</script>
+</head>
+
+<body onload="runTest()">
+<p>
+Verifies AST editing of minified source.
+</p>
+<pre class="snippet">div{color:red;/*display:block;*/margin:0}</pre>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/test-mapping-bad-expected.txt b/third_party/WebKit/LayoutTests/inspector/sass/test-mapping-bad-expected.txt
new file mode 100644
index 0000000..bc22b47f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sass/test-mapping-bad-expected.txt
@@ -0,0 +1 @@
+Verify that mapping is not valid for misaligned sources.
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/test-mapping-bad.html b/third_party/WebKit/LayoutTests/inspector/sass/test-mapping-bad.html
new file mode 100644
index 0000000..6ab7655
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sass/test-mapping-bad.html
@@ -0,0 +1,63 @@
+<html>
+<head>
+
+<link rel="stylesheet" href="resources/test-mapping-bad.css">
+
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="../../http/tests/inspector/debugger-test.js"></script>
+<script src="./sass-test.js"></script>
+<script>
+
+function test()
+{
+    var header = InspectorTest.cssModel.styleSheetHeaders().find(header => !!header.sourceMapURL)
+    InspectorTest.loadSourceMap(header, onSourceMapLoaded);
+    InspectorTest.waitForScriptSource("test-mapping-bad.css", onCSSLoaded);
+    InspectorTest.waitForScriptSource("test-mapping-bad.scss", onSCSSLoaded);
+
+    var cssAST;
+    var sassModels = new Map();
+    var sourceMap;
+
+    function onCSSLoaded(uiSourceCode)
+    {
+        uiSourceCode.requestContentPromise()
+            .then(text => InspectorTest.parseCSS(uiSourceCode.originURL(), text))
+            .then(ast => cssAST = ast)
+            .then(maybeCreateMapping);
+    }
+
+    function onSCSSLoaded(uiSourceCode)
+    {
+        uiSourceCode.requestContentPromise()
+            .then(text => InspectorTest.parseSCSS(uiSourceCode.originURL(), text))
+            .then(ast => sassModels.set(ast.document.url, ast))
+            .then(maybeCreateMapping);
+    }
+
+    function onSourceMapLoaded(sm)
+    {
+        sourceMap = sm;
+        maybeCreateMapping();
+    }
+
+    function maybeCreateMapping()
+    {
+        if (!cssAST || !sassModels.size || !sourceMap)
+            return;
+        var mapping = WebInspector.SASSLiveSourceMap.CSSToSASSMapping.fromSourceMap(sourceMap, cssAST, sassModels);
+        if (mapping.isValid()) {
+            InspectorTest.addResult("ERROR: a valid mapping created for misaligned sourcemap.");
+        }
+        InspectorTest.completeTest();
+    }
+}
+
+</script>
+
+</head>
+
+<body onload="runTest()">
+<p>Verify that mapping is not valid for misaligned sources.</p>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/test-mapping-good-expected.txt b/third_party/WebKit/LayoutTests/inspector/sass/test-mapping-good-expected.txt
new file mode 100644
index 0000000..813a825
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sass/test-mapping-good-expected.txt
@@ -0,0 +1,16 @@
+Verify CSSToSASSMapping rebaselines.
+
+Mapped CSS: 12
+Mapped SCSS: 12
+No stale entries found.
+
+Running: testCSSRebase
+Mapped CSS: 10
+Mapped SCSS: 10
+No stale entries found.
+
+Running: testSCSSRebase
+Mapped CSS: 8
+Mapped SCSS: 8
+No stale entries found.
+
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/test-mapping-good.html b/third_party/WebKit/LayoutTests/inspector/sass/test-mapping-good.html
new file mode 100644
index 0000000..4bc7ad7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sass/test-mapping-good.html
@@ -0,0 +1,103 @@
+<html>
+<head>
+
+<link rel="stylesheet" href="resources/test-mapping-good.css">
+
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="../../http/tests/inspector/debugger-test.js"></script>
+<script src="./sass-test.js"></script>
+<script>
+
+function test()
+{
+    var header = InspectorTest.cssModel.styleSheetHeaders().find(header => !!header.sourceMapURL)
+    InspectorTest.loadSourceMap(header, onSourceMapLoaded);
+    InspectorTest.waitForScriptSource("test-mapping-good.css", onCSSLoaded);
+    InspectorTest.waitForScriptSource("test-mapping-good.scss", onSCSSLoaded);
+
+    var cssAST;
+    var sassModels = new Map();
+    var sourceMap;
+    var mapping;
+
+    function onCSSLoaded(uiSourceCode)
+    {
+        uiSourceCode.requestContentPromise()
+            .then(text => InspectorTest.parseCSS(uiSourceCode.originURL(), text))
+            .then(ast => cssAST = ast)
+            .then(maybeCreateMapping);
+    }
+
+    function onSCSSLoaded(uiSourceCode)
+    {
+        uiSourceCode.requestContentPromise()
+            .then(text => InspectorTest.parseSCSS(uiSourceCode.originURL(), text))
+            .then(ast => sassModels.set(ast.document.url, ast))
+            .then(maybeCreateMapping);
+    }
+
+    function onSourceMapLoaded(sm)
+    {
+        sourceMap = sm;
+        maybeCreateMapping();
+    }
+
+    function maybeCreateMapping()
+    {
+        if (!cssAST || !sassModels.size || !sourceMap)
+            return;
+        mapping = WebInspector.SASSLiveSourceMap.CSSToSASSMapping.fromSourceMap(sourceMap, cssAST, sassModels);
+        if (!mapping.isValid()) {
+            InspectorTest.addResult("ERROR: mapping is not valid.");
+            InspectorTest.completeTest();
+            return;
+        }
+        InspectorTest.validateMapping(mapping, cssAST, sassModels);
+        InspectorTest.runTestSuite(testSuite);
+    }
+
+    var testSuite = [
+        function testCSSRebase(next)
+        {
+            var cssClone = cssAST.clone();
+            cssClone.rules[0].properties[1].remove();
+            var cssDiff = WebInspector.SASSSupport.diffModels(cssAST, cssClone);
+            var newMapping = mapping.rebaseForCSSDiff(cssDiff);
+            if (!newMapping.isValid()) {
+                InspectorTest.addResult("ERROR: mapping is not valid.");
+                InspectorTest.completeTest();
+                return;
+            }
+            InspectorTest.validateMapping(newMapping, cssClone, sassModels);
+            next();
+        },
+
+        function testSCSSRebase(next)
+        {
+            var sassAST = sassModels.valuesArray()[0];
+            var sassClone = sassAST.clone();
+            sassClone.rules[1].properties[2].remove();
+            sassClone.rules[1].properties[1].remove();
+            var sassDiff = WebInspector.SASSSupport.diffModels(sassAST, sassClone);
+            var newMapping = mapping.rebaseForSASSDiff(sassDiff);
+            if (!newMapping.isValid()) {
+                InspectorTest.addResult("ERROR: mapping is not valid.");
+                InspectorTest.completeTest();
+                return;
+            }
+            var sassModelsClone = new Map();
+            sassModelsClone.set(sassClone.document.url, sassClone);
+            InspectorTest.validateMapping(newMapping, cssAST, sassModelsClone);
+            next();
+        },
+    ];
+}
+
+</script>
+
+</head>
+
+<body onload="runTest()">
+<p>Verify CSSToSASSMapping rebaselines.</p>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/category-filter.html b/third_party/WebKit/LayoutTests/inspector/tracing/category-filter.html
index 658e2920..29003270 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/category-filter.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/category-filter.html
@@ -4,17 +4,6 @@
 <script src="../../http/tests/inspector/timeline-test.js"></script>
 <script>
 
-function initialize_CategoryFilterTest()
-{
-    InspectorTest.dumpVisibleRecords = function()
-    {
-        var presentationModel = InspectorTest.timelinePresentationModel();
-        var records = presentationModel.filteredRecords();
-        for (var i = 0; i < records.length; ++i)
-            InspectorTest.addResult(records[i].record().type());
-    }
-}
-
 function test()
 {
     var sessionId = "4.20";
@@ -46,28 +35,33 @@
         {"name": "foooooo", "ts": 1099999, "ph": "E", "tid": mainThread, "pid": pid, "cat":"toplevel", "args": {}}
     ];
 
-    InspectorTest.timelineModel().setEventsForTest(testData);
+    var panel = WebInspector.panels.timeline;
+    var model = InspectorTest.timelineModel();
+    model.setEventsForTest(testData);
+    var view = new WebInspector.EventsTimelineTreeView(model, null);
+    view.updateContents(WebInspector.TimelineSelection.fromRange(model.minimumRecordTime(), model.maximumRecordTime()));
+    var filtersControl = view._filtersControl;
 
-    var rootRecord = InspectorTest.timelinePresentationModel().rootRecord();
-    for (var i = 0; i < rootRecord.presentationChildren().length; ++i)
-        rootRecord.presentationChildren()[i].setCollapsed(false);
-
-    var filtersControl = WebInspector.panels.timeline._filtersControl;
     InspectorTest.addResult("Original records");
     filtersControl._notifyFiltersChanged();
-    InspectorTest.dumpVisibleRecords();
+    dumpVisibleRecords();
 
     InspectorTest.addResult("Visible records when 'loading' is disabled");
     WebInspector.TimelineUIUtils.categories().loading.hidden = true;
     filtersControl._notifyFiltersChanged();
-    InspectorTest.dumpVisibleRecords();
+    dumpVisibleRecords();
 
     InspectorTest.addResult("Visible records when 'scripting' is disabled");
     WebInspector.TimelineUIUtils.categories().scripting.hidden = true;
     filtersControl._notifyFiltersChanged();
-    InspectorTest.dumpVisibleRecords();
+    dumpVisibleRecords();
 
     InspectorTest.completeTest();
+
+    function dumpVisibleRecords()
+    {
+        InspectorTest.walkTimelineEventTreeUnderNode(event => InspectorTest.addResult(event.name), view._currentTree)
+    }
 }
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/compile-script-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/compile-script-expected.txt
index e8394a9..7129056 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/compile-script-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/compile-script-expected.txt
@@ -10,7 +10,6 @@
     }
     endTime : <number>
     startTime : <number>
-    thread : <string>
     type : "v8.compile"
 }
 Text details for v8.compile: undefined
@@ -23,7 +22,6 @@
     }
     endTime : <number>
     startTime : <number>
-    thread : <string>
     type : "v8.compile"
 }
 Text details for v8.compile: undefined
@@ -36,7 +34,6 @@
     }
     endTime : <number>
     startTime : <number>
-    thread : <string>
     type : "v8.compile"
 }
 Text details for v8.compile: timeline-script-tag-2.js:1
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/hit-test-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/hit-test-expected.txt
index 4459cd5..151590e 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/hit-test-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/hit-test-expected.txt
@@ -13,7 +13,6 @@
     }
     endTime : <number>
     startTime : <number>
-    thread : <string>
     type : "HitTest"
 }
 Text details for HitTest: null
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/paint-profiler-update.html b/third_party/WebKit/LayoutTests/inspector/tracing/paint-profiler-update.html
index 1dfcf2d3..3209ac2 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/paint-profiler-update.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/paint-profiler-update.html
@@ -27,7 +27,6 @@
     var panel = WebInspector.panels.timeline;
 
     panel._captureLayersAndPicturesSetting.set(true);
-    panel._flameChartEnabledSetting.set(true);
     panel._onModeChanged();
 
     InspectorTest.invokeAsyncWithTimeline("performActions", onRecordingDone);
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-animation-frame-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-animation-frame-expected.txt
index fe7c01eb..2022df56 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-animation-frame-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-animation-frame-expected.txt
@@ -11,13 +11,11 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "RequestAnimationFrame"
 }
 Text details for RequestAnimationFrame: timeline-animation-frame.html:8
 FireAnimationFrame Properties:
 {
-    children : <object>
     data : {
         frame : <string>
         id : <number>
@@ -25,7 +23,6 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "FireAnimationFrame"
 }
 Text details for FireAnimationFrame: timeline-animation-frame.html:8
@@ -40,7 +37,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "CancelAnimationFrame"
 }
 Text details for CancelAnimationFrame: timeline-animation-frame.html:11
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-coalescing-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-coalescing-expected.txt
deleted file mode 100644
index 5a0eba7..0000000
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-coalescing-expected.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-Test timeline records coalescing
-
-Root 
-----> FunctionCall duration: 299.99800:299.99800 (other: 0.00100, scripting: 0.30100, rendering: 299.69700)
---------> Layout x 3 duration: 299.89900:299.89900 (rendering: 299.69700)
-------------> Layout duration: 99.89900:99.89900 (rendering: 99.89900)
-------------> Layout duration: 99.89900:99.89900 (rendering: 99.89900)
-------------> Layout duration: 99.89900:99.89900 (rendering: 99.89900)
-----> Layout duration: 94.89900:94.89900 (rendering: 94.89900)
-----> FunctionCall duration: 199.99700:199.99700 (scripting: 0.19900, painting: 199.79800)
---------> Decode Image x 2 duration: 199.89800:199.89800 (painting: 199.79800)
-------------> Decode Image duration: 99.89800:99.89800 (painting: 99.89800)
-------------> Decode Image duration: 99.90000:99.90000 (painting: 99.90000)
-----> FunctionCall duration: 199.99700:199.99700 (scripting: 0.19900, painting: 199.79800)
---------> Decode Image x 2 duration: 199.89800:199.89800 (painting: 199.79800)
-------------> Decode Image duration: 99.89800:99.89800 (painting: 99.89800)
-------------> Decode Image duration: 99.90000:99.90000 (painting: 99.90000)
-----> RasterTask x 3 duration: 299.89900:299.89900 (painting: 299.69700)
---------> RasterTask duration: 99.89900:99.89900 (painting: 99.89900)
---------> RasterTask duration: 99.89900:99.89900 (painting: 99.89900)
---------> RasterTask duration: 99.89900:99.89900 (painting: 99.89900)
-----> Paint x 3 duration: 299.89900:299.89900 (painting: 299.69700)
---------> Paint duration: 99.89900:99.89900 (painting: 99.89900)
---------> Paint duration: 99.89900:99.89900 (painting: 99.89900)
---------> Paint duration: 99.89900:99.89900 (painting: 99.89900)
-coalesced record's hasWarnings(): false
-coalesced record's childHasWarnings(): true
-
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-coalescing.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-coalescing.html
deleted file mode 100644
index e7dac63..0000000
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-coalescing.html
+++ /dev/null
@@ -1,140 +0,0 @@
-<html>
-<head>
-<script src="../../http/tests/inspector/inspector-test.js"></script>
-<script src="../../http/tests/inspector/timeline-test.js"></script>
-<script>
-
-function initialize_TimelineCoalescing()
-{
-
-InspectorTest.dumpStats = function(presentationRecord)
-{
-    if (!presentationRecord.presentationParent())
-        return "";
-
-    var model = InspectorTest.timelineModel();
-    var aggregatedStats = {};
-    if (presentationRecord.coalesced()) {
-        var presentationChildren = presentationRecord.presentationChildren();
-        for (var i = 0; i < presentationChildren.length; ++i)
-            WebInspector.TimelineUIUtils.aggregateTimeForRecord(aggregatedStats, model, presentationChildren[i].record());
-    } else {
-        WebInspector.TimelineUIUtils.aggregateTimeForRecord(aggregatedStats, model, presentationRecord.record());
-    }
-
-    var timeByCategory = "";
-
-    for (category in aggregatedStats) {
-        if (timeByCategory)
-            timeByCategory += ", ";
-        timeByCategory += category + ": " + aggregatedStats[category].toFixed(5);
-    }
-    var duration = (presentationRecord.endTime() - presentationRecord.startTime()).toFixed(5);
-    var durationTillLastChild = (presentationRecord.endTime() - presentationRecord.startTime()).toFixed(5);
-    return "duration: " + duration + ":" + durationTillLastChild + (timeByCategory ? " (" + timeByCategory + ")" : "");
-}
-
-}
-
-function test()
-{
-    var sessionId = "4.20";
-    var mainThread = 1;
-    var pid = 100;
-
-    var testData = [
-        // Assure we coalesce records with short interval and don't coalesce records that stand apart.
-        {
-            "args": { "sessionId": sessionId },
-            "cat": "disabled-by-default-devtools.timeline",
-            "name": "TracingStartedInPage",
-            "ph": "I",
-            "pid": pid,
-            "tid": mainThread,
-            "ts": 100,
-        },
-        {"name": "Program", "ts": 1000000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-            {"name": "FunctionCall", "ts": 1000000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{"frame":"0x2","scriptId":"3","scriptLine":5,"scriptName":"http://example.com"}}},
-                {"name": "Layout", "ts": 1000001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"beginData":{"dirtyObjects":1,"frame":"0x2","partialLayout":false,"totalObjects":1}} },
-                    {"name": "CallStack", "ts": 1000002, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline.stack", "args":{
-                        "stack":[
-                            {"functionName":"func","url":"http://example.com","lineNumber":42,"columnNumber":1,"scriptId":"10"}
-                        ]}
-                    },
-                {"name": "Layout", "ts": 1099900, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"endData":{"root":[0,0,1570,0,1570,243,0,243],"rootNode":1}}},
-
-                {"name": "Layout", "ts": 1100001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"beginData":{"dirtyObjects":1,"frame":"0x2","partialLayout":false,"totalObjects":1}} },
-                {"name": "Layout", "ts": 1199900, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"endData":{"root":[0,0,1570,0,1570,243,0,243],"rootNode":1}}},
-
-                {"name": "Layout", "ts": 1200001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"beginData":{"dirtyObjects":1,"frame":"0x2","partialLayout":false,"totalObjects":1}} },
-                {"name": "Layout", "ts": 1299900, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"endData":{"root":[0,0,1570,0,1570,243,0,243],"rootNode":1}}},
-            {"name": "FunctionCall", "ts": 1299998, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-        {"name": "Program", "ts": 1299999, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-
-        {"name": "Program", "ts": 1300000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-            {"name": "Layout", "ts": 1305001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"beginData":{"dirtyObjects":1,"frame":"0x2","partialLayout":false,"totalObjects":1}} },
-            {"name": "Layout", "ts": 1399900, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"endData":{"root":[0,0,1570,0,1570,243,0,243],"rootNode":1}}},
-        {"name": "Program", "ts": 1399999, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-
-        // Assure we do coalesce on levels lower than root, but do not coalesce between different parents.
-        {"name": "Program", "ts": 2000000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-            {"name": "FunctionCall", "ts": 2000001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{"frame":"0x2","scriptId":"3","scriptLine":5,"scriptName":"http://example.com"}}},
-                {"name": "Decode Image", "ts": 2000002, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"imageType":"JPEG"}},
-                {"name": "Decode Image", "ts": 2099900, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-                {"name": "Decode Image", "ts": 2100000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"imageType":"JPEG"}},
-                {"name": "Decode Image", "ts": 2199900, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-            {"name": "FunctionCall", "ts": 2199998, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-            {"name": "FunctionCall", "ts": 2200001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{"frame":"0x2","scriptId":"3","scriptLine":5,"scriptName":"http://example.com"}}},
-                {"name": "Decode Image", "ts": 2200002, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"imageType":"JPEG"}},
-                {"name": "Decode Image", "ts": 2299900, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-                {"name": "Decode Image", "ts": 2300000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"imageType":"JPEG"}},
-                {"name": "Decode Image", "ts": 2399900, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-            {"name": "FunctionCall", "ts": 2399998, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-        {"name": "Program", "ts": 2399999, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-
-        // Assure we only coalesce timestamp records with the same message.
-        {"name": "Program", "ts": 3100000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-            {"name": "RasterTask", "ts": 3100001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"layerId":11}},
-            {"name": "RasterTask", "ts": 3199900, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{}},
-        {"name": "Program", "ts": 3199999, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-        {"name": "Program", "ts": 3200000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-            {"name": "RasterTask", "ts": 3200001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"layerId":11}},
-            {"name": "RasterTask", "ts": 3299900, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{}},
-        {"name": "Program", "ts": 3299999, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-        {"name": "Program", "ts": 3300000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-            {"name": "RasterTask", "ts": 3300001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"layerId":11}},
-            {"name": "RasterTask", "ts": 3399900, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{}},
-        {"name": "Program", "ts": 3399999, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-
-        // Assure we only coalesce event records with the same type.
-        {"name": "Program", "ts": 4100000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-            {"name": "Paint", "ts": 4100001, "dur": 99899, "ph": "X", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{"clip":[-15,-15,512,-15,512,512,-15,512],"frame":"0x2","layerId":11,"nodeId":2,   "type": "mouseover" }}},
-        {"name": "Program", "ts": 4199999, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-        {"name": "Program", "ts": 4200000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-            {"name": "Paint", "ts": 4200001, "dur": 99899, "ph": "X", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{"clip":[-15,-15,512,-15,512,512,-15,512],"frame":"0x2","layerId":11,"nodeId":2,   "type": "mouseover" }}},
-        {"name": "Program", "ts": 4299999, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-        {"name": "Program", "ts": 4300000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}},
-            {"name": "Paint", "ts": 4300001, "dur": 99899, "ph": "X", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{"clip":[-15,-15,512,-15,512,512,-15,512],"frame":"0x2","layerId":11,"nodeId":2,   "type": "keydown" }}},
-        {"name": "Program", "ts": 4399999, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}
-    ];
-
-    InspectorTest.timelineModel().setEventsForTest(testData);
-
-    var rootRecord = InspectorTest.timelinePresentationModel().rootRecord();
-    InspectorTest.dumpPresentationRecord(rootRecord, InspectorTest.dumpStats);
-    var coalesced = rootRecord.presentationChildren()[0];
-    InspectorTest.addResult("coalesced record's hasWarnings(): " + coalesced.hasWarnings());
-    InspectorTest.addResult("coalesced record's childHasWarnings(): " + coalesced.childHasWarnings());
-    InspectorTest.completeTest();
-}
-
-</script>
-</head>
-
-<body onload="runTest()">
-<p>
-Test timeline records coalescing
-</p>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-event-dispatch-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-event-dispatch-expected.txt
index 83f38f39..289f5295 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-event-dispatch-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-event-dispatch-expected.txt
@@ -10,7 +10,6 @@
     endTime : <number>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "EventDispatch"
 }
 Text details for EventDispatch: mouseover
@@ -23,13 +22,11 @@
     endTime : <number>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "EventDispatch"
 }
 Text details for EventDispatch: mousemove
 EventDispatch Properties:
 {
-    children : <object>
     data : {
         stackTrace : <object>
         type : "mousedown"
@@ -37,7 +34,6 @@
     endTime : <number>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "EventDispatch"
 }
 Text details for EventDispatch: mousedown
@@ -50,7 +46,6 @@
     endTime : <number>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "EventDispatch"
 }
 Text details for EventDispatch: selectstart
@@ -61,7 +56,6 @@
     }
     endTime : <number>
     startTime : <number>
-    thread : <string>
     type : "EventDispatch"
 }
 Text details for EventDispatch: selectionchange
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-filtering-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-filtering-expected.txt
index ca44d73d7..4de52cf 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-filtering-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-filtering-expected.txt
@@ -1,48 +1,45 @@
-Test filtering on timeline panel.
+Test filtering in Timeline Tree View panel.
 
 Initial:
- +bar01
- +bar04
- +bar07
- +foo10
- +foo13
- +foo16
+ bar01
+  bar02
+  bar03
+ bar04
+  foo05
+  bar06
+ bar07
+  foo08
+  foo09
+ foo10
+  bar11
+  bar12
+ foo13
+  foo14
+  bar15
+ foo16
+  foo17
+  foo18
 
 Filtered by 'bar':
- -bar01
-   bar02
-   bar03
- -bar04
-   bar06
-  bar07
- -foo10
-   bar11
-   bar12
- -foo13
-   bar15
-
-Collapsed 'bar04' and 'foo13':
- -bar01
-   bar02
-   bar03
- +bar04
-  bar07
- -foo10
-   bar11
-   bar12
- +foo13
+ bar01
+  bar02
+  bar03
+ bar04
+  bar06
+ bar07
+ bar11
+ bar12
+ bar15
 
 Filtered by 'foo':
- -bar04
-   foo05
- -bar07
-   foo08
-   foo09
-  foo10
- -foo13
-   foo14
- -foo16
-   foo17
-   foo18
+ foo05
+ foo08
+ foo09
+ foo10
+ foo13
+  foo14
+ foo16
+  foo17
+  foo18
 
 
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-filtering.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-filtering.html
index aa28af5..f6affed 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-filtering.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-filtering.html
@@ -50,28 +50,21 @@
         {"name": "Program", "ts": 2590000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}
     ];
 
+
     var panel = WebInspector.panels.timeline;
-    var model = InspectorTest.timelinePresentationModel();
-
-    InspectorTest.timelineModel().setEventsForTest(testData);
-
-    function printRecord(record)
+    var model = InspectorTest.timelineModel();
+    model.setEventsForTest(testData);
+    var view = new WebInspector.EventsTimelineTreeView(model, null);
+    view.updateContents(WebInspector.TimelineSelection.fromRange(model.minimumRecordTime(), model.maximumRecordTime()));
+    var filtersControl = view._filtersControl;
+    function printEventMessage(event, level)
     {
-        var prefix = [];
-        var current = record.presentationParent();
-        while (current) {
-            current = current.presentationParent();
-            prefix.push(" ");
-        }
-        var mark = record.expandable() ? (record.collapsed() ? "+" : "-") : " ";
-        InspectorTest.addResult(prefix.join("") + mark + record.record().traceEvent().args["data"].message);
+        InspectorTest.addResult(" ".repeat(level) + event.args["data"].message);
     }
 
     function dumpRecords()
     {
-        var records = model.filteredRecords();
-        for (var i = 0; i < records.length; ++i)
-            printRecord(records[i]);
+        InspectorTest.walkTimelineEventTreeUnderNode(printEventMessage, view._currentTree);
         InspectorTest.addResult("");
     }
 
@@ -79,21 +72,10 @@
     dumpRecords();
 
     InspectorTest.addResult("Filtered by 'bar':");
-    var textFilterUI = panel._filtersControl._textFilterUI;
+    var textFilterUI = filtersControl._textFilterUI;
     textFilterUI.setValue("bar");
     dumpRecords();
 
-    InspectorTest.addResult("Collapsed 'bar04' and 'foo13':");
-    var records = model.filteredRecords();
-    var collapseList = {"bar04":true, "foo13": true};
-    for (var i = 0; i < records.length; ++i) {
-        var record = records[i];
-        if (collapseList[record.record().traceEvent().args["data"].message])
-            record.setCollapsed(true);
-    }
-    model.invalidateFilteredRecords();
-    dumpRecords();
-
     InspectorTest.addResult("Filtered by 'foo':");
     textFilterUI.setValue("foo");
     dumpRecords();
@@ -106,7 +88,7 @@
 
 <body onload="runTest()">
 <p>
-Test filtering on timeline panel.</a>
+Test filtering in Timeline Tree View panel.</a>
 </p>
 
 </body>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-flame-chart-automatically-size-window.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-flame-chart-automatically-size-window.html
index c087883c..586bf48 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-flame-chart-automatically-size-window.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-flame-chart-automatically-size-window.html
@@ -11,7 +11,6 @@
     var timelineData = InspectorTest.timelineData();
 
     var timeline = WebInspector.panels.timeline;
-    timeline._flameChartEnabledSetting.set(true);
     timeline._onModeChanged();
     timeline._currentViews[0]._automaticallySizeWindow = true;
 
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-injected-script-eval-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-injected-script-eval-expected.txt
index d0c507f5..7e607251 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-injected-script-eval-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-injected-script-eval-expected.txt
@@ -2,7 +2,6 @@
 
 FunctionCall Properties:
 {
-    children : <object>
     data : {
         frame : <string>
         scriptId : <string>
@@ -14,7 +13,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "FunctionCall"
 }
 Text details for FunctionCall: undefined
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-expected.txt
index 59c142b..7db2453 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-expected.txt
@@ -24,7 +24,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "Layout"
 }
 Text details for Layout: timeline-layout.html:17
@@ -48,7 +47,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "Layout"
 }
 Text details for Layout: timeline-layout.html:17
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-load-event-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-load-event-expected.txt
index bb872e2d..3131bf0 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-load-event-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-load-event-expected.txt
@@ -13,7 +13,6 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "MarkDOMContent"
 }
 MarkLoad Properties:
@@ -26,7 +25,6 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "MarkLoad"
 }
 MarkFirstPaint Properties:
@@ -35,7 +33,6 @@
     }
     endTime : <number>
     startTime : <number>
-    thread : <string>
     type : "MarkFirstPaint"
 }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-mark-timeline-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-mark-timeline-expected.txt
index a527a98..88f4d38 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-mark-timeline-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-mark-timeline-expected.txt
@@ -10,7 +10,6 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "TimeStamp"
 }
 Text details for TimeStamp: null
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource-expected.txt
index e7c5944..aca4f68 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource-expected.txt
@@ -16,7 +16,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "ResourceSendRequest"
 }
 Text details for ResourceSendRequest: timeline-network-resource.js
@@ -32,7 +31,6 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "ResourceReceiveResponse"
 }
 Text details for ResourceReceiveResponse: timeline-network-resource.js
@@ -46,7 +44,6 @@
     }
     endTime : <number>
     startTime : <number>
-    thread : <string>
     type : "ResourceFinish"
 }
 Text details for ResourceFinish: timeline-network-resource.js
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource.html
index 8091c8e..c3011d8f 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource.html
@@ -20,7 +20,6 @@
     var scriptUrl = "timeline-network-resource.js";
 
     var model = WebInspector.panels.timeline._model;
-    var presentationModel = InspectorTest.timelinePresentationModel();
 
     InspectorTest.invokeAsyncWithTimeline("performActions", finish);
 
@@ -35,17 +34,7 @@
                 printReceive(record);
             else if (record.type() === WebInspector.TimelineModel.RecordType.ResourceFinish)
                 printFinish(record);
-
-            var presentationRecord = presentationModel.toPresentationRecord(record);
-            if (presentationRecord && record.thread() === WebInspector.TimelineModel.MainThreadName) {
-                var parentIsRoot = presentationRecord.presentationParent() && !presentationRecord.presentationParent().presentationParent();
-                if (parentIsRoot) {
-                    if (lastRecordStartTime)
-                        InspectorTest.assertGreaterOrEqual(record.startTime(), lastRecordStartTime, "Top level records order violation");
-                    lastRecordStartTime = record.startTime();
-                }
-            }
-        }
+       }
         model.forAllRecords(format);
         InspectorTest.completeTest();
     }
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-expected.txt
index 2b195a7..78e78af 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-expected.txt
@@ -3,7 +3,6 @@
 
 Paint Properties:
 {
-    children : <object>
     data : {
         clip : <object>
         frame : <string>
@@ -13,7 +12,6 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "Paint"
 }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-parse-html-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-parse-html-expected.txt
index 46f1c77..2198380 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-parse-html-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-parse-html-expected.txt
@@ -18,7 +18,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "ParseHTML"
 }
 Text details for ParseHTML: timeline-parse-html.html [1…]
@@ -39,7 +38,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "ParseHTML"
 }
 Text details for ParseHTML: timeline-parse-html.html [1…]
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-recalculate-styles-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-recalculate-styles-expected.txt
index b7ce203..dafad285 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-recalculate-styles-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-recalculate-styles-expected.txt
@@ -14,7 +14,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "UpdateLayoutTree"
 }
 Text details for UpdateLayoutTree: timeline-recalculate-styles.html:20
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-receive-response-event-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-receive-response-event-expected.txt
index 088ca5b6..c0dac66 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-receive-response-event-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-receive-response-event-expected.txt
@@ -1,6 +1,6 @@
 Tests the Timeline API instrumentation of a SendRequest, ReceiveResponse etc.
 
-ResourceSendRequest
+    ResourceSendRequest
 ResourceReceiveResponse
 ResourceReceivedData
 ResourceFinish
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-receive-response-event.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-receive-response-event.html
index 820adc54..dca3d34 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-receive-response-event.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-receive-response-event.html
@@ -29,30 +29,19 @@
         var recordTypes = WebInspector.TimelineModel.RecordType;
         var typesToDump = new Set([recordTypes.ResourceSendRequest, recordTypes.ResourceReceiveResponse, recordTypes.ResourceReceivedData, recordTypes.ResourceFinish,
             recordTypes.EventDispatch, recordTypes.FunctionCall]);
-        function dumpFormattedRecord(presentationRecord, prefix)
+        function dumpEvent(traceEvent, level)
         {
-            var record = presentationRecord.record();
-            prefix = prefix || "";
             // Ignore stray paint & rendering events for better stability.
-            var categoryName = WebInspector.TimelineUIUtils.categoryForRecord(record).name;
+            var categoryName = WebInspector.TimelineUIUtils.eventStyle(traceEvent).category.name;
                if (categoryName !== "loading" && categoryName !== "scripting")
                 return;
-            var childPrefix = prefix;
             // Here and below: pretend coalesced record are just not there, as coalescation is time dependent and, hence, not stable.
             // Filter out InjectedScript function call because they happen out of sync.
-            if (!presentationRecord.coalesced() && typesToDump.has(record.type())
-                && (record.type() !== "FunctionCall" || record.traceEvent().args["data"].scriptName)) {
-                InspectorTest.addResult(prefix + record.type());
-                childPrefix = childPrefix + "    ";
-            }
-            if (presentationRecord.presentationChildren()) {
-                for (var i = 0; i < presentationRecord.presentationChildren().length; ++i)
-                    dumpFormattedRecord(presentationRecord.presentationChildren()[i], childPrefix);
+            if (typesToDump.has(traceEvent.name) && (traceEvent.name !== "FunctionCall" || traceEvent.args["data"].scriptName)) {
+                InspectorTest.addResult("    ".repeat(level - 1) + traceEvent.name);
             }
         }
-        var records = InspectorTest.timelinePresentationModel().rootRecord().presentationChildren();
-        for (var i = 0; i < records.length; ++i)
-            dumpFormattedRecord(records[i]);
+        InspectorTest.walkTimelineEventTree(dumpEvent);
         InspectorTest.completeTest();
     }
 }
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-id.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-id.html
index d0f551c40e..ac751cc 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-id.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-id.html
@@ -32,24 +32,24 @@
 
     var linkifier = new WebInspector.Linkifier();
 
-    var recordTypes = ["TimerInstall", "TimerRemove", "FunctionCall"];
-    function formatter(record)
+    var recordTypes = new Set(["TimerInstall", "TimerRemove", "FunctionCall"]);
+    function formatter(event)
     {
-        if (recordTypes.indexOf(record.type()) === -1)
+        if (!recordTypes.has(event.name))
             return;
 
-        var detailsText = WebInspector.TimelineUIUtils.buildDetailsTextForTraceEvent(record.traceEvent(), InspectorTest.timelineModel().target());
-        InspectorTest.addResult("detailsTextContent for " + record.type() + " event: '" + detailsText + "'");
+        var detailsText = WebInspector.TimelineUIUtils.buildDetailsTextForTraceEvent(event, InspectorTest.timelineModel().target());
+        InspectorTest.addResult("detailsTextContent for " + event.name + " event: '" + detailsText + "'");
 
-        var details = WebInspector.TimelineUIUtils.buildDetailsNodeForTraceEvent(record.traceEvent(), InspectorTest.timelineModel().target(), linkifier);
+        var details = WebInspector.TimelineUIUtils.buildDetailsNodeForTraceEvent(event, InspectorTest.timelineModel().target(), linkifier);
         if (!details)
             return;
-        InspectorTest.addResult("details.textContent for " + record.type() + " event: '" + details.textContent.replace(/VM[\d]+/, "VM") + "'");
+        InspectorTest.addResult("details.textContent for " + event.name + " event: '" + details.textContent.replace(/VM[\d]+/, "VM") + "'");
     }
 
     function finish()
     {
-        InspectorTest.printTimelinePresentationRecords(null, formatter);
+        InspectorTest.walkTimelineEventTree(formatter);
         InspectorTest.completeTest();
     }
 }
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-1-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-1-expected.txt
index 173dfed..6ee00d9 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-1-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-1-expected.txt
@@ -6,7 +6,6 @@
 ----> Timestamp: SCRIPT TAG
 EvaluateScript Properties:
 {
-    children : <object>
     data : {
         columnNumber : <number>
         frame : <string>
@@ -18,7 +17,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "EvaluateScript"
 }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-2-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-2-expected.txt
index 7b3bbc5..88e7183 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-2-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-2-expected.txt
@@ -3,7 +3,6 @@
 
 EvaluateScript Properties:
 {
-    children : <object>
     data : {
         columnNumber : <number>
         frame : <string>
@@ -15,7 +14,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "EvaluateScript"
 }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time-expected.txt
index bde1202..0009030 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time-expected.txt
@@ -2,28 +2,17 @@
 
 
 Running: testSimpleConsoleTime
-Root
-----> FunctionCall
---------> a
+----> Function Call
 
 Running: testNestedConsoleTime
-Root
-----> FunctionCall
---------> a
-------------> b
-------------> c
-----------------> d
+----> Function Call
 
 Running: testUnbalancedConsoleTime
-Root
-----> FunctionCall
---------> a
+----> Function Call
 
 Running: testConsoleTimeWithoutConsoleTimeEnd
-Root
-----> FunctionCall
+----> Function Call
 --------> Timestamp: Foo
 --------> Timestamp: Bar
---------> d
-------------> Timestamp: Baz
+--------> Timestamp: Baz
 
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time-stamp-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time-stamp-expected.txt
index f422402..212ecdd 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time-stamp-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time-stamp-expected.txt
@@ -9,7 +9,6 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "TimeStamp"
 }
 Text details for TimeStamp: null
@@ -23,7 +22,6 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "TimeStamp"
 }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time.html
index 2ce0e43df..111ff5d 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time.html
@@ -75,11 +75,15 @@
 
     function performActions(actions, next)
     {
+        var namesToDump = new Set(["FunctionCall", "ConsoleTime", "TimeStamp"]);
+        function dumpName(event, level)
+        {
+            if (namesToDump.has(event.name))
+                InspectorTest.addResult("----".repeat(level) + "> " + WebInspector.TimelineUIUtils.eventTitle(event));
+        }
         function callback()
         {
-            var rootRecord = InspectorTest.timelinePresentationModel().rootRecord();
-            InspectorTest.dumpPresentationRecord(rootRecord, undefined, undefined, ["FunctionCall", "ConsoleTime", "TimeStamp"]);
-            InspectorTest.timelinePresentationModel().reset();
+            InspectorTest.walkTimelineEventTree(dumpName);
             next();
         }
         InspectorTest.evaluateWithTimeline(actions, InspectorTest.safeWrap(callback));
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-timer-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-timer-expected.txt
index e9d42da..9fc51da 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-timer-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-timer-expected.txt
@@ -13,7 +13,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "TimerInstall"
 }
 Text details for TimerInstall: timeline-timer.html:9
@@ -30,13 +29,11 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "TimerInstall"
 }
 Text details for TimerInstall: timeline-timer.html:10
 TimerFire Properties:
 {
-    children : <object>
     data : {
         frame : <string>
         timerId : <number>
@@ -44,13 +41,11 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "TimerFire"
 }
 Text details for TimerFire: timeline-timer.html:9
 TimerFire Properties:
 {
-    children : <object>
     data : {
         frame : <string>
         timerId : <number>
@@ -58,13 +53,11 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "TimerFire"
 }
 Text details for TimerFire: timeline-timer.html:10
 TimerFire Properties:
 {
-    children : <object>
     data : {
         frame : <string>
         timerId : <number>
@@ -72,7 +65,6 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "TimerFire"
 }
 Text details for TimerFire: timeline-timer.html:10
@@ -87,13 +79,11 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "TimerRemove"
 }
 Text details for TimerRemove: timeline-timer.html:17
 FunctionCall Properties:
 {
-    children : <object>
     data : {
         frame : <string>
         scriptId : <string>
@@ -105,7 +95,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "FunctionCall"
 }
 FunctionCall Properties:
@@ -121,12 +110,10 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "FunctionCall"
 }
 FunctionCall Properties:
 {
-    children : <object>
     data : {
         frame : <string>
         scriptId : <string>
@@ -138,12 +125,10 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "FunctionCall"
 }
 EvaluateScript Properties:
 {
-    children : <object>
     data : {
         columnNumber : <number>
         frame : <string>
@@ -155,7 +140,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "EvaluateScript"
 }
 Text details for EvaluateScript: undefined
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-window-filter-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-window-filter-expected.txt
index 6c14d59..15ed7538 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-window-filter-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-window-filter-expected.txt
@@ -2,28 +2,18 @@
 
 It applies different ranges to the OverviewGrid and expects that current view reflects the change.
 
-Also it detects that after switching to another view it gets the proper time range.
-
 OverviewPane:
 divider offsets: [0, 500, 1000, 1500]. We are expecting round numbers.
 
 range = 0 - 1
 time range = 1122673092.068 - 1122674564.291
-records count: 107
-divider offsets: [0, 500, 1000, 1500]. We are expecting round numbers.
 
 range = 0.25 - 0.75
 time range = 1122673460.12375 - 1122674196.23525
-records count: 48
-divider offsets: [400, 600, 800, 1000, 1200]. We are expecting round numbers.
 
 range = 0.33 - 0.66
 time range = 1122673577.90159 - 1122674063.73518
-records count: 24
-divider offsets: [500, 600, 700, 800, 900, 1000]. We are expecting round numbers.
 
 --------------------------------------------------------
 time range = 1122673239.2903001 - 1122674417.0686998
 
-time range = 1122673239.2903001 - 1122674417.0686998
-
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-window-filter.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-window-filter.html
index e15ec25..6ddbd6d 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-window-filter.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-window-filter.html
@@ -12,7 +12,6 @@
     var timeline = WebInspector.panels.timeline;
     var overviewPane = timeline._overviewPane;
     var model = timeline._model;
-    InspectorTest.switchTimelineToWaterfallMode();
 
     function createFileReader(file, delegate)
     {
@@ -22,7 +21,7 @@
     InspectorTest.override(model, "_createFileReader", createFileReader);
 
     model.loadFromFile({}, new WebInspector.Progress());
-    timeline._currentViews[0]._refresh();
+    timeline._currentViews[0].refreshRecords();
 
     overviewPane._update();
     InspectorTest.addResult("OverviewPane:");
@@ -30,28 +29,14 @@
     dumpDividers(overviewPane._overviewCalculator);
     InspectorTest.addResult("");
 
-    function dumpRecordsCountForRange(windowLeft, windowRight)
-    {
-        var view = timeline._currentViews[0];
-        overviewPane._overviewGrid.setWindow(windowLeft, windowRight);
-        view._refresh();
-        InspectorTest.addResult("range = " + windowLeft + " - " + windowRight);
-        InspectorTest.addResult("time range = " + view._windowStartTime + " - " + view._windowEndTime);
-        InspectorTest.addResult("records count: " + view._presentationModel.filteredRecords().length);
-        view._calculator.setDisplayWindow(455 + WebInspector.TimelineCalculator._minWidth, 5);
-        dumpDividers(view._calculator);
-        InspectorTest.addResult("");
-    }
-
     function dumpFlameChartRecordsCountForRange(windowLeft, windowRight)
     {
         var mainView = timeline._currentViews[0]._mainView;
+        mainView._muteAnimation = true;
         overviewPane._overviewGrid.setWindow(windowLeft, windowRight);
         mainView.update();
         InspectorTest.addResult("range = " + windowLeft + " - " + windowRight);
         InspectorTest.addResult("time range = " + mainView._timeWindowLeft + " - " + mainView._timeWindowRight);
-        mainView._calculator.setDisplayWindow(455 + WebInspector.TimelineCalculator._minWidth, 5);
-        dumpDividers(mainView._calculator);
         InspectorTest.addResult("");
     }
 
@@ -63,32 +48,14 @@
         InspectorTest.addResult("divider offsets: [" + dividers.join(", ") + "]. We are expecting round numbers.");
     }
 
-    timeline._onModeChanged();
-    dumpRecordsCountForRange(0, 1);
-    dumpRecordsCountForRange(0.25, 0.75);
-    dumpRecordsCountForRange(0.33, 0.66);
-
-    timeline._flameChartEnabledSetting.set(true);
-    timeline._onModeChanged();
-    // FIXME(394762): uncomment once we support loading tracing events.
-//     dumpFlameChartRecordsCountForRange(0, 1);
-//     dumpFlameChartRecordsCountForRange(0.25, 0.5);
-//     dumpFlameChartRecordsCountForRange(0.33, 0.4);
+    dumpFlameChartRecordsCountForRange(0, 1);
+    dumpFlameChartRecordsCountForRange(0.25, 0.75);
+    dumpFlameChartRecordsCountForRange(0.33, 0.66);
 
     overviewPane._overviewGrid.setWindow(0.1, 0.9);
 
     InspectorTest.addResult("--------------------------------------------------------");
-
     InspectorTest.addResult("time range = " + timeline._windowStartTime + " - " + timeline._windowEndTime);
-    timeline._flameChartEnabledSetting.set(false);
-    timeline._onModeChanged();
-
-    InspectorTest.addResult("");
-
-    InspectorTest.addResult("time range = " + timeline._windowStartTime + " - " + timeline._windowEndTime);
-    timeline._flameChartEnabledSetting.set(true);
-    timeline._onModeChanged();
-
     InspectorTest.completeTest();
 }
 
@@ -103,9 +70,6 @@
 <p>
 It applies different ranges to the OverviewGrid and expects that current view reflects the change.
 </p>
-<p>
-Also it detects that after switching to another view it gets the proper time range.
-</p>
 
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/loader/data-uri-images-load-asynchronously-expected.txt b/third_party/WebKit/LayoutTests/loader/data-uri-images-load-asynchronously-expected.txt
deleted file mode 100644
index 21927c9..0000000
--- a/third_party/WebKit/LayoutTests/loader/data-uri-images-load-asynchronously-expected.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Test for crbug.com/224317: data:uri images should load asynchronously.
-PASS
diff --git a/third_party/WebKit/LayoutTests/loader/data-uri-images-load-synchronously-expected.txt b/third_party/WebKit/LayoutTests/loader/data-uri-images-load-synchronously-expected.txt
new file mode 100644
index 0000000..1dddd7e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/loader/data-uri-images-load-synchronously-expected.txt
@@ -0,0 +1,2 @@
+Test for crbug.com/224317: data:uri images should load synchronously.
+PASS
diff --git a/third_party/WebKit/LayoutTests/loader/data-uri-images-load-asynchronously.html b/third_party/WebKit/LayoutTests/loader/data-uri-images-load-synchronously.html
similarity index 89%
rename from third_party/WebKit/LayoutTests/loader/data-uri-images-load-asynchronously.html
rename to third_party/WebKit/LayoutTests/loader/data-uri-images-load-synchronously.html
index 370eff19..7746f5b5 100644
--- a/third_party/WebKit/LayoutTests/loader/data-uri-images-load-asynchronously.html
+++ b/third_party/WebKit/LayoutTests/loader/data-uri-images-load-synchronously.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-Test for crbug.com/224317: data:uri images should load asynchronously.<br/>
+Test for crbug.com/224317: data:uri images should load synchronously.<br/>
 <script>
     if (window.testRunner)
         testRunner.dumpAsText();
@@ -10,9 +10,9 @@
     image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAnklEQVR42u3QMQEAAAgDoGlyo1vBzwciUJlw1ApkyZIlS5YsBbJkyZIlS5YCWbJkyZIlS4EsWbJkyZKlQJYsWbJkyVIgS5YsWbJkKZAlS5YsWbIUyJIlS5YsWQpkyZIlS5YsBbJkyZIlS5YCWbJkyZIlS4EsWbJkyZKlQJYsWbJkyVIgS5YsWbJkKZAlS5YsWbIUyJIlS5YsWQpkyfq2MosBSIeKONMAAAAASUVORK5CYII=";
 
     if (image.width == 100 && image.height == 100)
-        document.write("FAIL");
-    else
         document.write("PASS");
+    else
+        document.write("FAIL");
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/loader/data-uri-images-reload-asynchronously-expected.txt b/third_party/WebKit/LayoutTests/loader/data-uri-images-reload-asynchronously-expected.txt
deleted file mode 100644
index 8289b387..0000000
--- a/third_party/WebKit/LayoutTests/loader/data-uri-images-reload-asynchronously-expected.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Test for crbug.com/224317: data:uri images should load asynchronously and reload synchronously.
-PASS
diff --git a/third_party/WebKit/LayoutTests/loader/data-uri-images-reload-synchronously-expected.txt b/third_party/WebKit/LayoutTests/loader/data-uri-images-reload-synchronously-expected.txt
new file mode 100644
index 0000000..c0ed5e95
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/loader/data-uri-images-reload-synchronously-expected.txt
@@ -0,0 +1,2 @@
+Test for crbug.com/224317: data:uri images should reload synchronously.
+PASS
diff --git a/third_party/WebKit/LayoutTests/loader/data-uri-images-reload-asynchronously.html b/third_party/WebKit/LayoutTests/loader/data-uri-images-reload-synchronously.html
similarity index 65%
rename from third_party/WebKit/LayoutTests/loader/data-uri-images-reload-asynchronously.html
rename to third_party/WebKit/LayoutTests/loader/data-uri-images-reload-synchronously.html
index cc83ee51..9b583e07 100644
--- a/third_party/WebKit/LayoutTests/loader/data-uri-images-reload-asynchronously.html
+++ b/third_party/WebKit/LayoutTests/loader/data-uri-images-reload-synchronously.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-Test for crbug.com/224317: data:uri images should load asynchronously and reload synchronously.<br/>
+Test for crbug.com/224317: data:uri images should reload synchronously.<br/>
 <script>
     if (window.testRunner) {
         testRunner.waitUntilDone();
@@ -11,23 +11,17 @@
     var image = new Image();
     image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAnklEQVR42u3QMQEAAAgDoGlyo1vBzwciUJlw1ApkyZIlS5YsBbJkyZIlS5YCWbJkyZIlS4EsWbJkyZKlQJYsWbJkyVIgS5YsWbJkKZAlS5YsWbIUyJIlS5YsWQpkyZIlS5YsBbJkyZIlS5YCWbJkyZIlS4EsWbJkyZKlQJYsWbJkyVIgS5YsWbJkKZAlS5YsWbIUyJIlS5YsWQpkyfq2MosBSIeKONMAAAAASUVORK5CYII=";
 
-    if (location.hash != "#reloaded") {
-        if (image.width == 100 || image.height == 100) {
-            document.write("FAIL");
+    if (image.width != 100 || image.height != 100) {
+        document.write("FAIL");
+    } else {
+        if (location.hash == "#reloaded") {
+            document.write("PASS");
             if (window.testRunner)
                 testRunner.notifyDone();
         } else {
             location.hash = "#reloaded";
             location.reload();
         }
-    } else {
-        if (image.width == 100 || image.height == 100) {
-            document.write("PASS");
-        } else {
-            document.write("FAIL");
-        }
-        if (window.testRunner)
-            testRunner.notifyDone();
     }
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/platform/linux-x86/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/linux-x86/fast/canvas/canvas-shadow-source-in-expected.png
new file mode 100644
index 0000000..b5daa85
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux-x86/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-x86/fast/canvas/canvas-shadow-source-in-expected.txt b/third_party/WebKit/LayoutTests/platform/linux-x86/fast/canvas/canvas-shadow-source-in-expected.txt
new file mode 100644
index 0000000..c895823
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux-x86/fast/canvas/canvas-shadow-source-in-expected.txt
@@ -0,0 +1,21 @@
+layer at (0,0) size 1600x1200
+  LayoutView at (0,0) size 1600x1200
+layer at (0,0) size 1600x470
+  LayoutBlockFlow {HTML} at (0,0) size 1600x470
+    LayoutBlockFlow {BODY} at (8,8) size 1584x454
+      LayoutBlockFlow {DIV} at (0,0) size 1584x20
+        LayoutText {#text} at (0,0) size 57x19
+          text run at (0,0) width 57: "Test Rect"
+      LayoutBlockFlow (anonymous) at (0,20) size 1584x207
+        LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {DIV} at (0,227) size 1584x20
+        LayoutText {#text} at (0,0) size 66x19
+          text run at (0,0) width 66: "Test Image"
+      LayoutBlockFlow (anonymous) at (0,247) size 1584x207
+        LayoutText {#text} at (0,0) size 0x0
+        LayoutText {#text} at (0,0) size 0x0
+        LayoutText {#text} at (0,0) size 0x0
+layer at (8,28) size 202x202
+  LayoutHTMLCanvas {CANVAS} at (0,0) size 202x202 [border: (1px solid #999999)]
+layer at (8,255) size 202x202
+  LayoutHTMLCanvas {CANVAS} at (0,0) size 202x202 [border: (1px solid #999999)]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-shadow-source-in-expected.png
index 3adefc37..86319185 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
index 3adefc37..86319185 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
index a75ec0f..2252cfe 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
index ba514cc..9959f0c 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-shadow-source-in-expected.png
index 9d06ae3..b7a76dd 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-paint-invalidation-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/media/video-paint-invalidation-expected.txt
index e025f43..3b5383f 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/video-paint-invalidation-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-paint-invalidation-expected.txt
@@ -8,10 +8,7 @@
       "children": [
         {
           "position": [8, 8],
-          "bounds": [320, 240],
-          "paintInvalidationClients": [
-            "LayoutVideo VIDEO id='video'"
-          ]
+          "bounds": [320, 240]
         },
         {
           "shouldFlattenTransform": false,
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
index 9d06ae3..b7a76dd 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
index 1f88ce5..91aec5b38 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
index 2b992d5a..595327e 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/fast/canvas/canvas-shadow-source-in-expected.png
index 99cab5b..b5daa85 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/fast/canvas/canvas-shadow-source-in-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/fast/canvas/canvas-shadow-source-in-expected.txt
index d19c015..d5d3ee98 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/fast/canvas/canvas-shadow-source-in-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/fast/canvas/canvas-shadow-source-in-expected.txt
@@ -1,17 +1,17 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x470
-  LayoutBlockFlow {HTML} at (0,0) size 800x470
-    LayoutBlockFlow {BODY} at (8,8) size 784x454
-      LayoutBlockFlow {DIV} at (0,0) size 784x20
+layer at (0,0) size 1600x1200
+  LayoutView at (0,0) size 1600x1200
+layer at (0,0) size 1600x470
+  LayoutBlockFlow {HTML} at (0,0) size 1600x470
+    LayoutBlockFlow {BODY} at (8,8) size 1584x454
+      LayoutBlockFlow {DIV} at (0,0) size 1584x20
         LayoutText {#text} at (0,0) size 58x19
           text run at (0,0) width 58: "Test Rect"
-      LayoutBlockFlow (anonymous) at (0,20) size 784x207
+      LayoutBlockFlow (anonymous) at (0,20) size 1584x207
         LayoutText {#text} at (0,0) size 0x0
-      LayoutBlockFlow {DIV} at (0,227) size 784x20
+      LayoutBlockFlow {DIV} at (0,227) size 1584x20
         LayoutText {#text} at (0,0) size 67x19
           text run at (0,0) width 67: "Test Image"
-      LayoutBlockFlow (anonymous) at (0,247) size 784x207
+      LayoutBlockFlow (anonymous) at (0,247) size 1584x207
         LayoutText {#text} at (0,0) size 0x0
         LayoutText {#text} at (0,0) size 0x0
         LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-shadow-source-in-expected.png
index a023a9d0..cb58a88 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-paint-invalidation-expected.txt b/third_party/WebKit/LayoutTests/platform/win/media/video-paint-invalidation-expected.txt
index 1e4bc8e..ff69d1c 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/video-paint-invalidation-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/media/video-paint-invalidation-expected.txt
@@ -8,10 +8,7 @@
       "children": [
         {
           "position": [8, 8],
-          "bounds": [320, 240],
-          "paintInvalidationClients": [
-            "LayoutVideo VIDEO id='video'"
-          ]
+          "bounds": [320, 240]
         },
         {
           "shouldFlattenTransform": false,
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
index a023a9d0..cb58a88 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
index d9b91a17..6f0e991 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
index de66f18..4660eb3 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/canvas/canvas-draw-image-globalalpha.html b/third_party/WebKit/LayoutTests/svg/canvas/canvas-draw-image-globalalpha.html
index 24ba5cd..dec1382 100644
--- a/third_party/WebKit/LayoutTests/svg/canvas/canvas-draw-image-globalalpha.html
+++ b/third_party/WebKit/LayoutTests/svg/canvas/canvas-draw-image-globalalpha.html
@@ -3,9 +3,7 @@
 <script>
 var img = new Image();
 img.src = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" fill="#008000"/></svg>';
-img.onload = function() {
-    var c = document.querySelector('canvas').getContext('2d');
-    c.globalAlpha = 0.5;
-    c.drawImage(img, 0, 0);
-}
+var c = document.querySelector('canvas').getContext('2d');
+c.globalAlpha = 0.5;
+c.drawImage(img, 0, 0);
 </script>
diff --git a/third_party/WebKit/LayoutTests/svg/canvas/image-svg-intrinsic-size.html b/third_party/WebKit/LayoutTests/svg/canvas/image-svg-intrinsic-size.html
index bb94b5b..917e029e8 100644
--- a/third_party/WebKit/LayoutTests/svg/canvas/image-svg-intrinsic-size.html
+++ b/third_party/WebKit/LayoutTests/svg/canvas/image-svg-intrinsic-size.html
@@ -8,15 +8,12 @@
       image.src = "data:image/svg+xml," +
                   "<svg xmlns='http://www.w3.org/2000/svg' width='200' viewBox='0 0 1 1'>" +
                   "<rect width='1' height='1' fill='green'/></svg>";
-      image.onload = function() {
-          var canvas = document.querySelector('canvas');
-          var ctx = canvas.getContext("2d");
-          ctx.drawImage(document.querySelector('img'), 0, 0);
-          document.body.removeChild(document.querySelector('img'));
-      };
       return image;
   }
   document.body.appendChild(createSVGImage());
   document.body.offsetTop; // Force layout
-
+  var canvas = document.querySelector('canvas');
+  var ctx = canvas.getContext("2d");
+  ctx.drawImage(document.querySelector('img'), 0, 0);
+  document.body.removeChild(document.querySelector('img'));
 </script>
diff --git a/third_party/WebKit/LayoutTests/virtual/threaded/inspector/tracing/idle-callback-expected.txt b/third_party/WebKit/LayoutTests/virtual/threaded/inspector/tracing/idle-callback-expected.txt
index 42046d2..91a580f 100644
--- a/third_party/WebKit/LayoutTests/virtual/threaded/inspector/tracing/idle-callback-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/threaded/inspector/tracing/idle-callback-expected.txt
@@ -12,7 +12,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "RequestIdleCallback"
 }
 Text details for RequestIdleCallback: idle-callback.html:8
@@ -28,7 +27,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "RequestIdleCallback"
 }
 Text details for RequestIdleCallback: idle-callback.html:10
@@ -44,7 +42,6 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "RequestIdleCallback"
 }
 Text details for RequestIdleCallback: idle-callback.html:13
@@ -59,13 +56,11 @@
     frameId : <string>
     stackTrace : <object>
     startTime : <number>
-    thread : <string>
     type : "CancelIdleCallback"
 }
 Text details for CancelIdleCallback: idle-callback.html:9
 FireIdleCallback Properties:
 {
-    children : <object>
     data : {
         allottedMilliseconds : <number>
         frame : <string>
@@ -75,13 +70,11 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "FireIdleCallback"
 }
 Text details for FireIdleCallback: idle-callback.html:10
 FireIdleCallback Properties:
 {
-    children : <object>
     data : {
         allottedMilliseconds : <number>
         frame : <string>
@@ -91,7 +84,6 @@
     endTime : <number>
     frameId : <string>
     startTime : <number>
-    thread : <string>
     type : "FireIdleCallback"
 }
 Text details for FireIdleCallback: idle-callback.html:13
diff --git a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp
index 5380c60..590cb72 100644
--- a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp
@@ -274,7 +274,7 @@
     ASSERT(!m_domObjectHolders.contains(holderBase.get()));
     holderBase->setWorld(this);
     holderBase->setWeak(&DOMWrapperWorld::weakCallbackForDOMObjectHolder);
-    m_domObjectHolders.add(holderBase);
+    m_domObjectHolders.add(std::move(holderBase));
 }
 
 void DOMWrapperWorld::unregisterDOMObjectHolder(DOMObjectHolderBase* holderBase)
diff --git a/third_party/WebKit/Source/bindings/core/v8/Dictionary.cpp b/third_party/WebKit/Source/bindings/core/v8/Dictionary.cpp
index 01e46cd..2099598 100644
--- a/third_party/WebKit/Source/bindings/core/v8/Dictionary.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/Dictionary.cpp
@@ -46,7 +46,7 @@
 
 static ExceptionState& emptyExceptionState()
 {
-    AtomicallyInitializedStaticReference(WTF::ThreadSpecific<NonThrowableExceptionState>, exceptionState, new ThreadSpecific<NonThrowableExceptionState>);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(WTF::ThreadSpecific<NonThrowableExceptionState>, exceptionState, new ThreadSpecific<NonThrowableExceptionState>);
     return *exceptionState;
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/ReadableStreamOperationsTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ReadableStreamOperationsTest.cpp
index 4b25d986..6420acd 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ReadableStreamOperationsTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ReadableStreamOperationsTest.cpp
@@ -21,6 +21,24 @@
 
 namespace {
 
+// Unpacks |item|, stores the value of "done" member to |done| and returns
+// the value of "value" member. Returns an empty handle when errored.
+v8::MaybeLocal<v8::Value> unpack(ScriptState* scriptState, v8::Local<v8::Value> item, bool* done)
+{
+    if (!item->IsObject()) {
+        V8ThrowException::throwTypeError(scriptState->isolate(), "The iteration item is not an object.");
+        return v8::MaybeLocal<v8::Value>();
+    }
+    v8::Local<v8::Object> object = item.As<v8::Object>();
+    v8::Local<v8::Value> doneValue;
+    if (!v8Call(object->Get(scriptState->context(), v8String(scriptState->isolate(), "done")), doneValue))
+        return v8::MaybeLocal<v8::Value>();
+    v8::MaybeLocal<v8::Value> r = object->Get(scriptState->context(), v8String(scriptState->isolate(), "value"));
+    if (!r.IsEmpty())
+        *done = doneValue->ToBoolean()->Value();
+    return r;
+}
+
 class NotReached : public ScriptFunction {
 public:
     static v8::Local<v8::Function> createFunction(ScriptState* scriptState)
@@ -57,8 +75,7 @@
         m_isSet = true;
         v8::TryCatch block(v.scriptState()->isolate());
         v8::Local<v8::Value> value;
-        v8::Local<v8::Value> item = v.v8Value();
-        if (!item->IsObject() || !v8Call(v8UnpackIteratorResult(v.scriptState(), item.As<v8::Object>(), &m_isDone), value)) {
+        if (!v8Call(unpack(v.scriptState(), v.v8Value(), &m_isDone), value)) {
             m_isValid = false;
             return;
         }
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8CustomElementLifecycleCallbacks.cpp b/third_party/WebKit/Source/bindings/core/v8/V8CustomElementLifecycleCallbacks.cpp
index 3de51b5..68e463f 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8CustomElementLifecycleCallbacks.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8CustomElementLifecycleCallbacks.cpp
@@ -133,7 +133,7 @@
     // The context is responsible for keeping the prototype
     // alive. This in turn keeps callbacks alive through hidden
     // references; see CALLBACK_LIST(SET_HIDDEN_VALUE).
-    perContextData->addCustomElementBinding(owner, binding);
+    perContextData->addCustomElementBinding(owner, std::move(binding));
     return true;
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8DOMActivityLogger.cpp b/third_party/WebKit/Source/bindings/core/v8/V8DOMActivityLogger.cpp
index d33122d..323cf5e 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8DOMActivityLogger.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8DOMActivityLogger.cpp
@@ -33,9 +33,9 @@
 void V8DOMActivityLogger::setActivityLogger(int worldId, const String& extensionId, PassOwnPtr<V8DOMActivityLogger> logger)
 {
     if (worldId)
-        domActivityLoggersForIsolatedWorld().set(worldId, logger);
+        domActivityLoggersForIsolatedWorld().set(worldId, std::move(logger));
     else
-        domActivityLoggersForMainWorld().set(extensionId, logger);
+        domActivityLoggersForMainWorld().set(extensionId, std::move(logger));
 }
 
 V8DOMActivityLogger* V8DOMActivityLogger::activityLogger(int worldId, const String& extensionId)
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8IteratorResultValue.cpp b/third_party/WebKit/Source/bindings/core/v8/V8IteratorResultValue.cpp
index eeb1aa8..739e3a0 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8IteratorResultValue.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8IteratorResultValue.cpp
@@ -18,17 +18,4 @@
     return result;
 }
 
-v8::MaybeLocal<v8::Value> v8UnpackIteratorResult(ScriptState* scriptState, v8::Local<v8::Object> result, bool* done)
-{
-    v8::MaybeLocal<v8::Value> maybeValue = result->Get(scriptState->context(), v8String(scriptState->isolate(), "value"));
-    if (maybeValue.IsEmpty())
-        return maybeValue;
-    v8::Local<v8::Value> doneValue;
-    if (!v8Call(result->Get(scriptState->context(), v8String(scriptState->isolate(), "done")), doneValue)
-        || !v8Call(doneValue->BooleanValue(scriptState->context()), *done)) {
-        return v8::MaybeLocal<v8::Value>();
-    }
-    return maybeValue;
-}
-
 } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8IteratorResultValue.h b/third_party/WebKit/Source/bindings/core/v8/V8IteratorResultValue.h
index 739ad0a..b857e57 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8IteratorResultValue.h
+++ b/third_party/WebKit/Source/bindings/core/v8/V8IteratorResultValue.h
@@ -12,15 +12,8 @@
 
 namespace blink {
 
-// "Iterator result" in this file is an object returned from iterator.next()
-// having two members "done" and "value".
-
 CORE_EXPORT v8::Local<v8::Object> v8IteratorResultValue(v8::Isolate*, bool done, v8::Local<v8::Value>);
 
-// Unpacks |result|, stores the value of "done" member to |done| and returns
-// the value of "value" member. Returns an empty handle when errored.
-CORE_EXPORT v8::MaybeLocal<v8::Value> v8UnpackIteratorResult(ScriptState*, v8::Local<v8::Object> result, bool* done);
-
 template<typename T>
 inline ScriptValue v8IteratorResult(ScriptState* scriptState, const T& value)
 {
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp b/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp
index 020649e..c67cf53 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp
@@ -291,7 +291,7 @@
 void V8PerIsolateData::setScriptDebugger(PassOwnPtr<MainThreadDebugger> debugger)
 {
     ASSERT(!m_scriptDebugger);
-    m_scriptDebugger = debugger;
+    m_scriptDebugger = std::move(debugger);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8RecursionScope.h b/third_party/WebKit/Source/bindings/core/v8/V8RecursionScope.h
index ff3c133..18a10942 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8RecursionScope.h
+++ b/third_party/WebKit/Source/bindings/core/v8/V8RecursionScope.h
@@ -32,7 +32,6 @@
 #define V8RecursionScope_h
 
 #include "bindings/core/v8/V8PerIsolateData.h"
-#include "core/CoreExport.h"
 #include "platform/ScriptForbiddenScope.h"
 #include "wtf/Noncopyable.h"
 #include <v8.h>
@@ -56,7 +55,7 @@
 // happen at the end of the outer-most script stack frame of calls into page script:
 //
 // http://www.whatwg.org/specs/web-apps/current-work/#perform-a-microtask-checkpoint
-class CORE_EXPORT V8RecursionScope {
+class V8RecursionScope {
     STACK_ALLOCATED();
 public:
     explicit V8RecursionScope(v8::Isolate* isolate)
diff --git a/third_party/WebKit/Source/core/animation/SVGInterpolationType.h b/third_party/WebKit/Source/core/animation/SVGInterpolationType.h
index 6b37d5a7..06bb926e 100644
--- a/third_party/WebKit/Source/core/animation/SVGInterpolationType.h
+++ b/third_party/WebKit/Source/core/animation/SVGInterpolationType.h
@@ -25,7 +25,7 @@
 
     PassOwnPtr<InterpolationValue> maybeConvertSingle(const PropertySpecificKeyframe&, const InterpolationEnvironment&, const UnderlyingValue&, ConversionCheckers&) const override;
     PassOwnPtr<InterpolationValue> maybeConvertUnderlyingValue(const InterpolationEnvironment&) const override;
-    void apply(const InterpolableValue&, const NonInterpolableValue*, InterpolationEnvironment&) const final;
+    void apply(const InterpolableValue&, const NonInterpolableValue*, InterpolationEnvironment&) const override;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.cpp b/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.cpp
new file mode 100644
index 0000000..98da652
--- /dev/null
+++ b/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.cpp
@@ -0,0 +1,161 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/animation/SVGLengthInterpolationType.h"
+
+#include "core/animation/InterpolationEnvironment.h"
+#include "core/animation/StringKeyframe.h"
+#include "core/css/CSSHelper.h"
+#include "core/svg/SVGElement.h"
+#include "core/svg/SVGLength.h"
+#include "core/svg/SVGLengthContext.h"
+
+namespace blink {
+
+namespace {
+
+enum LengthInterpolatedUnit {
+    LengthInterpolatedNumber,
+    LengthInterpolatedPercentage,
+    LengthInterpolatedEMS,
+    LengthInterpolatedEXS,
+    LengthInterpolatedREMS,
+    LengthInterpolatedCHS,
+};
+
+static const CSSPrimitiveValue::UnitType unitTypes[] = {
+    CSSPrimitiveValue::UnitType::UserUnits,
+    CSSPrimitiveValue::UnitType::Percentage,
+    CSSPrimitiveValue::UnitType::Ems,
+    CSSPrimitiveValue::UnitType::Exs,
+    CSSPrimitiveValue::UnitType::Rems,
+    CSSPrimitiveValue::UnitType::Chs
+};
+
+const size_t numLengthInterpolatedUnits = WTF_ARRAY_LENGTH(unitTypes);
+
+LengthInterpolatedUnit convertToInterpolatedUnit(CSSPrimitiveValue::UnitType unitType, double& value)
+{
+    switch (unitType) {
+    case CSSPrimitiveValue::UnitType::Unknown:
+    default:
+        ASSERT_NOT_REACHED();
+    case CSSPrimitiveValue::UnitType::Pixels:
+    case CSSPrimitiveValue::UnitType::Number:
+    case CSSPrimitiveValue::UnitType::UserUnits:
+        return LengthInterpolatedNumber;
+    case CSSPrimitiveValue::UnitType::Percentage:
+        return LengthInterpolatedPercentage;
+    case CSSPrimitiveValue::UnitType::Ems:
+        return LengthInterpolatedEMS;
+    case CSSPrimitiveValue::UnitType::Exs:
+        return LengthInterpolatedEXS;
+    case CSSPrimitiveValue::UnitType::Centimeters:
+        value *= cssPixelsPerCentimeter;
+        return LengthInterpolatedNumber;
+    case CSSPrimitiveValue::UnitType::Millimeters:
+        value *= cssPixelsPerMillimeter;
+        return LengthInterpolatedNumber;
+    case CSSPrimitiveValue::UnitType::Inches:
+        value *= cssPixelsPerInch;
+        return LengthInterpolatedNumber;
+    case CSSPrimitiveValue::UnitType::Points:
+        value *= cssPixelsPerPoint;
+        return LengthInterpolatedNumber;
+    case CSSPrimitiveValue::UnitType::Picas:
+        value *= cssPixelsPerPica;
+        return LengthInterpolatedNumber;
+    case CSSPrimitiveValue::UnitType::Rems:
+        return LengthInterpolatedREMS;
+    case CSSPrimitiveValue::UnitType::Chs:
+        return LengthInterpolatedCHS;
+    }
+}
+
+} // namespace
+
+PassOwnPtr<InterpolationValue> SVGLengthInterpolationType::maybeConvertNeutral(const UnderlyingValue&, ConversionCheckers&) const
+{
+    OwnPtr<InterpolableList> listOfValues = InterpolableList::create(numLengthInterpolatedUnits);
+    for (size_t i = 0; i < numLengthInterpolatedUnits; ++i)
+        listOfValues->set(i, InterpolableNumber::create(0));
+
+    return InterpolationValue::create(*this, listOfValues.release());
+}
+
+PassOwnPtr<InterpolationValue> SVGLengthInterpolationType::maybeConvertSVGValue(const SVGPropertyBase& svgValue) const
+{
+    if (svgValue.type() != AnimatedLength)
+        return nullptr;
+
+    const SVGLength& length = toSVGLength(svgValue);
+    double value = length.valueInSpecifiedUnits();
+    LengthInterpolatedUnit unitType = convertToInterpolatedUnit(length.typeWithCalcResolved(), value);
+
+    double values[numLengthInterpolatedUnits] = { };
+    values[unitType] = value;
+
+    OwnPtr<InterpolableList> listOfValues = InterpolableList::create(numLengthInterpolatedUnits);
+    for (size_t i = 0; i < numLengthInterpolatedUnits; ++i)
+        listOfValues->set(i, InterpolableNumber::create(values[i]));
+
+    return InterpolationValue::create(*this, listOfValues.release());
+}
+
+PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGLengthInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue*) const
+{
+    ASSERT_NOT_REACHED();
+    // This function is no longer called, because apply has been overridden.
+    return nullptr;
+}
+
+PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGLengthInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue*, const SVGLengthContext& lengthContext) const
+{
+    const InterpolableList& listOfValues = toInterpolableList(interpolableValue);
+
+    double value = 0;
+    CSSPrimitiveValue::UnitType unitType = CSSPrimitiveValue::UnitType::UserUnits;
+    unsigned unitTypeCount = 0;
+    // We optimise for the common case where only one unit type is involved.
+    for (size_t i = 0; i < numLengthInterpolatedUnits; i++) {
+        double entry = toInterpolableNumber(listOfValues.get(i))->value();
+        if (!entry)
+            continue;
+        unitTypeCount++;
+        if (unitTypeCount > 1)
+            break;
+
+        value = entry;
+        unitType = unitTypes[i];
+    }
+
+    if (unitTypeCount > 1) {
+        value = 0;
+        unitType = CSSPrimitiveValue::UnitType::UserUnits;
+
+        // SVGLength does not support calc expressions, so we convert to canonical units.
+        for (size_t i = 0; i < numLengthInterpolatedUnits; i++) {
+            double entry = toInterpolableNumber(listOfValues.get(i))->value();
+            if (entry)
+                value += lengthContext.convertValueToUserUnits(entry, m_unitMode, unitTypes[i]);
+        }
+    }
+
+    if (m_negativeValuesForbidden && value < 0)
+        value = 0;
+
+    RefPtrWillBeRawPtr<SVGLength> result = SVGLength::create(m_unitMode); // defaults to the length 0
+    result->newValueSpecifiedUnits(unitType, value);
+    return result.release();
+}
+
+void SVGLengthInterpolationType::apply(const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue, InterpolationEnvironment& environment) const
+{
+    SVGElement& element = environment.svgElement();
+    SVGLengthContext lengthContext(&element);
+    element.setWebAnimatedAttribute(attribute(), appliedSVGValue(interpolableValue, nonInterpolableValue, lengthContext));
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.h b/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.h
new file mode 100644
index 0000000..d9b42ce5
--- /dev/null
+++ b/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.h
@@ -0,0 +1,38 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SVGLengthInterpolationType_h
+#define SVGLengthInterpolationType_h
+
+#include "core/animation/SVGInterpolationType.h"
+
+#include "core/svg/SVGLength.h"
+
+namespace blink {
+
+class SVGLengthContext;
+enum class SVGLengthMode;
+
+class SVGLengthInterpolationType : public SVGInterpolationType {
+public:
+    SVGLengthInterpolationType(const QualifiedName& attribute)
+        : SVGInterpolationType(attribute)
+        , m_unitMode(SVGLength::lengthModeForAnimatedLengthAttribute(attribute))
+        , m_negativeValuesForbidden(SVGLength::negativeValuesForbiddenForAnimatedLengthAttribute(attribute))
+    { }
+
+private:
+    PassOwnPtr<InterpolationValue> maybeConvertNeutral(const UnderlyingValue&, ConversionCheckers&) const final;
+    PassOwnPtr<InterpolationValue> maybeConvertSVGValue(const SVGPropertyBase& svgValue) const final;
+    PassRefPtrWillBeRawPtr<SVGPropertyBase> appliedSVGValue(const InterpolableValue&, const NonInterpolableValue*) const final;
+    PassRefPtrWillBeRawPtr<SVGPropertyBase> appliedSVGValue(const InterpolableValue&, const NonInterpolableValue*, const SVGLengthContext&) const;
+    void apply(const InterpolableValue&, const NonInterpolableValue*, InterpolationEnvironment&) const final;
+
+    const SVGLengthMode m_unitMode;
+    const bool m_negativeValuesForbidden;
+};
+
+} // namespace blink
+
+#endif // SVGLengthInterpolationType_h
diff --git a/third_party/WebKit/Source/core/animation/StringKeyframe.cpp b/third_party/WebKit/Source/core/animation/StringKeyframe.cpp
index ec2f581..64c81d5 100644
--- a/third_party/WebKit/Source/core/animation/StringKeyframe.cpp
+++ b/third_party/WebKit/Source/core/animation/StringKeyframe.cpp
@@ -34,6 +34,7 @@
 #include "core/animation/SVGAngleInterpolationType.h"
 #include "core/animation/SVGIntegerInterpolationType.h"
 #include "core/animation/SVGIntegerOptionalIntegerInterpolationType.h"
+#include "core/animation/SVGLengthInterpolationType.h"
 #include "core/animation/SVGNumberInterpolationType.h"
 #include "core/animation/SVGNumberListInterpolationType.h"
 #include "core/animation/SVGNumberOptionalNumberInterpolationType.h"
@@ -273,6 +274,27 @@
             applicableTypes->append(adoptPtr(new SVGIntegerInterpolationType(attribute)));
         } else if (attribute == SVGNames::orderAttr) {
             applicableTypes->append(adoptPtr(new SVGIntegerOptionalIntegerInterpolationType(attribute)));
+        } else if (attribute == SVGNames::cxAttr
+            || attribute == SVGNames::cyAttr
+            || attribute == SVGNames::fxAttr
+            || attribute == SVGNames::fyAttr
+            || attribute == SVGNames::heightAttr
+            || attribute == SVGNames::markerHeightAttr
+            || attribute == SVGNames::markerWidthAttr
+            || attribute == SVGNames::rAttr
+            || attribute == SVGNames::refXAttr
+            || attribute == SVGNames::refYAttr
+            || attribute == SVGNames::rxAttr
+            || attribute == SVGNames::ryAttr
+            || attribute == SVGNames::startOffsetAttr
+            || attribute == SVGNames::textLengthAttr
+            || attribute == SVGNames::widthAttr
+            || attribute == SVGNames::xAttr
+            || attribute == SVGNames::x1Attr
+            || attribute == SVGNames::x2Attr
+            || attribute == SVGNames::y1Attr
+            || attribute == SVGNames::y2Attr) {
+            applicableTypes->append(adoptPtr(new SVGLengthInterpolationType(attribute)));
         } else if (attribute == SVGNames::amplitudeAttr
             || attribute == SVGNames::azimuthAttr
             || attribute == SVGNames::biasAttr
@@ -576,8 +598,6 @@
     RefPtr<Interpolation> interpolation = nullptr;
     ASSERT(fromValue->type() == toValue->type());
     switch (fromValue->type()) {
-    case AnimatedLength:
-        return LengthSVGInterpolation::create(fromValue, toValue, attribute);
     case AnimatedLengthList:
         interpolation = ListSVGInterpolation<LengthSVGInterpolation>::maybeCreate(fromValue, toValue, attribute);
         break;
@@ -589,6 +609,7 @@
     case AnimatedAngle:
     case AnimatedInteger:
     case AnimatedIntegerOptionalInteger:
+    case AnimatedLength:
     case AnimatedNumber:
     case AnimatedNumberList:
     case AnimatedNumberOptionalNumber:
diff --git a/third_party/WebKit/Source/core/animation/animatable/AnimatablePath.cpp b/third_party/WebKit/Source/core/animation/animatable/AnimatablePath.cpp
new file mode 100644
index 0000000..e48c1e7b
--- /dev/null
+++ b/third_party/WebKit/Source/core/animation/animatable/AnimatablePath.cpp
@@ -0,0 +1,61 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/animation/animatable/AnimatablePath.h"
+
+#include "core/svg/SVGPathBlender.h"
+#include "core/svg/SVGPathByteStreamBuilder.h"
+#include "core/svg/SVGPathByteStreamSource.h"
+#include "core/svg/SVGPathUtilities.h"
+
+namespace blink {
+
+bool AnimatablePath::usesDefaultInterpolationWith(const AnimatableValue* value) const
+{
+    // Default interpolation is used if the paths have different lengths,
+    // or the paths have a segment with different types (ignoring "relativeness").
+
+    SVGPathByteStreamSource fromSource(pathValue()->byteStream());
+    SVGPathByteStreamSource toSource(toAnimatablePath(value)->pathValue()->byteStream());
+
+    while (fromSource.hasMoreData()) {
+        if (!toSource.hasMoreData())
+            return true;
+
+        PathSegmentData fromSeg = fromSource.parseSegment();
+        PathSegmentData toSeg = toSource.parseSegment();
+        ASSERT(fromSeg.command != PathSegUnknown);
+        ASSERT(toSeg.command != PathSegUnknown);
+
+        if (toAbsolutePathSegType(fromSeg.command) != toAbsolutePathSegType(toSeg.command))
+            return true;
+    }
+
+    return toSource.hasMoreData();
+}
+
+PassRefPtr<AnimatableValue> AnimatablePath::interpolateTo(const AnimatableValue* value, double fraction) const
+{
+    if (usesDefaultInterpolationWith(value))
+        return defaultInterpolateTo(this, value, fraction);
+
+    OwnPtr<SVGPathByteStream> byteStream = SVGPathByteStream::create();
+    SVGPathByteStreamBuilder builder(*byteStream);
+
+    SVGPathByteStreamSource fromSource(pathValue()->byteStream());
+    SVGPathByteStreamSource toSource(toAnimatablePath(value)->pathValue()->byteStream());
+
+    SVGPathBlender blender(&fromSource, &toSource, &builder);
+    bool ok = blender.blendAnimatedPath(fraction);
+    ASSERT_UNUSED(ok, ok);
+    return AnimatablePath::create(CSSPathValue::create(byteStream.release()));
+}
+
+bool AnimatablePath::equalTo(const AnimatableValue* value) const
+{
+    return pathValue()->equals(*toAnimatablePath(value)->pathValue());
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/animatable/AnimatablePath.h b/third_party/WebKit/Source/core/animation/animatable/AnimatablePath.h
new file mode 100644
index 0000000..27c38a6
--- /dev/null
+++ b/third_party/WebKit/Source/core/animation/animatable/AnimatablePath.h
@@ -0,0 +1,43 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef AnimatablePath_h
+#define AnimatablePath_h
+
+#include "core/CoreExport.h"
+#include "core/animation/animatable/AnimatableValue.h"
+#include "core/css/CSSPathValue.h"
+
+namespace blink {
+
+class CORE_EXPORT AnimatablePath final : public AnimatableValue {
+public:
+    ~AnimatablePath() override { }
+    static PassRefPtr<AnimatablePath> create(PassRefPtrWillBeRawPtr<CSSPathValue> pathValue)
+    {
+        return adoptRef(new AnimatablePath(pathValue));
+    }
+
+    CSSPathValue* pathValue() const { return m_pathValue.get(); }
+
+protected:
+    PassRefPtr<AnimatableValue> interpolateTo(const AnimatableValue*, double fraction) const override;
+    bool usesDefaultInterpolationWith(const AnimatableValue*) const override;
+
+private:
+    explicit AnimatablePath(PassRefPtrWillBeRawPtr<CSSPathValue> pathValue)
+        : m_pathValue(pathValue)
+    {
+        ASSERT(m_pathValue);
+    }
+    AnimatableType type() const override { return TypePath; }
+    bool equalTo(const AnimatableValue*) const override;
+    const RefPtrWillBePersistent<CSSPathValue> m_pathValue;
+};
+
+DEFINE_ANIMATABLE_VALUE_TYPE_CASTS(AnimatablePath, isPath());
+
+} // namespace blink
+
+#endif // AnimatablePath_h
diff --git a/third_party/WebKit/Source/core/animation/animatable/AnimatableValue.h b/third_party/WebKit/Source/core/animation/animatable/AnimatableValue.h
index 797e6b0..8d0fcba 100644
--- a/third_party/WebKit/Source/core/animation/animatable/AnimatableValue.h
+++ b/third_party/WebKit/Source/core/animation/animatable/AnimatableValue.h
@@ -72,6 +72,7 @@
     bool isLengthPoint3D() const { return type() == TypeLengthPoint3D; }
     bool isLengthSize() const { return type() == TypeLengthSize; }
     bool isNeutral() const { return type() == TypeNeutral; }
+    bool isPath() const { return type() == TypePath; }
     bool isRepeatable() const { return type() == TypeRepeatable; }
     bool isSVGLength() const { return type() == TypeSVGLength; }
     bool isSVGPaint() const { return type() == TypeSVGPaint; }
@@ -103,6 +104,7 @@
         TypeLengthPoint3D,
         TypeLengthSize,
         TypeNeutral,
+        TypePath,
         TypeRepeatable,
         TypeSVGLength,
         TypeSVGPaint,
diff --git a/third_party/WebKit/Source/core/animation/animatable/AnimatableValueTestHelper.cpp b/third_party/WebKit/Source/core/animation/animatable/AnimatableValueTestHelper.cpp
index 198b77b..7e190739 100644
--- a/third_party/WebKit/Source/core/animation/animatable/AnimatableValueTestHelper.cpp
+++ b/third_party/WebKit/Source/core/animation/animatable/AnimatableValueTestHelper.cpp
@@ -61,6 +61,11 @@
     *os << "AnimatableNeutral@" << &animValue;
 }
 
+void PrintTo(const AnimatablePath& animValue, ::std::ostream* os)
+{
+    *os << "AnimatablePath@" << &animValue;
+}
+
 void PrintTo(const AnimatableRepeatable& animValue, ::std::ostream* os)
 {
     *os << "AnimatableRepeatable(";
diff --git a/third_party/WebKit/Source/core/animation/animatable/AnimatableValueTestHelper.h b/third_party/WebKit/Source/core/animation/animatable/AnimatableValueTestHelper.h
index ef7a4c1..a27fce34 100644
--- a/third_party/WebKit/Source/core/animation/animatable/AnimatableValueTestHelper.h
+++ b/third_party/WebKit/Source/core/animation/animatable/AnimatableValueTestHelper.h
@@ -40,6 +40,7 @@
 #include "core/animation/animatable/AnimatableColor.h"
 #include "core/animation/animatable/AnimatableImage.h"
 #include "core/animation/animatable/AnimatableNeutral.h"
+#include "core/animation/animatable/AnimatablePath.h"
 #include "core/animation/animatable/AnimatableRepeatable.h"
 #include "core/animation/animatable/AnimatableSVGPaint.h"
 #include "core/animation/animatable/AnimatableShapeValue.h"
@@ -59,6 +60,7 @@
 void PrintTo(const AnimatableColor&, ::std::ostream*);
 void PrintTo(const AnimatableImage&, ::std::ostream*);
 void PrintTo(const AnimatableNeutral&, ::std::ostream*);
+void PrintTo(const AnimatablePath&, ::std::ostream*);
 void PrintTo(const AnimatableRepeatable&, ::std::ostream*);
 void PrintTo(const AnimatableShapeValue&, ::std::ostream*);
 void PrintTo(const AnimatableStrokeDasharrayList&, ::std::ostream*);
diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp b/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp
index 23fa5ca7..67cc56ae 100644
--- a/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp
+++ b/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp
@@ -44,6 +44,7 @@
 #include "core/animation/animatable/AnimatableLengthPoint.h"
 #include "core/animation/animatable/AnimatableLengthPoint3D.h"
 #include "core/animation/animatable/AnimatableLengthSize.h"
+#include "core/animation/animatable/AnimatablePath.h"
 #include "core/animation/animatable/AnimatableRepeatable.h"
 #include "core/animation/animatable/AnimatableSVGPaint.h"
 #include "core/animation/animatable/AnimatableShadow.h"
@@ -247,6 +248,11 @@
     return AnimatableUnknown::create(CSSValueNone);
 }
 
+static PassRefPtr<AnimatableValue> createFromPath(CSSPathValue* pathValue)
+{
+    return AnimatablePath::create(pathValue);
+}
+
 static double fontStretchToDouble(FontStretch fontStretch)
 {
     return static_cast<unsigned>(fontStretch);
@@ -573,6 +579,8 @@
         return AnimatableUnknown::create(CSSPrimitiveValue::create(style.verticalAlign()));
     case CSSPropertyVisibility:
         return AnimatableVisibility::create(style.visibility());
+    case CSSPropertyD:
+        return createFromPath(style.svgStyle().d());
     case CSSPropertyCx:
         return createFromLength(style.svgStyle().cx(), style);
     case CSSPropertyCy:
diff --git a/third_party/WebKit/Source/core/animation/css/CSSPropertyEquality.cpp b/third_party/WebKit/Source/core/animation/css/CSSPropertyEquality.cpp
index eaefc68..0e1fb96 100644
--- a/third_party/WebKit/Source/core/animation/css/CSSPropertyEquality.cpp
+++ b/third_party/WebKit/Source/core/animation/css/CSSPropertyEquality.cpp
@@ -315,6 +315,8 @@
         return a.width() == b.width();
     case CSSPropertyWordSpacing:
         return a.wordSpacing() == b.wordSpacing();
+    case CSSPropertyD:
+        return a.svgStyle().d()->equals(*b.svgStyle().d());
     case CSSPropertyCx:
         return a.svgStyle().cx() == b.svgStyle().cx();
     case CSSPropertyCy:
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi
index f623675e..c1fb992 100644
--- a/third_party/WebKit/Source/core/core.gypi
+++ b/third_party/WebKit/Source/core/core.gypi
@@ -920,6 +920,8 @@
             'animation/SVGInterpolation.h',
             'animation/SVGInterpolationType.cpp',
             'animation/SVGInterpolationType.h',
+            'animation/SVGLengthInterpolationType.cpp',
+            'animation/SVGLengthInterpolationType.h',
             'animation/SVGNumberInterpolationType.cpp',
             'animation/SVGNumberInterpolationType.h',
             'animation/SVGNumberListInterpolationType.cpp',
@@ -980,6 +982,8 @@
             'animation/animatable/AnimatableLengthSize.cpp',
             'animation/animatable/AnimatableLengthSize.h',
             'animation/animatable/AnimatableNeutral.h',
+            'animation/animatable/AnimatablePath.cpp',
+            'animation/animatable/AnimatablePath.h',
             'animation/animatable/AnimatableRepeatable.cpp',
             'animation/animatable/AnimatableRepeatable.h',
             'animation/animatable/AnimatableSVGPaint.cpp',
diff --git a/third_party/WebKit/Source/core/css/CSSPrimitiveValue.cpp b/third_party/WebKit/Source/core/css/CSSPrimitiveValue.cpp
index 83ba6ad..cbbb45b 100644
--- a/third_party/WebKit/Source/core/css/CSSPrimitiveValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSPrimitiveValue.cpp
@@ -184,7 +184,7 @@
 
 static CSSTextCache& cssTextCache()
 {
-    AtomicallyInitializedStaticReference(ThreadSpecific<CSSTextCacheWrapper>, cache, new ThreadSpecific<CSSTextCacheWrapper>);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(ThreadSpecific<CSSTextCacheWrapper>, cache, new ThreadSpecific<CSSTextCacheWrapper>);
     return *cache;
 }
 
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.in b/third_party/WebKit/Source/core/css/CSSProperties.in
index a0a6f8d..7f646cc4 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.in
+++ b/third_party/WebKit/Source/core/css/CSSProperties.in
@@ -170,7 +170,7 @@
 cursor inherited, custom_all
 cx interpolable, svg, converter=convertLength
 cy interpolable, svg, converter=convertLength
-d runtime_flag=CSSPropertyD, svg, converter=convertPath
+d runtime_flag=CSSPropertyD, interpolable, svg, converter=convertPath
 display
 dominant-baseline inherited, svg
 empty-cells inherited, type_name=EEmptyCell
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index 01669d1..eeb4124 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -3120,6 +3120,8 @@
         return consumeTransformOrigin(m_range, m_context.mode(), UnitlessQuirk::Forbid);
     case CSSPropertyContent:
         return consumeContent(m_range, m_context);
+    case CSSPropertyListStyleImage:
+        return consumeImage(m_range, m_context);
     default:
         return nullptr;
     }
@@ -3710,6 +3712,8 @@
         return consumeShorthandGreedily(flexFlowShorthand(), important);
     case CSSPropertyWebkitColumnRule:
         return consumeShorthandGreedily(webkitColumnRuleShorthand(), important);
+    case CSSPropertyListStyle:
+        return consumeShorthandGreedily(listStyleShorthand(), important);
     default:
         m_currentShorthand = oldShorthand;
         return false;
diff --git a/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp
index 0aea3c63..0763e24d 100644
--- a/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp
@@ -393,8 +393,7 @@
         m_implicitShorthand = false;
         return result;
     }
-    case CSSPropertyListStyleImage:     // <uri> | none | inherit
-    case CSSPropertyBorderImageSource:
+    case CSSPropertyBorderImageSource: // <uri> | none | inherit
     case CSSPropertyWebkitMaskBoxImageSource:
         if (parseFillImage(m_valueList, parsedValue))
             m_valueList->next();
@@ -663,8 +662,6 @@
     case CSSPropertyBorderStyle:
         // <border-style>{1,4} | inherit
         return parse4Values(propId, borderStyleShorthand().properties(), important);
-    case CSSPropertyListStyle:
-        return parseShorthand(propId, listStyleShorthand(), important);
     case CSSPropertyInvalid:
         return false;
     case CSSPropertyWebkitClipPath:
@@ -887,6 +884,8 @@
     case CSSPropertyCursor:
     case CSSPropertyTransformOrigin:
     case CSSPropertyContent:
+    case CSSPropertyListStyleImage:
+    case CSSPropertyListStyle:
         validPrimitive = false;
         break;
 
diff --git a/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp b/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp
index bd881bd..8b8a148 100644
--- a/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp
@@ -43,6 +43,7 @@
 #include "core/animation/animatable/AnimatableLengthPoint.h"
 #include "core/animation/animatable/AnimatableLengthPoint3D.h"
 #include "core/animation/animatable/AnimatableLengthSize.h"
+#include "core/animation/animatable/AnimatablePath.h"
 #include "core/animation/animatable/AnimatableRepeatable.h"
 #include "core/animation/animatable/AnimatableSVGPaint.h"
 #include "core/animation/animatable/AnimatableShadow.h"
@@ -681,6 +682,9 @@
     case CSSPropertyZIndex:
         style->setZIndex(clampTo<int>(round(toAnimatableDouble(value)->toDouble())));
         return;
+    case CSSPropertyD:
+        style->setD(toAnimatablePath(value)->pathValue());
+        return;
     case CSSPropertyCx:
         style->setCx(animatableValueToLength(value, state));
         return;
diff --git a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp
index a522dcc..b22cb6b0 100644
--- a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp
@@ -8,6 +8,8 @@
 #include "core/CSSPropertyNames.h"
 #include "core/CSSValueKeywords.h"
 #include "core/StyleBuilderFunctions.h"
+#include "core/StylePropertyShorthand.h"
+#include "core/css/CSSValuePool.h"
 #include "core/css/CSSVariableData.h"
 #include "core/css/CSSVariableReferenceValue.h"
 #include "core/css/parser/CSSParserToken.h"
@@ -109,24 +111,36 @@
 
 void CSSVariableResolver::resolveAndApplyVariableReferences(StyleResolverState& state, CSSPropertyID id, const CSSVariableReferenceValue& value)
 {
+
     // TODO(leviw): This should be a stack
     CSSVariableResolver resolver(state.style()->variables());
 
     Vector<CSSParserToken> tokens;
     ResolutionState resolutionContext;
     resolver.resolveVariableReferencesFromTokens(value.variableDataValue()->tokens(), tokens, resolutionContext);
-    if (!resolutionContext.success)
+
+    if (resolutionContext.success) {
+        CSSParserContext context(HTMLStandardMode, 0);
+
+        WillBeHeapVector<CSSProperty, 256> parsedProperties;
+
+        if (CSSPropertyParser::parseValue(id, false, CSSParserTokenRange(tokens), context, parsedProperties, StyleRule::Type::Style)) {
+            unsigned parsedPropertiesCount = parsedProperties.size();
+            for (unsigned i = 0; i < parsedPropertiesCount; ++i)
+                StyleBuilder::applyProperty(parsedProperties[i].id(), state, parsedProperties[i].value());
+            return;
+        }
+    }
+
+    RefPtrWillBeRawPtr<CSSUnsetValue> unset = cssValuePool().createUnsetValue();
+    if (isShorthandProperty(id)) {
+        StylePropertyShorthand shorthand = shorthandForProperty(id);
+        for (unsigned i = 0; i < shorthand.length(); i++)
+            StyleBuilder::applyProperty(shorthand.properties()[i], state, unset.get());
         return;
+    }
 
-    CSSParserContext context(HTMLStandardMode, 0);
-
-    WillBeHeapVector<CSSProperty, 256> parsedProperties;
-
-    CSSPropertyParser::parseValue(id, false, CSSParserTokenRange(tokens), context, parsedProperties, StyleRule::Type::Style);
-
-    unsigned parsedPropertiesCount = parsedProperties.size();
-    for (unsigned i = 0; i < parsedPropertiesCount; ++i)
-        StyleBuilder::applyProperty(parsedProperties[i].id(), state, parsedProperties[i].value());
+    StyleBuilder::applyProperty(id, state, unset.get());
 }
 
 void CSSVariableResolver::resolveVariableDefinitions(StyleVariableData* variables)
diff --git a/third_party/WebKit/Source/core/dom/ContainerNode.cpp b/third_party/WebKit/Source/core/dom/ContainerNode.cpp
index fa4aca1..bcc1d15d 100644
--- a/third_party/WebKit/Source/core/dom/ContainerNode.cpp
+++ b/third_party/WebKit/Source/core/dom/ContainerNode.cpp
@@ -866,14 +866,27 @@
 
 void ContainerNode::attach(const AttachContext& context)
 {
-    attachChildren(context);
+    AttachContext childrenContext(context);
+    childrenContext.resolvedStyle = nullptr;
+
+    for (Node* child = firstChild(); child; child = child->nextSibling()) {
+        ASSERT(child->needsAttach() || childAttachedAllowedWhenAttachingChildren(this));
+        if (child->needsAttach())
+            child->attach(childrenContext);
+    }
+
     clearChildNeedsStyleRecalc();
     Node::attach(context);
 }
 
 void ContainerNode::detach(const AttachContext& context)
 {
-    detachChildren(context);
+    AttachContext childrenContext(context);
+    childrenContext.resolvedStyle = nullptr;
+
+    for (Node* child = firstChild(); child; child = child->nextSibling())
+        child->detach(childrenContext);
+
     setChildNeedsStyleRecalc();
     Node::detach(context);
 }
diff --git a/third_party/WebKit/Source/core/dom/ContainerNode.h b/third_party/WebKit/Source/core/dom/ContainerNode.h
index 44f1f4e..b8193590 100644
--- a/third_party/WebKit/Source/core/dom/ContainerNode.h
+++ b/third_party/WebKit/Source/core/dom/ContainerNode.h
@@ -296,27 +296,6 @@
 {
 }
 
-inline void ContainerNode::attachChildren(const AttachContext& context)
-{
-    AttachContext childrenContext(context);
-    childrenContext.resolvedStyle = nullptr;
-
-    for (Node* child = firstChild(); child; child = child->nextSibling()) {
-        ASSERT(child->needsAttach() || childAttachedAllowedWhenAttachingChildren(this));
-        if (child->needsAttach())
-            child->attach(childrenContext);
-    }
-}
-
-inline void ContainerNode::detachChildren(const AttachContext& context)
-{
-    AttachContext childrenContext(context);
-    childrenContext.resolvedStyle = nullptr;
-
-    for (Node* child = firstChild(); child; child = child->nextSibling())
-        child->detach(childrenContext);
-}
-
 inline bool ContainerNode::needsAdjacentStyleRecalc() const
 {
     if (!childrenAffectedByDirectAdjacentRules() && !childrenAffectedByIndirectAdjacentRules())
diff --git a/third_party/WebKit/Source/core/dom/ContextFeatures.h b/third_party/WebKit/Source/core/dom/ContextFeatures.h
index 3f77f21..8d0ea1e 100644
--- a/third_party/WebKit/Source/core/dom/ContextFeatures.h
+++ b/third_party/WebKit/Source/core/dom/ContextFeatures.h
@@ -69,7 +69,7 @@
 
 private:
     explicit ContextFeatures(PassOwnPtr<ContextFeaturesClient> client)
-        : m_client(client)
+        : m_client(std::move(client))
     { }
 
     OwnPtr<ContextFeaturesClient> m_client;
@@ -90,7 +90,7 @@
 
 inline PassRefPtrWillBeRawPtr<ContextFeatures> ContextFeatures::create(PassOwnPtr<ContextFeaturesClient> client)
 {
-    return adoptRefWillBeNoop(new ContextFeatures(client));
+    return adoptRefWillBeNoop(new ContextFeatures(std::move(client)));
 }
 
 inline bool ContextFeatures::isEnabled(Document* document, FeatureType type, bool defaultValue) const
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index 8ce9402..5753950 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -3638,7 +3638,7 @@
 #else
     m_nodeListCounts[list->invalidationType()]++;
 #endif
-    if (list->isRootedAtDocument())
+    if (list->isRootedAtTreeScope())
         m_listsInvalidatedAtDocument.add(list);
 }
 
@@ -3650,7 +3650,7 @@
 #else
     m_nodeListCounts[list->invalidationType()]--;
 #endif
-    if (list->isRootedAtDocument()) {
+    if (list->isRootedAtTreeScope()) {
         ASSERT(m_listsInvalidatedAtDocument.contains(list));
         m_listsInvalidatedAtDocument.remove(list);
     }
diff --git a/third_party/WebKit/Source/core/dom/ExecutionContextTask.h b/third_party/WebKit/Source/core/dom/ExecutionContextTask.h
index 322a382..f3ccf53c 100644
--- a/third_party/WebKit/Source/core/dom/ExecutionContextTask.h
+++ b/third_party/WebKit/Source/core/dom/ExecutionContextTask.h
@@ -54,7 +54,7 @@
 class CallClosureTaskBase : public ExecutionContextTask {
 protected:
     CallClosureTaskBase(PassOwnPtr<Function<T>> closure, bool isSameThread)
-        : m_closure(closure)
+        : m_closure(std::move(closure))
 #if ENABLE(ASSERT)
         , m_isSameThread(isSameThread)
         , m_createdThread(currentThread())
@@ -87,7 +87,7 @@
     // See http://crbug.com/390851
     static PassOwnPtr<CallClosureTask> create(PassOwnPtr<Closure> closure, bool isSameThread = false)
     {
-        return adoptPtr(new CallClosureTask(closure, isSameThread));
+        return adoptPtr(new CallClosureTask(std::move(closure), isSameThread));
     }
 
     void performTask(ExecutionContext*) override
@@ -98,7 +98,7 @@
 
 private:
     CallClosureTask(PassOwnPtr<Closure> closure, bool isSameThread)
-        : CallClosureTaskBase<void()>(closure, isSameThread)
+        : CallClosureTaskBase<void()>(std::move(closure), isSameThread)
     {
     }
 };
diff --git a/third_party/WebKit/Source/core/dom/LiveNodeList.h b/third_party/WebKit/Source/core/dom/LiveNodeList.h
index 59011a2..c8457dd 100644
--- a/third_party/WebKit/Source/core/dom/LiveNodeList.h
+++ b/third_party/WebKit/Source/core/dom/LiveNodeList.h
@@ -38,7 +38,7 @@
 class LiveNodeList : public NodeList, public LiveNodeListBase {
     WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(LiveNodeList);
 public:
-    LiveNodeList(ContainerNode& ownerNode, CollectionType collectionType, NodeListInvalidationType invalidationType, NodeListRootType rootType = NodeListIsRootedAtNode)
+    LiveNodeList(ContainerNode& ownerNode, CollectionType collectionType, NodeListInvalidationType invalidationType, NodeListRootType rootType = NodeListRootType::Node)
         : LiveNodeListBase(ownerNode, rootType, invalidationType, collectionType) { }
 
     unsigned length() const final;
diff --git a/third_party/WebKit/Source/core/dom/LiveNodeListBase.cpp b/third_party/WebKit/Source/core/dom/LiveNodeListBase.cpp
index ceb8429..bf945c8 100644
--- a/third_party/WebKit/Source/core/dom/LiveNodeListBase.cpp
+++ b/third_party/WebKit/Source/core/dom/LiveNodeListBase.cpp
@@ -39,8 +39,8 @@
 
 ContainerNode& LiveNodeListBase::rootNode() const
 {
-    if (isRootedAtDocument() && m_ownerNode->inDocument())
-        return m_ownerNode->document();
+    if (isRootedAtTreeScope() && m_ownerNode->isInTreeScope())
+        return m_ownerNode->treeScope().rootNode();
     return *m_ownerNode;
 }
 
diff --git a/third_party/WebKit/Source/core/dom/LiveNodeListBase.h b/third_party/WebKit/Source/core/dom/LiveNodeListBase.h
index 86067d8d..306d3e8a 100644
--- a/third_party/WebKit/Source/core/dom/LiveNodeListBase.h
+++ b/third_party/WebKit/Source/core/dom/LiveNodeListBase.h
@@ -34,9 +34,9 @@
 
 namespace blink {
 
-enum NodeListRootType {
-    NodeListIsRootedAtNode,
-    NodeListIsRootedAtDocument
+enum class NodeListRootType {
+    Node,
+    TreeScope,
 };
 
 class CORE_EXPORT LiveNodeListBase : public WillBeGarbageCollectedMixin {
@@ -44,7 +44,7 @@
     LiveNodeListBase(ContainerNode& ownerNode, NodeListRootType rootType, NodeListInvalidationType invalidationType,
         CollectionType collectionType)
         : m_ownerNode(ownerNode)
-        , m_rootType(rootType)
+        , m_rootType(static_cast<unsigned>(rootType))
         , m_invalidationType(invalidationType)
         , m_collectionType(collectionType)
     {
@@ -65,7 +65,7 @@
     ContainerNode& rootNode() const;
 
     void didMoveToDocument(Document& oldDocument, Document& newDocument);
-    ALWAYS_INLINE bool isRootedAtDocument() const { return m_rootType == NodeListIsRootedAtDocument; }
+    ALWAYS_INLINE bool isRootedAtTreeScope() const { return m_rootType == static_cast<unsigned>(NodeListRootType::TreeScope); }
     ALWAYS_INLINE NodeListInvalidationType invalidationType() const { return static_cast<NodeListInvalidationType>(m_invalidationType); }
     ALWAYS_INLINE CollectionType type() const { return static_cast<CollectionType>(m_collectionType); }
     ContainerNode& ownerNode() const { return *m_ownerNode; }
diff --git a/third_party/WebKit/Source/core/dom/NodeListsNodeData.h b/third_party/WebKit/Source/core/dom/NodeListsNodeData.h
index 9da6dd6..5a3a3a4 100644
--- a/third_party/WebKit/Source/core/dom/NodeListsNodeData.h
+++ b/third_party/WebKit/Source/core/dom/NodeListsNodeData.h
@@ -197,7 +197,7 @@
         TagCollectionCacheNS::const_iterator tagEnd = m_tagCollectionCacheNS.end();
         for (TagCollectionCacheNS::const_iterator it = m_tagCollectionCacheNS.begin(); it != tagEnd; ++it) {
             LiveNodeListBase* list = it->value;
-            ASSERT(!list->isRootedAtDocument());
+            ASSERT(!list->isRootedAtTreeScope());
             list->didMoveToDocument(oldDocument, newDocument);
         }
     }
diff --git a/third_party/WebKit/Source/core/events/EventListenerMap.cpp b/third_party/WebKit/Source/core/events/EventListenerMap.cpp
index 8e25e681..c2b85e5 100644
--- a/third_party/WebKit/Source/core/events/EventListenerMap.cpp
+++ b/third_party/WebKit/Source/core/events/EventListenerMap.cpp
@@ -49,7 +49,7 @@
 #if ENABLE(ASSERT)
 static Mutex& activeIteratorCountMutex()
 {
-    AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex());
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(Mutex, mutex, new Mutex());
     return mutex;
 }
 
diff --git a/third_party/WebKit/Source/core/events/MessageEvent.h b/third_party/WebKit/Source/core/events/MessageEvent.h
index 958f126..36cb8145 100644
--- a/third_party/WebKit/Source/core/events/MessageEvent.h
+++ b/third_party/WebKit/Source/core/events/MessageEvent.h
@@ -57,7 +57,7 @@
     }
     static PassRefPtrWillBeRawPtr<MessageEvent> create(PassOwnPtr<MessagePortChannelArray> channels, PassRefPtr<SerializedScriptValue> data, const String& origin = String(), const String& lastEventId = String(), PassRefPtrWillBeRawPtr<EventTarget> source = nullptr, const String& suborigin = String())
     {
-        return adoptRefWillBeNoop(new MessageEvent(data, origin, lastEventId, source, channels, suborigin));
+        return adoptRefWillBeNoop(new MessageEvent(data, origin, lastEventId, source, std::move(channels), suborigin));
     }
     static PassRefPtrWillBeRawPtr<MessageEvent> create(const String& data, const String& origin = String(), const String& suborigin = String())
     {
diff --git a/third_party/WebKit/Source/core/fetch/CrossOriginAccessControl.cpp b/third_party/WebKit/Source/core/fetch/CrossOriginAccessControl.cpp
index 3f7502e..38be6ee 100644
--- a/third_party/WebKit/Source/core/fetch/CrossOriginAccessControl.cpp
+++ b/third_party/WebKit/Source/core/fetch/CrossOriginAccessControl.cpp
@@ -57,7 +57,7 @@
 
 bool isOnAccessControlResponseHeaderWhitelist(const String& name)
 {
-    AtomicallyInitializedStaticReference(HTTPHeaderSet, allowedCrossOriginResponseHeaders, (createAllowedCrossOriginResponseHeadersSet().leakPtr()));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(HTTPHeaderSet, allowedCrossOriginResponseHeaders, (createAllowedCrossOriginResponseHeadersSet().leakPtr()));
 
     return allowedCrossOriginResponseHeaders.contains(name);
 }
@@ -130,9 +130,9 @@
 
 bool passesAccessControlCheck(const ResourceResponse& response, StoredCredentials includeCredentials, SecurityOrigin* securityOrigin, String& errorDescription, WebURLRequest::RequestContext context)
 {
-    AtomicallyInitializedStaticReference(AtomicString, allowOriginHeaderName, (new AtomicString("access-control-allow-origin", AtomicString::ConstructFromLiteral)));
-    AtomicallyInitializedStaticReference(AtomicString, allowCredentialsHeaderName, (new AtomicString("access-control-allow-credentials", AtomicString::ConstructFromLiteral)));
-    AtomicallyInitializedStaticReference(AtomicString, allowSuboriginHeaderName, (new AtomicString("access-control-allow-suborigin", AtomicString::ConstructFromLiteral)));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(AtomicString, allowOriginHeaderName, (new AtomicString("access-control-allow-origin", AtomicString::ConstructFromLiteral)));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(AtomicString, allowCredentialsHeaderName, (new AtomicString("access-control-allow-credentials", AtomicString::ConstructFromLiteral)));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(AtomicString, allowSuboriginHeaderName, (new AtomicString("access-control-allow-suborigin", AtomicString::ConstructFromLiteral)));
 
     int statusCode = response.httpStatusCode();
 
diff --git a/third_party/WebKit/Source/core/fetch/FetchUtils.cpp b/third_party/WebKit/Source/core/fetch/FetchUtils.cpp
index b01a9b80..96f58da 100644
--- a/third_party/WebKit/Source/core/fetch/FetchUtils.cpp
+++ b/third_party/WebKit/Source/core/fetch/FetchUtils.cpp
@@ -70,7 +70,7 @@
 
 const ForbiddenHeaderNames& ForbiddenHeaderNames::get()
 {
-    AtomicallyInitializedStaticReference(const ForbiddenHeaderNames, instance, new ForbiddenHeaderNames);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(const ForbiddenHeaderNames, instance, new ForbiddenHeaderNames);
     return instance;
 }
 
diff --git a/third_party/WebKit/Source/core/fetch/Resource.cpp b/third_party/WebKit/Source/core/fetch/Resource.cpp
index 2898d9e..b06b567 100644
--- a/third_party/WebKit/Source/core/fetch/Resource.cpp
+++ b/third_party/WebKit/Source/core/fetch/Resource.cpp
@@ -44,6 +44,7 @@
 #include "wtf/MathExtras.h"
 #include "wtf/StdLibExtras.h"
 #include "wtf/Vector.h"
+#include "wtf/WeakPtr.h"
 #include "wtf/text/CString.h"
 
 using namespace WTF;
@@ -147,6 +148,9 @@
     : m_resourceRequest(request)
     , m_responseTimestamp(currentTime())
     , m_cancelTimer(this, &Resource::cancelTimerFired)
+#if !ENABLE(OILPAN)
+    , m_weakPtrFactory(this)
+#endif
     , m_loadFinishTime(0)
     , m_identifier(0)
     , m_encodedSize(0)
@@ -516,6 +520,15 @@
         Platform::current()->cacheMetadata(m_response.url(), m_response.responseTime(), 0, 0);
 }
 
+WeakPtrWillBeRawPtr<Resource> Resource::asWeakPtr()
+{
+#if ENABLE(OILPAN)
+    return this;
+#else
+    return m_weakPtrFactory.createWeakPtr();
+#endif
+}
+
 bool Resource::canDelete() const
 {
     return !hasClients() && !m_loader && !m_preloadCount && hasRightHandleCountApartFromCache(0)
diff --git a/third_party/WebKit/Source/core/fetch/Resource.h b/third_party/WebKit/Source/core/fetch/Resource.h
index 39bca1c..1f91aa9 100644
--- a/third_party/WebKit/Source/core/fetch/Resource.h
+++ b/third_party/WebKit/Source/core/fetch/Resource.h
@@ -265,6 +265,9 @@
 
     static const char* resourceTypeToString(Type, const FetchInitiatorInfo&);
 
+    // TODO(japhet): Remove once oilpan ships, it doesn't need the WeakPtr.
+    WeakPtrWillBeRawPtr<Resource> asWeakPtr();
+
 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK
     void assertAlive() const { RELEASE_ASSERT(!m_deleted); }
 #else
@@ -382,6 +385,10 @@
 
     String m_fragmentIdentifierForRequest;
 
+#if !ENABLE(OILPAN)
+    WeakPtrFactory<Resource> m_weakPtrFactory;
+#endif
+
     RefPtr<CachedMetadata> m_cachedMetadata;
     OwnPtrWillBeMember<CacheHandler> m_cacheHandler;
 
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
index d51f193..2d48380 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
@@ -166,7 +166,6 @@
 
 ResourceFetcher::ResourceFetcher(FetchContext* context)
     : m_context(context)
-    , m_garbageCollectDocumentResourcesTimer(this, &ResourceFetcher::garbageCollectDocumentResourcesTimerFired)
     , m_resourceTimingReportTimer(this, &ResourceFetcher::resourceTimingReportTimerFired)
     , m_autoLoadImages(true)
     , m_imagesEnabled(true)
@@ -195,7 +194,8 @@
 Resource* ResourceFetcher::cachedResource(const KURL& resourceURL) const
 {
     KURL url = MemoryCache::removeFragmentIdentifierIfNeeded(resourceURL);
-    return m_documentResources.get(url).get();
+    const WeakPtrWillBeWeakMember<Resource>& resource = m_documentResources.get(url);
+    return resource.get();
 }
 
 bool ResourceFetcher::canAccessResource(Resource* resource, SecurityOrigin* sourceOrigin, const KURL& url, AccessControlLoggingDecision logErrorsDecision) const
@@ -321,7 +321,6 @@
     resource->setCacheIdentifier(cacheIdentifier);
     resource->finish();
     memoryCache()->add(resource.get());
-    scheduleDocumentResourcesGC();
 }
 
 void ResourceFetcher::moveCachedNonBlockingResourceToBlocking(Resource* resource)
@@ -458,7 +457,7 @@
     requestLoadStarted(resource.get(), request, policy == Use ? ResourceLoadingFromCache : ResourceLoadingFromNetwork, isStaticData);
 
     ASSERT(resource->url() == url.string());
-    m_documentResources.set(resource->url(), resource);
+    m_documentResources.set(resource->url(), resource->asWeakPtr());
     return resource;
 }
 
@@ -770,9 +769,12 @@
 
 void ResourceFetcher::reloadImagesIfNotDeferred()
 {
+    // TODO(japhet): Once oilpan ships, the const auto&
+    // can be replaced with a Resource*. Also, null checking
+    // the resource probably won't be necesssary.
     for (const auto& documentResource : m_documentResources) {
         Resource* resource = documentResource.value.get();
-        if (resource->type() == Resource::Image && resource->stillNeedsLoad() && !clientDefersImage(resource->url()))
+        if (resource && resource->type() == Resource::Image && resource->stillNeedsLoad() && !clientDefersImage(resource->url()))
             const_cast<Resource*>(resource)->load(this, defaultResourceOptions());
     }
 }
@@ -786,41 +788,9 @@
 
 void ResourceFetcher::didLoadResource()
 {
-    scheduleDocumentResourcesGC();
     context().didLoadResource();
 }
 
-void ResourceFetcher::scheduleDocumentResourcesGC()
-{
-    if (!m_garbageCollectDocumentResourcesTimer.isActive())
-        m_garbageCollectDocumentResourcesTimer.startOneShot(0, BLINK_FROM_HERE);
-}
-
-// Garbage collecting m_documentResources is a workaround for the
-// ResourcePtrs on the RHS being strong references. Ideally this
-// would be a weak map, however ResourcePtrs perform additional
-// bookkeeping on Resources, so instead pseudo-GC them -- when the
-// reference count reaches 1, m_documentResources is the only reference, so
-// remove it from the map.
-void ResourceFetcher::garbageCollectDocumentResourcesTimerFired(Timer<ResourceFetcher>* timer)
-{
-    ASSERT_UNUSED(timer, timer == &m_garbageCollectDocumentResourcesTimer);
-    garbageCollectDocumentResources();
-}
-
-void ResourceFetcher::garbageCollectDocumentResources()
-{
-    typedef Vector<String, 10> StringVector;
-    StringVector resourcesToDelete;
-
-    for (const auto& documentResource : m_documentResources) {
-        if (documentResource.value->hasOneHandle())
-            resourcesToDelete.append(documentResource.key);
-    }
-
-    m_documentResources.removeAll(resourcesToDelete);
-}
-
 int ResourceFetcher::requestCount() const
 {
     return m_loaders ? m_loaders->size() : 0;
@@ -1182,6 +1152,7 @@
     visitor->trace(m_loaders);
     visitor->trace(m_nonBlockingLoaders);
 #if ENABLE(OILPAN)
+    visitor->trace(m_documentResources);
     visitor->trace(m_preloads);
     visitor->trace(m_resourceTimingInfoMap);
 #endif
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
index 992bc49..5b1eab060 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
+++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
@@ -78,7 +78,7 @@
 
     Resource* cachedResource(const KURL&) const;
 
-    typedef HashMap<String, ResourcePtr<Resource>> DocumentResourceMap;
+    typedef WillBeHeapHashMap<String, WeakPtrWillBeWeakMember<Resource>> DocumentResourceMap;
     const DocumentResourceMap& allResources() const { return m_documentResources; }
 
     bool autoLoadImages() const { return m_autoLoadImages; }
@@ -91,8 +91,6 @@
     FetchContext& context() const { return m_context ? *m_context.get() : FetchContext::nullInstance(); }
     void clearContext() { m_context.clear(); }
 
-    void garbageCollectDocumentResources();
-
     int requestCount() const;
 
     bool isPreloaded(const KURL&) const;
@@ -174,8 +172,6 @@
 
     static bool resourceNeedsLoad(Resource*, const FetchRequest&, RevalidationPolicy);
 
-    void garbageCollectDocumentResourcesTimerFired(Timer<ResourceFetcher>*);
-
     void resourceTimingReportTimerFired(Timer<ResourceFetcher>*);
 
     void reloadImagesIfNotDeferred();
@@ -197,7 +193,6 @@
     OwnPtrWillBeMember<WillBeHeapListHashSet<RawPtrWillBeMember<Resource>>> m_preloads;
     OwnPtrWillBeMember<ArchiveResourceCollection> m_archiveResourceCollection;
 
-    Timer<ResourceFetcher> m_garbageCollectDocumentResourcesTimer;
     Timer<ResourceFetcher> m_resourceTimingReportTimer;
 
     // We intentionally use a Member instead of a ResourcePtr.
diff --git a/third_party/WebKit/Source/core/fileapi/Blob.cpp b/third_party/WebKit/Source/core/fileapi/Blob.cpp
index 74da867..e415616 100644
--- a/third_party/WebKit/Source/core/fileapi/Blob.cpp
+++ b/third_party/WebKit/Source/core/fileapi/Blob.cpp
@@ -69,7 +69,7 @@
     // (This code assumes it is safe to register or unregister URLs on
     // BlobURLRegistry (that is implemented by the embedder) on
     // multiple threads.)
-    AtomicallyInitializedStaticReference(BlobURLRegistry, instance, new BlobURLRegistry());
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(BlobURLRegistry, instance, new BlobURLRegistry());
     return instance;
 }
 
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp
index a81f7c1..579557a 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -2457,10 +2457,9 @@
 void FrameView::synchronizedPaintRecursively(GraphicsLayer* graphicsLayer)
 {
     if (graphicsLayer->drawsContent()) {
-        ASSERT(graphicsLayer->paintController());
-        GraphicsContext context(*graphicsLayer->paintController());
+        GraphicsContext context(graphicsLayer->paintController());
         graphicsLayer->paint(context, nullptr);
-        graphicsLayer->paintController()->commitNewDisplayItems();
+        graphicsLayer->paintController().commitNewDisplayItems();
     }
 
     if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
@@ -2489,7 +2488,9 @@
     if (!layer->hasCompositedLayerMapping())
         return;
     GraphicsLayer* rootGraphicsLayer = layer->compositedLayerMapping()->mainGraphicsLayer();
-    const PaintArtifact& paintArtifact = rootGraphicsLayer->paintController()->paintArtifact();
+    if (!rootGraphicsLayer->drawsContent())
+        return;
+    const PaintArtifact& paintArtifact = rootGraphicsLayer->paintController().paintArtifact();
 
     Page* page = frame().page();
     if (!page)
diff --git a/third_party/WebKit/Source/core/frame/NavigatorID.cpp b/third_party/WebKit/Source/core/frame/NavigatorID.cpp
index 8fd83bd..36aa4eb 100644
--- a/third_party/WebKit/Source/core/frame/NavigatorID.cpp
+++ b/third_party/WebKit/Source/core/frame/NavigatorID.cpp
@@ -67,7 +67,7 @@
     return "Win32";
 #else // Unix-like systems
     struct utsname osname;
-    AtomicallyInitializedStaticReference(ThreadSpecific<String>, platformName, new ThreadSpecific<String>());
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(ThreadSpecific<String>, platformName, new ThreadSpecific<String>());
     if (platformName->isNull()) {
         *platformName = String(uname(&osname) >= 0 ? String(osname.sysname) + String(" ") + String(osname.machine) : emptyString());
     }
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h
index 0a339b1..d189700 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.h
+++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -947,6 +947,8 @@
         V8SVGSVGElement_CreateSVGRect_Method = 1090,
         V8SVGSVGElement_CreateSVGTransform_Method = 1091,
         V8SVGSVGElement_CreateSVGTransformFromMatrix_Method = 1092,
+        FormNameAccessForNonDescendantImageElement = 1093,
+        FormControlsCollectionNameAccessForImageElement = 1094,
 
         // Add new features immediately above this line. Don't change assigned
         // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/core/html/HTMLCollection.cpp b/third_party/WebKit/Source/core/html/HTMLCollection.cpp
index f9c28be..0cf1470 100644
--- a/third_party/WebKit/Source/core/html/HTMLCollection.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLCollection.cpp
@@ -94,7 +94,7 @@
     case WindowNamedItems:
     case DocumentNamedItems:
     case FormControls:
-        return NodeListIsRootedAtDocument;
+        return NodeListRootType::TreeScope;
     case ClassCollectionType:
     case TagCollectionType:
     case HTMLTagCollectionType:
@@ -107,7 +107,7 @@
     case SelectedOptions:
     case DataListOptions:
     case MapAreas:
-        return NodeListIsRootedAtNode;
+        return NodeListRootType::Node;
     case NameNodeListType:
     case RadioNodeListType:
     case RadioImgNodeListType:
@@ -115,7 +115,7 @@
         break;
     }
     ASSERT_NOT_REACHED();
-    return NodeListIsRootedAtNode;
+    return NodeListRootType::Node;
 }
 
 static NodeListInvalidationType invalidationTypeExcludingIdAndNameAttributes(CollectionType type)
diff --git a/third_party/WebKit/Source/core/html/HTMLCollection.h b/third_party/WebKit/Source/core/html/HTMLCollection.h
index 2b063cd..35f4b549 100644
--- a/third_party/WebKit/Source/core/html/HTMLCollection.h
+++ b/third_party/WebKit/Source/core/html/HTMLCollection.h
@@ -118,7 +118,7 @@
     {
         ASSERT(!m_namedItemCache);
         document().registerNodeListWithIdNameCache(this);
-        m_namedItemCache = cache;
+        m_namedItemCache = std::move(cache);
     }
 
     NamedItemCache& namedItemCache() const
diff --git a/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.cpp b/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.cpp
index e7ced66..bbdceba87 100644
--- a/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.cpp
@@ -202,10 +202,14 @@
         return;
 
     if (namedItems.size() == 1) {
+        if (isHTMLImageElement(*namedItems[0]))
+            UseCounter::count(document(), UseCounter::FormControlsCollectionNameAccessForImageElement);
         returnValue.setElement(namedItems.at(0));
         return;
     }
 
+    // This path never returns a RadioNodeList for <img> because
+    // onlyMatchingImgElements flag is false by default.
     returnValue.setRadioNodeList(ownerNode().radioNodeList(name));
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLFormElement.cpp b/third_party/WebKit/Source/core/html/HTMLFormElement.cpp
index df13f4ae..c4c074b 100644
--- a/third_party/WebKit/Source/core/html/HTMLFormElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLFormElement.cpp
@@ -812,8 +812,17 @@
     ASSERT(!elements.isEmpty());
 
     bool onlyMatchImg = !elements.isEmpty() && isHTMLImageElement(*elements.first());
-    if (onlyMatchImg)
+    if (onlyMatchImg) {
         UseCounter::count(document(), UseCounter::FormNameAccessForImageElement);
+        // The following code has performance impact, but it should be small
+        // because <img> access via <form> name getter is rarely used.
+        for (auto& element : elements) {
+            if (isHTMLImageElement(*element) && !element->isDescendantOf(this)) {
+                UseCounter::count(document(), UseCounter::FormNameAccessForNonDescendantImageElement);
+                break;
+            }
+        }
+    }
     if (elements.size() == 1) {
         returnValue.setElement(elements.at(0));
         return;
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
index 4b3082f..bf13f74 100644
--- a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
@@ -53,6 +53,7 @@
 #include "core/loader/NetworkHintsInterface.h"
 #include "core/style/StyleInheritedData.h"
 #include "platform/RuntimeEnabledFeatures.h"
+#include "public/platform/Platform.h"
 #include "wtf/StdLibExtras.h"
 
 namespace blink {
@@ -515,9 +516,11 @@
 
     CSSParserContext parserContext(m_owner->document(), 0, baseURL, charset);
 
+    bool restoredCachedStyleSheet = false;
     if (RefPtrWillBeRawPtr<StyleSheetContents> restoredSheet = const_cast<CSSStyleSheetResource*>(cachedStyleSheet)->restoreParsedStyleSheet(parserContext)) {
         ASSERT(restoredSheet->isCacheable());
         ASSERT(!restoredSheet->isLoading());
+        restoredCachedStyleSheet = true;
 
         if (m_sheet)
             clearSheet();
@@ -530,6 +533,7 @@
         restoredSheet->checkLoaded();
         return;
     }
+    Platform::current()->histogramEnumeration("Blink.RestoredCachedStyleSheet", restoredCachedStyleSheet, 2);
 
     RefPtrWillBeRawPtr<StyleSheetContents> styleSheet = StyleSheetContents::create(href, parserContext);
 
diff --git a/third_party/WebKit/Source/core/html/LabelsNodeList.cpp b/third_party/WebKit/Source/core/html/LabelsNodeList.cpp
index 85d1baf9..bbf43f5 100644
--- a/third_party/WebKit/Source/core/html/LabelsNodeList.cpp
+++ b/third_party/WebKit/Source/core/html/LabelsNodeList.cpp
@@ -34,7 +34,7 @@
 using namespace HTMLNames;
 
 LabelsNodeList::LabelsNodeList(ContainerNode& ownerNode)
-    : LiveNodeList(ownerNode, LabelsNodeListType, InvalidateOnForAttrChange, NodeListIsRootedAtDocument)
+    : LiveNodeList(ownerNode, LabelsNodeListType, InvalidateOnForAttrChange, NodeListRootType::TreeScope)
 {
 }
 
diff --git a/third_party/WebKit/Source/core/html/RadioNodeList.cpp b/third_party/WebKit/Source/core/html/RadioNodeList.cpp
index 3b572089..2f2831fa 100644
--- a/third_party/WebKit/Source/core/html/RadioNodeList.cpp
+++ b/third_party/WebKit/Source/core/html/RadioNodeList.cpp
@@ -40,7 +40,7 @@
 using namespace HTMLNames;
 
 RadioNodeList::RadioNodeList(ContainerNode& rootNode, const AtomicString& name, CollectionType type)
-    : LiveNodeList(rootNode, type, InvalidateForFormControls, isHTMLFormElement(rootNode) ? NodeListIsRootedAtDocument : NodeListIsRootedAtNode)
+    : LiveNodeList(rootNode, type, InvalidateForFormControls, isHTMLFormElement(rootNode) ? NodeListRootType::TreeScope : NodeListRootType::Node)
     , m_name(name)
 {
 }
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLSrcsetParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLSrcsetParser.cpp
index f3f08e1..b9910d8 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLSrcsetParser.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLSrcsetParser.cpp
@@ -355,7 +355,7 @@
         return winner;
     for (unsigned i = imageCandidates.size() - 1; i > winner; --i) {
         KURL url = document->completeURL(stripLeadingAndTrailingHTMLSpaces(imageCandidates[i]->url()));
-        if (memoryCache()->resourceForURL(url, document->fetcher()->getCacheIdentifier()) || url.protocolIsData())
+        if (memoryCache()->resourceForURL(url, document->fetcher()->getCacheIdentifier()))
             return i;
     }
     return winner;
diff --git a/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp b/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp
index 516b07ea..5451ac6 100644
--- a/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp
+++ b/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp
@@ -21,7 +21,7 @@
         unsigned value;
     };
 
-    AtomicallyInitializedStaticReference(WTF::ThreadSpecific<MessageId>, messageId, new WTF::ThreadSpecific<MessageId>);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(WTF::ThreadSpecific<MessageId>, messageId, new WTF::ThreadSpecific<MessageId>);
     return ++messageId->value;
 }
 
diff --git a/third_party/WebKit/Source/core/inspector/InjectedScriptHost.h b/third_party/WebKit/Source/core/inspector/InjectedScriptHost.h
index 87fe9db..5d5b107 100644
--- a/third_party/WebKit/Source/core/inspector/InjectedScriptHost.h
+++ b/third_party/WebKit/Source/core/inspector/InjectedScriptHost.h
@@ -69,9 +69,9 @@
     {
         m_consoleAgent = consoleAgent;
         m_debuggerAgent = debuggerAgent;
-        m_inspectCallback = inspectCallback;
+        m_inspectCallback = std::move(inspectCallback);
         m_debugger = debugger;
-        m_client = injectedScriptHostClient;
+        m_client = std::move(injectedScriptHostClient);
     }
 
     static EventTarget* eventTargetFromV8Value(v8::Isolate*, v8::Local<v8::Value>);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp
index b2b10e8b..f01c0550 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp
@@ -321,18 +321,18 @@
 void InspectorLayerTreeAgent::makeSnapshot(ErrorString* errorString, const String& layerId, String* snapshotId)
 {
     GraphicsLayer* layer = layerById(errorString, layerId);
-    if (!layer)
+    if (!layer || !layer->drawsContent())
         return;
 
     IntSize size = expandedIntSize(layer->size());
 
-    GraphicsContext context(*layer->paintController());
+    GraphicsContext context(layer->paintController());
     IntRect interestRect(IntPoint(0, 0), size);
     layer->paint(context, &interestRect);
-    layer->paintController()->commitNewDisplayItems();
+    layer->paintController().commitNewDisplayItems();
 
     context.beginRecording(interestRect);
-    layer->paintController()->paintArtifact().replay(context);
+    layer->paintController().paintArtifact().replay(context);
     RefPtr<PictureSnapshot> snapshot = adoptRef(new PictureSnapshot(context.endRecording()));
 
     *snapshotId = String::number(++s_lastSnapshotId);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
index eb017f0..3417146 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
@@ -430,6 +430,8 @@
     const ResourceFetcher::DocumentResourceMap& allResources = document->fetcher()->allResources();
     for (const auto& resource : allResources) {
         Resource* cachedResource = resource.value.get();
+        if (!cachedResource)
+            continue;
 
         switch (cachedResource->type()) {
         case Resource::Image:
diff --git a/third_party/WebKit/Source/core/inspector/InspectorResourceAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorResourceAgent.cpp
index f1e24c0..916d056 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorResourceAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorResourceAgent.cpp
@@ -1026,8 +1026,6 @@
     m_state->setBoolean(ResourceAgentState::cacheDisabled, cacheDisabled);
     if (cacheDisabled)
         memoryCache()->evictResources();
-    for (LocalFrame* frame : *m_inspectedFrames)
-        frame->document()->fetcher()->garbageCollectDocumentResources();
 }
 
 void InspectorResourceAgent::emulateNetworkConditions(ErrorString*, bool, double, double, double)
diff --git a/third_party/WebKit/Source/core/inspector/MainThreadDebugger.cpp b/third_party/WebKit/Source/core/inspector/MainThreadDebugger.cpp
index 058da74..0303f97 100644
--- a/third_party/WebKit/Source/core/inspector/MainThreadDebugger.cpp
+++ b/third_party/WebKit/Source/core/inspector/MainThreadDebugger.cpp
@@ -77,7 +77,7 @@
 
 Mutex& MainThreadDebugger::creationMutex()
 {
-    AtomicallyInitializedStaticReference(Mutex, mutex, (new Mutex));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(Mutex, mutex, (new Mutex));
     return mutex;
 }
 
diff --git a/third_party/WebKit/Source/core/inspector/MainThreadDebugger.h b/third_party/WebKit/Source/core/inspector/MainThreadDebugger.h
index 8f609398..6022ae9 100644
--- a/third_party/WebKit/Source/core/inspector/MainThreadDebugger.h
+++ b/third_party/WebKit/Source/core/inspector/MainThreadDebugger.h
@@ -59,7 +59,7 @@
 
     static PassOwnPtr<MainThreadDebugger> create(PassOwnPtr<ClientMessageLoop> clientMessageLoop, v8::Isolate* isolate)
     {
-        return adoptPtr(new MainThreadDebugger(clientMessageLoop, isolate));
+        return adoptPtr(new MainThreadDebugger(std::move(clientMessageLoop), isolate));
     }
 
     ~MainThreadDebugger() override;
diff --git a/third_party/WebKit/Source/core/loader/ImageLoader.cpp b/third_party/WebKit/Source/core/loader/ImageLoader.cpp
index d8ccf60..6273f6e 100644
--- a/third_party/WebKit/Source/core/loader/ImageLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/ImageLoader.cpp
@@ -468,7 +468,7 @@
         if (resource && !resource->errorOccurred())
             return true;
     }
-    return (m_loadingImageDocument || isHTMLObjectElement(m_element) || isHTMLEmbedElement(m_element));
+    return (m_loadingImageDocument || isHTMLObjectElement(m_element) || isHTMLEmbedElement(m_element) || url.protocolIsData());
 }
 
 void ImageLoader::notifyFinished(Resource* resource)
diff --git a/third_party/WebKit/Source/core/page/NetworkStateNotifier.cpp b/third_party/WebKit/Source/core/page/NetworkStateNotifier.cpp
index 6f94f09..36abcb0 100644
--- a/third_party/WebKit/Source/core/page/NetworkStateNotifier.cpp
+++ b/third_party/WebKit/Source/core/page/NetworkStateNotifier.cpp
@@ -39,7 +39,7 @@
 
 NetworkStateNotifier& networkStateNotifier()
 {
-    AtomicallyInitializedStaticReference(NetworkStateNotifier, networkStateNotifier, new NetworkStateNotifier);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(NetworkStateNotifier, networkStateNotifier, new NetworkStateNotifier);
     return networkStateNotifier;
 }
 
diff --git a/third_party/WebKit/Source/core/page/Page.cpp b/third_party/WebKit/Source/core/page/Page.cpp
index c2aec15d..9a16609 100644
--- a/third_party/WebKit/Source/core/page/Page.cpp
+++ b/third_party/WebKit/Source/core/page/Page.cpp
@@ -514,12 +514,8 @@
 
 void Page::purgeMemory(DeviceKind deviceKind)
 {
-    Frame* frame = mainFrame();
-    if (deviceKind != DeviceKind::LowEnd || !frame || !frame->isLocalFrame())
-        return;
-    if (Document* document = toLocalFrame(frame)->document())
-        document->fetcher()->garbageCollectDocumentResources();
-    memoryCache()->pruneAll();
+    if (deviceKind == DeviceKind::LowEnd)
+        memoryCache()->pruneAll();
 }
 
 DEFINE_TRACE(Page)
diff --git a/third_party/WebKit/Source/core/paint/LayerClipRecorderTest.cpp b/third_party/WebKit/Source/core/paint/LayerClipRecorderTest.cpp
index db539a1..4007b27b 100644
--- a/third_party/WebKit/Source/core/paint/LayerClipRecorderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/LayerClipRecorderTest.cpp
@@ -25,7 +25,7 @@
 
 protected:
     LayoutView& layoutView() { return *m_layoutView; }
-    PaintController& rootPaintController() { return *layoutView().layer()->graphicsLayerBacking()->paintController(); }
+    PaintController& rootPaintController() { return layoutView().layer()->graphicsLayerBacking()->paintController(); }
 
 private:
     void SetUp() override
diff --git a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h
index b9d61393..ddb7bccc 100644
--- a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h
+++ b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h
@@ -26,7 +26,7 @@
 
 protected:
     LayoutView& layoutView() { return *document().layoutView(); }
-    PaintController& rootPaintController() { return *layoutView().layer()->graphicsLayerBacking()->paintController(); }
+    PaintController& rootPaintController() { return layoutView().layer()->graphicsLayerBacking()->paintController(); }
 
     void SetUp() override
     {
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGElement.cpp
index 103c2ab6..e4bc03fe 100644
--- a/third_party/WebKit/Source/core/svg/SVGElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGElement.cpp
@@ -248,7 +248,7 @@
 {
     document().accessSVGExtensions().addWebAnimationsPendingSVGElement(*this);
     ensureSVGRareData()->setWebAnimatedAttributesDirty(true);
-    elementData()->m_animatedSVGAttributesAreDirty = true;
+    ensureUniqueElementData().m_animatedSVGAttributesAreDirty = true;
 }
 
 static bool isSVGAttributeHandle(const PropertyHandle& propertyHandle)
@@ -1070,7 +1070,7 @@
 {
     // This static is atomically initialized to dodge a warning about
     // a race when dumping debug data for a layer.
-    AtomicallyInitializedStaticReference(HashSet<QualifiedName>, animatableAttributes, new HashSet<QualifiedName>());
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(HashSet<QualifiedName>, animatableAttributes, new HashSet<QualifiedName>());
 
     if (animatableAttributes.isEmpty()) {
         const QualifiedName* const animatableAttrs[] = {
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp
index 511576e..f3bcbda 100644
--- a/third_party/WebKit/Source/core/testing/Internals.cpp
+++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -1722,15 +1722,6 @@
     return page->nonFastScrollableRects(document->frame());
 }
 
-void Internals::garbageCollectDocumentResources(Document* document) const
-{
-    ASSERT(document);
-    ResourceFetcher* fetcher = document->fetcher();
-    if (!fetcher)
-        return;
-    fetcher->garbageCollectDocumentResources();
-}
-
 void Internals::evictAllResources() const
 {
     memoryCache()->evictResources();
@@ -1982,19 +1973,26 @@
 void Internals::startTrackingPaintInvalidationObjects()
 {
     ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
-    toLocalFrame(frame()->page()->mainFrame())->view()->layoutView()->layer()->graphicsLayerBacking()->paintController()->startTrackingPaintInvalidationObjects();
+    GraphicsLayer* graphicsLayer = toLocalFrame(frame()->page()->mainFrame())->view()->layoutView()->layer()->graphicsLayerBacking();
+    if (graphicsLayer->drawsContent())
+        graphicsLayer->paintController().startTrackingPaintInvalidationObjects();
 }
 
 void Internals::stopTrackingPaintInvalidationObjects()
 {
     ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
-    toLocalFrame(frame()->page()->mainFrame())->view()->layoutView()->layer()->graphicsLayerBacking()->paintController()->stopTrackingPaintInvalidationObjects();
+    GraphicsLayer* graphicsLayer = toLocalFrame(frame()->page()->mainFrame())->view()->layoutView()->layer()->graphicsLayerBacking();
+    if (graphicsLayer->drawsContent())
+        graphicsLayer->paintController().stopTrackingPaintInvalidationObjects();
 }
 
 Vector<String> Internals::trackedPaintInvalidationObjects()
 {
     ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
-    return toLocalFrame(frame()->page()->mainFrame())->view()->layoutView()->layer()->graphicsLayerBacking()->paintController()->trackedPaintInvalidationObjects();
+    GraphicsLayer* graphicsLayer = toLocalFrame(frame()->page()->mainFrame())->view()->layoutView()->layer()->graphicsLayerBacking();
+    if (!graphicsLayer->drawsContent())
+        return Vector<String>();
+    return graphicsLayer->paintController().trackedPaintInvalidationObjects();
 }
 
 ClientRectList* Internals::draggableRegions(Document* document, ExceptionState& exceptionState)
diff --git a/third_party/WebKit/Source/core/testing/Internals.h b/third_party/WebKit/Source/core/testing/Internals.h
index cab82d14..5962c03 100644
--- a/third_party/WebKit/Source/core/testing/Internals.h
+++ b/third_party/WebKit/Source/core/testing/Internals.h
@@ -236,7 +236,6 @@
     String mainThreadScrollingReasons(Document*, ExceptionState&) const;
     ClientRectList* nonFastScrollableRects(Document*, ExceptionState&) const;
 
-    void garbageCollectDocumentResources(Document*) const;
     void evictAllResources() const;
 
     unsigned numberOfLiveNodes() const;
diff --git a/third_party/WebKit/Source/core/testing/Internals.idl b/third_party/WebKit/Source/core/testing/Internals.idl
index 953ec941..5350003d 100644
--- a/third_party/WebKit/Source/core/testing/Internals.idl
+++ b/third_party/WebKit/Source/core/testing/Internals.idl
@@ -191,7 +191,6 @@
     [RaisesException] DOMString mainThreadScrollingReasons(Document document);
     [RaisesException] ClientRectList nonFastScrollableRects(Document document);
 
-    void garbageCollectDocumentResources(Document document);
     void evictAllResources();
 
     unsigned long numberOfLiveNodes();
diff --git a/third_party/WebKit/Source/core/timing/MemoryInfo.cpp b/third_party/WebKit/Source/core/timing/MemoryInfo.cpp
index ef6c06f..45f1abb 100644
--- a/third_party/WebKit/Source/core/timing/MemoryInfo.cpp
+++ b/third_party/WebKit/Source/core/timing/MemoryInfo.cpp
@@ -70,7 +70,7 @@
 
     static HeapSizeCache& forCurrentThread()
     {
-        AtomicallyInitializedStaticReference(ThreadSpecific<HeapSizeCache>, heapSizeCache, new ThreadSpecific<HeapSizeCache>);
+        DEFINE_STATIC_LOCAL_THREAD_SAFE(ThreadSpecific<HeapSizeCache>, heapSizeCache, new ThreadSpecific<HeapSizeCache>);
         return *heapSizeCache;
     }
 
diff --git a/third_party/WebKit/Source/core/timing/PerformanceBase.cpp b/third_party/WebKit/Source/core/timing/PerformanceBase.cpp
index 6eafc4b..7811189 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceBase.cpp
+++ b/third_party/WebKit/Source/core/timing/PerformanceBase.cpp
@@ -187,7 +187,7 @@
 
 static bool passesTimingAllowCheck(const ResourceResponse& response, const SecurityOrigin& initiatorSecurityOrigin, const AtomicString& originalTimingAllowOrigin)
 {
-    AtomicallyInitializedStaticReference(AtomicString, timingAllowOrigin, new AtomicString("timing-allow-origin"));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(AtomicString, timingAllowOrigin, new AtomicString("timing-allow-origin"));
 
     RefPtr<SecurityOrigin> resourceOrigin = SecurityOrigin::create(response.url());
     if (resourceOrigin->isSameSchemeHostPort(&initiatorSecurityOrigin))
diff --git a/third_party/WebKit/Source/core/timing/PerformanceUserTiming.cpp b/third_party/WebKit/Source/core/timing/PerformanceUserTiming.cpp
index 8ada4efd..b6bf842 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceUserTiming.cpp
+++ b/third_party/WebKit/Source/core/timing/PerformanceUserTiming.cpp
@@ -70,7 +70,7 @@
 
 const RestrictedKeyMap& restrictedKeyMap()
 {
-    AtomicallyInitializedStaticReference(RestrictedKeyMap, map, createRestrictedKeyMap());
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(RestrictedKeyMap, map, createRestrictedKeyMap());
     return map;
 }
 
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.cpp b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
index c4a731a6..643aee3 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThread.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
@@ -89,7 +89,7 @@
 
 static Mutex& threadSetMutex()
 {
-    AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(Mutex, mutex, new Mutex);
     return mutex;
 }
 
diff --git a/third_party/WebKit/Source/devtools/devtools.gypi b/third_party/WebKit/Source/devtools/devtools.gypi
index 7fa2d34..49ec1e2 100644
--- a/third_party/WebKit/Source/devtools/devtools.gypi
+++ b/third_party/WebKit/Source/devtools/devtools.gypi
@@ -128,6 +128,7 @@
             'front_end/host/UserMetrics.js',
         ],
         'devtools_sass_js_files': [
+            'front_end/sass/SASSLiveSourceMap.js',
             'front_end/sass/SASSSupport.js',
         ],
         'devtools_screencast_js_files': [
@@ -692,10 +693,8 @@
             'front_end/timeline/TimelineModel.js',
             'front_end/timeline/TimelinePaintProfilerView.js',
             'front_end/timeline/TimelinePanel.js',
-            'front_end/timeline/TimelinePresentationModel.js',
             'front_end/timeline/TimelineTreeView.js',
             'front_end/timeline/TimelineUIUtils.js',
-            'front_end/timeline/TimelineView.js',
             'front_end/timeline/TransformController.js',
         ],
         'devtools_ui_lazy_js_files': [
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js b/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js
index a3022be..8312ddb4 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js
@@ -269,8 +269,10 @@
 
     _debuggerReset: function()
     {
-        this._boundUISourceCodes.forEach(this._unbindUISourceCode.bind(this));
+        var sourceCodes = this._boundUISourceCodes;
         this._boundUISourceCodes = [];
+        sourceCodes.forEach(this._unbindUISourceCode.bind(this));
+        console.assert(!this._uiSourceCodeToScriptFile.size);
     },
 
     dispose: function()
diff --git a/third_party/WebKit/Source/devtools/front_end/common/TextRange.js b/third_party/WebKit/Source/devtools/front_end/common/TextRange.js
index 59ae5d9..e9d4e9a 100644
--- a/third_party/WebKit/Source/devtools/front_end/common/TextRange.js
+++ b/third_party/WebKit/Source/devtools/front_end/common/TextRange.js
@@ -315,3 +315,49 @@
     this.offset = offset;
     this.length = length;
 }
+
+/**
+ * @constructor
+ * @param {string} sourceURL
+ * @param {!WebInspector.TextRange} oldRange
+ * @param {string} oldText
+ * @param {string} newText
+ */
+WebInspector.SourceEdit = function(sourceURL, oldRange, oldText, newText)
+{
+    this.sourceURL = sourceURL;
+    this.oldRange = oldRange;
+    this.oldText = oldText;
+    this.newText = newText;
+}
+
+WebInspector.SourceEdit.prototype = {
+    /**
+     * @return {!WebInspector.TextRange}
+     */
+    newRange: function()
+    {
+        var endLine = this.oldRange.startLine;
+        var endColumn = this.oldRange.startColumn + this.newText.length;
+        var lineEndings = this.newText.lineEndings();
+        if (lineEndings.length > 1) {
+            endLine = this.oldRange.startLine + lineEndings.length - 1;
+            var len = lineEndings.length;
+            endColumn = lineEndings[len - 1] - lineEndings[len - 2] - 1;
+        }
+        return new WebInspector.TextRange(
+            this.oldRange.startLine,
+            this.oldRange.startColumn,
+            endLine,
+            endColumn);
+    },
+
+    /**
+     * @param {string} text
+     * @return {string}
+     */
+    applyToText: function(text)
+    {
+        return this.oldRange.replaceInText(text, this.newText);
+    },
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/components/inspectorViewTabbedPane.css b/third_party/WebKit/Source/devtools/front_end/components/inspectorViewTabbedPane.css
index a8f6968..94c7ee4f 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/inspectorViewTabbedPane.css
+++ b/third_party/WebKit/Source/devtools/front_end/components/inspectorViewTabbedPane.css
@@ -8,7 +8,7 @@
 .tabbed-pane-header-tab.selected {
     height: 26px;
     margin: 0;
-    background: none;
+    background: #f3f3f3;
     border: none;
     border-left: 2px solid transparent;
     border-right: 2px solid transparent;
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js
index 75c5f43..0d11460 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/Main.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -128,7 +128,6 @@
         Runtime.experiments.register("stepIntoAsync", "Step into async");
         Runtime.experiments.register("timelineInvalidationTracking", "Timeline invalidation tracking", true);
         Runtime.experiments.register("timelineTracingJSProfile", "Timeline tracing based JS profiler", true);
-        Runtime.experiments.register("timelineEventsTreeView", "Timeline events tree view", true);
         Runtime.experiments.register("timelineFlowEvents", "Timeline flow events", true);
 
         Runtime.experiments.cleanUpStaleExperiments();
@@ -138,8 +137,6 @@
             // Enable experiments for testing.
             if (testPath.indexOf("debugger/promise") !== -1)
                 Runtime.experiments.enableForTest("promiseTracker");
-            if (testPath.indexOf("elements/") !== -1)
-                Runtime.experiments.enableForTest("animationInspection");
             if (testPath.indexOf("layers/") !== -1)
                 Runtime.experiments.enableForTest("layersPanel");
             if (testPath.indexOf("timeline/") !== -1 || testPath.indexOf("layers/") !== -1)
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
index 651eec4..194f85df 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
@@ -269,8 +269,6 @@
                 cell.title = failText + " " + this._request.localizedFailDescription;
             } else
                 cell.setTextAndTitle(failText);
-        } else if (this._request.statusText == "Service Worker Fallback Required") {
-            cell.setTextAndTitle(WebInspector.UIString("(Service Worker Fallback)"));
         } else if (this._request.statusCode) {
             cell.createTextChild("" + this._request.statusCode);
             this._appendSubtitle(cell, this._request.statusText);
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
index 9d6afd2..1f205435 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
@@ -1635,6 +1635,8 @@
             return false;
         if (this._dataURLFilterUI.checked() && request.parsedURL.isDataURL())
             return false;
+        if (request.statusText === "Service Worker Fallback Required")
+            return false;
         for (var i = 0; i < this._filters.length; ++i) {
             if (!this._filters[i](request))
                 return false;
diff --git a/third_party/WebKit/Source/devtools/front_end/platform/utilities.js b/third_party/WebKit/Source/devtools/front_end/platform/utilities.js
index 6c552de..e616ed34 100644
--- a/third_party/WebKit/Source/devtools/front_end/platform/utilities.js
+++ b/third_party/WebKit/Source/devtools/front_end/platform/utilities.js
@@ -1334,6 +1334,23 @@
 
     /**
      * @param {K} key
+     * @return {boolean}
+     */
+    has: function(key)
+    {
+        return this._map.has(key);
+    },
+
+    /**
+     * @return {number}
+     */
+    get size()
+    {
+        return this._map.size;
+    },
+
+    /**
+     * @param {K} key
      * @param {V} value
      */
     remove: function(key, value)
diff --git a/third_party/WebKit/Source/devtools/front_end/sass/SASSLiveSourceMap.js b/third_party/WebKit/Source/devtools/front_end/sass/SASSLiveSourceMap.js
new file mode 100644
index 0000000..9cf0c45
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/sass/SASSLiveSourceMap.js
@@ -0,0 +1,163 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+WebInspector.SASSLiveSourceMap = {}
+
+/**
+ * @constructor
+ */
+WebInspector.SASSLiveSourceMap.CSSToSASSMapping = function()
+{
+    /** @type {!Map<!WebInspector.SASSSupport.TextNode, !WebInspector.SASSSupport.TextNode>} */
+    this._cssToSass = new Map();
+    /** @type {!Multimap<!WebInspector.SASSSupport.TextNode, !WebInspector.SASSSupport.TextNode>} */
+    this._sassToCss = new Multimap();
+}
+
+/**
+ * @param {!WebInspector.SourceMap} sourceMap
+ * @param {!WebInspector.SASSSupport.AST} cssAST
+ * @param {!Map<string, !WebInspector.SASSSupport.AST>} sassModels
+ * @return {!WebInspector.SASSLiveSourceMap.CSSToSASSMapping}
+ */
+WebInspector.SASSLiveSourceMap.CSSToSASSMapping.fromSourceMap = function(sourceMap, cssAST, sassModels)
+{
+    var mapping = new WebInspector.SASSLiveSourceMap.CSSToSASSMapping();
+    //FIXME: this works O(N^2).
+    cssAST.visit(map);
+    return mapping;
+
+    /**
+     * @param {!WebInspector.SASSSupport.Node} cssNode
+     */
+    function map(cssNode)
+    {
+        if (!(cssNode instanceof WebInspector.SASSSupport.TextNode))
+            return;
+        var entry = sourceMap.findEntry(cssNode.range.endLine, cssNode.range.endColumn);
+        if (!entry || !entry.sourceURL || typeof entry.sourceLineNumber === "undefined" || typeof entry.sourceColumnNumber === "undefined")
+            return;
+        var sassAST = sassModels.get(entry.sourceURL);
+        if (!sassAST)
+            return;
+        var sassNode = sassAST.findNodeForPosition(entry.sourceLineNumber, entry.sourceColumnNumber);
+        if (sassNode)
+            mapping.mapCssToSass(cssNode, sassNode);
+    }
+}
+
+WebInspector.SASSLiveSourceMap.CSSToSASSMapping.prototype = {
+    /**
+     * @param {!WebInspector.SASSSupport.TextNode} css
+     * @param {!WebInspector.SASSSupport.TextNode} sass
+     */
+    mapCssToSass: function(css, sass)
+    {
+        this._cssToSass.set(css, sass);
+        this._sassToCss.set(sass, css);
+    },
+
+    /**
+     * @param {!WebInspector.SASSSupport.TextNode} css
+     * @param {!WebInspector.SASSSupport.TextNode} sass
+     */
+    unmapCssFromSass: function(css, sass)
+    {
+        this._cssToSass.delete(css);
+        this._sassToCss.remove(sass, css);
+    },
+
+    /**
+     * @param {!WebInspector.SASSSupport.TextNode} css
+     * @return {?WebInspector.SASSSupport.TextNode}
+     */
+    toSASSNode: function(css)
+    {
+        return this._cssToSass.get(css) || null;
+    },
+
+    /**
+     * @param {!WebInspector.SASSSupport.TextNode} sass
+     * @return {!Array<!WebInspector.SASSSupport.TextNode>}
+     */
+    toCSSNodes: function(sass)
+    {
+        var cssNodes = this._sassToCss.get(sass);
+        return cssNodes ? cssNodes.valuesArray() : [];
+    },
+
+    /**
+     * @param {!WebInspector.SASSSupport.Property} cssProperty
+     * @return {?WebInspector.SASSSupport.Property}
+     */
+    toSASSProperty: function(cssProperty)
+    {
+        var sassName = this._cssToSass.get(cssProperty.name);
+        return sassName ? sassName.parent : null;
+    },
+
+    /**
+     * @param {!WebInspector.SASSSupport.Property} sassProperty
+     * @return {!Array<!WebInspector.SASSSupport.Property>}
+     */
+    toCSSProperties: function(sassProperty)
+    {
+        return this.toCSSNodes(sassProperty.name).map(name => name.parent);
+    },
+
+    /**
+     * @param {!WebInspector.SASSSupport.ASTDiff} cssDiff
+     * @return {!WebInspector.SASSLiveSourceMap.CSSToSASSMapping}
+     */
+    rebaseForCSSDiff: function(cssDiff)
+    {
+        var newMapping = new WebInspector.SASSLiveSourceMap.CSSToSASSMapping();
+        var cssNodes = this._cssToSass.keysArray();
+        for (var i = 0; i < cssNodes.length; ++i) {
+            var cssNode = cssNodes[i];
+            var sassNode = this._cssToSass.get(cssNode);
+            var mappedNode = cssDiff.mapping.get(cssNode);
+            if (mappedNode && sassNode)
+                newMapping.mapCssToSass(mappedNode, sassNode);
+        }
+        return newMapping;
+    },
+
+    /**
+     * @param {!WebInspector.SASSSupport.ASTDiff} sassDiff
+     * @return {!WebInspector.SASSLiveSourceMap.CSSToSASSMapping}
+     */
+    rebaseForSASSDiff: function(sassDiff)
+    {
+        var newMapping = new WebInspector.SASSLiveSourceMap.CSSToSASSMapping();
+        var cssNodes = this._cssToSass.keysArray();
+        for (var i = 0; i < cssNodes.length; ++i) {
+            var cssNode = cssNodes[i];
+            var sassNode = this._cssToSass.get(cssNode);
+            var mappedNode = sassNode.document.url === sassDiff.url ? sassDiff.mapping.get(sassNode) : sassNode;
+            if (mappedNode)
+                newMapping.mapCssToSass(cssNode, mappedNode);
+        }
+        return newMapping;
+    },
+
+    /**
+     * @return {boolean}
+     */
+    isValid: function()
+    {
+        var cssNodes = this._cssToSass.keysArray();
+        for (var i = 0; i < cssNodes.length; ++i) {
+            var cssNode = cssNodes[i];
+            if (!cssNode.parent || !(cssNode.parent instanceof WebInspector.SASSSupport.Property))
+                continue;
+            if (cssNode !== cssNode.parent.name)
+                continue;
+            var sassNode = this._cssToSass.get(cssNode);
+            if (sassNode && cssNode.text.trim() !== sassNode.text.trim())
+                return false;
+        }
+        return true;
+    }
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/sass/SASSSupport.js b/third_party/WebKit/Source/devtools/front_end/sass/SASSSupport.js
index 2a8fb596..c810de0 100644
--- a/third_party/WebKit/Source/devtools/front_end/sass/SASSSupport.js
+++ b/third_party/WebKit/Source/devtools/front_end/sass/SASSSupport.js
@@ -241,6 +241,43 @@
 {
     this.url = url;
     this.text = text;
+    this.edits = [];
+}
+
+WebInspector.SASSSupport.ASTDocument.prototype = {
+    /**
+     * @return {!WebInspector.SASSSupport.ASTDocument}
+     */
+    clone: function()
+    {
+        return new WebInspector.SASSSupport.ASTDocument(this.url, this.text);
+    },
+
+    /**
+     * @return {string}
+     */
+    newText: function()
+    {
+        this.edits.stableSort(sequentialOrder);
+        var text = this.text;
+        for (var i = this.edits.length - 1; i >= 0; --i)
+            text = this.edits[i].applyToText(text);
+        return text;
+
+        /**
+         * @param {!WebInspector.SourceEdit} edit1
+         * @param {!WebInspector.SourceEdit} edit2
+         * @return {number}
+         */
+        function sequentialOrder(edit1, edit2)
+        {
+            var range1 = edit1.oldRange.collapseToStart();
+            var range2 = edit2.oldRange.collapseToStart();
+            if (range1.equal(range2))
+                return 0;
+            return range1.follows(range2) ? 1 : -1;
+        }
+    },
 }
 
 /**
@@ -268,11 +305,23 @@
 
 WebInspector.SASSSupport.TextNode.prototype = {
     /**
+     * @param {string} newText
+     */
+    setText: function(newText)
+    {
+        if (this.text === newText)
+            return;
+        this.text = newText;
+        this.document.edits.push(new WebInspector.SourceEdit(this.document.url, this.range, this.text, newText));
+    },
+
+    /**
+     * @param {!WebInspector.SASSSupport.ASTDocument} document
      * @return {!WebInspector.SASSSupport.TextNode}
      */
-    clone: function()
+    clone: function(document)
     {
-        return new WebInspector.SASSSupport.TextNode(this.document, this.text, this.range.clone());
+        return new WebInspector.SASSSupport.TextNode(document, this.text, this.range.clone());
     },
 
     __proto__: WebInspector.SASSSupport.Node.prototype
@@ -300,11 +349,63 @@
 
 WebInspector.SASSSupport.Property.prototype = {
     /**
+     * @param {!WebInspector.SASSSupport.ASTDocument} document
      * @return {!WebInspector.SASSSupport.Property}
      */
-    clone: function()
+    clone: function(document)
     {
-        return new WebInspector.SASSSupport.Property(this.document, this.name.clone(), this.value.clone(), this.range.clone(), this.disabled);
+        return new WebInspector.SASSSupport.Property(document, this.name.clone(document), this.value.clone(document), this.range.clone(), this.disabled);
+    },
+
+    /**
+     * @param {function(!WebInspector.SASSSupport.Node)} callback
+     */
+    visit: function(callback)
+    {
+        callback(this);
+        callback(this.name);
+        callback(this.value);
+    },
+
+    /**
+     * @param {boolean} disabled
+     */
+    setDisabled: function(disabled)
+    {
+        if (this.disabled === disabled)
+            return;
+        this.disabled = disabled;
+        if (disabled) {
+            var oldRange1 = WebInspector.TextRange.createFromLocation(this.range.startLine, this.range.startColumn);
+            var edit1 = new WebInspector.SourceEdit(this.document.url, oldRange1, "", "/* ");
+            var oldRange2 = WebInspector.TextRange.createFromLocation(this.range.endLine, this.range.endColumn);
+            var edit2 = new WebInspector.SourceEdit(this.document.url, oldRange2, "", " */");
+            this.document.edits.push(edit1, edit2);
+            return;
+        }
+        var oldRange1 = new WebInspector.TextRange(this.range.startLine, this.range.startColumn, this.range.startLine, this.name.range.startColumn);
+        var text = this.document.text;
+        var edit1 = new WebInspector.SourceEdit(this.document.url, oldRange1, oldRange1.extract(text), "");
+        var oldRange2 = new WebInspector.TextRange(this.range.endLine, this.range.endColumn - 2, this.range.endLine, this.range.endColumn);
+        var edit2 = new WebInspector.SourceEdit(this.document.url, oldRange2, "*/", "");
+        this.document.edits.push(edit1, edit2);
+    },
+
+    remove: function()
+    {
+        console.assert(this.parent);
+        var rule = this.parent;
+        var index = rule.properties.indexOf(this);
+        rule.properties.splice(index, 1);
+        this.parent = null;
+
+        var lineRange = new WebInspector.TextRange(this.range.startLine, 0, this.range.endLine + 1, 0);
+        var oldRange;
+        if (lineRange.extract(this.document.text).trim() === this.range.extract(this.document.text).trim())
+            oldRange = lineRange;
+        else
+            oldRange = this.range;
+        this.document.edits.push(new WebInspector.SourceEdit(this.document.url, oldRange, oldRange.extract(this.document.text), ""));
     },
 
     __proto__: WebInspector.SASSSupport.Node.prototype
@@ -324,18 +425,78 @@
     this.properties = properties;
     for (var i = 0; i < this.properties.length; ++i)
         this.properties[i].parent = this;
+
+    this._hasTrailingSemicolon = !this.properties.length || this.properties.peekLast().range.extract(this.document.text).endsWith(";");
 }
 
 WebInspector.SASSSupport.Rule.prototype = {
     /**
+     * @param {!WebInspector.SASSSupport.ASTDocument} document
      * @return {!WebInspector.SASSSupport.Rule}
      */
-    clone: function()
+    clone: function(document)
     {
         var properties = [];
         for (var i = 0; i < this.properties.length; ++i)
-            properties.push(this.properties[i].clone());
-        return new WebInspector.SASSSupport.Rule(this.document, this.selector, properties);
+            properties.push(this.properties[i].clone(document));
+        return new WebInspector.SASSSupport.Rule(document, this.selector, properties);
+    },
+
+    /**
+     * @param {function(!WebInspector.SASSSupport.Node)} callback
+     */
+    visit: function(callback)
+    {
+        callback(this);
+        for (var i = 0; i < this.properties.length; ++i)
+            this.properties[i].visit(callback);
+    },
+
+    _addTrailingSemicolon: function()
+    {
+        if (this._hasTrailingSemicolon || !this.properties)
+            return;
+        this._hasTrailingSemicolon = true;
+        this.document.edits.push(new WebInspector.SourceEdit(this.document.url, this.properties.peekLast().range.collapseToEnd(), "", ";"))
+    },
+
+    /**
+     * @param {string} nameText
+     * @param {string} valueText
+     * @param {boolean} disabled
+     * @param {!WebInspector.SASSSupport.Property} anchorProperty
+     * @param {boolean} insertBefore
+     * @return {!WebInspector.SASSSupport.Property}
+     */
+    insertProperty: function(nameText, valueText, disabled, anchorProperty, insertBefore)
+    {
+        console.assert(this.properties.length, "Cannot insert in empty rule.");
+
+        this._addTrailingSemicolon();
+
+        var name = new WebInspector.SASSSupport.TextNode(this.document, nameText, WebInspector.TextRange.createFromLocation(10, 0));
+        var value = new WebInspector.SASSSupport.TextNode(this.document, valueText, WebInspector.TextRange.createFromLocation(10, 0));
+        var newProperty = new WebInspector.SASSSupport.Property(this.document, name, value, WebInspector.TextRange.createFromLocation(10, 0), disabled);
+
+        var index = this.properties.indexOf(anchorProperty);
+        this.properties.splice(insertBefore ? index : index + 1, 0, newProperty);
+        newProperty.parent = this;
+
+        var oldRange = insertBefore ? anchorProperty.range.collapseToStart() : anchorProperty.range.collapseToEnd();
+        var indent = (new WebInspector.TextRange(anchorProperty.range.startLine, 0, anchorProperty.range.startLine, anchorProperty.range.startColumn)).extract(this.document.text);
+        if (!/^\s+$/.test(indent)) indent = "";
+
+        var newText = "";
+        var leftComment = disabled ? "/* " : "";
+        var rightComment = disabled ? " */" : "";
+
+        if (insertBefore) {
+            newText = String.sprintf("%s%s: %s;%s\n%s", leftComment, newProperty.name.text, newProperty.value.text, rightComment, indent);
+        } else {
+            newText = String.sprintf("\n%s%s%s: %s;%s", indent, leftComment, newProperty.name.text, newProperty.value.text, rightComment);
+        }
+        this.document.edits.push(new WebInspector.SourceEdit(this.document.url, oldRange, "", newText));
+        return newProperty;
     },
 
     __proto__: WebInspector.SASSSupport.Node.prototype
@@ -361,16 +522,49 @@
      */
     clone: function()
     {
+        var document = this.document.clone();
         var rules = [];
         for (var i = 0; i < this.rules.length; ++i)
-            rules.push(this.rules[i].clone());
-        return new WebInspector.SASSSupport.AST(this.document, rules);
+            rules.push(this.rules[i].clone(document));
+        return new WebInspector.SASSSupport.AST(document, rules);
+    },
+
+    /**
+     * @param {function(!WebInspector.SASSSupport.Node)} callback
+     */
+    visit: function(callback)
+    {
+        callback(this);
+        for (var i = 0; i < this.rules.length; ++i)
+            this.rules[i].visit(callback);
+    },
+
+    /**
+     * @param {number} lineNumber
+     * @param {number} columnNumber
+     * @return {?WebInspector.SASSSupport.TextNode}
+     */
+    findNodeForPosition: function(lineNumber, columnNumber)
+    {
+        var result = null;
+        this.visit(onNode);
+        return result;
+
+        /**
+         * @param {!WebInspector.SASSSupport.Node} node
+         */
+        function onNode(node)
+        {
+            if (!(node instanceof WebInspector.SASSSupport.TextNode))
+                return;
+            if (node.range.containsLocation(lineNumber, columnNumber))
+                result = node;
+        }
     },
 
     __proto__: WebInspector.SASSSupport.Node.prototype
 }
 
-
 /** @enum {string} */
 WebInspector.SASSSupport.PropertyChangeType = {
     PropertyAdded: "PropertyAdded",
@@ -399,11 +593,13 @@
 
 /**
  * @constructor
+ * @param {string} url
  * @param {!Map<!WebInspector.SASSSupport.TextNode, !WebInspector.SASSSupport.TextNode>} mapping
  * @param {!Array<!WebInspector.SASSSupport.PropertyChange>} changes
  */
-WebInspector.SASSSupport.ASTDiff = function(mapping, changes)
+WebInspector.SASSSupport.ASTDiff = function(url, mapping, changes)
 {
+    this.url = url;
     this.mapping = mapping;
     this.changes = changes;
 }
@@ -416,6 +612,7 @@
 WebInspector.SASSSupport.diffModels = function(oldAST, newAST)
 {
     console.assert(oldAST.rules.length === newAST.rules.length, "Not implemented for rule diff.");
+    console.assert(oldAST.document.url === newAST.document.url, "Diff makes sense for models with the same url.");
     var T = WebInspector.SASSSupport.PropertyChangeType;
     var changes = [];
     /** @type {!Map<!WebInspector.SASSSupport.TextNode, !WebInspector.SASSSupport.TextNode>} */
@@ -425,7 +622,7 @@
         var newRule = newAST.rules[i];
         computeRuleDiff(mapping, oldRule, newRule);
     }
-    return new WebInspector.SASSSupport.ASTDiff(mapping, changes);
+    return new WebInspector.SASSSupport.ASTDiff(oldAST.document.url, mapping, changes);
 
     /**
      * @param {!WebInspector.SASSSupport.PropertyChangeType} type
diff --git a/third_party/WebKit/Source/devtools/front_end/sass/module.json b/third_party/WebKit/Source/devtools/front_end/sass/module.json
index 21761c54..7547bc71 100644
--- a/third_party/WebKit/Source/devtools/front_end/sass/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/sass/module.json
@@ -1,6 +1,7 @@
 {
     "dependencies": ["platform", "common", "diff", "sdk"],
     "scripts": [
-        "SASSSupport.js"
+        "SASSSupport.js",
+        "SASSLiveSourceMap.js"
     ]
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js b/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js
index ba98da72..ffbe3539 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js
@@ -46,7 +46,7 @@
     this._delegate = delegate;
     this._model = model;
     this._filters = filters;
-    this._calculator = new WebInspector.TimelineCalculator(this._model);
+    this._calculator = new WebInspector.CounterGraphCalculator(this._model);
 
     this._graphsContainer = new WebInspector.VBox();
     this.setMainWidget(this._graphsContainer);
@@ -219,7 +219,7 @@
             return false;
         }
         this._model.forAllRecords(null, findRecordToReveal.bind(this));
-        this._delegate.select(recordToReveal ? WebInspector.TimelineSelection.fromRecord(recordToReveal) : null);
+        this._delegate.select(recordToReveal ? WebInspector.TimelineSelection.fromTraceEvent(recordToReveal.traceEvent()) : null);
     },
 
     /**
@@ -264,11 +264,8 @@
 
     /**
      * @override
-     * @param {?RegExp} textFilter
      */
-    refreshRecords: function(textFilter)
-    {
-    },
+    refreshRecords: function() { },
 
     _clear: function()
     {
@@ -366,7 +363,7 @@
     },
 
     /**
-     * @param {!WebInspector.TimelineCalculator} calculator
+     * @param {!WebInspector.CounterGraphCalculator} calculator
      */
     _calculateVisibleIndexes: function(calculator)
     {
@@ -566,3 +563,99 @@
         return this._filter.checked();
     }
 }
+
+/**
+ * @constructor
+ * @param {!WebInspector.TimelineModel} model
+ * @implements {WebInspector.TimelineGrid.Calculator}
+ */
+WebInspector.CounterGraphCalculator = function(model)
+{
+    this._model = model;
+}
+
+WebInspector.CounterGraphCalculator._minWidth = 5;
+
+WebInspector.CounterGraphCalculator.prototype = {
+    /**
+     * @override
+     * @return {number}
+     */
+    paddingLeft: function()
+    {
+        return this._paddingLeft;
+    },
+
+    /**
+     * @override
+     * @param {number} time
+     * @return {number}
+     */
+    computePosition: function(time)
+    {
+        return (time - this._minimumBoundary) / this.boundarySpan() * this._workingArea + this._paddingLeft;
+    },
+
+    setWindow: function(minimumBoundary, maximumBoundary)
+    {
+        this._minimumBoundary = minimumBoundary;
+        this._maximumBoundary = maximumBoundary;
+    },
+
+    /**
+     * @param {number} clientWidth
+     * @param {number=} paddingLeft
+     */
+    setDisplayWindow: function(clientWidth, paddingLeft)
+    {
+        this._paddingLeft = paddingLeft || 0;
+        this._workingArea = clientWidth - WebInspector.CounterGraphCalculator._minWidth - this._paddingLeft;
+    },
+
+    /**
+     * @override
+     * @param {number} value
+     * @param {number=} precision
+     * @return {string}
+     */
+    formatTime: function(value, precision)
+    {
+        return Number.preciseMillisToString(value - this.zeroTime(), precision);
+    },
+
+    /**
+     * @override
+     * @return {number}
+     */
+    maximumBoundary: function()
+    {
+        return this._maximumBoundary;
+    },
+
+    /**
+     * @override
+     * @return {number}
+     */
+    minimumBoundary: function()
+    {
+        return this._minimumBoundary;
+    },
+
+    /**
+     * @override
+     * @return {number}
+     */
+    zeroTime: function()
+    {
+        return this._model.minimumRecordTime();
+    },
+
+    /**
+     * @override
+     * @return {number}
+     */
+    boundarySpan: function()
+    {
+        return this._maximumBoundary - this._minimumBoundary;
+    }
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/MemoryCountersGraph.js b/third_party/WebKit/Source/devtools/front_end/timeline/MemoryCountersGraph.js
index c4704c4..4a04cbe4 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/MemoryCountersGraph.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/MemoryCountersGraph.js
@@ -53,9 +53,8 @@
 WebInspector.MemoryCountersGraph.prototype = {
     /**
      * @override
-     * @param {?RegExp} textFilter
      */
-    refreshRecords: function(textFilter)
+    refreshRecords: function()
     {
         this.reset();
         var events = this._model.mainThreadEvents();
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js
index 46718f0..2c7457c 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js
@@ -1206,7 +1206,7 @@
     this._model.addEventListener(WebInspector.TimelineModel.Events.RecordingStarted, this._onRecordingStarted, this);
     this._mainView.addEventListener(WebInspector.FlameChart.Events.EntrySelected, this._onMainEntrySelected, this);
     this._networkView.addEventListener(WebInspector.FlameChart.Events.EntrySelected, this._onNetworkEntrySelected, this);
-    WebInspector.BlackboxSupport.addChangeListener(this._refresh, this);
+    WebInspector.BlackboxSupport.addChangeListener(this.refreshRecords, this);
 }
 
 WebInspector.TimelineFlameChartView.prototype = {
@@ -1218,7 +1218,7 @@
         this._model.removeEventListener(WebInspector.TimelineModel.Events.RecordingStarted, this._onRecordingStarted, this);
         this._mainView.removeEventListener(WebInspector.FlameChart.Events.EntrySelected, this._onMainEntrySelected, this);
         this._networkView.removeEventListener(WebInspector.FlameChart.Events.EntrySelected, this._onNetworkEntrySelected, this);
-        WebInspector.BlackboxSupport.removeChangeListener(this._refresh, this);
+        WebInspector.BlackboxSupport.removeChangeListener(this.refreshRecords, this);
     },
 
     /**
@@ -1252,11 +1252,13 @@
 
     /**
      * @override
-     * @param {?RegExp} textFilter
      */
-    refreshRecords: function(textFilter)
+    refreshRecords: function()
     {
-        this._refresh();
+        this._dataProvider.reset();
+        this._mainView.scheduleUpdate();
+        this._networkDataProvider.reset();
+        this._networkView.scheduleUpdate();
     },
 
     /**
@@ -1384,14 +1386,6 @@
             this._splitWidget.hideSidebar(animate);
     },
 
-    _refresh: function()
-    {
-        this._dataProvider.reset();
-        this._mainView.scheduleUpdate();
-        this._networkDataProvider.reset();
-        this._networkView.scheduleUpdate();
-    },
-
     __proto__: WebInspector.VBox.prototype
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
index a7d0159..7438a98 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
@@ -64,17 +64,9 @@
     if (Runtime.experiments.isEnabled("cpuThrottling"))
         this._cpuThrottlingManager = new WebInspector.CPUThrottlingManager();
 
-    this._waterfallFilters = [new WebInspector.TimelineStaticFilter()];
-    if (!Runtime.experiments.isEnabled("timelineEventsTreeView")) {
-        this._filtersControl = new WebInspector.TimelineFilters();
-        this._filtersControl.addEventListener(WebInspector.TimelineFilters.Events.FilterChanged, this._refreshViews, this);
-        this._waterfallFilters = this._waterfallFilters.concat(this._filtersControl.filters());
-    }
-
     /** @type {!Array.<!WebInspector.TimelineModeView>} */
     this._currentViews = [];
 
-    this._flameChartEnabledSetting = WebInspector.settings.createSetting("timelineFlameChartEnabled", true);
     this._viewModeSetting = WebInspector.settings.createSetting("timelineViewMode", WebInspector.TimelinePanel.ViewMode.FlameChart);
     this._createToolbarItems();
 
@@ -111,7 +103,6 @@
     if (Runtime.experiments.isEnabled("multipleTimelineViews")) {
         this._tabbedPane = new WebInspector.TabbedPane();
         this._tabbedPane.appendTab(WebInspector.TimelinePanel.ViewMode.FlameChart, WebInspector.UIString("Flame Chart"), new WebInspector.VBox());
-        this._tabbedPane.appendTab(WebInspector.TimelinePanel.ViewMode.Waterfall, WebInspector.UIString("Waterfall"), new WebInspector.VBox());
         this._tabbedPane.appendTab(WebInspector.TimelinePanel.ViewMode.CallTree, WebInspector.UIString("Call Tree"), new WebInspector.VBox());
         this._tabbedPane.appendTab(WebInspector.TimelinePanel.ViewMode.BottomUp, WebInspector.UIString("Bottom-Up"), new WebInspector.VBox());
         this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._onMainViewChanged.bind(this));
@@ -120,7 +111,6 @@
         this._stackView.show(this._searchableView.element);
         this._onModeChanged();
     }
-    this._flameChartEnabledSetting.addChangeListener(this._onModeChanged, this);
     this._detailsSplitWidget.show(timelinePane.element);
     this._detailsSplitWidget.hideSidebar();
     WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Events.SuspendStateChanged, this._onSuspendStateChanged, this);
@@ -131,7 +121,6 @@
  * @enum {string}
  */
 WebInspector.TimelinePanel.ViewMode = {
-    Waterfall: "Waterfall",
     FlameChart: "FlameChart",
     CallTree: "CallTree",
     BottomUp: "BottomUp",
@@ -296,7 +285,7 @@
     _addModeView: function(modeView)
     {
         modeView.setWindowTimes(this.windowStartTime(), this.windowEndTime());
-        modeView.refreshRecords(this._filterRegExp);
+        modeView.refreshRecords();
         this._stackView.appendView(modeView.view(), "timelinePanelTimelineStackSplitViewState", undefined, 112);
         modeView.view().addEventListener(WebInspector.SplitWidget.Events.SidebarSizeChanged, this._sidebarResized, this);
         this._currentViews.push(modeView);
@@ -348,23 +337,11 @@
         this._panelToolbar.appendToolbarItem(clearButton);
         this._panelToolbar.appendSeparator();
 
-        if (this._filtersControl)
-            this._panelToolbar.appendToolbarItem(this._filtersControl.filterButton());
-
         var garbageCollectButton = new WebInspector.ToolbarButton(WebInspector.UIString("Collect garbage"), "garbage-collect-toolbar-item");
         garbageCollectButton.addEventListener("click", this._garbageCollectButtonClicked, this);
         this._panelToolbar.appendToolbarItem(garbageCollectButton);
         this._panelToolbar.appendSeparator();
 
-        if (!Runtime.experiments.isEnabled("multipleTimelineViews")) {
-            var viewModeLabel = new WebInspector.ToolbarText(WebInspector.UIString("View:"), "toolbar-group-label");
-            this._panelToolbar.appendToolbarItem(viewModeLabel);
-
-            this._flameChartToggleButton = new WebInspector.ToolbarSettingToggle(this._flameChartEnabledSetting, "flame-chart-toolbar-item", WebInspector.UIString("Flame chart view. (Use WASD or time selection to navigate)"));
-            this._panelToolbar.appendToolbarItem(this._flameChartToggleButton);
-            this._panelToolbar.appendSeparator();
-        }
-
         var captureSettingsLabel = new WebInspector.ToolbarText(WebInspector.UIString("Capture:"), "toolbar-group-label");
         this._panelToolbar.appendToolbarItem(captureSettingsLabel);
 
@@ -420,9 +397,6 @@
         this._progressToolbarItem = new WebInspector.ToolbarItem(createElement("div"));
         this._progressToolbarItem.setVisible(false);
         this._panelToolbar.appendToolbarItem(this._progressToolbarItem);
-
-        if (this._filtersControl)
-            this._filtersControl.filtersWidget().show(this.element);
     },
 
     /**
@@ -527,10 +501,9 @@
 
     _refreshViews: function()
     {
-        this._filterRegExp = this._filtersControl && this._filtersControl.searchRegExp();
         for (var i = 0; i < this._currentViews.length; ++i) {
             var view = this._currentViews[i];
-            view.refreshRecords(this._filterRegExp);
+            view.refreshRecords();
         }
         this._updateSelectionDetails();
     },
@@ -554,7 +527,7 @@
         // Set up the main view.
         this._stackView.detach();
         this._removeAllModeViews();
-        var viewMode = this._flameChartEnabledSetting.get() ? WebInspector.TimelinePanel.ViewMode.FlameChart : WebInspector.TimelinePanel.ViewMode.Waterfall;
+        var viewMode = WebInspector.TimelinePanel.ViewMode.FlameChart;
         if (Runtime.experiments.isEnabled("multipleTimelineViews") && this._tabbedPane) {
             viewMode = this._tabbedPane.selectedTabId;
             this._stackView.show(this._tabbedPane.visibleView.element);
@@ -562,16 +535,10 @@
             this._stackView.show(this._searchableView.element);
         }
         this._flameChart = null;
-        if (this._filtersControl)
-            this._filtersControl.filtersWidget().setEnabled(viewMode === WebInspector.TimelinePanel.ViewMode.Waterfall);
         if (viewMode === WebInspector.TimelinePanel.ViewMode.FlameChart) {
             this._flameChart = new WebInspector.TimelineFlameChartView(this, this._model, this._frameModel);
             this._flameChart.enableNetworkPane(this._captureNetworkSetting.get());
             this._addModeView(this._flameChart);
-        } else if (viewMode === WebInspector.TimelinePanel.ViewMode.Waterfall) {
-            var timelineView = new WebInspector.TimelineView(this, this._model, this._waterfallFilters);
-            this._addModeView(timelineView);
-            timelineView.setFrameModel(this._frameModel);
         } else if (viewMode === WebInspector.TimelinePanel.ViewMode.CallTree || viewMode === WebInspector.TimelinePanel.ViewMode.BottomUp) {
             var innerView = viewMode === WebInspector.TimelinePanel.ViewMode.BottomUp ? new WebInspector.BottomUpTimelineTreeView(this._model) : new WebInspector.CallTreeTimelineTreeView(this._model);
             var treeView = new WebInspector.TimelineTreeModeView(this, innerView);
@@ -579,7 +546,7 @@
         }
 
         if (this._captureMemorySetting.get() && viewMode !== WebInspector.TimelinePanel.ViewMode.CallTree && viewMode !== WebInspector.TimelinePanel.ViewMode.BottomUp)
-            this._addModeView(new WebInspector.MemoryCountersGraph(this, this._model, this._waterfallFilters));
+            this._addModeView(new WebInspector.MemoryCountersGraph(this, this._model, [WebInspector.TimelineUIUtils.visibleEventsFilter()]));
 
         this.doResize();
         this.select(null);
@@ -915,7 +882,7 @@
      */
     _updateSearchHighlight: function(revealRecord, shouldJump, jumpBackwards)
     {
-        if (this._filterRegExp || !this._searchRegex) {
+        if (!this._searchRegex) {
             this._clearHighlight();
             return;
         }
@@ -949,7 +916,7 @@
             if (WebInspector.TimelineUIUtils.testContentMatching(record.traceEvent(), searchRegExp))
                 matches.push(record);
         }
-        this._model.forAllFilteredRecords(this._waterfallFilters, processRecord.bind(this));
+        this._model.forAllFilteredRecords([WebInspector.TimelineUIUtils.visibleEventsFilter()], processRecord.bind(this));
 
         var matchesCount = matches.length;
         if (matchesCount) {
@@ -994,11 +961,6 @@
     _updateSelectionDetails: function()
     {
         switch (this._selection.type()) {
-        case WebInspector.TimelineSelection.Type.Record:
-            var record = /** @type {!WebInspector.TimelineModel.Record} */ (this._selection.object());
-            var event = record.traceEvent();
-            WebInspector.TimelineUIUtils.buildTraceEventDetails(event, this._model, this._detailsLinkifier, true, this._appendDetailsTabsForTraceEventAndShowDetails.bind(this, event));
-            break;
         case WebInspector.TimelineSelection.Type.TraceEvent:
             var event = /** @type {!WebInspector.TracingModel.Event} */ (this._selection.object());
             WebInspector.TimelineUIUtils.buildTraceEventDetails(event, this._model, this._detailsLinkifier, true, this._appendDetailsTabsForTraceEventAndShowDetails.bind(this, event));
@@ -1043,7 +1005,6 @@
             return /** @type {!WebInspector.TimelineFrame} */ (selection.object());
         case WebInspector.TimelineSelection.Type.Range:
             return null;
-        case WebInspector.TimelineSelection.Type.Record:
         case WebInspector.TimelineSelection.Type.TraceEvent:
             return this._frameModel.filteredFrames(selection._endTime, selection._endTime)[0];
         default:
@@ -1342,11 +1303,9 @@
         this.appendTab(tabIds.CallTree, WebInspector.UIString("Call Tree"), callTreeView);
         this._rangeDetailViews.set(tabIds.CallTree, callTreeView);
 
-        if (Runtime.experiments.isEnabled("timelineEventsTreeView")) {
-            var eventsView = new WebInspector.EventsTimelineTreeView(timelineModel, delegate);
-            this.appendTab(tabIds.Events, WebInspector.UIString("Event Log"), eventsView);
-            this._rangeDetailViews.set(tabIds.Events, eventsView);
-        }
+        var eventsView = new WebInspector.EventsTimelineTreeView(timelineModel, delegate);
+        this.appendTab(tabIds.Events, WebInspector.UIString("Event Log"), eventsView);
+        this._rangeDetailViews.set(tabIds.Events, eventsView);
     }
 
     this.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this);
@@ -1435,7 +1394,6 @@
  * @enum {string}
  */
 WebInspector.TimelineSelection.Type = {
-    Record: "Record",
     Frame: "Frame",
     NetworkRequest: "NetworkRequest",
     TraceEvent: "TraceEvent",
@@ -1443,18 +1401,6 @@
 };
 
 /**
- * @param {!WebInspector.TimelineModel.Record} record
- * @return {!WebInspector.TimelineSelection}
- */
-WebInspector.TimelineSelection.fromRecord = function(record)
-{
-    return new WebInspector.TimelineSelection(
-        WebInspector.TimelineSelection.Type.Record,
-        record.startTime(), record.endTime(),
-        record);
-}
-
-/**
  * @param {!WebInspector.TimelineFrame} frame
  * @return {!WebInspector.TimelineSelection}
  */
@@ -1554,10 +1500,7 @@
 
     reset: function() {},
 
-    /**
-     * @param {?RegExp} textFilter
-     */
-    refreshRecords: function(textFilter) {},
+    refreshRecords: function() {},
 
     /**
      * @param {?WebInspector.TimelineModel.Record} record
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePresentationModel.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePresentationModel.js
deleted file mode 100644
index 3b8cff2b..0000000
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePresentationModel.js
+++ /dev/null
@@ -1,595 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- * Copyright (C) 2012 Intel Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * 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.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "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 COPYRIGHT
- * OWNER OR CONTRIBUTORS 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.
- */
-
-/**
- * @constructor
- * @extends {WebInspector.Object}
- * @param {!WebInspector.TimelineModel} model
- * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
- */
-WebInspector.TimelinePresentationModel = function(model, filters)
-{
-    this._model = model;
-    this._filters = filters;
-    /**
-     * @type {!Map.<!WebInspector.TimelineModel.Record, !WebInspector.TimelinePresentationModel.Record>}
-     */
-    this._recordToPresentationRecord = new Map();
-    this.reset();
-}
-
-WebInspector.TimelinePresentationModel.prototype = {
-    /**
-     * @param {number} startTime
-     * @param {number} endTime
-     */
-    setWindowTimes: function(startTime, endTime)
-    {
-        this._windowStartTime = startTime;
-        this._windowEndTime = endTime;
-    },
-
-    /**
-     * @param {?WebInspector.TimelineModel.Record} record
-     * @return {?WebInspector.TimelinePresentationModel.Record}
-     */
-    toPresentationRecord: function(record)
-    {
-        return record ? this._recordToPresentationRecord.get(record) || null : null;
-    },
-
-    /**
-     * @return {!WebInspector.TimelinePresentationModel.Record}
-     */
-    rootRecord: function()
-    {
-        return this._rootRecord;
-    },
-
-    reset: function()
-    {
-        this._recordToPresentationRecord.clear();
-        this._rootRecord = new WebInspector.TimelinePresentationModel.RootRecord();
-        /** @type {!Object.<string, !WebInspector.TimelinePresentationModel.Record>} */
-        this._coalescingBuckets = {};
-    },
-
-    /**
-     * @param {!WebInspector.TimelineModel.Record} record
-     */
-    addRecord: function(record)
-    {
-        if (WebInspector.TracingModel.isTopLevelEvent(record.traceEvent())) {
-            var records = record.children();
-            for (var i = 0; i < records.length; ++i)
-                this._innerAddRecord(this._rootRecord, records[i]);
-        } else {
-            this._innerAddRecord(this._rootRecord, record);
-        }
-    },
-
-    /**
-     * @param {!WebInspector.TimelinePresentationModel.Record} parentRecord
-     * @param {!WebInspector.TimelineModel.Record} record
-     */
-    _innerAddRecord: function(parentRecord, record)
-    {
-        var coalescingBucket;
-
-        // On main thread, only coalesce if the last event is of same type.
-        if (parentRecord === this._rootRecord)
-            coalescingBucket = record.thread() ? record.type() : "mainThread";
-        var coalescedRecord = this._findCoalescedParent(record, parentRecord, coalescingBucket);
-        if (coalescedRecord)
-            parentRecord = coalescedRecord;
-
-        var formattedRecord = new WebInspector.TimelinePresentationModel.ActualRecord(record, parentRecord);
-        this._recordToPresentationRecord.set(record, formattedRecord);
-
-        formattedRecord._collapsed = parentRecord === this._rootRecord;
-        if (coalescingBucket)
-            this._coalescingBuckets[coalescingBucket] = formattedRecord;
-
-        for (var i = 0; record.children() && i < record.children().length; ++i)
-            this._innerAddRecord(formattedRecord, record.children()[i]);
-
-        if (parentRecord.coalesced())
-            this._updateCoalescingParent(formattedRecord);
-    },
-
-    /**
-     * @param {!WebInspector.TimelineModel.Record} record
-     * @param {!WebInspector.TimelinePresentationModel.Record} newParent
-     * @param {string=} bucket
-     * @return {?WebInspector.TimelinePresentationModel.Record}
-     */
-    _findCoalescedParent: function(record, newParent, bucket)
-    {
-        const coalescingThresholdMillis = 5;
-
-        var lastRecord = bucket ? this._coalescingBuckets[bucket] : newParent._presentationChildren.peekLast();
-        if (lastRecord && lastRecord.coalesced())
-            lastRecord = lastRecord._presentationChildren.peekLast();
-        var startTime = record.startTime();
-        var endTime = record.endTime();
-        if (!lastRecord)
-            return null;
-        if (lastRecord.record().type() !== record.type())
-            return null;
-        if (!WebInspector.TimelineUIUtils.isCoalescable(record.type()))
-            return null;
-        if (lastRecord.record().endTime() + coalescingThresholdMillis < startTime)
-            return null;
-        if (endTime + coalescingThresholdMillis < lastRecord.record().startTime())
-            return null;
-        if (lastRecord.presentationParent().coalesced())
-            return lastRecord.presentationParent();
-        return this._replaceWithCoalescedRecord(lastRecord);
-    },
-
-    /**
-     * @param {!WebInspector.TimelinePresentationModel.Record} presentationRecord
-     * @return {!WebInspector.TimelinePresentationModel.Record}
-     */
-    _replaceWithCoalescedRecord: function(presentationRecord)
-    {
-        var record = presentationRecord.record();
-        var parent = presentationRecord._presentationParent;
-        var coalescedRecord = new WebInspector.TimelinePresentationModel.CoalescedRecord(record);
-
-        coalescedRecord._collapsed = true;
-        coalescedRecord._presentationChildren.push(presentationRecord);
-        presentationRecord._presentationParent = coalescedRecord;
-        if (presentationRecord.hasWarnings() || presentationRecord.childHasWarnings())
-            coalescedRecord._childHasWarnings = true;
-
-        coalescedRecord._presentationParent = parent;
-        parent._presentationChildren[parent._presentationChildren.indexOf(presentationRecord)] = coalescedRecord;
-
-        return coalescedRecord;
-    },
-
-    /**
-     * @param {!WebInspector.TimelinePresentationModel.Record} presentationRecord
-     */
-    _updateCoalescingParent: function(presentationRecord)
-    {
-        var parentRecord = presentationRecord._presentationParent;
-        if (parentRecord.endTime() < presentationRecord.endTime())
-            parentRecord._endTime = presentationRecord.endTime();
-    },
-
-    /**
-     * @param {?RegExp} textFilter
-     */
-    setTextFilter: function(textFilter)
-    {
-        var records = this._recordToPresentationRecord.valuesArray();
-        for (var i = 0; i < records.length; ++i)
-            records[i]._expandedOrCollapsedWhileFiltered = false;
-        this._textFilter = textFilter;
-    },
-
-    refreshRecords: function()
-    {
-        this.reset();
-        var modelRecords = this._model.records();
-        for (var i = 0; i < modelRecords.length; ++i)
-            this.addRecord(modelRecords[i]);
-    },
-
-    invalidateFilteredRecords: function()
-    {
-        delete this._filteredRecords;
-    },
-
-    /**
-     * @return {!Array.<!WebInspector.TimelinePresentationModel.Record>}
-     */
-    filteredRecords: function()
-    {
-        if (!this._rootRecord.presentationChildren().length)
-            this.refreshRecords();
-        if (this._filteredRecords)
-            return this._filteredRecords;
-
-        var recordsInWindow = [];
-
-        var stack = [{children: this._rootRecord._presentationChildren, index: 0, parentIsCollapsed: false, parentRecord: {}}];
-        var revealedDepth = 0;
-
-        function revealRecordsInStack() {
-            for (var depth = revealedDepth + 1; depth < stack.length; ++depth) {
-                if (stack[depth - 1].parentIsCollapsed) {
-                    stack[depth].parentRecord._presentationParent._expandable = true;
-                    return;
-                }
-                stack[depth - 1].parentRecord._collapsed = false;
-                recordsInWindow.push(stack[depth].parentRecord);
-                stack[depth].windowLengthBeforeChildrenTraversal = recordsInWindow.length;
-                stack[depth].parentIsRevealed = true;
-                revealedDepth = depth;
-            }
-        }
-
-        while (stack.length) {
-            var entry = stack[stack.length - 1];
-            var records = entry.children;
-            if (records && entry.index < records.length) {
-                var record = records[entry.index];
-                ++entry.index;
-                if (record.startTime() < this._windowEndTime && record.endTime() > this._windowStartTime) {
-                    if (WebInspector.TimelineModel.isVisible(this._filters, record.record().traceEvent())) {
-                        record._presentationParent._expandable = true;
-                        if (this._textFilter)
-                            revealRecordsInStack();
-                        if (!entry.parentIsCollapsed) {
-                            recordsInWindow.push(record);
-                            revealedDepth = stack.length;
-                            entry.parentRecord._collapsed = false;
-                        }
-                    }
-                }
-
-                record._expandable = false;
-
-                stack.push({children: record._presentationChildren,
-                            index: 0,
-                            parentIsCollapsed: entry.parentIsCollapsed || (record._collapsed && (!this._textFilter || record._expandedOrCollapsedWhileFiltered)),
-                            parentRecord: record,
-                            windowLengthBeforeChildrenTraversal: recordsInWindow.length});
-            } else {
-                stack.pop();
-                revealedDepth = Math.min(revealedDepth, stack.length - 1);
-                entry.parentRecord._visibleChildrenCount = recordsInWindow.length - entry.windowLengthBeforeChildrenTraversal;
-            }
-        }
-
-        this._filteredRecords = recordsInWindow;
-        return recordsInWindow;
-    },
-
-    __proto__: WebInspector.Object.prototype
-}
-
-/**
- * @constructor
- * @param {?WebInspector.TimelinePresentationModel.Record} parentRecord
- */
-WebInspector.TimelinePresentationModel.Record = function(parentRecord)
-{
-    /**
-     * @type {!Array.<!WebInspector.TimelinePresentationModel.Record>}
-     */
-    this._presentationChildren = [];
-
-    if (parentRecord) {
-        this._presentationParent = parentRecord;
-        parentRecord._presentationChildren.push(this);
-    }
-}
-
-WebInspector.TimelinePresentationModel.Record.prototype = {
-    /**
-     * @return {number}
-     */
-    startTime: function()
-    {
-        throw new Error("Not implemented.");
-    },
-
-    /**
-     * @return {number}
-     */
-    endTime: function()
-    {
-        throw new Error("Not implemented.");
-    },
-
-    /**
-     * @return {number}
-     */
-    selfTime: function()
-    {
-        throw new Error("Not implemented.");
-    },
-
-    /**
-     * @return {!WebInspector.TimelineModel.Record}
-     */
-    record: function()
-    {
-        throw new Error("Not implemented.");
-    },
-
-    /**
-     * @return {!Array.<!WebInspector.TimelinePresentationModel.Record>}
-     */
-    presentationChildren: function()
-    {
-        return this._presentationChildren;
-    },
-
-    /**
-     * @return {boolean}
-     */
-    coalesced: function()
-    {
-        return false;
-    },
-
-    /**
-     * @return {boolean}
-     */
-    collapsed: function()
-    {
-        return this._collapsed;
-    },
-
-    /**
-     * @param {boolean} collapsed
-     */
-    setCollapsed: function(collapsed)
-    {
-        this._collapsed = collapsed;
-        this._expandedOrCollapsedWhileFiltered = true;
-    },
-
-    /**
-     * @return {?WebInspector.TimelinePresentationModel.Record}
-     */
-    presentationParent: function()
-    {
-        return this._presentationParent || null;
-    },
-
-    /**
-     * @return {number}
-     */
-    visibleChildrenCount: function()
-    {
-        return this._visibleChildrenCount || 0;
-    },
-
-    /**
-     * @return {boolean}
-     */
-    expandable: function()
-    {
-        return !!this._expandable;
-    },
-
-    /**
-     * @return {boolean}
-     */
-    hasWarnings: function()
-    {
-        return false;
-    },
-
-    /**
-     * @return {boolean}
-     */
-    childHasWarnings: function()
-    {
-        return this._childHasWarnings;
-    },
-
-    /**
-     * @return {?WebInspector.TimelineRecordListRow}
-     */
-    listRow: function()
-    {
-        return this._listRow;
-    },
-
-    /**
-     * @param {!WebInspector.TimelineRecordListRow} listRow
-     */
-    setListRow: function(listRow)
-    {
-        this._listRow = listRow;
-    },
-
-    /**
-     * @return {?WebInspector.TimelineRecordGraphRow}
-     */
-    graphRow: function()
-    {
-        return this._graphRow;
-    },
-
-    /**
-     * @param {!WebInspector.TimelineRecordGraphRow} graphRow
-     */
-    setGraphRow: function(graphRow)
-    {
-        this._graphRow = graphRow;
-    }
-}
-
-/**
- * @constructor
- * @extends {WebInspector.TimelinePresentationModel.Record}
- * @param {!WebInspector.TimelineModel.Record} record
- * @param {?WebInspector.TimelinePresentationModel.Record} parentRecord
- */
-WebInspector.TimelinePresentationModel.ActualRecord = function(record, parentRecord)
-{
-    WebInspector.TimelinePresentationModel.Record.call(this, parentRecord);
-    this._record = record;
-
-    if (this.hasWarnings()) {
-        for (var parent = this._presentationParent; parent && !parent._childHasWarnings; parent = parent._presentationParent)
-            parent._childHasWarnings = true;
-    }
-}
-
-WebInspector.TimelinePresentationModel.ActualRecord.prototype = {
-    /**
-     * @override
-     * @return {number}
-     */
-    startTime: function()
-    {
-        return this._record.startTime();
-    },
-
-    /**
-     * @override
-     * @return {number}
-     */
-    endTime: function()
-    {
-        return this._record.endTime();
-    },
-
-    /**
-     * @override
-     * @return {number}
-     */
-    selfTime: function()
-    {
-        return this._record.traceEvent().selfTime;
-    },
-
-    /**
-     * @override
-     * @return {!WebInspector.TimelineModel.Record}
-     */
-    record: function()
-    {
-        return this._record;
-    },
-
-    /**
-     * @override
-     * @return {boolean}
-     */
-    hasWarnings: function()
-    {
-        return !!this._record.traceEvent().warning;
-    },
-
-    __proto__: WebInspector.TimelinePresentationModel.Record.prototype
-}
-
-/**
- * @constructor
- * @extends {WebInspector.TimelinePresentationModel.Record}
- * @param {!WebInspector.TimelineModel.Record} record
- */
-WebInspector.TimelinePresentationModel.CoalescedRecord = function(record)
-{
-    WebInspector.TimelinePresentationModel.Record.call(this, null);
-    this._startTime = record.startTime();
-    this._endTime = record.endTime();
-}
-
-WebInspector.TimelinePresentationModel.CoalescedRecord.prototype = {
-    /**
-     * @override
-     * @return {number}
-     */
-    startTime: function()
-    {
-        return this._startTime;
-    },
-
-    /**
-     * @override
-     * @return {number}
-     */
-    endTime: function()
-    {
-        return this._endTime;
-    },
-
-    /**
-     * @override
-     * @return {number}
-     */
-    selfTime: function()
-    {
-        return 0;
-    },
-
-    /**
-     * @override
-     * @return {!WebInspector.TimelineModel.Record}
-     */
-    record: function()
-    {
-        return this._presentationChildren[0].record();
-    },
-
-    /**
-     * @override
-     * @return {boolean}
-     */
-    coalesced: function()
-    {
-        return true;
-    },
-
-    /**
-     * @override
-     * @return {boolean}
-     */
-    hasWarnings: function()
-    {
-        return false;
-    },
-
-    __proto__: WebInspector.TimelinePresentationModel.Record.prototype
-}
-
-/**
- * @constructor
- * @extends {WebInspector.TimelinePresentationModel.Record}
- */
-WebInspector.TimelinePresentationModel.RootRecord = function()
-{
-    WebInspector.TimelinePresentationModel.Record.call(this, null);
-}
-
-WebInspector.TimelinePresentationModel.RootRecord.prototype = {
-    /**
-     * @override
-     * @return {boolean}
-     */
-    hasWarnings: function()
-    {
-        return false;
-    },
-
-    __proto__: WebInspector.TimelinePresentationModel.Record.prototype
-}
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
index 125fd1d..d379445 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
@@ -122,23 +122,6 @@
     WebInspector.TimelineUIUtils._eventStylesMap = eventStyles;
     return eventStyles;
 }
-
-WebInspector.TimelineUIUtils._coalescableRecordTypes = {};
-WebInspector.TimelineUIUtils._coalescableRecordTypes[WebInspector.TimelineModel.RecordType.Layout] = 1;
-WebInspector.TimelineUIUtils._coalescableRecordTypes[WebInspector.TimelineModel.RecordType.Paint] = 1;
-WebInspector.TimelineUIUtils._coalescableRecordTypes[WebInspector.TimelineModel.RecordType.RasterTask] = 1;
-WebInspector.TimelineUIUtils._coalescableRecordTypes[WebInspector.TimelineModel.RecordType.DecodeImage] = 1;
-WebInspector.TimelineUIUtils._coalescableRecordTypes[WebInspector.TimelineModel.RecordType.ResizeImage] = 1;
-
-/**
- * @param {string} recordType
- * @return {boolean}
- */
-WebInspector.TimelineUIUtils.isCoalescable = function(recordType)
-{
-    return !!WebInspector.TimelineUIUtils._coalescableRecordTypes[recordType];
-}
-
 /**
  * @param {!WebInspector.TracingModel.Event} traceEvent
  * @param {!RegExp} regExp
@@ -1234,16 +1217,6 @@
 /**
  * @param {!Object} total
  * @param {!WebInspector.TimelineModel} model
- * @param {!WebInspector.TimelineModel.Record} record
- */
-WebInspector.TimelineUIUtils.aggregateTimeForRecord = function(total, model, record)
-{
-    WebInspector.TimelineUIUtils._aggregatedStatsForTraceEvent(total, model, record.traceEvent());
-}
-
-/**
- * @param {!Object} total
- * @param {!WebInspector.TimelineModel} model
  * @param {!WebInspector.TracingModel.Event} event
  * @return {boolean}
  */
@@ -1446,36 +1419,6 @@
 }
 
 /**
- * @param {!WebInspector.TimelineModel} model
- * @param {!{name: string, tasks: !Array.<!WebInspector.TimelineModel.Record>, firstTaskIndex: number, lastTaskIndex: number}} info
- * @return {!Element}
- */
-WebInspector.TimelineUIUtils.generateMainThreadBarPopupContent = function(model, info)
-{
-    var firstTaskIndex = info.firstTaskIndex;
-    var lastTaskIndex = info.lastTaskIndex;
-    var tasks = info.tasks;
-    var messageCount = lastTaskIndex - firstTaskIndex + 1;
-    var cpuTime = 0;
-
-    for (var i = firstTaskIndex; i <= lastTaskIndex; ++i) {
-        var task = tasks[i];
-        cpuTime += task.endTime() - task.startTime();
-    }
-    var startTime = tasks[firstTaskIndex].startTime();
-    var endTime = tasks[lastTaskIndex].endTime();
-    var duration = endTime - startTime;
-
-    var contentHelper = new WebInspector.TimelinePopupContentHelper(info.name);
-    var durationText = WebInspector.UIString("%s (at %s)", Number.millisToString(duration, true),
-        Number.millisToString(startTime - model.minimumRecordTime(), true));
-    contentHelper.appendTextRow(WebInspector.UIString("Duration"), durationText);
-    contentHelper.appendTextRow(WebInspector.UIString("CPU time"), Number.millisToString(cpuTime, true));
-    contentHelper.appendTextRow(WebInspector.UIString("Message Count"), messageCount);
-    return contentHelper.contentTable();
-}
-
-/**
  * @param {!Object} aggregatedStats
  * @param {!WebInspector.TimelineCategory=} selfCategory
  * @param {number=} selfTime
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineView.js
deleted file mode 100644
index fa1c702..0000000
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineView.js
+++ /dev/null
@@ -1,1320 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- * Copyright (C) 2012 Intel Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * 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.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "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 COPYRIGHT
- * OWNER OR CONTRIBUTORS 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.
- */
-
-/**
- * @constructor
- * @extends {WebInspector.VBox}
- * @implements {WebInspector.TimelineModeView}
- * @param {!WebInspector.TimelineModeViewDelegate} delegate
- * @param {!WebInspector.TimelineModel} model
- * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
- */
-WebInspector.TimelineView = function(delegate, model, filters)
-{
-    WebInspector.VBox.call(this);
-    this.element.classList.add("timeline-view");
-
-    this._delegate = delegate;
-    this._model = model;
-    this._presentationModel = new WebInspector.TimelinePresentationModel(model, filters);
-    this._calculator = new WebInspector.TimelineCalculator(model);
-    this._linkifier = new WebInspector.Linkifier();
-    this._frameStripByFrame = new Map();
-
-    this._boundariesAreValid = true;
-    this._scrollTop = 0;
-
-    this._recordsView = this._createRecordsView();
-    this._recordsView.addEventListener(WebInspector.SplitWidget.Events.SidebarSizeChanged, this._sidebarResized, this);
-
-    this._topGapElement = this.element.createChild("div", "timeline-gap");
-    this._recordsView.show(this.element);
-    this._bottomGapElement = this.element.createChild("div", "timeline-gap");
-
-    this._headerElement = this.element.createChild("div", "fill");
-    this._headerElement.id = "timeline-graph-records-header";
-
-    // Create gpu tasks containers.
-    this._cpuBarsElement = this._headerElement.createChild("div", "timeline-utilization-strip");
-    if (Runtime.experiments.isEnabled("gpuTimeline"))
-        this._gpuBarsElement = this._headerElement.createChild("div", "timeline-utilization-strip gpu");
-
-    this._popoverHelper = new WebInspector.PopoverHelper(this.element, this._getPopoverAnchor.bind(this), this._showPopover.bind(this));
-
-    this.element.addEventListener("mousemove", this._mouseMove.bind(this), false);
-    this.element.addEventListener("mouseleave", this._mouseLeave.bind(this), false);
-    this.element.addEventListener("keydown", this._keyDown.bind(this), false);
-
-    this._expandOffset = 15;
-}
-
-WebInspector.TimelineView.prototype = {
-    /**
-     * @param {?WebInspector.TimelineFrameModelBase} frameModel
-     */
-    setFrameModel: function(frameModel)
-    {
-        this._frameModel = frameModel;
-    },
-
-    /**
-     * @return {!WebInspector.SplitWidget}
-     */
-    _createRecordsView: function()
-    {
-        this._containerElement = this.element;
-        this._containerElement.tabIndex = 0;
-        this._containerElement.id = "timeline-container";
-        this._containerElement.addEventListener("scroll", this._onScroll.bind(this), false);
-
-        var recordsView = new WebInspector.SplitWidget(true, false, "timelinePanelRecorsSplitViewState");
-        recordsView.element.style.flex = "1 0 auto";
-
-        // Create records list in the records sidebar.
-        var sidebarWidget = new WebInspector.VBox();
-        sidebarWidget.element.createChild("div", "timeline-records-title").textContent = WebInspector.UIString("RECORDS");
-        recordsView.setSidebarWidget(sidebarWidget);
-        this._sidebarListElement = sidebarWidget.element.createChild("div", "timeline-records-list");
-
-        // Create grid in the records main area.
-        this._gridContainer = new WebInspector.VBoxWithResizeCallback(this._onViewportResize.bind(this));
-        this._gridContainer.element.id = "resources-container-content";
-        recordsView.setMainWidget(this._gridContainer);
-        this._timelineGrid = new WebInspector.TimelineGrid();
-        this._gridContainer.element.appendChild(this._timelineGrid.element);
-
-        this._itemsGraphsElement = this._gridContainer.element.createChild("div");
-        this._itemsGraphsElement.id = "timeline-graphs";
-
-        // Create gap elements
-        this._graphRowsElement = this._itemsGraphsElement.createChild("div");
-        this._expandElements = this._itemsGraphsElement.createChild("div");
-        this._expandElements.id = "orphan-expand-elements";
-
-        return recordsView;
-    },
-
-    _rootRecord: function()
-    {
-        return this._presentationModel.rootRecord();
-    },
-
-    _updateEventDividers: function()
-    {
-        this._timelineGrid.removeEventDividers();
-        var clientWidth = this._graphRowsElementWidth;
-        var dividers = new Map();
-        var eventDividerRecords = this._model.eventDividerRecords();
-
-        for (var i = 0; i < eventDividerRecords.length; ++i) {
-            var record = eventDividerRecords[i];
-            var position = this._calculator.computePosition(record.startTime());
-            var dividerPosition = Math.round(position);
-            if (dividerPosition < 0 || dividerPosition >= clientWidth || dividers.has(dividerPosition))
-                continue;
-            dividers.set(dividerPosition, WebInspector.TimelineUIUtils.createDividerForRecord(record, this._calculator.zeroTime(), dividerPosition));
-        }
-        this._timelineGrid.addEventDividers(dividers.valuesArray());
-    },
-
-    _updateFrameBars: function(frames)
-    {
-        if (this._frameContainer) {
-            this._frameContainer.removeChildren();
-        } else {
-            const frameContainerBorderWidth = 1;
-            this._frameContainer = createElementWithClass("div", "fill timeline-frame-container");
-            this._frameContainer.style.height = WebInspector.TimelinePanel.rowHeight + frameContainerBorderWidth + "px";
-            this._frameContainer.addEventListener("dblclick", this._onFrameDoubleClicked.bind(this), false);
-            this._frameContainer.addEventListener("click", this._onFrameClicked.bind(this), false);
-        }
-        this._frameStripByFrame.clear();
-
-        var dividers = [];
-
-        for (var i = 0; i < frames.length; ++i) {
-            var frame = frames[i];
-            var frameStart = this._calculator.computePosition(frame.startTime);
-            var frameEnd = this._calculator.computePosition(frame.endTime);
-
-            var frameStrip = createElementWithClass("div", "timeline-frame-strip");
-            var actualStart = Math.max(frameStart, 0);
-            var width = frameEnd - actualStart;
-            frameStrip.style.left = actualStart + "px";
-            frameStrip.style.width = width + "px";
-            frameStrip._frame = frame;
-            this._frameStripByFrame.set(frame, frameStrip);
-
-            const minWidthForFrameInfo = 60;
-            if (width > minWidthForFrameInfo)
-                frameStrip.textContent = Number.millisToString(frame.endTime - frame.startTime, true);
-
-            this._frameContainer.appendChild(frameStrip);
-
-            if (actualStart > 0)
-                dividers.push(WebInspector.TimelineUIUtils.createEventDivider(WebInspector.TimelineModel.RecordType.BeginFrame, WebInspector.UIString("Frame"), frameStart));
-        }
-        this._timelineGrid.addEventDividers(dividers);
-        this._headerElement.appendChild(this._frameContainer);
-    },
-
-    _onFrameDoubleClicked: function(event)
-    {
-        var frameBar = event.target.enclosingNodeOrSelfWithClass("timeline-frame-strip");
-        if (!frameBar)
-            return;
-        this._delegate.requestWindowTimes(frameBar._frame.startTime, frameBar._frame.endTime);
-    },
-
-    _onFrameClicked: function(event)
-    {
-        var frameBar = event.target.enclosingNodeOrSelfWithClass("timeline-frame-strip");
-        if (!frameBar)
-            return;
-        this._delegate.select(WebInspector.TimelineSelection.fromFrame(frameBar._frame));
-    },
-
-    /**
-     * @override
-     * @param {number} width
-     */
-    setSidebarSize: function(width)
-    {
-        this._recordsView.setSidebarSize(width);
-    },
-
-    /**
-     * @param {!WebInspector.Event} event
-     */
-    _sidebarResized: function(event)
-    {
-        this.dispatchEventToListeners(WebInspector.SplitWidget.Events.SidebarSizeChanged, event.data);
-    },
-
-    _onViewportResize: function()
-    {
-        this._resize(this._recordsView.sidebarSize());
-    },
-
-    /**
-     * @param {number} sidebarWidth
-     */
-    _resize: function(sidebarWidth)
-    {
-        this._closeRecordDetails();
-        this._graphRowsElementWidth = this._graphRowsElement.offsetWidth;
-        this._headerElement.style.left = sidebarWidth + "px";
-        this._headerElement.style.width = this._itemsGraphsElement.offsetWidth + "px";
-        this._scheduleRefresh(false, true);
-    },
-
-    _resetView: function()
-    {
-        this._windowStartTime = 0;
-        this._windowEndTime = 0;
-        this._boundariesAreValid = false;
-        this._adjustScrollPosition(0);
-        this._linkifier.reset();
-        this._closeRecordDetails();
-        this._automaticallySizeWindow = true;
-        this._presentationModel.reset();
-    },
-
-
-    /**
-     * @override
-     * @return {!WebInspector.Widget}
-     */
-    view: function()
-    {
-        return this;
-    },
-
-    /**
-     * @override
-     */
-    dispose: function()
-    {
-    },
-
-    /**
-     * @override
-     */
-    reset: function()
-    {
-        this._resetView();
-        this._invalidateAndScheduleRefresh(true, true);
-    },
-
-    /**
-     * @override
-     * @return {!Array.<!Element>}
-     */
-    elementsToRestoreScrollPositionsFor: function()
-    {
-        return [this._containerElement];
-    },
-
-    /**
-     * @override
-     * @param {?RegExp} textFilter
-     */
-    refreshRecords: function(textFilter)
-    {
-        this._automaticallySizeWindow = false;
-        this._presentationModel.setTextFilter(textFilter);
-        this._invalidateAndScheduleRefresh(false, true);
-    },
-
-    willHide: function()
-    {
-        this._closeRecordDetails();
-        WebInspector.Widget.prototype.willHide.call(this);
-    },
-
-    _onScroll: function(event)
-    {
-        this._closeRecordDetails();
-        this._scrollTop = this._containerElement.scrollTop;
-        this._headerElement.style.top = this._scrollTop + "px";
-        this._scheduleRefresh(true, true);
-    },
-
-    /**
-     * @param {boolean} preserveBoundaries
-     * @param {boolean} userGesture
-     */
-    _invalidateAndScheduleRefresh: function(preserveBoundaries, userGesture)
-    {
-        this._presentationModel.invalidateFilteredRecords();
-        this._scheduleRefresh(preserveBoundaries, userGesture);
-    },
-
-    _clearSelection: function()
-    {
-        this._delegate.select(null);
-    },
-
-    /**
-     * @param {?WebInspector.TimelinePresentationModel.Record} presentationRecord
-     */
-    _selectRecord: function(presentationRecord)
-    {
-        if (presentationRecord.coalesced()) {
-            // Presentation record does not have model record to highlight.
-            this._innerSetSelectedRecord(presentationRecord);
-            var aggregatedStats = {};
-            var presentationChildren = presentationRecord.presentationChildren();
-            for (var i = 0; i < presentationChildren.length; ++i)
-                WebInspector.TimelineUIUtils.aggregateTimeForRecord(aggregatedStats, this._model, presentationChildren[i].record());
-            var idle = presentationRecord.endTime() - presentationRecord.startTime();
-            for (var category in aggregatedStats)
-                idle -= aggregatedStats[category];
-            aggregatedStats["idle"] = idle;
-
-            var contentHelper = new WebInspector.TimelineDetailsContentHelper(null, null);
-            var pieChart = WebInspector.TimelineUIUtils.generatePieChart(aggregatedStats);
-            var title = WebInspector.TimelineUIUtils.eventTitle(presentationRecord.record().traceEvent());
-            contentHelper.appendTextRow(WebInspector.UIString("Type"), title);
-            contentHelper.appendElementRow(WebInspector.UIString("Aggregated Time"), pieChart);
-            this._delegate.showInDetails(contentHelper.element);
-            return;
-        }
-        this._delegate.select(WebInspector.TimelineSelection.fromRecord(presentationRecord.record()));
-    },
-
-    /**
-     * @override
-     * @param {?WebInspector.TimelineSelection} selection
-     */
-    setSelection: function(selection)
-    {
-        if (!selection) {
-            this._innerSetSelectedRecord(null);
-            this._setSelectedFrame(null);
-            return;
-        }
-        if (selection.type() === WebInspector.TimelineSelection.Type.Record) {
-            var record = /** @type {!WebInspector.TimelineModel.Record} */ (selection.object());
-            this._innerSetSelectedRecord(this._presentationModel.toPresentationRecord(record));
-            this._setSelectedFrame(null);
-        } else if (selection.type() === WebInspector.TimelineSelection.Type.Frame) {
-            var frame = /** @type {!WebInspector.TimelineFrame} */ (selection.object());
-            this._innerSetSelectedRecord(null);
-            this._setSelectedFrame(frame);
-        }
-    },
-
-    /**
-     * @param {?WebInspector.TimelinePresentationModel.Record} presentationRecord
-     */
-    _innerSetSelectedRecord: function(presentationRecord)
-    {
-        if (presentationRecord === this._lastSelectedRecord)
-            return;
-
-        // Remove selection rendering.p
-        if (this._lastSelectedRecord) {
-            if (this._lastSelectedRecord.listRow())
-                this._lastSelectedRecord.listRow().renderAsSelected(false);
-            if (this._lastSelectedRecord.graphRow())
-                this._lastSelectedRecord.graphRow().renderAsSelected(false);
-        }
-
-        this._lastSelectedRecord = presentationRecord;
-        if (!presentationRecord)
-            return;
-
-        this._innerRevealRecord(presentationRecord);
-        if (presentationRecord.listRow())
-            presentationRecord.listRow().renderAsSelected(true);
-        if (presentationRecord.graphRow())
-            presentationRecord.graphRow().renderAsSelected(true);
-    },
-
-    /**
-     * @param {?WebInspector.TimelineFrame} frame
-     */
-    _setSelectedFrame: function(frame)
-    {
-        if (this._lastSelectedFrame === frame)
-            return;
-        var oldStripElement = this._lastSelectedFrame && this._frameStripByFrame.get(this._lastSelectedFrame);
-        if (oldStripElement)
-            oldStripElement.classList.remove("selected");
-        var newStripElement = frame && this._frameStripByFrame.get(frame);
-        if (newStripElement)
-            newStripElement.classList.add("selected");
-        this._lastSelectedFrame = frame;
-    },
-
-    /**
-     * @override
-     * @param {number} startTime
-     * @param {number} endTime
-     */
-    setWindowTimes: function(startTime, endTime)
-    {
-        this._windowStartTime = startTime;
-        this._windowEndTime = endTime;
-        this._presentationModel.setWindowTimes(startTime, endTime);
-        this._automaticallySizeWindow = false;
-        this._invalidateAndScheduleRefresh(false, true);
-        this._clearSelection();
-    },
-
-    /**
-     * @param {boolean} preserveBoundaries
-     * @param {boolean} userGesture
-     */
-    _scheduleRefresh: function(preserveBoundaries, userGesture)
-    {
-        this._closeRecordDetails();
-        this._boundariesAreValid &= preserveBoundaries;
-
-        if (!this.isShowing())
-            return;
-
-        if (preserveBoundaries || userGesture)
-            this._refresh();
-        else {
-            if (!this._refreshTimeout)
-                this._refreshTimeout = setTimeout(this._refresh.bind(this), 300);
-        }
-    },
-
-    _refresh: function()
-    {
-        if (this._refreshTimeout) {
-            clearTimeout(this._refreshTimeout);
-            delete this._refreshTimeout;
-        }
-        var windowStartTime = this._windowStartTime || this._model.minimumRecordTime();
-        var windowEndTime = this._windowEndTime || this._model.maximumRecordTime();
-        this._timelinePaddingLeft = this._expandOffset;
-        this._calculator.setWindow(windowStartTime, windowEndTime);
-        this._calculator.setDisplayWindow(this._graphRowsElementWidth, this._timelinePaddingLeft);
-
-        this._refreshRecords();
-        if (!this._boundariesAreValid) {
-            this._updateEventDividers();
-            if (this._frameContainer)
-                this._frameContainer.remove();
-            if (this._frameModel) {
-                var frames = this._frameModel.filteredFrames(windowStartTime, windowEndTime);
-                const maxFramesForFrameBars = 30;
-                if  (frames.length && frames.length < maxFramesForFrameBars) {
-                    this._timelineGrid.removeDividers();
-                    this._updateFrameBars(frames);
-                } else {
-                    this._timelineGrid.updateDividers(this._calculator);
-                }
-            } else
-                this._timelineGrid.updateDividers(this._calculator);
-            this._refreshAllUtilizationBars();
-        }
-        this._boundariesAreValid = true;
-    },
-
-    /**
-     * @param {!WebInspector.TimelinePresentationModel.Record} recordToReveal
-     */
-    _innerRevealRecord: function(recordToReveal)
-    {
-        var needRefresh = false;
-        // Expand all ancestors.
-        for (var parent = recordToReveal.presentationParent(); parent !== this._rootRecord(); parent = parent.presentationParent()) {
-            if (!parent.collapsed())
-                continue;
-            this._presentationModel.invalidateFilteredRecords();
-            parent.setCollapsed(false);
-            needRefresh = true;
-        }
-        var recordsInWindow = this._presentationModel.filteredRecords();
-        var index = recordsInWindow.indexOf(recordToReveal);
-        console.assert(index >= 0, "Failed to find record in window");
-        var itemOffset = index * WebInspector.TimelinePanel.rowHeight;
-        var visibleTop = this._scrollTop - WebInspector.TimelinePanel.headerHeight;
-        var visibleBottom = visibleTop + this._containerElementHeight - WebInspector.TimelinePanel.rowHeight;
-        if (itemOffset < visibleTop)
-            this._containerElement.scrollTop = itemOffset;
-        else if (itemOffset > visibleBottom)
-            this._containerElement.scrollTop = itemOffset - this._containerElementHeight + WebInspector.TimelinePanel.headerHeight + WebInspector.TimelinePanel.rowHeight;
-        else if (needRefresh)
-            this._refreshRecords();
-    },
-
-    _refreshRecords: function()
-    {
-        this._containerElementHeight = this._containerElement.clientHeight;
-        var recordsInWindow = this._presentationModel.filteredRecords();
-
-        // Calculate the visible area.
-        var visibleTop = this._scrollTop;
-        var visibleBottom = visibleTop + this._containerElementHeight;
-
-        var rowHeight = WebInspector.TimelinePanel.rowHeight;
-        var headerHeight = WebInspector.TimelinePanel.headerHeight;
-
-        // Convert visible area to visible indexes. Always include top-level record for a visible nested record.
-        var startIndex = Math.max(0, Math.min(Math.floor((visibleTop - headerHeight) / rowHeight), recordsInWindow.length - 1));
-        var endIndex = Math.min(recordsInWindow.length, Math.ceil(visibleBottom / rowHeight));
-        var lastVisibleLine = Math.max(0, Math.floor((visibleBottom - headerHeight) / rowHeight));
-        if (this._automaticallySizeWindow && recordsInWindow.length > lastVisibleLine) {
-            this._automaticallySizeWindow = false;
-            this._clearSelection();
-            // If we're at the top, always use real timeline start as a left window bound so that expansion arrow padding logic works.
-            var windowStartTime = startIndex ? recordsInWindow[startIndex].startTime() : this._model.minimumRecordTime();
-            var windowEndTime = recordsInWindow[Math.max(0, lastVisibleLine - 1)].endTime();
-            this._delegate.requestWindowTimes(windowStartTime, windowEndTime);
-            recordsInWindow = this._presentationModel.filteredRecords();
-            endIndex = Math.min(recordsInWindow.length, lastVisibleLine);
-        }
-
-        // Resize gaps first.
-        var topGapSize = startIndex * rowHeight;
-        this._topGapElement.style.height = topGapSize + "px";
-        this._bottomGapElement.style.height = (recordsInWindow.length - endIndex) * rowHeight + "px";
-        this._recordsView.element.style.height = Math.max(this._containerElementHeight, (endIndex - startIndex) * rowHeight) + "px";
-        this._timelineGrid.setScrollTop(this._scrollTop - topGapSize);
-        this._recordsView.onResize();
-
-        // Update visible rows.
-        var listRowElement = this._sidebarListElement.firstChild;
-        this._itemsGraphsElement.removeChild(this._graphRowsElement);
-        var graphRowElement = this._graphRowsElement.firstChild;
-        var scheduleRefreshCallback = this._invalidateAndScheduleRefresh.bind(this, true, true);
-        var selectRecordCallback = this._selectRecord.bind(this);
-        this._itemsGraphsElement.removeChild(this._expandElements);
-        this._expandElements.removeChildren();
-
-        for (var i = 0; i < endIndex; ++i) {
-            var record = recordsInWindow[i];
-
-            if (i < startIndex) {
-                var lastChildIndex = i + record.visibleChildrenCount();
-                if (lastChildIndex >= startIndex && lastChildIndex < endIndex) {
-                    var expandElement = new WebInspector.TimelineExpandableElement(this._expandElements);
-                    var positions = this._calculator.computeBarGraphWindowPosition(record);
-                    expandElement._update(record, i, topGapSize, positions.left - this._expandOffset, positions.width);
-                }
-            } else {
-                if (!listRowElement) {
-                    listRowElement = new WebInspector.TimelineRecordListRow(this._linkifier, this._model.target(), selectRecordCallback, scheduleRefreshCallback).element;
-                    this._sidebarListElement.appendChild(listRowElement);
-                }
-                if (!graphRowElement) {
-                    graphRowElement = new WebInspector.TimelineRecordGraphRow(this._itemsGraphsElement, selectRecordCallback, scheduleRefreshCallback).element;
-                    this._graphRowsElement.appendChild(graphRowElement);
-                }
-
-                listRowElement.row.update(record, visibleTop);
-                graphRowElement.row.update(record, this._calculator, this._expandOffset, i, topGapSize);
-                if (this._lastSelectedRecord === record) {
-                    listRowElement.row.renderAsSelected(true);
-                    graphRowElement.row.renderAsSelected(true);
-                }
-
-                listRowElement = listRowElement.nextSibling;
-                graphRowElement = graphRowElement.nextSibling;
-            }
-        }
-
-        // Remove extra rows.
-        while (listRowElement) {
-            var nextElement = listRowElement.nextSibling;
-            listRowElement.row.dispose();
-            listRowElement = nextElement;
-        }
-        while (graphRowElement) {
-            var nextElement = graphRowElement.nextSibling;
-            graphRowElement.row.dispose();
-            graphRowElement = nextElement;
-        }
-
-        this._itemsGraphsElement.appendChild(this._graphRowsElement);
-        this._itemsGraphsElement.appendChild(this._expandElements);
-        this._adjustScrollPosition(recordsInWindow.length * rowHeight + headerHeight);
-
-        return recordsInWindow.length;
-    },
-
-    _refreshAllUtilizationBars: function()
-    {
-        this._refreshUtilizationBars(WebInspector.UIString("CPU"), this._model.mainThreadTasks(), this._cpuBarsElement);
-        if (Runtime.experiments.isEnabled("gpuTimeline"))
-            this._refreshUtilizationBars(WebInspector.UIString("GPU"), this._model.gpuTasks(), this._gpuBarsElement);
-    },
-
-    /**
-     * @param {string} name
-     * @param {!Array.<!WebInspector.TimelineModel.Record>} tasks
-     * @param {?Element} container
-     */
-    _refreshUtilizationBars: function(name, tasks, container)
-    {
-        if (!container)
-            return;
-
-        const barOffset = 3;
-        const minGap = 3;
-
-        var minWidth = WebInspector.TimelineCalculator._minWidth;
-        var widthAdjustment = minWidth / 2;
-
-        var width = this._graphRowsElementWidth;
-        var boundarySpan = this._windowEndTime - this._windowStartTime;
-        var scale = boundarySpan / (width - minWidth - this._timelinePaddingLeft);
-        var startTime = (this._windowStartTime - this._timelinePaddingLeft * scale);
-        var endTime = startTime + width * scale;
-
-        /**
-         * @param {number} value
-         * @param {!WebInspector.TimelineModel.Record} task
-         * @return {number}
-         */
-        function compareEndTime(value, task)
-        {
-            return value < task.endTime() ? -1 : 1;
-        }
-
-        var taskIndex = insertionIndexForObjectInListSortedByFunction(startTime, tasks, compareEndTime);
-
-        var foreignStyle = "gpu-task-foreign";
-        var element = /** @type {?Element} */ (container.firstChild);
-        var lastElement;
-        var lastLeft;
-        var lastRight;
-
-        for (; taskIndex < tasks.length; ++taskIndex) {
-            var task = tasks[taskIndex];
-            if (task.startTime() > endTime)
-                break;
-
-            var data = task.traceEvent().args["data"];
-            var foreign = data && data["foreign"];
-            var left = Math.max(0, this._calculator.computePosition(task.startTime()) + barOffset - widthAdjustment);
-            var right = Math.min(width, this._calculator.computePosition(task.endTime() || 0) + barOffset + widthAdjustment);
-
-            if (lastElement) {
-                var gap = Math.floor(left) - Math.ceil(lastRight);
-                if (gap < minGap) {
-                    if (!foreign)
-                        lastElement.classList.remove(foreignStyle);
-                    lastRight = right;
-                    lastElement._tasksInfo.lastTaskIndex = taskIndex;
-                    continue;
-                }
-                lastElement.style.width = (lastRight - lastLeft) + "px";
-            }
-
-            if (!element)
-                element = container.createChild("div", "timeline-graph-bar");
-            element.style.left = left + "px";
-            element._tasksInfo = {name: name, tasks: tasks, firstTaskIndex: taskIndex, lastTaskIndex: taskIndex};
-            if (foreign)
-                element.classList.add(foreignStyle);
-            lastLeft = left;
-            lastRight = right;
-            lastElement = element;
-            element = /** @type {?Element} */ (element.nextSibling);
-        }
-
-        if (lastElement)
-            lastElement.style.width = (lastRight - lastLeft) + "px";
-
-        while (element) {
-            var nextElement = element.nextSibling;
-            element._tasksInfo = null;
-            container.removeChild(element);
-            element = nextElement;
-        }
-    },
-
-    _adjustScrollPosition: function(totalHeight)
-    {
-        // Prevent the container from being scrolled off the end.
-        if ((this._scrollTop + this._containerElementHeight) > totalHeight + 1)
-            this._containerElement.scrollTop = (totalHeight - this._containerElement.offsetHeight);
-    },
-
-    /**
-     * @param {!Element} element
-     * @param {!Event} event
-     * @return {!Element|!AnchorBox|undefined}
-     */
-    _getPopoverAnchor: function(element, event)
-    {
-        var anchor = element.enclosingNodeOrSelfWithClass("timeline-graph-bar");
-        if (anchor && anchor._tasksInfo)
-            return anchor;
-    },
-
-    _mouseLeave: function()
-    {
-        this._hideQuadHighlight();
-    },
-
-    /**
-     * @param {!Event} e
-     */
-    _mouseMove: function(e)
-    {
-        var rowElement = e.target.enclosingNodeOrSelfWithClass("timeline-tree-item");
-        if (!this._highlightQuad(rowElement))
-            this._hideQuadHighlight();
-
-        var taskBarElement = e.target.enclosingNodeOrSelfWithClass("timeline-graph-bar");
-        if (taskBarElement && taskBarElement._tasksInfo) {
-            var parentWidth = taskBarElement.parentElement.offsetWidth;
-            var offset = Math.max(0, taskBarElement.offsetLeft);
-            var width = taskBarElement.offsetWidth;
-            this._timelineGrid.showCurtains(offset / parentWidth, (offset + width) / parentWidth);
-        } else
-            this._timelineGrid.hideCurtains();
-    },
-
-    /**
-     * @param {!Event} event
-     */
-    _keyDown: function(event)
-    {
-        if (!this._lastSelectedRecord || event.shiftKey || event.metaKey || event.ctrlKey)
-            return;
-
-        var record = this._lastSelectedRecord;
-        var recordsInWindow = this._presentationModel.filteredRecords();
-        var index = recordsInWindow.indexOf(record);
-        var recordsInPage = Math.floor(this._containerElementHeight / WebInspector.TimelinePanel.rowHeight);
-        var rowHeight = WebInspector.TimelinePanel.rowHeight;
-
-        if (index === -1)
-            index = 0;
-
-        switch (event.keyIdentifier) {
-        case "Left":
-            if (record.presentationParent()) {
-                if ((!record.expandable() || record.collapsed()) && record.presentationParent() !== this._presentationModel.rootRecord()) {
-                    this._selectRecord(record.presentationParent());
-                } else {
-                    record.setCollapsed(true);
-                    this._invalidateAndScheduleRefresh(true, true);
-                }
-            }
-            event.consume(true);
-            break;
-        case "Up":
-            if (--index < 0)
-                break;
-            this._selectRecord(recordsInWindow[index]);
-            event.consume(true);
-            break;
-        case "Right":
-            if (record.expandable() && record.collapsed()) {
-                record.setCollapsed(false);
-                this._invalidateAndScheduleRefresh(true, true);
-            } else {
-                if (++index >= recordsInWindow.length)
-                    break;
-                this._selectRecord(recordsInWindow[index]);
-            }
-            event.consume(true);
-            break;
-        case "Down":
-            if (++index >= recordsInWindow.length)
-                break;
-            this._selectRecord(recordsInWindow[index]);
-            event.consume(true);
-            break;
-        case "PageUp":
-            index = Math.max(0, index - recordsInPage);
-            this._scrollTop = Math.max(0, this._scrollTop - recordsInPage * rowHeight);
-            this._containerElement.scrollTop = this._scrollTop;
-            this._selectRecord(recordsInWindow[index]);
-            event.consume(true);
-            break;
-        case "PageDown":
-            index = Math.min(recordsInWindow.length - 1, index + recordsInPage);
-            this._scrollTop = Math.min(this._containerElement.scrollHeight - this._containerElementHeight, this._scrollTop + recordsInPage * rowHeight);
-            this._containerElement.scrollTop = this._scrollTop;
-            this._selectRecord(recordsInWindow[index]);
-            event.consume(true);
-            break;
-        case "Home":
-            index = 0;
-            this._selectRecord(recordsInWindow[index]);
-            event.consume(true);
-            break;
-        case "End":
-            index = recordsInWindow.length - 1;
-            this._selectRecord(recordsInWindow[index]);
-            event.consume(true);
-            break;
-        }
-    },
-
-    /**
-     * @param {?Element} rowElement
-     * @return {boolean}
-     */
-    _highlightQuad: function(rowElement)
-    {
-        if (!rowElement || !rowElement.row)
-            return false;
-        var presentationRecord = rowElement.row._record;
-        if (presentationRecord.coalesced())
-            return false;
-        var record = presentationRecord.record();
-        if (this._highlightedQuadRecord === record)
-            return true;
-
-        var quad = record.traceEvent().highlightQuad;
-        var target = record.target();
-        if (!quad || !target)
-            return false;
-        this._highlightedQuadRecord = record;
-        target.domAgent().highlightQuad(quad, WebInspector.Color.PageHighlight.Content.toProtocolRGBA(), WebInspector.Color.PageHighlight.ContentOutline.toProtocolRGBA());
-        return true;
-    },
-
-    _hideQuadHighlight: function()
-    {
-        var target = this._highlightedQuadRecord ? this._highlightedQuadRecord.target() : null;
-        if (target)
-            target.domAgent().hideHighlight();
-
-        if (this._highlightedQuadRecord)
-            delete this._highlightedQuadRecord;
-    },
-
-    /**
-     * @param {!Element} anchor
-     * @param {!WebInspector.Popover} popover
-     */
-    _showPopover: function(anchor, popover)
-    {
-        if (!anchor._tasksInfo)
-            return;
-        popover.showForAnchor(WebInspector.TimelineUIUtils.generateMainThreadBarPopupContent(this._model, anchor._tasksInfo), anchor);
-    },
-
-    _closeRecordDetails: function()
-    {
-        this._popoverHelper.hidePopover();
-    },
-
-    /**
-     * @override
-     * @param {?WebInspector.TimelineModel.Record} record
-     * @param {string=} regex
-     * @param {boolean=} selectRecord
-     */
-    highlightSearchResult: function(record, regex, selectRecord)
-    {
-       if (this._highlightDomChanges)
-            WebInspector.revertDomChanges(this._highlightDomChanges);
-        this._highlightDomChanges = [];
-
-        var presentationRecord = this._presentationModel.toPresentationRecord(record);
-        if (!presentationRecord)
-            return;
-
-        if (selectRecord)
-            this._selectRecord(presentationRecord);
-
-        for (var element = this._sidebarListElement.firstChild; element; element = element.nextSibling) {
-            if (element.row._record === presentationRecord) {
-                element.row.highlight(regex, this._highlightDomChanges);
-                break;
-            }
-        }
-    },
-
-    /**
-     * @override
-     * @param {?WebInspector.TracingModel.Event} event
-     */
-    highlightEvent: function(event) { },
-
-    __proto__: WebInspector.VBox.prototype
-}
-
-/**
- * @constructor
- * @param {!WebInspector.TimelineModel} model
- * @implements {WebInspector.TimelineGrid.Calculator}
- */
-WebInspector.TimelineCalculator = function(model)
-{
-    this._model = model;
-}
-
-WebInspector.TimelineCalculator._minWidth = 5;
-
-WebInspector.TimelineCalculator.prototype = {
-    /**
-     * @override
-     * @return {number}
-     */
-    paddingLeft: function()
-    {
-        return this._paddingLeft;
-    },
-
-    /**
-     * @override
-     * @param {number} time
-     * @return {number}
-     */
-    computePosition: function(time)
-    {
-        return (time - this._minimumBoundary) / this.boundarySpan() * this._workingArea + this._paddingLeft;
-    },
-
-    /**
-     * @param {!WebInspector.TimelinePresentationModel.Record} record
-     * @return {!{start: number, end: number, cpuWidth: number}}
-     */
-    computeBarGraphPercentages: function(record)
-    {
-        var start = (record.startTime() - this._minimumBoundary) / this.boundarySpan() * 100;
-        var end = (record.startTime() + record.selfTime() - this._minimumBoundary) / this.boundarySpan() * 100;
-        var cpuWidth = (record.endTime() - record.startTime()) / this.boundarySpan() * 100;
-        return {start: start, end: end, cpuWidth: cpuWidth};
-    },
-
-    /**
-     * @param {!WebInspector.TimelinePresentationModel.Record} record
-     * @return {!{left: number, width: number, cpuWidth: number}}
-     */
-    computeBarGraphWindowPosition: function(record)
-    {
-        var percentages = this.computeBarGraphPercentages(record);
-        var widthAdjustment = 0;
-
-        var left = this.computePosition(record.startTime());
-        var width = (percentages.end - percentages.start) / 100 * this._workingArea;
-        if (width < WebInspector.TimelineCalculator._minWidth) {
-            widthAdjustment = WebInspector.TimelineCalculator._minWidth - width;
-            width = WebInspector.TimelineCalculator._minWidth;
-        }
-        var cpuWidth = percentages.cpuWidth / 100 * this._workingArea + widthAdjustment;
-        return {left: left, width: width, cpuWidth: cpuWidth};
-    },
-
-    setWindow: function(minimumBoundary, maximumBoundary)
-    {
-        this._minimumBoundary = minimumBoundary;
-        this._maximumBoundary = maximumBoundary;
-    },
-
-    /**
-     * @param {number} clientWidth
-     * @param {number=} paddingLeft
-     */
-    setDisplayWindow: function(clientWidth, paddingLeft)
-    {
-        this._paddingLeft = paddingLeft || 0;
-        this._workingArea = clientWidth - WebInspector.TimelineCalculator._minWidth - this._paddingLeft;
-    },
-
-    /**
-     * @override
-     * @param {number} value
-     * @param {number=} precision
-     * @return {string}
-     */
-    formatTime: function(value, precision)
-    {
-        return Number.preciseMillisToString(value - this.zeroTime(), precision);
-    },
-
-    /**
-     * @override
-     * @return {number}
-     */
-    maximumBoundary: function()
-    {
-        return this._maximumBoundary;
-    },
-
-    /**
-     * @override
-     * @return {number}
-     */
-    minimumBoundary: function()
-    {
-        return this._minimumBoundary;
-    },
-
-    /**
-     * @override
-     * @return {number}
-     */
-    zeroTime: function()
-    {
-        return this._model.minimumRecordTime();
-    },
-
-    /**
-     * @override
-     * @return {number}
-     */
-    boundarySpan: function()
-    {
-        return this._maximumBoundary - this._minimumBoundary;
-    }
-}
-
-/**
- * @constructor
- * @param {!WebInspector.Linkifier} linkifier
- * @param {function(!WebInspector.TimelinePresentationModel.Record)} selectRecord
- * @param {?WebInspector.Target} target
- * @param {function()} scheduleRefresh
- */
-WebInspector.TimelineRecordListRow = function(linkifier, target, selectRecord, scheduleRefresh)
-{
-    this.element = createElement("div");
-    this.element.row = this;
-    this.element.style.cursor = "pointer";
-    this.element.addEventListener("click", this._onClick.bind(this), false);
-    this.element.addEventListener("mouseover", this._onMouseOver.bind(this), false);
-    this.element.addEventListener("mouseleave", this._onMouseLeave.bind(this), false);
-    this._linkifier = linkifier;
-
-    // Warning is float right block, it goes first.
-    this._warningElement = this.element.createChild("div", "timeline-tree-item-warning hidden");
-
-    this._expandArrowElement = this.element.createChild("div", "timeline-tree-item-expand-arrow");
-    this._expandArrowElement.addEventListener("click", this._onExpandClick.bind(this), false);
-    this.element.createChild("span", "timeline-tree-icon");
-    this._typeElement = this.element.createChild("span", "type");
-
-    this._dataElement = this.element.createChild("span", "data dimmed");
-    this._scheduleRefresh = scheduleRefresh;
-    this._selectRecord = selectRecord;
-    this._target = target;
-}
-
-WebInspector.TimelineRecordListRow.prototype = {
-    /**
-     * @param {!WebInspector.TimelinePresentationModel.Record} presentationRecord
-     * @param {number} offset
-     */
-    update: function(presentationRecord, offset)
-    {
-        this._record = presentationRecord;
-        var record = presentationRecord.record();
-        this._offset = offset;
-
-        this.element.className = "timeline-tree-item timeline-category-" + WebInspector.TimelineUIUtils.categoryForRecord(record).name;
-        var paddingLeft = 5;
-        var step = -3;
-        for (var currentRecord = presentationRecord.presentationParent() ? presentationRecord.presentationParent().presentationParent() : null; currentRecord; currentRecord = currentRecord.presentationParent())
-            paddingLeft += 12 / (Math.max(1, step++));
-        this.element.style.paddingLeft = paddingLeft + "px";
-        if (record.thread() !== WebInspector.TimelineModel.MainThreadName)
-            this.element.classList.add("background");
-
-        this._typeElement.textContent = WebInspector.TimelineUIUtils.eventTitle(record.traceEvent());
-
-        if (this._dataElement.firstChild)
-            this._dataElement.removeChildren();
-
-        this._warningElement.classList.toggle("hidden", !presentationRecord.hasWarnings() && !presentationRecord.childHasWarnings());
-        this._warningElement.classList.toggle("timeline-tree-item-child-warning", presentationRecord.childHasWarnings() && !presentationRecord.hasWarnings());
-
-        if (presentationRecord.coalesced()) {
-            this._dataElement.createTextChild(WebInspector.UIString("× %d", presentationRecord.presentationChildren().length));
-        } else {
-            var detailsNode = WebInspector.TimelineUIUtils.buildDetailsNodeForTraceEvent(record.traceEvent(), this._target, this._linkifier);
-            if (detailsNode) {
-                this._dataElement.createTextChild("(");
-                this._dataElement.appendChild(detailsNode);
-                this._dataElement.createTextChild(")");
-            }
-        }
-
-        this._expandArrowElement.classList.toggle("parent", presentationRecord.expandable());
-        this._expandArrowElement.classList.toggle("expanded", !!presentationRecord.visibleChildrenCount());
-        this._record.setListRow(this);
-    },
-
-    highlight: function(regExp, domChanges)
-    {
-        var matchInfo = this.element.textContent.match(regExp);
-        if (matchInfo)
-            WebInspector.highlightSearchResult(this.element, matchInfo.index, matchInfo[0].length, domChanges);
-    },
-
-    dispose: function()
-    {
-        this.element.remove();
-    },
-
-    /**
-     * @param {!Event} event
-     */
-    _onExpandClick: function(event)
-    {
-        this._record.setCollapsed(!this._record.collapsed());
-        this._scheduleRefresh();
-        event.consume(true);
-    },
-
-    /**
-     * @param {!Event} event
-     */
-    _onClick: function(event)
-    {
-        this._selectRecord(this._record);
-    },
-
-    /**
-     * @param {boolean} selected
-     */
-    renderAsSelected: function(selected)
-    {
-        this.element.classList.toggle("selected", selected);
-    },
-
-    /**
-     * @param {!Event} event
-     */
-    _onMouseOver: function(event)
-    {
-        this.element.classList.add("hovered");
-        if (this._record.graphRow())
-            this._record.graphRow().element.classList.add("hovered");
-    },
-
-    /**
-     * @param {!Event} event
-     */
-    _onMouseLeave: function(event)
-    {
-        this.element.classList.remove("hovered");
-        if (this._record.graphRow())
-            this._record.graphRow().element.classList.remove("hovered");
-    }
-}
-
-/**
- * @constructor
- * @param {!Element} graphContainer
- * @param {function(!WebInspector.TimelinePresentationModel.Record)} selectRecord
- * @param {function()} scheduleRefresh
- */
-WebInspector.TimelineRecordGraphRow = function(graphContainer, selectRecord, scheduleRefresh)
-{
-    this.element = createElement("div");
-    this.element.row = this;
-    this.element.addEventListener("mouseover", this._onMouseOver.bind(this), false);
-    this.element.addEventListener("mouseleave", this._onMouseLeave.bind(this), false);
-    this.element.addEventListener("click", this._onClick.bind(this), false);
-
-    this._barAreaElement = this.element.createChild("div", "timeline-graph-bar-area");
-
-    this._barCpuElement = this._barAreaElement.createChild("div", "timeline-graph-bar cpu");
-    this._barCpuElement.row = this;
-
-    this._barElement = this._barAreaElement.createChild("div", "timeline-graph-bar");
-    this._barElement.row = this;
-
-    this._expandElement = new WebInspector.TimelineExpandableElement(graphContainer);
-
-    this._selectRecord = selectRecord;
-    this._scheduleRefresh = scheduleRefresh;
-}
-
-WebInspector.TimelineRecordGraphRow.prototype = {
-    /**
-     * @param {!WebInspector.TimelinePresentationModel.Record} presentationRecord
-     * @param {!WebInspector.TimelineCalculator} calculator
-     * @param {number} expandOffset
-     * @param {number} index
-     * @param {number} topGapSize
-     */
-    update: function(presentationRecord, calculator, expandOffset, index, topGapSize)
-    {
-        this._record = presentationRecord;
-        var record = presentationRecord.record();
-        this.element.className = "timeline-graph-side timeline-category-" + WebInspector.TimelineUIUtils.categoryForRecord(record).name;
-        if (record.thread() !== WebInspector.TimelineModel.MainThreadName)
-            this.element.classList.add("background");
-
-        var barPosition = calculator.computeBarGraphWindowPosition(presentationRecord);
-        this._barElement.style.left = barPosition.left + "px";
-        this._barElement.style.width = barPosition.width + "px";
-        this._barCpuElement.style.left = barPosition.left + "px";
-        this._barCpuElement.style.width = barPosition.cpuWidth + "px";
-        this._expandElement._update(presentationRecord, index, topGapSize, barPosition.left - expandOffset, barPosition.width);
-        this._record.setGraphRow(this);
-    },
-
-    /**
-     * @param {!Event} event
-     */
-    _onClick: function(event)
-    {
-        // check if we click arrow and expand if yes.
-        if (this._expandElement._arrow.containsEventPoint(event))
-            this._expand();
-        this._selectRecord(this._record);
-    },
-
-    /**
-     * @param {boolean} selected
-     */
-    renderAsSelected: function(selected)
-    {
-        this.element.classList.toggle("selected", selected);
-    },
-
-    _expand: function()
-    {
-        this._record.setCollapsed(!this._record.collapsed());
-        this._scheduleRefresh();
-    },
-
-    /**
-     * @param {!Event} event
-     */
-    _onMouseOver: function(event)
-    {
-        this.element.classList.add("hovered");
-        if (this._record.listRow())
-            this._record.listRow().element.classList.add("hovered");
-    },
-
-    /**
-     * @param {!Event} event
-     */
-    _onMouseLeave: function(event)
-    {
-        this.element.classList.remove("hovered");
-        if (this._record.listRow())
-            this._record.listRow().element.classList.remove("hovered");
-    },
-
-    dispose: function()
-    {
-        this.element.remove();
-        this._expandElement._dispose();
-    }
-}
-
-/**
- * @constructor
- */
-WebInspector.TimelineExpandableElement = function(container)
-{
-    this._element = container.createChild("div", "timeline-expandable");
-    this._element.createChild("div", "timeline-expandable-left");
-    this._arrow = this._element.createChild("div", "timeline-expandable-arrow");
-}
-
-WebInspector.TimelineExpandableElement.prototype = {
-    /**
-     * @param {!WebInspector.TimelinePresentationModel.Record} record
-     * @param {number} index
-     * @param {number} topGapSize
-     * @param {number} left
-     * @param {number} width
-     */
-    _update: function(record, index, topGapSize, left, width)
-    {
-        const rowHeight = WebInspector.TimelinePanel.rowHeight;
-        if (record.visibleChildrenCount() || record.expandable()) {
-            this._element.style.top = (index * rowHeight - topGapSize) + "px";
-            this._element.style.left = left + "px";
-            this._element.style.width = Math.max(12, width + 25) + "px";
-            if (!record.collapsed()) {
-                this._element.style.height = (record.visibleChildrenCount() + 1) * rowHeight + "px";
-                this._element.classList.add("timeline-expandable-expanded");
-                this._element.classList.remove("timeline-expandable-collapsed");
-            } else {
-                this._element.style.height = rowHeight + "px";
-                this._element.classList.add("timeline-expandable-collapsed");
-                this._element.classList.remove("timeline-expandable-expanded");
-            }
-            this._element.classList.remove("hidden");
-        } else {
-            this._element.classList.add("hidden");
-        }
-    },
-
-    _dispose: function()
-    {
-        this._element.remove();
-    }
-}
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/module.json b/third_party/WebKit/Source/devtools/front_end/timeline/module.json
index 7977911..980a766a 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/module.json
@@ -108,13 +108,11 @@
         "MemoryCountersGraph.js",
         "TimelineModel.js",
         "TimelineJSProfile.js",
-        "TimelinePresentationModel.js",
         "TimelineFrameModel.js",
         "TimelineEventOverview.js",
         "TimelineFlameChart.js",
         "TimelineTreeView.js",
         "TimelineUIUtils.js",
-        "TimelineView.js",
         "TimelineLayersView.js",
         "TimelinePaintProfilerView.js",
         "TransformController.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
index 6942fefa..cb5e126 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
@@ -63,20 +63,6 @@
     pointer-events: none;
 }
 
-.timeline-records-title, .timeline-records-list {
-    background-color: #f3f3f3;
-}
-
-.timeline-records-title {
-    padding: 3px 3px 3px 5px;
-    flex: 0 0 19px;
-    color: rgb(92, 110, 129); text-shadow: rgba(255, 255, 255, 0.75) 0 1px 0;
-}
-
-.timeline-records-list {
-    flex: auto;
-}
-
 #timeline-overview-grid {
     background-color: rgb(255, 255, 255);
 }
@@ -94,21 +80,10 @@
     top: 1px;
 }
 
-#timeline-container {
-    border-right: 0 none transparent;
-    overflow-y: scroll;
-    overflow-x: hidden;
-}
-
 .timeline-details-split {
     flex: auto;
 }
 
-.timeline-view {
-    flex: auto;
-    overflow: auto;
-}
-
 .timeline-view-stack {
     flex: auto;
     display: flex;
@@ -119,157 +94,10 @@
     color: inherit;
 }
 
-.timeline-tree-item {
-    height: 18px;
-    line-height: 15px;
-    padding-right: 5px;
-    padding-left: 5px;
-    padding-top: 2px;
-    white-space: nowrap;
-    text-overflow: ellipsis;
-    overflow: hidden;
-}
-
-.timeline-tree-item.selected {
-    background-color: rgb(56, 121, 217) !important;
-    color: white;
-}
-
-.timeline-tree-item.hovered:not(.selected),
 .timeline-graph-side.hovered {
     background-color: rgba(0, 0, 0, 0.05) !important;
 }
 
-.timeline-expandable {
-    position: absolute;
-    border-left: 1px solid rgb(163, 163, 163);
-    pointer-events: none;
-}
-
-.timeline-expandable-left {
-    position: absolute;
-    top: 0;
-    bottom: 0;
-    left: 0;
-    width: 3px;
-    border-top: 1px solid rgb(163, 163, 163);
-    border-bottom: 1px solid rgb(163, 163, 163);
-}
-
-.timeline-tree-item-expand-arrow {
-    display: inline-block;
-    -webkit-user-select: none;
-    -webkit-mask-image: url(Images/toolbarButtonGlyphs.png);
-    -webkit-mask-size: 352px 168px;
-    width: 10px;
-    height: 10px;
-    content: "";
-    background-color: rgb(110, 110, 110);
-    position: relative;
-    top: -1px;
-    left: -1px;
-}
-
-@media (-webkit-min-device-pixel-ratio: 1.5) {
-.timeline-tree-item-expand-arrow {
-    -webkit-mask-image: url(Images/toolbarButtonGlyphs_2x.png);
-}
-} /* media */
-
-.timeline-tree-item-expand-arrow.parent {
-    -webkit-mask-position: -4px -96px;
-}
-
-.timeline-tree-item-expand-arrow.parent.expanded {
-    -webkit-mask-position: -20px -96px;
-}
-
-.timeline-expandable-arrow {
-    background-image: url(Images/toolbarButtonGlyphs.png);
-    background-size: 352px 168px;
-    opacity: 0.5;
-    width: 10px;
-    height: 10px;
-    position: relative;
-    top: 3px;
-    left: 2px;
-}
-
-@media (-webkit-min-device-pixel-ratio: 1.5) {
-.timeline-expandable-arrow {
-    background-image: url(Images/toolbarButtonGlyphs_2x.png);
-}
-} /* media */
-
-.timeline-expandable-collapsed .timeline-expandable-arrow {
-    background-position: -4px -96px;
-}
-
-.timeline-expandable-expanded .timeline-expandable-arrow {
-    background-position: -20px -96px;
-}
-
-.timeline-tree-item .type {
-    padding-left: 5px;
-}
-
-.timeline-tree-item .count {
-    font-weight: bold;
-}
-
-.timeline-tree-item .timeline-tree-icon {
-    position: relative;
-    top: -1px;
-    left: 1px;
-    width: 7px;
-    height: 7px;
-    border-radius: 1px;
-    border-style: solid;
-    border-width: 1px;
-    display: inline-block;
-}
-
-.timeline-tree-item.background .timeline-tree-icon {
-    background: none !important;
-}
-
-.timeline-tree-item-warning {
-    display: block;
-    background-image: url(Images/toolbarButtonGlyphs.png);
-    background-size: 352px 168px;
-    width: 10px;
-    height: 10px;
-    float: right;
-    background-position: -202px -107px;
-    position: relative;
-    top: 2px;
-}
-
-.timeline-tree-item-child-warning {
-    opacity: 0.6;
-}
-
-@media (-webkit-min-device-pixel-ratio: 1.5) {
-.timeline-tree-item-warning {
-    background-image: url(Images/toolbarButtonGlyphs_2x.png);
-}
-} /* media */
-
-.timeline-tree-item .data.dimmed {
-    color: rgba(0, 0, 0, 0.7);
-    pointer-events: none;
-    padding-left: 4px;
-}
-
-.timeline-tree-item.selected .data.dimmed {
-    color: rgba(255, 255, 255, 0.8);
-    pointer-events: auto;
-}
-
-.timeline-tree-item.selected .timeline-tree-item-expand-arrow {
-    background-color: white;
-}
-
 .timeline.panel .status-pane-container {
     z-index: 1000;
     pointer-events: none;
@@ -370,51 +198,6 @@
     top: 20px;
 }
 
-.timeline-graph-side {
-    position: relative;
-    height: 18px;
-    padding: 0 5px;
-    white-space: nowrap;
-    margin-top: 0;
-    border-top: 1px solid transparent;
-    overflow: hidden;
-}
-
-.timeline-graph-side.selected {
-    background-color: rgba(56, 121, 217, 0.1) !important;
-}
-
-.timeline-graph-bar-area {
-    position: absolute;
-    top: 0;
-    bottom: 0;
-    right: 0;
-    left: 3px;
-    pointer-events: none;
-}
-
-.timeline-graph-bar {
-    position: absolute;
-    top: -1px;
-    bottom: 0;
-    margin: auto -2px;
-    height: 10px;
-    min-width: 5px;
-    z-index: 180;
-    pointer-events: visibleFill;
-    border-radius: 1px;
-    border: 1px solid;
-}
-
-.timeline-graph-bar.cpu {
-    opacity: 0.7;
-}
-
-.timeline-graph-side.background .timeline-graph-bar {
-    background: transparent !important;
-    border-width: 2px;
-}
-
 .timeline-aggregated-legend-title {
     display: inline-block;
 }
@@ -510,115 +293,6 @@
     line-height: 18px;
 }
 
-.timeline .resources-event-divider {
-    height: 20px;
-    width: 6px;
-    pointer-events: auto;
-    margin-left: -2px;
-}
-
-.timeline .resources-event-divider::before {
-    height: 19px;
-    width: 2px;
-    margin: 0 2px;
-    background-color: rgb(163, 109, 0);
-    bottom: auto;
-    content: "";
-    display: block;
-}
-
-.timeline .resources-event-divider:hover::before {
-    width: 4px;
-    margin: 0 1px;
-}
-
-.timeline .resources-event-divider.timeline-frame-divider::before {
-    display: none;
-}
-
-.timeline .resources-event-divider.resources-red-divider::before {
-    background-color: rgb(255, 0, 0);
-}
-
-.timeline .resources-event-divider.resources-blue-divider::before {
-    background-color: rgb(0, 0, 255);
-}
-
-.timeline .resources-event-divider.resources-orange-divider::before {
-    background-color: rgb(255, 178, 23);
-}
-
-.timeline .resources-event-divider.resources-green-divider::before {
-    background-color: rgb(0, 130, 0);
-}
-
-.resources-divider:last-child {
-    border-color: transparent;
-}
-
-.timeline .resources-event-divider.timeline-frame-divider {
-    background-color: rgba(180, 180, 180, 0.8);
-    border-style: none;
-    width: 1px;
-    height: 100%;
-    pointer-events: none;
-}
-
-.timeline-frame-container {
-    height: 19px;
-    overflow: hidden;
-    background-color: rgb(220, 220, 220);
-    opacity: 0.8;
-    color: black;
-    text-align: center;
-    z-index: 220;
-    pointer-events: auto;
-}
-
-.timeline-frame-strip {
-    position: absolute;
-    height: 19px;
-    padding-top: 3px;
-}
-
-.timeline-frame-strip.selected {
-    background-color: rgb(56, 121, 217);
-    color: white;
-}
-
-#timeline-graph-records-header {
-    pointer-events: none;
-    height: 19px;
-    padding: 1px 0;
-    justify-content: center;
-}
-
-.timeline-utilization-strip {
-    z-index: 250;
-    overflow: hidden;
-    flex: 0 1 12px;
-    position: relative;
-    height: 9px;
-}
-
-.timeline-utilization-strip .timeline-graph-bar {
-    border-color: rgb(192, 192, 192);
-    background-color: rgba(0, 0, 0, 0.1);
-    margin: 1.5px auto;
-    height: auto;
-}
-
-.timeline-utilization-strip.gpu .timeline-graph-bar {
-    background-color: #00a;
-    border: none;
-    opacity: 0.3;
-    min-width: 0;
-}
-
-.timeline-utilization-strip.gpu .timeline-graph-bar.gpu-task-foreign {
-    background-color: #aaa;
-}
-
 .image-preview-container {
     background: transparent;
     text-align: left;
diff --git a/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js b/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
index 8b037012..aad3ca8 100644
--- a/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
+++ b/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
@@ -235,6 +235,14 @@
     },
 
     /**
+     * @return {!Promise.<?string>}
+     */
+    requestContentPromise: function()
+    {
+        return new Promise(succ => this.requestContent(succ));
+    },
+
+    /**
      * @param {function()} callback
      */
     _pushCheckContentUpdatedCallback: function(callback)
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp
index 06f2ab86..95924e7f5 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp
@@ -28,7 +28,7 @@
 
 NameToAssignedNumberMap* getAssignedNumberToServiceNameMap()
 {
-    AtomicallyInitializedStaticReference(NameToAssignedNumberMap, servicesMap, []() {
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(NameToAssignedNumberMap, servicesMap, []() {
         // https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx
         NameToAssignedNumberMap* services = new NameToAssignedNumberMap();
         services->add("alert_notification", 0x1811);
@@ -71,7 +71,7 @@
 
 NameToAssignedNumberMap* getAssignedNumberForCharacteristicNameMap()
 {
-    AtomicallyInitializedStaticReference(NameToAssignedNumberMap, characteristicsMap, []() {
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(NameToAssignedNumberMap, characteristicsMap, []() {
         // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicsHome.aspx
         NameToAssignedNumberMap* characteristics = new NameToAssignedNumberMap();
         characteristics->add("aerobic_heart_rate_lower_limit", 0x2A7E);
@@ -243,7 +243,7 @@
 
 NameToAssignedNumberMap* getAssignedNumberForDescriptorNameMap()
 {
-    AtomicallyInitializedStaticReference(NameToAssignedNumberMap, descriptorsMap, []() {
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(NameToAssignedNumberMap, descriptorsMap, []() {
         // https://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorsHomePage.aspx
         NameToAssignedNumberMap* descriptors = new NameToAssignedNumberMap();
         descriptors->add("gatt.characteristic_extended_properties", 0x2900);
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
index 7976efe..5d5cecb 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
@@ -1308,26 +1308,20 @@
     SkPaint imagePaint = *paint;
 
     if (paint->getImageFilter()) {
-        SkMatrix ctm = c->getTotalMatrix();
         SkMatrix invCtm;
-        if (!ctm.invert(&invCtm)) {
+        if (!c->getTotalMatrix().invert(&invCtm)) {
             // There is an earlier check for invertibility, but the arithmetic
             // in AffineTransform is not exactly identical, so it is possible
             // for SkMatrix to find the transform to be non-invertible at this stage.
             // crbug.com/504687
             return;
         }
-        c->save();
-        c->concat(invCtm);
         SkRect bounds = dstRect;
-        ctm.mapRect(&bounds);
-        SkRect filteredBounds;
-        paint->getImageFilter()->computeFastBounds(bounds, &filteredBounds);
         SkPaint layerPaint;
         layerPaint.setXfermode(paint->getXfermode());
-        layerPaint.setImageFilter(paint->getImageFilter());
-        c->saveLayer(&filteredBounds, &layerPaint);
-        c->concat(ctm);
+        SkAutoTUnref<SkImageFilter> localFilter(paint->getImageFilter()->newWithLocalMatrix(invCtm));
+        layerPaint.setImageFilter(localFilter);
+        c->saveLayer(&bounds, &layerPaint);
         imagePaint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
         imagePaint.setImageFilter(nullptr);
     }
diff --git a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp
index 9bdd80eb..16018306 100644
--- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp
+++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp
@@ -30,7 +30,7 @@
 public:
     static CompositorWorkerSharedState& instance()
     {
-        AtomicallyInitializedStaticReference(CompositorWorkerSharedState, compositorWorkerSharedState, (new CompositorWorkerSharedState()));
+        DEFINE_STATIC_LOCAL_THREAD_SAFE(CompositorWorkerSharedState, compositorWorkerSharedState, (new CompositorWorkerSharedState()));
         return compositorWorkerSharedState;
     }
 
diff --git a/third_party/WebKit/Source/modules/fetch/ReadableStreamDataConsumerHandle.cpp b/third_party/WebKit/Source/modules/fetch/ReadableStreamDataConsumerHandle.cpp
deleted file mode 100644
index c3e2c77..0000000
--- a/third_party/WebKit/Source/modules/fetch/ReadableStreamDataConsumerHandle.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "config.h"
-#include "modules/fetch/ReadableStreamDataConsumerHandle.h"
-
-#include "bindings/core/v8/ExceptionState.h"
-#include "bindings/core/v8/ReadableStreamOperations.h"
-#include "bindings/core/v8/ScriptFunction.h"
-#include "bindings/core/v8/ScriptState.h"
-#include "bindings/core/v8/ScriptValue.h"
-#include "bindings/core/v8/V8BindingMacros.h"
-#include "bindings/core/v8/V8IteratorResultValue.h"
-#include "bindings/core/v8/V8RecursionScope.h"
-#include "bindings/core/v8/V8Uint8Array.h"
-#include "core/dom/DOMTypedArray.h"
-#include "public/platform/Platform.h"
-#include "public/platform/WebTaskRunner.h"
-#include "public/platform/WebThread.h"
-#include "public/platform/WebTraceLocation.h"
-#include "wtf/Assertions.h"
-#include "wtf/Functional.h"
-#include "wtf/RefCounted.h"
-#include <algorithm>
-#include <string.h>
-#include <v8.h>
-
-namespace blink {
-
-using Result = WebDataConsumerHandle::Result;
-using Flags = WebDataConsumerHandle::Flags;
-
-// This context is not yet thread-safe.
-class ReadableStreamDataConsumerHandle::ReadingContext final : public RefCounted<ReadingContext> {
-    WTF_MAKE_NONCOPYABLE(ReadingContext);
-public:
-    class OnFulfilled final : public ScriptFunction {
-    public:
-        static v8::Local<v8::Function> createFunction(ScriptState* scriptState, PassRefPtr<ReadingContext> context)
-        {
-            return (new OnFulfilled(scriptState, context))->bindToV8Function();
-        }
-
-        ScriptValue call(ScriptValue v) override
-        {
-            bool done;
-            v8::Local<v8::Value> item = v.v8Value();
-            ASSERT(item->IsObject());
-            v8::Local<v8::Value> value = v8CallOrCrash(v8UnpackIteratorResult(v.scriptState(), item.As<v8::Object>(), &done));
-            if (done) {
-                m_readingContext->onReadDone();
-                return v;
-            }
-            if (!V8Uint8Array::hasInstance(value, v.isolate())) {
-                m_readingContext->onRejected();
-                return ScriptValue();
-            }
-            m_readingContext->onRead(V8Uint8Array::toImpl(value.As<v8::Object>()));
-            return v;
-        }
-
-    private:
-        OnFulfilled(ScriptState* scriptState, PassRefPtr<ReadingContext> context)
-            : ScriptFunction(scriptState), m_readingContext(context) {}
-
-        RefPtr<ReadingContext> m_readingContext;
-    };
-
-    class OnRejected final : public ScriptFunction {
-    public:
-        static v8::Local<v8::Function> createFunction(ScriptState* scriptState, PassRefPtr<ReadingContext> context)
-        {
-            return (new OnRejected(scriptState, context))->bindToV8Function();
-        }
-
-        ScriptValue call(ScriptValue v) override
-        {
-            m_readingContext->onRejected();
-            return v;
-        }
-
-    private:
-        OnRejected(ScriptState* scriptState, PassRefPtr<ReadingContext> context)
-            : ScriptFunction(scriptState), m_readingContext(context) {}
-
-        RefPtr<ReadingContext> m_readingContext;
-    };
-
-    class ReaderImpl final : public FetchDataConsumerHandle::Reader {
-    public:
-        ReaderImpl(PassRefPtr<ReadingContext> context, Client* client)
-            : m_readingContext(context)
-        {
-            m_readingContext->attachReader(client);
-        }
-        ~ReaderImpl() override
-        {
-            m_readingContext->detachReader();
-        }
-
-        Result read(void* buffer, size_t size, Flags flags, size_t* readSize) override
-        {
-            *readSize = 0;
-            const void* src = nullptr;
-            size_t available;
-            Result r = beginRead(&src, flags, &available);
-            if (r != WebDataConsumerHandle::Ok)
-                return r;
-            *readSize = std::min(available, size);
-            memcpy(buffer, src, *readSize);
-            return endRead(*readSize);
-        }
-
-        Result beginRead(const void** buffer, Flags, size_t* available) override
-        {
-            return m_readingContext->beginRead(buffer, available);
-        }
-
-        Result endRead(size_t readSize) override
-        {
-            return m_readingContext->endRead(readSize);
-        }
-
-    private:
-        RefPtr<ReadingContext> m_readingContext;
-    };
-
-    static PassRefPtr<ReadingContext> create(ScriptState* scriptState, v8::Local<v8::Value> stream)
-    {
-        return adoptRef(new ReadingContext(scriptState, stream));
-    }
-
-    void attachReader(WebDataConsumerHandle::Client* client)
-    {
-        m_client = client;
-        notifyLater();
-    }
-
-    void detachReader()
-    {
-        m_client = nullptr;
-    }
-
-    Result beginRead(const void** buffer, size_t* available)
-    {
-        *buffer = nullptr;
-        *available = 0;
-        if (m_hasError)
-            return WebDataConsumerHandle::UnexpectedError;
-        if (m_isDone)
-            return WebDataConsumerHandle::Done;
-
-        if (m_pendingBuffer) {
-            ASSERT(m_pendingOffset < m_pendingBuffer->length());
-            *buffer = m_pendingBuffer->data() + m_pendingOffset;
-            *available = m_pendingBuffer->length() - m_pendingOffset;
-            return WebDataConsumerHandle::Ok;
-        }
-        ASSERT(!m_reader.isEmpty());
-        m_isInRecursion = true;
-        if (!m_isReading) {
-            m_isReading = true;
-            ScriptState::Scope scope(m_reader.scriptState());
-            V8RecursionScope recursionScope(m_reader.isolate());
-            ReadableStreamOperations::read(m_reader.scriptState(), m_reader.v8Value()).then(
-                OnFulfilled::createFunction(m_reader.scriptState(), this),
-                OnRejected::createFunction(m_reader.scriptState(), this));
-            // Note: Microtasks may run here.
-        }
-        m_isInRecursion = false;
-        return WebDataConsumerHandle::ShouldWait;
-    }
-
-    Result endRead(size_t readSize)
-    {
-        ASSERT(m_pendingBuffer);
-        ASSERT(m_pendingOffset + readSize <= m_pendingBuffer->length());
-        m_pendingOffset += readSize;
-        if (m_pendingOffset == m_pendingBuffer->length()) {
-            m_pendingBuffer = nullptr;
-            m_pendingOffset = 0;
-        }
-        return WebDataConsumerHandle::Ok;
-    }
-
-    void onRead(DOMUint8Array* buffer)
-    {
-        ASSERT(m_isReading);
-        ASSERT(buffer);
-        ASSERT(!m_pendingBuffer);
-        ASSERT(!m_pendingOffset);
-        m_isReading = false;
-        m_pendingBuffer = buffer;
-        notify();
-    }
-
-    void onReadDone()
-    {
-        ASSERT(m_isReading);
-        ASSERT(!m_pendingBuffer);
-        m_isReading = false;
-        m_isDone = true;
-        m_reader.clear();
-        notify();
-    }
-
-    void onRejected()
-    {
-        ASSERT(m_isReading);
-        ASSERT(!m_pendingBuffer);
-        m_hasError = true;
-        m_isReading = false;
-        m_reader.clear();
-        notify();
-    }
-
-    void notify()
-    {
-        if (!m_client)
-            return;
-        if (m_isInRecursion) {
-            notifyLater();
-            return;
-        }
-        m_client->didGetReadable();
-    }
-
-    void notifyLater()
-    {
-        ASSERT(m_client);
-        Platform::current()->currentThread()->taskRunner()->postTask(BLINK_FROM_HERE, bind(&ReadingContext::notify, PassRefPtr<ReadingContext>(this)));
-    }
-
-private:
-    ReadingContext(ScriptState* scriptState, v8::Local<v8::Value> stream)
-        : m_client(nullptr)
-        , m_pendingOffset(0)
-        , m_isReading(false)
-        , m_isDone(false)
-        , m_hasError(false)
-        , m_isInRecursion(false)
-    {
-        if (!ReadableStreamOperations::isLocked(scriptState, stream)) {
-            // Here the stream implementation must not throw an exception.
-            NonThrowableExceptionState es;
-            m_reader = ReadableStreamOperations::getReader(scriptState, stream, es);
-        }
-        m_hasError = m_reader.isEmpty();
-    }
-
-    // This ScriptValue is leaky because it stores a strong reference to a
-    // JavaScript object.
-    // TODO(yhirano): Fix it.
-    //
-    // Holding a ScriptValue here is safe in terms of cross-world wrapper
-    // leakage because we read only Uint8Array chunks from the reader.
-    ScriptValue m_reader;
-    WebDataConsumerHandle::Client* m_client;
-    RefPtr<DOMUint8Array> m_pendingBuffer;
-    size_t m_pendingOffset;
-    bool m_isReading;
-    bool m_isDone;
-    bool m_hasError;
-    bool m_isInRecursion;
-};
-
-ReadableStreamDataConsumerHandle::ReadableStreamDataConsumerHandle(ScriptState* scriptState, v8::Local<v8::Value> stream)
-    : m_readingContext(ReadingContext::create(scriptState, stream))
-{
-}
-ReadableStreamDataConsumerHandle::~ReadableStreamDataConsumerHandle() = default;
-
-FetchDataConsumerHandle::Reader* ReadableStreamDataConsumerHandle::obtainReaderInternal(Client* client)
-{
-    return new ReadingContext::ReaderImpl(m_readingContext, client);
-}
-
-} // namespace blink
-
diff --git a/third_party/WebKit/Source/modules/fetch/ReadableStreamDataConsumerHandle.h b/third_party/WebKit/Source/modules/fetch/ReadableStreamDataConsumerHandle.h
deleted file mode 100644
index 9c634f73..0000000
--- a/third_party/WebKit/Source/modules/fetch/ReadableStreamDataConsumerHandle.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ReadableStreamDataConsumerHandle_h
-#define ReadableStreamDataConsumerHandle_h
-
-#include "modules/ModulesExport.h"
-#include "modules/fetch/FetchDataConsumerHandle.h"
-#include "wtf/Forward.h"
-#include "wtf/PassOwnPtr.h"
-#include "wtf/RefPtr.h"
-#include <v8.h>
-
-namespace blink {
-
-class ScriptState;
-
-// This class is a FetchDataConsumerHandle pulling bytes from ReadableStream
-// implemented with V8 Extras.
-// The stream will be immediately locked by the handle and will never be
-// released.
-// TODO(yhirano): CURRENTLY THIS HANDLE SUPPORTS READING ONLY FROM THE THREAD ON
-// WHICH IT IS CREATED. FIX THIS.
-// TODO(yhirano): This implementation may cause leaks because the handle and
-// the reader own a strong reference to the associated ReadableStreamReader.
-// Fix it.
-class MODULES_EXPORT ReadableStreamDataConsumerHandle final : public FetchDataConsumerHandle {
-    WTF_MAKE_NONCOPYABLE(ReadableStreamDataConsumerHandle);
-public:
-    static PassOwnPtr<ReadableStreamDataConsumerHandle> create(ScriptState* scriptState, v8::Local<v8::Value> stream)
-    {
-        return adoptPtr(new ReadableStreamDataConsumerHandle(scriptState, stream));
-    }
-    ~ReadableStreamDataConsumerHandle() override;
-
-private:
-    class ReadingContext;
-    ReadableStreamDataConsumerHandle(ScriptState*, v8::Local<v8::Value> stream);
-    Reader* obtainReaderInternal(Client*) override;
-    const char* debugName() const override { return "ReadableStreamDataConsumerHandle"; }
-
-    RefPtr<ReadingContext> m_readingContext;
-};
-
-} // namespace blink
-
-#endif // ReadableStreamDataConsumerHandle_h
diff --git a/third_party/WebKit/Source/modules/fetch/ReadableStreamDataConsumerHandleTest.cpp b/third_party/WebKit/Source/modules/fetch/ReadableStreamDataConsumerHandleTest.cpp
deleted file mode 100644
index aaaadddc..0000000
--- a/third_party/WebKit/Source/modules/fetch/ReadableStreamDataConsumerHandleTest.cpp
+++ /dev/null
@@ -1,441 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "config.h"
-#include "modules/fetch/ReadableStreamDataConsumerHandle.h"
-
-#include "bindings/core/v8/ScriptState.h"
-#include "bindings/core/v8/V8BindingMacros.h"
-#include "core/dom/Document.h"
-#include "core/testing/DummyPageHolder.h"
-#include "modules/fetch/DataConsumerHandleTestUtil.h"
-#include "platform/heap/Handle.h"
-#include "platform/testing/UnitTestHelpers.h"
-#include "public/platform/WebDataConsumerHandle.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include <v8.h>
-
-// TODO(yhirano): Add cross-thread tests once the handle gets thread-safe.
-namespace blink {
-
-namespace {
-
-using ::testing::InSequence;
-using ::testing::StrictMock;
-using Checkpoint = StrictMock<::testing::MockFunction<void(int)>>;
-using Result = WebDataConsumerHandle::Result;
-const Result kOk = WebDataConsumerHandle::Ok;
-const Result kShouldWait = WebDataConsumerHandle::ShouldWait;
-const Result kUnexpectedError = WebDataConsumerHandle::UnexpectedError;
-const Result kDone = WebDataConsumerHandle::Done;
-using Flags = WebDataConsumerHandle::Flags;
-const Flags kNone = WebDataConsumerHandle::FlagNone;
-
-class MockClient : public GarbageCollectedFinalized<MockClient>, public WebDataConsumerHandle::Client {
-public:
-    static StrictMock<MockClient>* create() { return new StrictMock<MockClient>(); }
-    MOCK_METHOD0(didGetReadable, void());
-
-    DEFINE_INLINE_TRACE() {}
-
-protected:
-    MockClient() = default;
-};
-
-class ReadableStreamDataConsumerHandleTest : public ::testing::Test {
-public:
-    ReadableStreamDataConsumerHandleTest()
-        : m_page(DummyPageHolder::create())
-    {
-    }
-
-    ScriptState* scriptState() { return ScriptState::forMainWorld(m_page->document().frame()); }
-    v8::Isolate* isolate() { return scriptState()->isolate(); }
-
-    v8::MaybeLocal<v8::Value> eval(const char* s)
-    {
-        v8::Local<v8::String> source;
-        v8::Local<v8::Script> script;
-        if (!v8Call(v8::String::NewFromUtf8(isolate(), s, v8::NewStringType::kNormal), source)) {
-            ADD_FAILURE();
-            return v8::MaybeLocal<v8::Value>();
-        }
-        if (!v8Call(v8::Script::Compile(scriptState()->context(), source), script)) {
-            ADD_FAILURE() << "Compilation fails";
-            return v8::MaybeLocal<v8::Value>();
-        }
-        return script->Run(scriptState()->context());
-    }
-    v8::MaybeLocal<v8::Value> evalWithPrintingError(const char* s)
-    {
-        v8::TryCatch block(isolate());
-        v8::MaybeLocal<v8::Value> r = eval(s);
-        if (block.HasCaught()) {
-            ADD_FAILURE() << toCoreString(block.Exception()->ToString(isolate())).utf8().data();
-            block.ReThrow();
-        }
-        return r;
-    }
-
-private:
-    OwnPtr<DummyPageHolder> m_page;
-};
-
-TEST_F(ReadableStreamDataConsumerHandleTest, Create)
-{
-    ScriptState::Scope scope(scriptState());
-    ScriptValue stream(scriptState(), evalWithPrintingError("new ReadableStream"));
-    ASSERT_FALSE(stream.isEmpty());
-    OwnPtr<ReadableStreamDataConsumerHandle> handle = ReadableStreamDataConsumerHandle::create(scriptState(), stream.v8Value());
-    ASSERT_TRUE(handle);
-    MockClient* client = MockClient::create();
-    Checkpoint checkpoint;
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(2));
-
-    OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(client);
-    ASSERT_TRUE(reader);
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-}
-
-TEST_F(ReadableStreamDataConsumerHandleTest, EmptyStream)
-{
-    ScriptState::Scope scope(scriptState());
-    ScriptValue stream(scriptState(), evalWithPrintingError(
-        "new ReadableStream({start: c => c.close()})"));
-    ASSERT_FALSE(stream.isEmpty());
-    OwnPtr<ReadableStreamDataConsumerHandle> handle = ReadableStreamDataConsumerHandle::create(scriptState(), stream.v8Value());
-    ASSERT_TRUE(handle);
-    MockClient* client = MockClient::create();
-    Checkpoint checkpoint;
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(3));
-
-    char c;
-    size_t readBytes;
-    OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(client);
-    ASSERT_TRUE(reader);
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-    EXPECT_EQ(kShouldWait, reader->read(&c, 1, kNone, &readBytes));
-    testing::runPendingTasks();
-    checkpoint.Call(3);
-    EXPECT_EQ(kDone, reader->read(&c, 1, kNone, &readBytes));
-}
-
-TEST_F(ReadableStreamDataConsumerHandleTest, ErroredStream)
-{
-    ScriptState::Scope scope(scriptState());
-    ScriptValue stream(scriptState(), evalWithPrintingError(
-        "new ReadableStream({start: c => c.error()})"));
-    ASSERT_FALSE(stream.isEmpty());
-    OwnPtr<ReadableStreamDataConsumerHandle> handle = ReadableStreamDataConsumerHandle::create(scriptState(), stream.v8Value());
-    ASSERT_TRUE(handle);
-    MockClient* client = MockClient::create();
-    Checkpoint checkpoint;
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(3));
-
-    char c;
-    size_t readBytes;
-    OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(client);
-    ASSERT_TRUE(reader);
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-    EXPECT_EQ(kShouldWait, reader->read(&c, 1, kNone, &readBytes));
-    testing::runPendingTasks();
-    checkpoint.Call(3);
-    EXPECT_EQ(kUnexpectedError, reader->read(&c, 1, kNone, &readBytes));
-}
-
-TEST_F(ReadableStreamDataConsumerHandleTest, Read)
-{
-    ScriptState::Scope scope(scriptState());
-    ScriptValue stream(scriptState(), evalWithPrintingError(
-        "var controller;"
-        "var stream = new ReadableStream({start: c => controller = c});"
-        "controller.enqueue(new Uint8Array([0x43, 0x44, 0x45, 0x46]));"
-        "controller.enqueue(new Uint8Array([0x47, 0x48, 0x49, 0x4a]));"
-        "controller.close();"
-        "stream"));
-    ASSERT_FALSE(stream.isEmpty());
-    OwnPtr<ReadableStreamDataConsumerHandle> handle = ReadableStreamDataConsumerHandle::create(scriptState(), stream.v8Value());
-    ASSERT_TRUE(handle);
-    MockClient* client = MockClient::create();
-    Checkpoint checkpoint;
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(3));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(4));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(5));
-
-    char buffer[3];
-    size_t readBytes;
-    OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(client);
-    ASSERT_TRUE(reader);
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-    EXPECT_EQ(kShouldWait, reader->read(buffer, 3, kNone, &readBytes));
-    testing::runPendingTasks();
-    checkpoint.Call(3);
-    EXPECT_EQ(kOk, reader->read(buffer, 3, kNone, &readBytes));
-    EXPECT_EQ(3u, readBytes);
-    EXPECT_EQ(0x43, buffer[0]);
-    EXPECT_EQ(0x44, buffer[1]);
-    EXPECT_EQ(0x45, buffer[2]);
-    EXPECT_EQ(kOk, reader->read(buffer, 3, kNone, &readBytes));
-    EXPECT_EQ(1u, readBytes);
-    EXPECT_EQ(0x46, buffer[0]);
-    EXPECT_EQ(kShouldWait, reader->read(buffer, 3, kNone, &readBytes));
-    testing::runPendingTasks();
-    checkpoint.Call(4);
-    EXPECT_EQ(kOk, reader->read(buffer, 3, kNone, &readBytes));
-    EXPECT_EQ(3u, readBytes);
-    EXPECT_EQ(0x47, buffer[0]);
-    EXPECT_EQ(0x48, buffer[1]);
-    EXPECT_EQ(0x49, buffer[2]);
-    EXPECT_EQ(kOk, reader->read(buffer, 3, kNone, &readBytes));
-    EXPECT_EQ(1u, readBytes);
-    EXPECT_EQ(0x4a, buffer[0]);
-    EXPECT_EQ(kShouldWait, reader->read(buffer, 3, kNone, &readBytes));
-    testing::runPendingTasks();
-    checkpoint.Call(5);
-    EXPECT_EQ(kDone, reader->read(buffer, 3, kNone, &readBytes));
-}
-
-TEST_F(ReadableStreamDataConsumerHandleTest, TwoPhaseRead)
-{
-    ScriptState::Scope scope(scriptState());
-    ScriptValue stream(scriptState(), evalWithPrintingError(
-        "var controller;"
-        "var stream = new ReadableStream({start: c => controller = c});"
-        "controller.enqueue(new Uint8Array([0x43, 0x44, 0x45, 0x46]));"
-        "controller.enqueue(new Uint8Array([0x47, 0x48, 0x49, 0x4a]));"
-        "controller.close();"
-        "stream"));
-    ASSERT_FALSE(stream.isEmpty());
-    OwnPtr<ReadableStreamDataConsumerHandle> handle = ReadableStreamDataConsumerHandle::create(scriptState(), stream.v8Value());
-    ASSERT_TRUE(handle);
-    MockClient* client = MockClient::create();
-    Checkpoint checkpoint;
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(3));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(4));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(5));
-
-    const void* buffer;
-    size_t available;
-    OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(client);
-    ASSERT_TRUE(reader);
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-    EXPECT_EQ(kShouldWait, reader->beginRead(&buffer, kNone, &available));
-    testing::runPendingTasks();
-    checkpoint.Call(3);
-    EXPECT_EQ(kOk, reader->beginRead(&buffer, kNone, &available));
-    EXPECT_EQ(4u, available);
-    EXPECT_EQ(0x43, static_cast<const char*>(buffer)[0]);
-    EXPECT_EQ(0x44, static_cast<const char*>(buffer)[1]);
-    EXPECT_EQ(0x45, static_cast<const char*>(buffer)[2]);
-    EXPECT_EQ(0x46, static_cast<const char*>(buffer)[3]);
-    EXPECT_EQ(kOk, reader->endRead(0));
-    EXPECT_EQ(kOk, reader->beginRead(&buffer, kNone, &available));
-    EXPECT_EQ(4u, available);
-    EXPECT_EQ(0x43, static_cast<const char*>(buffer)[0]);
-    EXPECT_EQ(0x44, static_cast<const char*>(buffer)[1]);
-    EXPECT_EQ(0x45, static_cast<const char*>(buffer)[2]);
-    EXPECT_EQ(0x46, static_cast<const char*>(buffer)[3]);
-    EXPECT_EQ(kOk, reader->endRead(1));
-    EXPECT_EQ(kOk, reader->beginRead(&buffer, kNone, &available));
-    EXPECT_EQ(3u, available);
-    EXPECT_EQ(0x44, static_cast<const char*>(buffer)[0]);
-    EXPECT_EQ(0x45, static_cast<const char*>(buffer)[1]);
-    EXPECT_EQ(0x46, static_cast<const char*>(buffer)[2]);
-    EXPECT_EQ(kOk, reader->endRead(3));
-    EXPECT_EQ(kShouldWait, reader->beginRead(&buffer, kNone, &available));
-    testing::runPendingTasks();
-    checkpoint.Call(4);
-    EXPECT_EQ(kOk, reader->beginRead(&buffer, kNone, &available));
-    EXPECT_EQ(4u, available);
-    EXPECT_EQ(0x47, static_cast<const char*>(buffer)[0]);
-    EXPECT_EQ(0x48, static_cast<const char*>(buffer)[1]);
-    EXPECT_EQ(0x49, static_cast<const char*>(buffer)[2]);
-    EXPECT_EQ(0x4a, static_cast<const char*>(buffer)[3]);
-    EXPECT_EQ(kOk, reader->endRead(4));
-    EXPECT_EQ(kShouldWait, reader->beginRead(&buffer, kNone, &available));
-    testing::runPendingTasks();
-    checkpoint.Call(5);
-    EXPECT_EQ(kDone, reader->beginRead(&buffer, kNone, &available));
-}
-
-TEST_F(ReadableStreamDataConsumerHandleTest, LockedStream)
-{
-    ScriptState::Scope scope(scriptState());
-    ScriptValue stream(scriptState(), evalWithPrintingError(
-        "var stream = new ReadableStream;"
-        "stream.getReader();"
-        "stream"));
-    ASSERT_FALSE(stream.isEmpty());
-    OwnPtr<ReadableStreamDataConsumerHandle> handle = ReadableStreamDataConsumerHandle::create(scriptState(), stream.v8Value());
-    ASSERT_TRUE(handle);
-    MockClient* client = MockClient::create();
-    Checkpoint checkpoint;
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(2));
-
-    char c;
-    size_t readBytes;
-    OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(client);
-    ASSERT_TRUE(reader);
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-    EXPECT_EQ(kUnexpectedError, reader->read(&c, 1, kNone, &readBytes));
-}
-
-TEST_F(ReadableStreamDataConsumerHandleTest, EnqueueUndefined)
-{
-    ScriptState::Scope scope(scriptState());
-    ScriptValue stream(scriptState(), evalWithPrintingError(
-        "var controller;"
-        "var stream = new ReadableStream({start: c => controller = c});"
-        "controller.enqueue(undefined);"
-        "controller.close();"
-        "stream"));
-    ASSERT_FALSE(stream.isEmpty());
-    OwnPtr<ReadableStreamDataConsumerHandle> handle = ReadableStreamDataConsumerHandle::create(scriptState(), stream.v8Value());
-    ASSERT_TRUE(handle);
-    MockClient* client = MockClient::create();
-    Checkpoint checkpoint;
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(3));
-
-    const void* buffer;
-    size_t available;
-    OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(client);
-    ASSERT_TRUE(reader);
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-    EXPECT_EQ(kShouldWait, reader->beginRead(&buffer, kNone, &available));
-    testing::runPendingTasks();
-    checkpoint.Call(3);
-    EXPECT_EQ(kUnexpectedError, reader->beginRead(&buffer, kNone, &available));
-}
-
-TEST_F(ReadableStreamDataConsumerHandleTest, EnqueueNull)
-{
-    ScriptState::Scope scope(scriptState());
-    ScriptValue stream(scriptState(), evalWithPrintingError(
-        "var controller;"
-        "var stream = new ReadableStream({start: c => controller = c});"
-        "controller.enqueue(null);"
-        "controller.close();"
-        "stream"));
-    ASSERT_FALSE(stream.isEmpty());
-    OwnPtr<ReadableStreamDataConsumerHandle> handle = ReadableStreamDataConsumerHandle::create(scriptState(), stream.v8Value());
-    ASSERT_TRUE(handle);
-    MockClient* client = MockClient::create();
-    Checkpoint checkpoint;
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(3));
-
-    const void* buffer;
-    size_t available;
-    OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(client);
-    ASSERT_TRUE(reader);
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-    EXPECT_EQ(kShouldWait, reader->beginRead(&buffer, kNone, &available));
-    testing::runPendingTasks();
-    checkpoint.Call(3);
-    EXPECT_EQ(kUnexpectedError, reader->beginRead(&buffer, kNone, &available));
-}
-
-TEST_F(ReadableStreamDataConsumerHandleTest, EnqueueString)
-{
-    ScriptState::Scope scope(scriptState());
-    ScriptValue stream(scriptState(), evalWithPrintingError(
-        "var controller;"
-        "var stream = new ReadableStream({start: c => controller = c});"
-        "controller.enqueue('hello');"
-        "controller.close();"
-        "stream"));
-    ASSERT_FALSE(stream.isEmpty());
-    OwnPtr<ReadableStreamDataConsumerHandle> handle = ReadableStreamDataConsumerHandle::create(scriptState(), stream.v8Value());
-    ASSERT_TRUE(handle);
-    MockClient* client = MockClient::create();
-    Checkpoint checkpoint;
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*client, didGetReadable());
-    EXPECT_CALL(checkpoint, Call(3));
-
-    const void* buffer;
-    size_t available;
-    OwnPtr<FetchDataConsumerHandle::Reader> reader = handle->obtainReader(client);
-    ASSERT_TRUE(reader);
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-    EXPECT_EQ(kShouldWait, reader->beginRead(&buffer, kNone, &available));
-    testing::runPendingTasks();
-    checkpoint.Call(3);
-    EXPECT_EQ(kUnexpectedError, reader->beginRead(&buffer, kNone, &available));
-}
-
-} // namespace
-
-} // namespace blink
-
diff --git a/third_party/WebKit/Source/modules/fetch/Response.cpp b/third_party/WebKit/Source/modules/fetch/Response.cpp
index 66c6e82..ac92166 100644
--- a/third_party/WebKit/Source/modules/fetch/Response.cpp
+++ b/third_party/WebKit/Source/modules/fetch/Response.cpp
@@ -7,13 +7,6 @@
 
 #include "bindings/core/v8/Dictionary.h"
 #include "bindings/core/v8/ExceptionState.h"
-#include "bindings/core/v8/ReadableStreamOperations.h"
-#include "bindings/core/v8/ScriptState.h"
-#include "bindings/core/v8/V8ArrayBuffer.h"
-#include "bindings/core/v8/V8ArrayBufferView.h"
-#include "bindings/core/v8/V8Binding.h"
-#include "bindings/core/v8/V8Blob.h"
-#include "bindings/core/v8/V8FormData.h"
 #include "core/dom/DOMArrayBuffer.h"
 #include "core/dom/DOMArrayBufferView.h"
 #include "core/fileapi/Blob.h"
@@ -21,9 +14,7 @@
 #include "modules/fetch/BodyStreamBuffer.h"
 #include "modules/fetch/FetchBlobDataConsumerHandle.h"
 #include "modules/fetch/FetchFormDataConsumerHandle.h"
-#include "modules/fetch/ReadableStreamDataConsumerHandle.h"
 #include "modules/fetch/ResponseInit.h"
-#include "platform/RuntimeEnabledFeatures.h"
 #include "platform/network/EncodedFormData.h"
 #include "platform/network/HTTPHeaderMap.h"
 #include "public/platform/modules/serviceworker/WebServiceWorkerResponse.h"
@@ -104,44 +95,37 @@
 
 }
 
-Response* Response::create(ScriptState* scriptState, ExceptionState& exceptionState)
+Response* Response::create(ExecutionContext* context, ExceptionState& exceptionState)
 {
-    return create(scriptState->executionContext(), nullptr, String(), ResponseInit(), exceptionState);
+    return create(context, nullptr, String(), ResponseInit(), exceptionState);
 }
 
-Response* Response::create(ScriptState* scriptState, ScriptValue bodyValue, const Dictionary& init, ExceptionState& exceptionState)
+Response* Response::create(ExecutionContext* context, const BodyInit& body, const Dictionary& init, ExceptionState& exceptionState)
 {
-    v8::Local<v8::Value> body = bodyValue.v8Value();
-    v8::Isolate* isolate = scriptState->isolate();
-    ExecutionContext* executionContext = scriptState->executionContext();
-
+    ASSERT(!body.isNull());
     OwnPtr<FetchDataConsumerHandle> bodyHandle;
     String contentType;
-    if (V8Blob::hasInstance(body, isolate)) {
-        Blob* blob = V8Blob::toImpl(body.As<v8::Object>());
-        bodyHandle = FetchBlobDataConsumerHandle::create(executionContext, blob->blobDataHandle());
-        contentType = blob->type();
-    } else if (V8ArrayBuffer::hasInstance(body, isolate)) {
-        bodyHandle = FetchFormDataConsumerHandle::create(V8ArrayBuffer::toImpl(body.As<v8::Object>()));
-    } else if (V8ArrayBufferView::hasInstance(body, isolate)) {
-        bodyHandle = FetchFormDataConsumerHandle::create(V8ArrayBufferView::toImpl(body.As<v8::Object>()));
-    } else if (V8FormData::hasInstance(body, isolate)) {
-        RefPtr<EncodedFormData> formData = V8FormData::toImpl(body.As<v8::Object>())->encodeMultiPartFormData();
+    if (body.isBlob()) {
+        bodyHandle = FetchBlobDataConsumerHandle::create(context, body.getAsBlob()->blobDataHandle());
+        contentType = body.getAsBlob()->type();
+    } else if (body.isUSVString()) {
+        bodyHandle = FetchFormDataConsumerHandle::create(body.getAsUSVString());
+        contentType = "text/plain;charset=UTF-8";
+    } else if (body.isArrayBuffer()) {
+        bodyHandle = FetchFormDataConsumerHandle::create(body.getAsArrayBuffer());
+    } else if (body.isArrayBufferView()) {
+        bodyHandle = FetchFormDataConsumerHandle::create(body.getAsArrayBufferView());
+    } else if (body.isFormData()) {
+        RefPtr<EncodedFormData> formData = body.getAsFormData()->encodeMultiPartFormData();
         // Here we handle formData->boundary() as a C-style string. See
         // FormDataEncoder::generateUniqueBoundaryString.
         contentType = AtomicString("multipart/form-data; boundary=", AtomicString::ConstructFromLiteral) + formData->boundary().data();
-        bodyHandle = FetchFormDataConsumerHandle::create(executionContext, formData.release());
-    } else if (RuntimeEnabledFeatures::responseConstructedWithReadableStreamEnabled() && ReadableStreamOperations::isReadableStream(scriptState, body)) {
-        bodyHandle = ReadableStreamDataConsumerHandle::create(scriptState, body);
+        bodyHandle = FetchFormDataConsumerHandle::create(context, formData.release());
     } else {
-        String string = toUSVString(isolate, body, exceptionState);
-        if (exceptionState.hadException())
-            return nullptr;
-        bodyHandle = FetchFormDataConsumerHandle::create(string);
-        contentType = "text/plain;charset=UTF-8";
+        ASSERT_NOT_REACHED();
+        return nullptr;
     }
-    // TODO(yhirano): Add the URLSearchParams case.
-    return create(executionContext, bodyHandle.release(), contentType, ResponseInit(init, exceptionState), exceptionState);
+    return create(context, bodyHandle.release(), contentType, ResponseInit(init, exceptionState), exceptionState);
 }
 
 Response* Response::create(ExecutionContext* context, PassOwnPtr<FetchDataConsumerHandle> bodyHandle, const String& contentType, const ResponseInit& init, ExceptionState& exceptionState)
diff --git a/third_party/WebKit/Source/modules/fetch/Response.h b/third_party/WebKit/Source/modules/fetch/Response.h
index 2244e61f..b7433d5 100644
--- a/third_party/WebKit/Source/modules/fetch/Response.h
+++ b/third_party/WebKit/Source/modules/fetch/Response.h
@@ -6,7 +6,6 @@
 #define Response_h
 
 #include "bindings/core/v8/Dictionary.h"
-#include "bindings/core/v8/ScriptValue.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/modules/v8/UnionTypesModules.h"
 #include "modules/ModulesExport.h"
@@ -25,9 +24,10 @@
 class ExceptionState;
 class FetchDataConsumerHandle;
 class ResponseInit;
-class ScriptState;
 class WebServiceWorkerResponse;
 
+typedef BlobOrArrayBufferOrArrayBufferViewOrFormDataOrUSVString BodyInit;
+
 class MODULES_EXPORT Response final : public Body {
     DEFINE_WRAPPERTYPEINFO();
     WTF_MAKE_NONCOPYABLE(Response);
@@ -35,8 +35,8 @@
     ~Response() override { }
 
     // From Response.idl:
-    static Response* create(ScriptState*, ExceptionState&);
-    static Response* create(ScriptState*, ScriptValue body, const Dictionary&, ExceptionState&);
+    static Response* create(ExecutionContext*, ExceptionState&);
+    static Response* create(ExecutionContext*, const BodyInit&, const Dictionary&, ExceptionState&);
 
     static Response* create(ExecutionContext*, PassOwnPtr<FetchDataConsumerHandle> bodyHandle, const String& contentType, const ResponseInit&, ExceptionState&);
     static Response* create(ExecutionContext*, FetchResponseData*);
diff --git a/third_party/WebKit/Source/modules/fetch/Response.idl b/third_party/WebKit/Source/modules/fetch/Response.idl
index 4ac9f403..556488f7 100644
--- a/third_party/WebKit/Source/modules/fetch/Response.idl
+++ b/third_party/WebKit/Source/modules/fetch/Response.idl
@@ -6,11 +6,12 @@
 
 enum ResponseType { "basic", "cors", "default", "error", "opaque", "opaqueredirect" };
 
+// FIXME: Add union type: URLSearchParams
+typedef (Blob or ArrayBuffer or ArrayBufferView or FormData or USVString) BodyInit;
+
 [
-    // TODO(yhirano): We use "any" for body because the IDL processor doesn't
-    // recognize ReadableStream implemented with V8 extras. Fix it.
-    Constructor(optional any body, optional Dictionary responseInitDict),
-    ConstructorCallWith=ScriptState,
+    Constructor(optional BodyInit body, optional Dictionary responseInitDict),
+    ConstructorCallWith=ExecutionContext,
     Exposed=(Window,Worker),
     RaisesException=Constructor,
     ActiveDOMObject,
diff --git a/third_party/WebKit/Source/modules/modules.gypi b/third_party/WebKit/Source/modules/modules.gypi
index a22e4754..753b7a6 100644
--- a/third_party/WebKit/Source/modules/modules.gypi
+++ b/third_party/WebKit/Source/modules/modules.gypi
@@ -977,8 +977,6 @@
       'fetch/GlobalFetch.h',
       'fetch/Headers.cpp',
       'fetch/Headers.h',
-      'fetch/ReadableStreamDataConsumerHandle.cpp',
-      'fetch/ReadableStreamDataConsumerHandle.h',
       'fetch/Request.cpp',
       'fetch/Request.h',
       'fetch/RequestInit.cpp',
@@ -1877,7 +1875,6 @@
       'fetch/FetchDataLoaderTest.cpp',
       'fetch/FetchFormDataConsumerHandleTest.cpp',
       'fetch/FetchResponseDataTest.cpp',
-      'fetch/ReadableStreamDataConsumerHandleTest.cpp',
       'fetch/RequestTest.cpp',
       'fetch/ResponseTest.cpp',
       'filesystem/DOMFileSystemBaseTest.cpp',
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp
index 136a0850..154fad0a 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp
@@ -210,7 +210,7 @@
     String errorMessage;
     // Restrict to secure origins: https://w3c.github.io/webappsec/specs/powerfulfeatures/#settings-privileged
     if (!executionContext->isSecureContext(errorMessage)) {
-        resolver->reject(DOMException::create(NotSupportedError, errorMessage));
+        resolver->reject(DOMException::create(SecurityError, errorMessage));
         return promise;
     }
 
@@ -278,7 +278,7 @@
     RefPtr<SecurityOrigin> documentOrigin = executionContext->securityOrigin();
     String errorMessage;
     if (!executionContext->isSecureContext(errorMessage)) {
-        resolver->reject(DOMException::create(NotSupportedError, errorMessage));
+        resolver->reject(DOMException::create(SecurityError, errorMessage));
         return promise;
     }
 
@@ -314,7 +314,7 @@
     RefPtr<SecurityOrigin> documentOrigin = executionContext->securityOrigin();
     String errorMessage;
     if (!executionContext->isSecureContext(errorMessage)) {
-        resolver->reject(DOMException::create(NotSupportedError, errorMessage));
+        resolver->reject(DOMException::create(SecurityError, errorMessage));
         return promise;
     }
 
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerTest.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerTest.cpp
index 5d803d1..476b194a 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerTest.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerTest.cpp
@@ -215,7 +215,7 @@
     testRegisterRejected(
         "http://www.example.com/worker.js",
         "http://www.example.com/",
-        ExpectDOMException("NotSupportedError", "Only secure origins are allowed (see: https://goo.gl/Y0ZkNV)."));
+        ExpectDOMException("SecurityError", "Only secure origins are allowed (see: https://goo.gl/Y0ZkNV)."));
 }
 
 TEST_F(ServiceWorkerContainerTest, Register_CrossOriginScriptIsRejected)
@@ -241,7 +241,7 @@
     setPageURL("http://www.example.com/");
     testGetRegistrationRejected(
         "http://www.example.com/",
-        ExpectDOMException("NotSupportedError", "Only secure origins are allowed (see: https://goo.gl/Y0ZkNV)."));
+        ExpectDOMException("SecurityError", "Only secure origins are allowed (see: https://goo.gl/Y0ZkNV)."));
 }
 
 TEST_F(ServiceWorkerContainerTest, GetRegistration_CrossOriginURLIsRejected)
diff --git a/third_party/WebKit/Source/modules/webdatabase/Database.cpp b/third_party/WebKit/Source/modules/webdatabase/Database.cpp
index 737f4f8..ac3f475 100644
--- a/third_party/WebKit/Source/modules/webdatabase/Database.cpp
+++ b/third_party/WebKit/Source/modules/webdatabase/Database.cpp
@@ -149,7 +149,7 @@
 // FIXME: move all guid-related functions to a DatabaseVersionTracker class.
 static RecursiveMutex& guidMutex()
 {
-    AtomicallyInitializedStaticReference(RecursiveMutex, mutex, new RecursiveMutex);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(RecursiveMutex, mutex, new RecursiveMutex);
     return mutex;
 }
 
diff --git a/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp b/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp
index e6833f61..53304ea 100644
--- a/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp
+++ b/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp
@@ -60,7 +60,7 @@
 
 DatabaseTracker& DatabaseTracker::tracker()
 {
-    AtomicallyInitializedStaticReference(DatabaseTracker, tracker, new DatabaseTracker);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(DatabaseTracker, tracker, new DatabaseTracker);
     return tracker;
 }
 
diff --git a/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.cpp b/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.cpp
index a4f5dcd..490484e 100644
--- a/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.cpp
+++ b/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.cpp
@@ -39,7 +39,7 @@
 
 QuotaTracker& QuotaTracker::instance()
 {
-    AtomicallyInitializedStaticReference(QuotaTracker, tracker, new QuotaTracker);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(QuotaTracker, tracker, new QuotaTracker);
     return tracker;
 }
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
index 3b4149a1..fb556fdc 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
@@ -675,6 +675,12 @@
         if (!samples) {
             webContext()->renderbufferStorage(target, internalformat, width, height);
         } else {
+            GLint maxNumberOfSamples = 0;
+            webContext()->getInternalformativ(target, internalformat, GL_SAMPLES, 1, &maxNumberOfSamples);
+            if (samples > maxNumberOfSamples) {
+                synthesizeGLError(GL_INVALID_OPERATION, functionName, "samples out of range");
+                return;
+            }
             webContext()->renderbufferStorageMultisampleCHROMIUM(
                 target, samples, internalformat, width, height);
         }
@@ -1442,6 +1448,39 @@
     attribValue.value.uintValue[3] = value[3];
 }
 
+bool WebGL2RenderingContextBase::validateVertexAttribPointerTypeAndSize(GLenum type, GLint size)
+{
+    switch (type) {
+    case GL_BYTE:
+    case GL_UNSIGNED_BYTE:
+    case GL_SHORT:
+    case GL_UNSIGNED_SHORT:
+    case GL_INT:
+    case GL_UNSIGNED_INT:
+    case GL_FLOAT:
+    case GL_HALF_FLOAT:
+        if (size < 1 || size > 4) {
+            synthesizeGLError(GL_INVALID_VALUE, "vertexAttribPointer", "invalid size");
+            return false;
+        }
+        return true;
+    case GL_INT_2_10_10_10_REV:
+    case GL_UNSIGNED_INT_2_10_10_10_REV:
+        if (size < 1 || size > 4) {
+            synthesizeGLError(GL_INVALID_VALUE, "vertexAttribPointer", "invalid size");
+            return false;
+        }
+        if (size != 4) {
+            synthesizeGLError(GL_INVALID_OPERATION, "vertexAttribPointer", "size != 4");
+            return false;
+        }
+        return true;
+    default:
+        synthesizeGLError(GL_INVALID_ENUM, "vertexAttribPointer", "invalid type");
+        return false;
+    }
+}
+
 void WebGL2RenderingContextBase::vertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, long long offset)
 {
     if (isContextLost())
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h
index f859b3824..f904dae6 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h
@@ -224,6 +224,8 @@
     WebGLTexture* validateTextureBinding(const char* functionName, GLenum target, bool useSixEnumsForCubeMap) override;
     bool validateFramebufferTarget(GLenum target) override;
     bool validateReadPixelsFormatAndType(GLenum format, GLenum type) override;
+    bool validateVertexAttribPointerTypeAndSize(GLenum type, GLint size) override;
+
     DOMArrayBufferView::ViewType readPixelsExpectedArrayBufferViewType(GLenum type) override;
     WebGLFramebuffer* getFramebufferBinding(GLenum target) override;
     GLint getMaxTextureLevelForTarget(GLenum target) override;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
index 12429eec..8693f3e1 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -5135,27 +5135,35 @@
     vertexAttribfvImpl("vertexAttrib4fv", index, v.data(), v.size(), 4);
 }
 
-void WebGLRenderingContextBase::vertexAttribPointer(ScriptState* scriptState, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, long long offset)
+bool WebGLRenderingContextBase::validateVertexAttribPointerTypeAndSize(GLenum type, GLint size)
 {
-    if (isContextLost())
-        return;
     switch (type) {
     case GL_BYTE:
     case GL_UNSIGNED_BYTE:
     case GL_SHORT:
     case GL_UNSIGNED_SHORT:
     case GL_FLOAT:
-        break;
+        if (size < 1 || size > 4) {
+            synthesizeGLError(GL_INVALID_VALUE, "vertexAttribPointer", "bad size");
+            return false;
+        }
+        return true;
     default:
         synthesizeGLError(GL_INVALID_ENUM, "vertexAttribPointer", "invalid type");
-        return;
+        return false;
     }
+}
+
+void WebGLRenderingContextBase::vertexAttribPointer(ScriptState* scriptState, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, long long offset)
+{
+    if (isContextLost() || !validateVertexAttribPointerTypeAndSize(type, size))
+        return;
     if (index >= m_maxVertexAttribs) {
         synthesizeGLError(GL_INVALID_VALUE, "vertexAttribPointer", "index out of range");
         return;
     }
-    if (size < 1 || size > 4 || stride < 0 || stride > 255) {
-        synthesizeGLError(GL_INVALID_VALUE, "vertexAttribPointer", "bad size or stride");
+    if (stride < 0 || stride > 255) {
+        synthesizeGLError(GL_INVALID_VALUE, "vertexAttribPointer", "bad stride");
         return;
     }
     if (!validateValueFitNonNegInt32("vertexAttribPointer", "offset", offset))
@@ -5906,10 +5914,7 @@
 
 bool WebGLRenderingContextBase::validateCompressedTexFuncData(const char* functionName, GLsizei width, GLsizei height, GLsizei depth, GLenum format, DOMArrayBufferView* pixels)
 {
-    if (!pixels) {
-        synthesizeGLError(GL_INVALID_VALUE, functionName, "no pixels");
-        return false;
-    }
+    ASSERT(pixels);
 
     CheckedInt<unsigned> bytesRequired = 0;
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
index e7ac73c..e02dfa5 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
@@ -907,6 +907,9 @@
     // are valid. Otherwise, generates appropriate error and returns false.
     bool validateReadPixelsFuncParameters(GLsizei width, GLsizei height, GLenum format, GLenum type, long long bufferSize);
 
+    // Helper function to check type and size of vertexAttribPointer. Return true if type and size are valid. Otherwise, generates appropriates error and return false.
+    virtual bool validateVertexAttribPointerTypeAndSize(GLenum type, GLint size);
+
     virtual GLint getMaxTextureLevelForTarget(GLenum target);
 
     // Helper function to check input level for functions {copy}Tex{Sub}Image.
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.idl b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.idl
index 03df3622..cec3428f 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.idl
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.idl
@@ -501,9 +501,9 @@
     void compileShader(WebGLShader? shader);
 
     void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat,
-                              GLsizei width, GLsizei height, GLint border, ArrayBufferView? data);
+                              GLsizei width, GLsizei height, GLint border, ArrayBufferView data);
     void compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
-                                 GLsizei width, GLsizei height, GLenum format, ArrayBufferView? data);
+                                 GLsizei width, GLsizei height, GLenum format, ArrayBufferView data);
 
     void copyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
     void copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
diff --git a/third_party/WebKit/Source/platform/ContentSettingCallbacks.cpp b/third_party/WebKit/Source/platform/ContentSettingCallbacks.cpp
index b6f07e5..4cab115 100644
--- a/third_party/WebKit/Source/platform/ContentSettingCallbacks.cpp
+++ b/third_party/WebKit/Source/platform/ContentSettingCallbacks.cpp
@@ -36,12 +36,12 @@
 
 PassOwnPtr<ContentSettingCallbacks> ContentSettingCallbacks::create(PassOwnPtr<Closure> allowed, PassOwnPtr<Closure> denied)
 {
-    return adoptPtr(new ContentSettingCallbacks(allowed, denied));
+    return adoptPtr(new ContentSettingCallbacks(std::move(allowed), std::move(denied)));
 }
 
 ContentSettingCallbacks::ContentSettingCallbacks(PassOwnPtr<Closure> allowed, PassOwnPtr<Closure> denied)
-    : m_allowed(allowed)
-    , m_denied(denied)
+    : m_allowed(std::move(allowed))
+    , m_denied(std::move(denied))
 {
 }
 
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
index 9213e5c..baf6256 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -145,7 +145,6 @@
 RenderingPipelineThrottling status=experimental
 RequestIdleCallback status=stable
 RequestAutocomplete status=test
-ResponseConstructedWithReadableStream status=experimental
 RestrictIFramePermissions
 RTCCertificate status=experimental
 SandboxBlocksModals status=stable
diff --git a/third_party/WebKit/Source/platform/Task.h b/third_party/WebKit/Source/platform/Task.h
index 35813870..64b656c 100644
--- a/third_party/WebKit/Source/platform/Task.h
+++ b/third_party/WebKit/Source/platform/Task.h
@@ -45,7 +45,7 @@
     WTF_MAKE_NONCOPYABLE(Task);
 public:
     explicit Task(PassOwnPtr<Closure> closure)
-        : m_closure(closure)
+        : m_closure(std::move(closure))
     {
     }
 
diff --git a/third_party/WebKit/Source/platform/WebScheduler.cpp b/third_party/WebKit/Source/platform/WebScheduler.cpp
index 4579596..7f610db 100644
--- a/third_party/WebKit/Source/platform/WebScheduler.cpp
+++ b/third_party/WebKit/Source/platform/WebScheduler.cpp
@@ -21,7 +21,7 @@
 
 public:
     explicit IdleTaskRunner(PassOwnPtr<WebScheduler::IdleTask> task)
-        : m_task(task)
+        : m_task(std::move(task))
     {
     }
 
@@ -43,17 +43,17 @@
 
 void WebScheduler::postIdleTask(const WebTraceLocation& location, PassOwnPtr<IdleTask> idleTask)
 {
-    postIdleTask(location, new IdleTaskRunner(idleTask));
+    postIdleTask(location, new IdleTaskRunner(std::move(idleTask)));
 }
 
 void WebScheduler::postNonNestableIdleTask(const WebTraceLocation& location, PassOwnPtr<IdleTask> idleTask)
 {
-    postNonNestableIdleTask(location, new IdleTaskRunner(idleTask));
+    postNonNestableIdleTask(location, new IdleTaskRunner(std::move(idleTask)));
 }
 
 void WebScheduler::postIdleTaskAfterWakeup(const WebTraceLocation& location, PassOwnPtr<IdleTask> idleTask)
 {
-    postIdleTaskAfterWakeup(location, new IdleTaskRunner(idleTask));
+    postIdleTaskAfterWakeup(location, new IdleTaskRunner(std::move(idleTask)));
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/WebTaskRunner.cpp b/third_party/WebKit/Source/platform/WebTaskRunner.cpp
index 435a90c8..ebdd79bd 100644
--- a/third_party/WebKit/Source/platform/WebTaskRunner.cpp
+++ b/third_party/WebKit/Source/platform/WebTaskRunner.cpp
@@ -11,17 +11,17 @@
 
 void WebTaskRunner::postTask(const WebTraceLocation& location, PassOwnPtr<ClosureTask> task)
 {
-    postTask(location, new blink::Task(task));
+    postTask(std::move(location), new blink::Task(std::move(task)));
 }
 
 void WebTaskRunner::postDelayedTask(const WebTraceLocation& location, PassOwnPtr <ClosureTask> task, long long delayMs)
 {
-    postDelayedTask(location, new blink::Task(task), delayMs);
+    postDelayedTask(location, new blink::Task(std::move(task)), delayMs);
 }
 
 void WebTaskRunner::postDelayedTask(const WebTraceLocation& location, PassOwnPtr <ClosureTask> task, double delayMs)
 {
-    postDelayedTask(location, new blink::Task(task), delayMs);
+    postDelayedTask(location, new blink::Task(std::move(task)), delayMs);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/HRTFElevation.cpp b/third_party/WebKit/Source/platform/audio/HRTFElevation.cpp
index 6ea1c07..3e07bc2 100644
--- a/third_party/WebKit/Source/platform/audio/HRTFElevation.cpp
+++ b/third_party/WebKit/Source/platform/audio/HRTFElevation.cpp
@@ -71,8 +71,8 @@
 static PassRefPtr<AudioBus> getConcatenatedImpulseResponsesForSubject(const String& subjectName)
 {
     typedef HashMap<String, RefPtr<AudioBus>> AudioBusMap;
-    AtomicallyInitializedStaticReference(AudioBusMap, audioBusMap, new AudioBusMap());
-    AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex());
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(AudioBusMap, audioBusMap, new AudioBusMap());
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(Mutex, mutex, new Mutex());
 
     MutexLocker locker(mutex);
     RefPtr<AudioBus> bus;
diff --git a/third_party/WebKit/Source/platform/audio/HRTFElevation.h b/third_party/WebKit/Source/platform/audio/HRTFElevation.h
index 826e1c4..f9c74f7 100644
--- a/third_party/WebKit/Source/platform/audio/HRTFElevation.h
+++ b/third_party/WebKit/Source/platform/audio/HRTFElevation.h
@@ -89,8 +89,8 @@
 
 private:
     HRTFElevation(PassOwnPtr<HRTFKernelList> kernelListL, PassOwnPtr<HRTFKernelList> kernelListR, int elevation, float sampleRate)
-        : m_kernelListL(kernelListL)
-        , m_kernelListR(kernelListR)
+        : m_kernelListL(std::move(kernelListL))
+        , m_kernelListR(std::move(kernelListR))
         , m_elevationAngle(elevation)
         , m_sampleRate(sampleRate)
     {
diff --git a/third_party/WebKit/Source/platform/audio/HRTFKernel.h b/third_party/WebKit/Source/platform/audio/HRTFKernel.h
index 298d0ea..bbe0ac0 100644
--- a/third_party/WebKit/Source/platform/audio/HRTFKernel.h
+++ b/third_party/WebKit/Source/platform/audio/HRTFKernel.h
@@ -62,7 +62,7 @@
 
     static PassOwnPtr<HRTFKernel> create(PassOwnPtr<FFTFrame> fftFrame, float frameDelay, float sampleRate)
     {
-        return adoptPtr(new HRTFKernel(fftFrame, frameDelay, sampleRate));
+        return adoptPtr(new HRTFKernel(std::move(fftFrame), frameDelay, sampleRate));
     }
 
     // Given two HRTFKernels, and an interpolation factor x: 0 -> 1, returns an interpolated HRTFKernel.
@@ -84,7 +84,7 @@
     HRTFKernel(AudioChannel*, size_t fftSize, float sampleRate);
 
     HRTFKernel(PassOwnPtr<FFTFrame> fftFrame, float frameDelay, float sampleRate)
-        : m_fftFrame(fftFrame)
+        : m_fftFrame(std::move(fftFrame))
         , m_frameDelay(frameDelay)
         , m_sampleRate(sampleRate)
     {
diff --git a/third_party/WebKit/Source/platform/blink_platform.gypi b/third_party/WebKit/Source/platform/blink_platform.gypi
index c8d6b876..9b05356 100644
--- a/third_party/WebKit/Source/platform/blink_platform.gypi
+++ b/third_party/WebKit/Source/platform/blink_platform.gypi
@@ -501,11 +501,13 @@
       'geometry/mac/IntSizeMac.mm',
       'graphics/BitmapImage.cpp',
       'graphics/BitmapImage.h',
+      'graphics/BitmapImageMetrics.cpp',
+      'graphics/BitmapImageMetrics.h',
       'graphics/Canvas2DImageBufferSurface.h',
       'graphics/Canvas2DLayerBridge.cpp',
       'graphics/Canvas2DLayerBridge.h',
-      'graphics/CanvasMetrics.h',
       'graphics/CanvasMetrics.cpp',
+      'graphics/CanvasMetrics.h',
       'graphics/Color.cpp',
       'graphics/Color.h',
       'graphics/ColorSpace.cpp',
diff --git a/third_party/WebKit/Source/platform/blob/BlobData.cpp b/third_party/WebKit/Source/platform/blob/BlobData.cpp
index 0310bb23..97c5f86 100644
--- a/third_party/WebKit/Source/platform/blob/BlobData.cpp
+++ b/third_party/WebKit/Source/platform/blob/BlobData.cpp
@@ -209,7 +209,7 @@
     , m_type(data->contentType().isolatedCopy())
     , m_size(size)
 {
-    BlobRegistry::registerBlobData(m_uuid, data);
+    BlobRegistry::registerBlobData(m_uuid, std::move(data));
 }
 
 BlobDataHandle::BlobDataHandle(const String& uuid, const String& type, long long size)
diff --git a/third_party/WebKit/Source/platform/blob/BlobData.h b/third_party/WebKit/Source/platform/blob/BlobData.h
index 0106a41a..e54becf6 100644
--- a/third_party/WebKit/Source/platform/blob/BlobData.h
+++ b/third_party/WebKit/Source/platform/blob/BlobData.h
@@ -210,7 +210,7 @@
     // For initial creation.
     static PassRefPtr<BlobDataHandle> create(PassOwnPtr<BlobData> data, long long size)
     {
-        return adoptRef(new BlobDataHandle(data, size));
+        return adoptRef(new BlobDataHandle(std::move(data), size));
     }
 
     // For deserialization of script values and ipc messages.
diff --git a/third_party/WebKit/Source/platform/blob/BlobRegistry.cpp b/third_party/WebKit/Source/platform/blob/BlobRegistry.cpp
index 2e06c727..ea287662 100644
--- a/third_party/WebKit/Source/platform/blob/BlobRegistry.cpp
+++ b/third_party/WebKit/Source/platform/blob/BlobRegistry.cpp
@@ -68,10 +68,10 @@
 static ThreadSpecific<BlobURLOriginMap>& originMap()
 {
     // We want to create the BlobOriginCache exactly once because it is shared by all the threads.
-    AtomicallyInitializedStaticReference(BlobOriginCache, cache, new BlobOriginCache);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(BlobOriginCache, cache, new BlobOriginCache);
     (void)cache; // BlobOriginCache's constructor does the interesting work.
 
-    AtomicallyInitializedStaticReference(ThreadSpecific<BlobURLOriginMap>, map, new ThreadSpecific<BlobURLOriginMap>);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(ThreadSpecific<BlobURLOriginMap>, map, new ThreadSpecific<BlobURLOriginMap>);
     return map;
 }
 
@@ -92,7 +92,7 @@
 
 void BlobRegistry::registerBlobData(const String& uuid, PassOwnPtr<BlobData> data)
 {
-    blobRegistry()->registerBlobData(uuid, WebBlobData(data));
+    blobRegistry()->registerBlobData(uuid, WebBlobData(std::move(data)));
 }
 
 void BlobRegistry::addBlobDataRef(const String& uuid)
diff --git a/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp b/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp
index f0a5eb6..feaf778 100644
--- a/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp
@@ -33,12 +33,12 @@
 
 PassOwnPtr<WebActiveGestureAnimation> WebActiveGestureAnimation::createAtAnimationStart(PassOwnPtr<WebGestureCurve> curve, WebGestureCurveTarget* target)
 {
-    return adoptPtr(new WebActiveGestureAnimation(curve, target, 0, true));
+    return adoptPtr(new WebActiveGestureAnimation(std::move(curve), target, 0, true));
 }
 
 PassOwnPtr<WebActiveGestureAnimation> WebActiveGestureAnimation::createWithTimeOffset(PassOwnPtr<WebGestureCurve> curve, WebGestureCurveTarget* target, double startTime)
 {
-    return adoptPtr(new WebActiveGestureAnimation(curve, target, startTime, false));
+    return adoptPtr(new WebActiveGestureAnimation(std::move(curve), target, startTime, false));
 }
 
 WebActiveGestureAnimation::~WebActiveGestureAnimation()
@@ -48,7 +48,7 @@
 WebActiveGestureAnimation::WebActiveGestureAnimation(PassOwnPtr<WebGestureCurve> curve, WebGestureCurveTarget* target, double startTime, bool waitingForFirstTick)
     : m_startTime(startTime)
     , m_waitingForFirstTick(waitingForFirstTick)
-    , m_curve(curve)
+    , m_curve(std::move(curve))
     , m_target(target)
 {
 }
diff --git a/third_party/WebKit/Source/platform/exported/WebCryptoAlgorithm.cpp b/third_party/WebKit/Source/platform/exported/WebCryptoAlgorithm.cpp
index 7c8e882..bfd61b6 100644
--- a/third_party/WebKit/Source/platform/exported/WebCryptoAlgorithm.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebCryptoAlgorithm.cpp
@@ -298,7 +298,7 @@
 public:
     WebCryptoAlgorithmPrivate(WebCryptoAlgorithmId id, PassOwnPtr<WebCryptoAlgorithmParams> params)
         : id(id)
-        , params(params)
+        , params(std::move(params))
     {
     }
 
@@ -307,7 +307,7 @@
 };
 
 WebCryptoAlgorithm::WebCryptoAlgorithm(WebCryptoAlgorithmId id, PassOwnPtr<WebCryptoAlgorithmParams> params)
-    : m_private(adoptRef(new WebCryptoAlgorithmPrivate(id, params)))
+    : m_private(adoptRef(new WebCryptoAlgorithmPrivate(id, std::move(params))))
 {
 }
 
diff --git a/third_party/WebKit/Source/platform/exported/WebCryptoKey.cpp b/third_party/WebKit/Source/platform/exported/WebCryptoKey.cpp
index 74d0ca7..248ff6d 100644
--- a/third_party/WebKit/Source/platform/exported/WebCryptoKey.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebCryptoKey.cpp
@@ -42,7 +42,7 @@
 class WebCryptoKeyPrivate : public ThreadSafeRefCounted<WebCryptoKeyPrivate> {
 public:
     WebCryptoKeyPrivate(PassOwnPtr<WebCryptoKeyHandle> handle, WebCryptoKeyType type, bool extractable, const WebCryptoKeyAlgorithm& algorithm, WebCryptoKeyUsageMask usages)
-        : handle(handle)
+        : handle(std::move(handle))
         , type(type)
         , extractable(extractable)
         , algorithm(algorithm)
diff --git a/third_party/WebKit/Source/platform/exported/WebCryptoKeyAlgorithm.cpp b/third_party/WebKit/Source/platform/exported/WebCryptoKeyAlgorithm.cpp
index d2d259855..66058ead 100644
--- a/third_party/WebKit/Source/platform/exported/WebCryptoKeyAlgorithm.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebCryptoKeyAlgorithm.cpp
@@ -46,7 +46,7 @@
 public:
     WebCryptoKeyAlgorithmPrivate(WebCryptoAlgorithmId id, PassOwnPtr<WebCryptoKeyAlgorithmParams> params)
         : id(id)
-        , params(params)
+        , params(std::move(params))
     {
     }
 
@@ -55,7 +55,7 @@
 };
 
 WebCryptoKeyAlgorithm::WebCryptoKeyAlgorithm(WebCryptoAlgorithmId id, PassOwnPtr<WebCryptoKeyAlgorithmParams> params)
-    : m_private(adoptRef(new WebCryptoKeyAlgorithmPrivate(id, params)))
+    : m_private(adoptRef(new WebCryptoKeyAlgorithmPrivate(id, std::move(params))))
 {
 }
 
diff --git a/third_party/WebKit/Source/platform/exported/WebFilterKeyframe.cpp b/third_party/WebKit/Source/platform/exported/WebFilterKeyframe.cpp
index 454d317e..be6774e4 100644
--- a/third_party/WebKit/Source/platform/exported/WebFilterKeyframe.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebFilterKeyframe.cpp
@@ -31,7 +31,7 @@
 
 WebFilterKeyframe::WebFilterKeyframe(double time, PassOwnPtr<WebFilterOperations> value)
     : m_time(time)
-    , m_value(value)
+    , m_value(std::move(value))
 {
 }
 
diff --git a/third_party/WebKit/Source/platform/exported/WebMediaStream.cpp b/third_party/WebKit/Source/platform/exported/WebMediaStream.cpp
index 42f7fa3..5fd7fbb7 100644
--- a/third_party/WebKit/Source/platform/exported/WebMediaStream.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebMediaStream.cpp
@@ -43,7 +43,7 @@
 
 class ExtraDataContainer : public MediaStreamDescriptor::ExtraData {
 public:
-    ExtraDataContainer(PassOwnPtr<WebMediaStream::ExtraData> extraData) : m_extraData(extraData) { }
+    ExtraDataContainer(PassOwnPtr<WebMediaStream::ExtraData> extraData) : m_extraData(std::move(extraData)) { }
 
     WebMediaStream::ExtraData* extraData() { return m_extraData.get(); }
 
diff --git a/third_party/WebKit/Source/platform/exported/WebMediaStreamSource.cpp b/third_party/WebKit/Source/platform/exported/WebMediaStreamSource.cpp
index 79fe106..5659e6c 100644
--- a/third_party/WebKit/Source/platform/exported/WebMediaStreamSource.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebMediaStreamSource.cpp
@@ -47,7 +47,7 @@
 
 class ExtraDataContainer : public MediaStreamSource::ExtraData {
 public:
-    ExtraDataContainer(PassOwnPtr<WebMediaStreamSource::ExtraData> extraData) : m_extraData(extraData) { }
+    ExtraDataContainer(PassOwnPtr<WebMediaStreamSource::ExtraData> extraData) : m_extraData(std::move(extraData)) { }
 
     WebMediaStreamSource::ExtraData* extraData() { return m_extraData.get(); }
 
diff --git a/third_party/WebKit/Source/platform/exported/WebMediaStreamTrack.cpp b/third_party/WebKit/Source/platform/exported/WebMediaStreamTrack.cpp
index 804e957..bc4460c 100644
--- a/third_party/WebKit/Source/platform/exported/WebMediaStreamTrack.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebMediaStreamTrack.cpp
@@ -39,7 +39,7 @@
 
 class ExtraDataContainer : public MediaStreamComponent::ExtraData {
 public:
-    explicit ExtraDataContainer(PassOwnPtr<WebMediaStreamTrack::ExtraData> extraData) : m_extraData(extraData) { }
+    explicit ExtraDataContainer(PassOwnPtr<WebMediaStreamTrack::ExtraData> extraData) : m_extraData(std::move(extraData)) { }
 
     WebMediaStreamTrack::ExtraData* extraData() { return m_extraData.get(); }
 
diff --git a/third_party/WebKit/Source/platform/exported/WebTransformKeyframe.cpp b/third_party/WebKit/Source/platform/exported/WebTransformKeyframe.cpp
index 8bf333f..0c28e77 100644
--- a/third_party/WebKit/Source/platform/exported/WebTransformKeyframe.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebTransformKeyframe.cpp
@@ -31,7 +31,7 @@
 
 WebTransformKeyframe::WebTransformKeyframe(double time, PassOwnPtr<WebTransformOperations> value)
     : m_time(time)
-    , m_value(value)
+    , m_value(std::move(value))
 {
 }
 
diff --git a/third_party/WebKit/Source/platform/fonts/ScriptRunIterator.cpp b/third_party/WebKit/Source/platform/fonts/ScriptRunIterator.cpp
index d326083..ced65ee3 100644
--- a/third_party/WebKit/Source/platform/fonts/ScriptRunIterator.cpp
+++ b/third_party/WebKit/Source/platform/fonts/ScriptRunIterator.cpp
@@ -111,7 +111,7 @@
 
 const ICUScriptData* ICUScriptData::instance()
 {
-    AtomicallyInitializedStaticReference(const ICUScriptData, icuScriptDataInstance, (new ICUScriptData()));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(const ICUScriptData, icuScriptDataInstance, (new ICUScriptData()));
     return &icuScriptDataInstance;
 }
 
diff --git a/third_party/WebKit/Source/platform/fonts/ScriptRunIteratorTest.cpp b/third_party/WebKit/Source/platform/fonts/ScriptRunIteratorTest.cpp
index c7beb0f3..432d923 100644
--- a/third_party/WebKit/Source/platform/fonts/ScriptRunIteratorTest.cpp
+++ b/third_party/WebKit/Source/platform/fonts/ScriptRunIteratorTest.cpp
@@ -36,7 +36,7 @@
 
     static const MockScriptData* instance()
     {
-        AtomicallyInitializedStaticReference(const MockScriptData, mockScriptData, (new MockScriptData()));
+        DEFINE_STATIC_LOCAL_THREAD_SAFE(const MockScriptData, mockScriptData, (new MockScriptData()));
 
         return &mockScriptData;
     }
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp
index c8a5a00..60e3534f 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp
@@ -634,7 +634,7 @@
     hb_buffer_t* harfBuzzBuffer)
 {
     ASSERT(numGlyphs > 0);
-    OwnPtr<ShapeResult::RunInfo> run(runToInsert);
+    OwnPtr<ShapeResult::RunInfo> run(std::move(runToInsert));
 
     const SimpleFontData* currentFontData = run->m_fontData.get();
     hb_glyph_info_t* glyphInfos = hb_buffer_get_glyph_infos(harfBuzzBuffer, 0);
diff --git a/third_party/WebKit/Source/platform/geometry/FloatPolygon.cpp b/third_party/WebKit/Source/platform/geometry/FloatPolygon.cpp
index 11fc6be..7b214ee 100644
--- a/third_party/WebKit/Source/platform/geometry/FloatPolygon.cpp
+++ b/third_party/WebKit/Source/platform/geometry/FloatPolygon.cpp
@@ -80,7 +80,7 @@
 }
 
 FloatPolygon::FloatPolygon(PassOwnPtr<Vector<FloatPoint>> vertices, WindRule fillRule)
-    : m_vertices(vertices)
+    : m_vertices(std::move(vertices))
     , m_fillRule(fillRule)
 {
     unsigned nVertices = numberOfVertices();
diff --git a/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp b/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
index 38cbbf4..272e408 100644
--- a/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
+++ b/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
@@ -31,6 +31,7 @@
 #include "platform/Timer.h"
 #include "platform/TraceEvent.h"
 #include "platform/geometry/FloatRect.h"
+#include "platform/graphics/BitmapImageMetrics.h"
 #include "platform/graphics/DeferredImageDecoder.h"
 #include "platform/graphics/ImageObserver.h"
 #include "platform/graphics/StaticBitmapImage.h"
@@ -327,24 +328,6 @@
     return m_frameCount;
 }
 
-enum DecodedImageType {
-    // These values are histogrammed over time; do not change their ordinal
-    // values.  When deleting an image type, replace it with a dummy value;
-    // when adding an image type, do so at the bottom (and update LastDecodedImageType
-    // so that it equals the last real image type).
-    // Also, this enum should be in sync with the 'DecodedImageType' enum in
-    // src/tools/metrics/histograms/histograms.xml
-    ImageUnknown = 0,
-    ImageJPEG,
-    ImagePNG,
-    ImageGIF,
-    ImageWebP,
-    ImageICO,
-    ImageBMP,
-
-    LastDecodedImageType = ImageBMP
-};
-
 static inline bool hasVisibleImageSize(IntSize size)
 {
     return (size.width() > 1 || size.height() > 1);
@@ -358,17 +341,8 @@
     m_sizeAvailable = m_source.isSizeAvailable();
 
     if (m_sizeAvailable && hasVisibleImageSize(size())) {
-        String fileExtention = m_source.filenameExtension();
-        DecodedImageType type =
-            fileExtention == "jpg"  ? ImageJPEG :
-            fileExtention == "png"  ? ImagePNG :
-            fileExtention == "gif"  ? ImageGIF :
-            fileExtention == "webp" ? ImageWebP :
-            fileExtention == "ico"  ? ImageICO :
-            fileExtention == "bmp"  ? ImageBMP :
-            ImageUnknown;
-        Platform::current()->histogramEnumeration("Blink.DecodedImageType", type, LastDecodedImageType + 1);
-        Platform::current()->histogramEnumeration("Blink.DecodedImage.Orientation", m_source.orientationAtIndex(0).orientation(), ImageOrientationEnumEnd);
+        BitmapImageMetrics::countDecodedImageType(m_source.filenameExtension());
+        BitmapImageMetrics::countImageOrientation(m_source.orientationAtIndex(0).orientation());
     }
 
     return m_sizeAvailable;
diff --git a/third_party/WebKit/Source/platform/graphics/BitmapImageMetrics.cpp b/third_party/WebKit/Source/platform/graphics/BitmapImageMetrics.cpp
new file mode 100644
index 0000000..c8a9715
--- /dev/null
+++ b/third_party/WebKit/Source/platform/graphics/BitmapImageMetrics.cpp
@@ -0,0 +1,42 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "platform/graphics/BitmapImageMetrics.h"
+
+#include "public/platform/Platform.h"
+#include "wtf/text/WTFString.h"
+
+namespace blink {
+
+void BitmapImageMetrics::countDecodedImageType(const String& type)
+{
+    enum DecodedImageType { // Values synced with 'DecodedImageType' in src/tools/metrics/histograms/histograms.xml
+        ImageUnknown = 0,
+        ImageJPEG = 1,
+        ImagePNG = 2,
+        ImageGIF = 3,
+        ImageWebP = 4,
+        ImageICO = 5,
+        ImageBMP = 6,
+        DecodedImageTypeEnumEnd = ImageBMP + 1
+    };
+
+    DecodedImageType decodedImageType =
+        type == "jpg"  ? ImageJPEG :
+        type == "png"  ? ImagePNG  :
+        type == "gif"  ? ImageGIF  :
+        type == "webp" ? ImageWebP :
+        type == "ico"  ? ImageICO  :
+        type == "bmp"  ? ImageBMP  : DecodedImageType::ImageUnknown;
+
+    Platform::current()->histogramEnumeration("Blink.DecodedImageType", decodedImageType, DecodedImageTypeEnumEnd);
+}
+
+void BitmapImageMetrics::countImageOrientation(const ImageOrientationEnum orientation)
+{
+    Platform::current()->histogramEnumeration("Blink.DecodedImage.Orientation", orientation, ImageOrientationEnumEnd);
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/BitmapImageMetrics.h b/third_party/WebKit/Source/platform/graphics/BitmapImageMetrics.h
new file mode 100644
index 0000000..6d5b862
--- /dev/null
+++ b/third_party/WebKit/Source/platform/graphics/BitmapImageMetrics.h
@@ -0,0 +1,24 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BitmapImageMetrics_h
+#define BitmapImageMetrics_h
+
+#include "platform/PlatformExport.h"
+#include "platform/graphics/ImageOrientation.h"
+#include "wtf/Allocator.h"
+#include "wtf/Forward.h"
+
+namespace blink {
+
+class PLATFORM_EXPORT BitmapImageMetrics {
+    STATIC_ONLY(BitmapImageMetrics);
+public:
+    static void countDecodedImageType(const String& type);
+    static void countImageOrientation(const ImageOrientationEnum);
+};
+
+} // namespace blink
+
+#endif
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
index e8c7bdfe..249ab19 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -105,7 +105,7 @@
 }
 
 Canvas2DLayerBridge::Canvas2DLayerBridge(PassOwnPtr<WebGraphicsContext3DProvider> contextProvider, const IntSize& size, int msaaSampleCount, OpacityMode opacityMode, AccelerationMode accelerationMode)
-    : m_contextProvider(contextProvider)
+    : m_contextProvider(std::move(contextProvider))
     , m_logger(adoptPtr(new Logger))
     , m_weakPtrFactory(this)
     , m_imageBuffer(0)
@@ -157,7 +157,7 @@
 
 void Canvas2DLayerBridge::setLoggerForTesting(PassOwnPtr<Logger> logger)
 {
-    m_logger = logger;
+    m_logger = std::move(logger);
 }
 
 bool Canvas2DLayerBridge::shouldAccelerate(AccelerationHint hint) const
diff --git a/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp b/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp
index af5600f6..8886705d 100644
--- a/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp
@@ -76,32 +76,31 @@
 {
     TRACE_EVENT0("blink,benchmark", "ContentLayerDelegate::paintContents");
 
-    PaintController* paintController = m_painter->paintController();
-    ASSERT(paintController);
-    paintController->setDisplayItemConstructionIsDisabled(
+    PaintController& paintController = m_painter->paintController();
+    paintController.setDisplayItemConstructionIsDisabled(
         paintingControl == WebContentLayerClient::DisplayListConstructionDisabled);
 
     // We also disable caching when Painting or Construction are disabled. In both cases we would like
     // to compare assuming the full cost of recording, not the cost of re-using cached content.
     if (paintingControl != WebContentLayerClient::PaintDefaultBehavior)
-        paintController->invalidateAll();
+        paintController.invalidateAll();
 
     GraphicsContext::DisabledMode disabledMode = GraphicsContext::NothingDisabled;
     if (paintingControl == WebContentLayerClient::DisplayListPaintingDisabled
         || paintingControl == WebContentLayerClient::DisplayListConstructionDisabled)
         disabledMode = GraphicsContext::FullyDisabled;
-    GraphicsContext context(*paintController, disabledMode);
+    GraphicsContext context(paintController, disabledMode);
 
     m_painter->paint(context, nullptr);
 
-    paintController->commitNewDisplayItems();
-    paintArtifactToWebDisplayItemList(webDisplayItemList, paintController->paintArtifact(), paintableRegion());
-    paintController->setDisplayItemConstructionIsDisabled(false);
+    paintController.commitNewDisplayItems();
+    paintArtifactToWebDisplayItemList(webDisplayItemList, paintController.paintArtifact(), paintableRegion());
+    paintController.setDisplayItemConstructionIsDisabled(false);
 }
 
 size_t ContentLayerDelegate::approximateUnsharedMemoryUsage() const
 {
-    return m_painter->paintController()->approximateUnsharedMemoryUsage();
+    return m_painter->paintController().approximateUnsharedMemoryUsage();
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.h b/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.h
index b1a86a1..5f1d80c0 100644
--- a/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.h
+++ b/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.h
@@ -48,7 +48,7 @@
 public:
     virtual IntRect interestRect() = 0;
     virtual void paint(GraphicsContext&, const IntRect* interestRect) = 0;
-    virtual PaintController* paintController() = 0;
+    virtual PaintController& paintController() = 0;
 
 protected:
     virtual ~GraphicsContextPainter() { }
diff --git a/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.cpp b/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.cpp
index 960d5e0..0005bb59 100644
--- a/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.cpp
@@ -50,13 +50,13 @@
 
 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::createForTesting(PassOwnPtr<ImageDecoder> actualDecoder)
 {
-    return adoptPtr(new DeferredImageDecoder(actualDecoder));
+    return adoptPtr(new DeferredImageDecoder(std::move(actualDecoder)));
 }
 
 DeferredImageDecoder::DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecoder)
     : m_allDataReceived(false)
     , m_lastDataSize(0)
-    , m_actualDecoder(actualDecoder)
+    , m_actualDecoder(std::move(actualDecoder))
     , m_repetitionCount(cAnimationNone)
     , m_hasColorProfile(false)
     , m_canYUVDecode(false)
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
index cde702f0..5a289ed7 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
@@ -326,8 +326,8 @@
     }
 
     if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) {
-        if (!m_client->needsRepaint() && !paintController()->cacheIsEmpty() && m_previousInterestRect == *interestRect) {
-            paintController()->createAndAppend<CachedDisplayItem>(*this, DisplayItem::CachedDisplayItemList);
+        if (!m_client->needsRepaint() && !paintController().cacheIsEmpty() && m_previousInterestRect == *interestRect) {
+            paintController().createAndAppend<CachedDisplayItem>(*this, DisplayItem::CachedDisplayItemList);
             return;
         }
     }
@@ -1031,7 +1031,7 @@
     for (size_t i = 0; i < m_linkHighlights.size(); ++i)
         m_linkHighlights[i]->invalidate();
 
-    paintController()->invalidateAll();
+    paintController().invalidateAll();
     if (isTrackingPaintInvalidations())
         trackPaintInvalidationObject("##ALL##");
 }
@@ -1052,7 +1052,10 @@
 
 void GraphicsLayer::invalidateDisplayItemClient(const DisplayItemClient& displayItemClient, PaintInvalidationReason paintInvalidationReason, const IntRect* visualRect)
 {
-    paintController()->invalidate(displayItemClient, paintInvalidationReason, visualRect);
+    if (!drawsContent())
+        return;
+
+    paintController().invalidate(displayItemClient, paintInvalidationReason, visualRect);
     if (isTrackingPaintInvalidations())
         trackPaintInvalidationObject(displayItemClient.debugName());
 }
@@ -1097,7 +1100,7 @@
 
 bool GraphicsLayer::addAnimation(PassOwnPtr<WebCompositorAnimation> popAnimation)
 {
-    OwnPtr<WebCompositorAnimation> animation(popAnimation);
+    OwnPtr<WebCompositorAnimation> animation(std::move(popAnimation));
     ASSERT(animation);
     platformLayer()->setAnimationDelegate(this);
 
@@ -1214,11 +1217,12 @@
     return tracedValue;
 }
 
-PaintController* GraphicsLayer::paintController()
+PaintController& GraphicsLayer::paintController()
 {
+    RELEASE_ASSERT(drawsContent());
     if (!m_paintController)
         m_paintController = PaintController::create();
-    return m_paintController.get();
+    return *m_paintController;
 }
 
 void GraphicsLayer::setElementId(uint64_t id)
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
index 8fbd829..87e9e56b 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
@@ -256,7 +256,7 @@
     // cc::LayerClient implementation.
     scoped_refptr<base::trace_event::ConvertableToTraceFormat> TakeDebugInfo(cc::Layer*) override;
 
-    PaintController* paintController() override;
+    PaintController& paintController() override;
 
     // Exposed for tests.
     WebLayer* contentsLayer() const { return m_contentsLayer; }
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
index f48174e..53c7d44 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
@@ -64,7 +64,7 @@
 {
     if (!surface->isValid())
         return nullptr;
-    return adoptPtr(new ImageBuffer(surface));
+    return adoptPtr(new ImageBuffer(std::move(surface)));
 }
 
 PassOwnPtr<ImageBuffer> ImageBuffer::create(const IntSize& size, OpacityMode opacityMode, ImageInitializationMode initializationMode)
@@ -77,7 +77,7 @@
 
 ImageBuffer::ImageBuffer(PassOwnPtr<ImageBufferSurface> surface)
     : m_snapshotState(InitialSnapshotState)
-    , m_surface(surface)
+    , m_surface(std::move(surface))
     , m_client(0)
     , m_gpuMemoryUsage(0)
 {
diff --git a/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.cpp b/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.cpp
index f65428b4..a488419 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.cpp
@@ -55,7 +55,7 @@
 
 ImageDecodingStore& ImageDecodingStore::instance()
 {
-    AtomicallyInitializedStaticReference(ImageDecodingStore, store, ImageDecodingStore::create().leakPtr());
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(ImageDecodingStore, store, ImageDecodingStore::create().leakPtr());
     return store;
 }
 
@@ -96,7 +96,7 @@
     // Prune old cache entries to give space for the new one.
     prune();
 
-    OwnPtr<DecoderCacheEntry> newCacheEntry = DecoderCacheEntry::create(generator, decoder);
+    OwnPtr<DecoderCacheEntry> newCacheEntry = DecoderCacheEntry::create(generator, std::move(decoder));
 
     MutexLocker lock(m_mutex);
     ASSERT(!m_decoderCacheMap.contains(newCacheEntry->cacheKey()));
@@ -220,7 +220,7 @@
     typename U::KeyType key = cacheEntry->cacheKey();
     typename V::AddResult result = identifierMap->add(cacheEntry->generator(), typename V::MappedType());
     result.storedValue->value.add(key);
-    cacheMap->add(key, cacheEntry);
+    cacheMap->add(key, std::move(cacheEntry));
 
     TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.image_decoding"), "ImageDecodingStoreHeapMemoryUsageBytes", m_heapMemoryUsageInBytes);
     TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.image_decoding"), "ImageDecodingStoreNumOfDecoders", m_decoderCacheMap.size());
diff --git a/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.h b/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.h
index 0ff40b3..3d94a35 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.h
+++ b/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.h
@@ -138,12 +138,12 @@
     public:
         static PassOwnPtr<DecoderCacheEntry> create(const ImageFrameGenerator* generator, PassOwnPtr<ImageDecoder> decoder)
         {
-            return adoptPtr(new DecoderCacheEntry(generator, 0, decoder));
+            return adoptPtr(new DecoderCacheEntry(generator, 0, std::move(decoder)));
         }
 
         DecoderCacheEntry(const ImageFrameGenerator* generator, int count, PassOwnPtr<ImageDecoder> decoder)
             : CacheEntry(generator, count)
-            , m_cachedDecoder(decoder)
+            , m_cachedDecoder(std::move(decoder))
             , m_size(SkISize::Make(m_cachedDecoder->decodedSize().width(), m_cachedDecoder->decodedSize().height()))
         {
         }
diff --git a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.h b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.h
index acf7b75..2924cad 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.h
+++ b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.h
@@ -97,7 +97,7 @@
     friend class ImageFrameGeneratorTest;
     friend class DeferredImageDecoderTest;
     // For testing. |factory| will overwrite the default ImageDecoder creation logic if |factory->create()| returns non-zero.
-    void setImageDecoderFactory(PassOwnPtr<ImageDecoderFactory> factory) { m_imageDecoderFactory = factory; }
+    void setImageDecoderFactory(PassOwnPtr<ImageDecoderFactory> factory) { m_imageDecoderFactory = std::move(factory); }
 
     void setHasAlpha(size_t index, bool hasAlpha);
 
diff --git a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp
index 0c187dd8..a995604 100644
--- a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp
+++ b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp
@@ -27,7 +27,7 @@
     , m_didRecordDrawCommandsInCurrentFrame(false)
     , m_currentFrameHasExpensiveOp(false)
     , m_previousFrameHasExpensiveOp(false)
-    , m_fallbackFactory(fallbackFactory)
+    , m_fallbackFactory(std::move(fallbackFactory))
 {
     initializeCurrentFrame();
 }
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
index ee13ad8d..f2025cf 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -120,7 +120,7 @@
     if (discardFramebufferSupported)
         extensionsUtil->ensureExtensionEnabled("GL_EXT_discard_framebuffer");
 
-    RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(context, extensionsUtil.release(), multisampleSupported, packedDepthStencilSupported, discardFramebufferSupported, preserve, requestedAttributes));
+    RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(std::move(context), extensionsUtil.release(), multisampleSupported, packedDepthStencilSupported, discardFramebufferSupported, preserve, requestedAttributes));
     if (!drawingBuffer->initialize(size)) {
         drawingBuffer->beginDestruction();
         return PassRefPtr<DrawingBuffer>();
@@ -146,8 +146,8 @@
     , m_drawFramebufferBinding(0)
     , m_readFramebufferBinding(0)
     , m_activeTextureUnit(GL_TEXTURE0)
-    , m_context(context)
-    , m_extensionsUtil(extensionsUtil)
+    , m_context(std::move(context))
+    , m_extensionsUtil(std::move(extensionsUtil))
     , m_size(-1, -1)
     , m_requestedAttributes(requestedAttributes)
     , m_multisampleExtensionSupported(multisampleExtensionSupported)
diff --git a/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.cpp
index f107ce7..5c2cf44 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.cpp
@@ -10,20 +10,10 @@
 
 namespace blink {
 
-static FloatRect mapImageFilterRect(SkImageFilter* filter, const FloatRect& bounds)
-{
-    SkRect filterBounds;
-    filter->computeFastBounds(bounds, &filterBounds);
-    filterBounds.offset(-bounds.x(), -bounds.y());
-    return filterBounds;
-}
-
 void BeginFilterDisplayItem::replay(GraphicsContext& context) const
 {
+    FloatRect imageFilterBounds(FloatPoint(), m_bounds.size());
     context.save();
-
-    FloatRect imageFilterBounds = mapImageFilterRect(m_imageFilter.get(), m_bounds);
-
     context.translate(m_bounds.x(), m_bounds.y());
     context.beginLayer(1, SkXfermode::kSrcOver_Mode, &imageFilterBounds, ColorFilterNone, m_imageFilter.get());
     context.translate(-m_bounds.x(), -m_bounds.y());
diff --git a/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.h
index 9d4ce95..750082a 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.h
@@ -21,7 +21,7 @@
     BeginFilterDisplayItem(const DisplayItemClient& client, PassRefPtr<SkImageFilter> imageFilter, const FloatRect& bounds, PassOwnPtr<WebFilterOperations> filterOperations = nullptr)
         : PairedBeginDisplayItem(client, BeginFilter, sizeof(*this))
         , m_imageFilter(imageFilter)
-        , m_webFilterOperations(filterOperations)
+        , m_webFilterOperations(std::move(filterOperations))
         , m_bounds(bounds) { }
 
     void replay(GraphicsContext&) const override;
diff --git a/third_party/WebKit/Source/platform/heap/GCInfo.cpp b/third_party/WebKit/Source/platform/heap/GCInfo.cpp
index 3b502f3..db5f87e 100644
--- a/third_party/WebKit/Source/platform/heap/GCInfo.cpp
+++ b/third_party/WebKit/Source/platform/heap/GCInfo.cpp
@@ -22,7 +22,7 @@
     ASSERT(gcInfo);
     ASSERT(gcInfoIndexSlot);
     // Keep a global GCInfoTable lock while allocating a new slot.
-    AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(Mutex, mutex, new Mutex);
     MutexLocker locker(mutex);
 
     // If more than one thread ends up allocating a slot for
diff --git a/third_party/WebKit/Source/platform/heap/Heap.cpp b/third_party/WebKit/Source/platform/heap/Heap.cpp
index d1d40cec..8d17306 100644
--- a/third_party/WebKit/Source/platform/heap/Heap.cpp
+++ b/third_party/WebKit/Source/platform/heap/Heap.cpp
@@ -655,7 +655,7 @@
 
 static Mutex& regionTreeMutex()
 {
-    AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(Mutex, mutex, new Mutex);
     return mutex;
 }
 
diff --git a/third_party/WebKit/Source/platform/heap/HeapTest.cpp b/third_party/WebKit/Source/platform/heap/HeapTest.cpp
index 02fa6ee..f4cadcf23 100644
--- a/third_party/WebKit/Source/platform/heap/HeapTest.cpp
+++ b/third_party/WebKit/Source/platform/heap/HeapTest.cpp
@@ -5321,13 +5321,13 @@
 
 static Mutex& mainThreadMutex()
 {
-    AtomicallyInitializedStaticReference(Mutex, mainMutex, new Mutex);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(Mutex, mainMutex, new Mutex);
     return mainMutex;
 }
 
 static ThreadCondition& mainThreadCondition()
 {
-    AtomicallyInitializedStaticReference(ThreadCondition, mainCondition, new ThreadCondition);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(ThreadCondition, mainCondition, new ThreadCondition);
     return mainCondition;
 }
 
@@ -5344,13 +5344,13 @@
 
 static Mutex& workerThreadMutex()
 {
-    AtomicallyInitializedStaticReference(Mutex, workerMutex, new Mutex);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(Mutex, workerMutex, new Mutex);
     return workerMutex;
 }
 
 static ThreadCondition& workerThreadCondition()
 {
-    AtomicallyInitializedStaticReference(ThreadCondition, workerCondition, new ThreadCondition);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(ThreadCondition, workerCondition, new ThreadCondition);
     return workerCondition;
 }
 
@@ -5645,7 +5645,7 @@
 
 static RecursiveMutex& recursiveMutex()
 {
-    AtomicallyInitializedStaticReference(RecursiveMutex, recursiveMutex, new RecursiveMutex);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(RecursiveMutex, recursiveMutex, new RecursiveMutex);
     return recursiveMutex;
 }
 
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.cpp b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
index 8670018..26ede92f 100644
--- a/third_party/WebKit/Source/platform/heap/ThreadState.cpp
+++ b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
@@ -75,7 +75,7 @@
 
 RecursiveMutex& ThreadState::threadAttachMutex()
 {
-    AtomicallyInitializedStaticReference(RecursiveMutex, mutex, (new RecursiveMutex));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(RecursiveMutex, mutex, (new RecursiveMutex));
     return mutex;
 }
 
@@ -494,7 +494,7 @@
 
 CrossThreadPersistentRegion& ThreadState::crossThreadPersistentRegion()
 {
-    AtomicallyInitializedStaticReference(CrossThreadPersistentRegion, persistentRegion, new CrossThreadPersistentRegion());
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(CrossThreadPersistentRegion, persistentRegion, new CrossThreadPersistentRegion());
     return persistentRegion;
 }
 
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
index 36075eea0..69a73f78 100644
--- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
+++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
@@ -255,7 +255,7 @@
 
     static qcms_profile* qcmsOutputDeviceProfile()
     {
-        AtomicallyInitializedStaticReference(OutputDeviceProfile, outputDeviceProfile, new OutputDeviceProfile);
+        DEFINE_STATIC_LOCAL_THREAD_SAFE(OutputDeviceProfile, outputDeviceProfile, new OutputDeviceProfile);
 
         return outputDeviceProfile.profile();
     }
diff --git a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
index 1704bc2..91ff175 100644
--- a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
@@ -650,11 +650,19 @@
         qcms_profile* inputProfile = qcms_profile_from_memory(colorProfile.data(), colorProfile.size());
         if (!inputProfile)
             return;
+
         // We currently only support color profiles for RGB profiled images.
         ASSERT(rgbData == qcms_profile_get_color_space(inputProfile));
-        qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8;
+
+        if (qcms_profile_match(inputProfile, deviceProfile)) {
+            qcms_profile_release(inputProfile);
+            return;
+        }
+
         // FIXME: Don't force perceptual intent if the image profile contains an intent.
+        qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8;
         m_transform = qcms_transform_create(inputProfile, dataFormat, deviceProfile, dataFormat, QCMS_INTENT_PERCEPTUAL);
+
         qcms_profile_release(inputProfile);
     }
 #endif
@@ -839,7 +847,7 @@
 
 void JPEGImageDecoder::setImagePlanes(PassOwnPtr<ImagePlanes> imagePlanes)
 {
-    m_imagePlanes = imagePlanes;
+    m_imagePlanes = std::move(imagePlanes);
 }
 
 template <J_COLOR_SPACE colorSpace> void setPixel(ImageFrame& buffer, ImageFrame::PixelData* pixel, JSAMPARRAY samples, int column)
diff --git a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp
index 9cf5ad6..a5083a7 100644
--- a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp
@@ -174,11 +174,19 @@
             inputProfile = qcms_profile_sRGB();
         if (!inputProfile)
             return;
+
         // We currently only support color profiles for RGB and RGBA images.
         ASSERT(rgbData == qcms_profile_get_color_space(inputProfile));
-        qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8;
+
+        if (qcms_profile_match(inputProfile, deviceProfile)) {
+            qcms_profile_release(inputProfile);
+            return;
+        }
+
         // FIXME: Don't force perceptual intent if the image profile contains an intent.
+        qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8;
         m_transform = qcms_transform_create(inputProfile, dataFormat, deviceProfile, dataFormat, QCMS_INTENT_PERCEPTUAL);
+
         qcms_profile_release(inputProfile);
     }
 #endif
diff --git a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp
index 8653487..16df7c6 100644
--- a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp
@@ -329,6 +329,12 @@
 
     // We currently only support color profiles for RGB profiled images.
     ASSERT(rgbData == qcms_profile_get_color_space(inputProfile));
+
+    if (qcms_profile_match(inputProfile, deviceProfile)) {
+        qcms_profile_release(inputProfile);
+        return false;
+    }
+
     // The input image pixels are RGBA format.
     qcms_data_type format = QCMS_DATA_RGBA_8;
     // FIXME: Don't force perceptual intent if the image profile contains an intent.
diff --git a/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.h b/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.h
index 8a826e21..a07dff05 100644
--- a/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.h
+++ b/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.h
@@ -75,7 +75,7 @@
 #endif // ENABLE(WEB_AUDIO)
 
     ExtraData* extraData() const { return m_extraData.get(); }
-    void setExtraData(PassOwnPtr<ExtraData> extraData) { m_extraData = extraData; }
+    void setExtraData(PassOwnPtr<ExtraData> extraData) { m_extraData = std::move(extraData); }
 
     DECLARE_TRACE();
 
diff --git a/third_party/WebKit/Source/platform/mediastream/MediaStreamDescriptor.h b/third_party/WebKit/Source/platform/mediastream/MediaStreamDescriptor.h
index 89e55c7..13c0b56 100644
--- a/third_party/WebKit/Source/platform/mediastream/MediaStreamDescriptor.h
+++ b/third_party/WebKit/Source/platform/mediastream/MediaStreamDescriptor.h
@@ -90,7 +90,7 @@
     void setEnded() { m_ended = true; }
 
     ExtraData* extraData() const { return m_extraData.get(); }
-    void setExtraData(PassOwnPtr<ExtraData> extraData) { m_extraData = extraData; }
+    void setExtraData(PassOwnPtr<ExtraData> extraData) { m_extraData = std::move(extraData); }
 
     // |m_extraData| may hold pointers to GC objects, and it may touch them in destruction.
     // So this class is eagerly finalized to finalize |m_extraData| promptly.
diff --git a/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.h b/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.h
index 66364b5a..d791cb5 100644
--- a/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.h
+++ b/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.h
@@ -84,7 +84,7 @@
     void addObserver(Observer*);
 
     ExtraData* extraData() const { return m_extraData.get(); }
-    void setExtraData(PassOwnPtr<ExtraData> extraData) { m_extraData = extraData; }
+    void setExtraData(PassOwnPtr<ExtraData> extraData) { m_extraData = std::move(extraData); }
 
     void setConstraints(WebMediaConstraints constraints) { m_constraints = constraints; }
     WebMediaConstraints constraints() { return m_constraints; }
diff --git a/third_party/WebKit/Source/platform/mediastream/MediaStreamWebAudioSource.cpp b/third_party/WebKit/Source/platform/mediastream/MediaStreamWebAudioSource.cpp
index 488f282..35aad12 100644
--- a/third_party/WebKit/Source/platform/mediastream/MediaStreamWebAudioSource.cpp
+++ b/third_party/WebKit/Source/platform/mediastream/MediaStreamWebAudioSource.cpp
@@ -38,7 +38,7 @@
 namespace blink {
 
 MediaStreamWebAudioSource::MediaStreamWebAudioSource(PassOwnPtr<WebAudioSourceProvider> provider)
-    : m_webAudioSourceProvider(provider)
+    : m_webAudioSourceProvider(std::move(provider))
 {
 }
 
diff --git a/third_party/WebKit/Source/platform/mediastream/MediaStreamWebAudioSource.h b/third_party/WebKit/Source/platform/mediastream/MediaStreamWebAudioSource.h
index 4b42ced..6cb2278 100644
--- a/third_party/WebKit/Source/platform/mediastream/MediaStreamWebAudioSource.h
+++ b/third_party/WebKit/Source/platform/mediastream/MediaStreamWebAudioSource.h
@@ -44,7 +44,7 @@
 class MediaStreamWebAudioSource : public AudioSourceProvider {
     WTF_MAKE_NONCOPYABLE(MediaStreamWebAudioSource);
 public:
-    static PassOwnPtr<MediaStreamWebAudioSource> create(PassOwnPtr<WebAudioSourceProvider> provider) { return adoptPtr(new MediaStreamWebAudioSource(provider)); }
+    static PassOwnPtr<MediaStreamWebAudioSource> create(PassOwnPtr<WebAudioSourceProvider> provider) { return adoptPtr(new MediaStreamWebAudioSource(std::move(provider))); }
 
     ~MediaStreamWebAudioSource() override;
 
diff --git a/third_party/WebKit/Source/platform/scheduler/CancellableTaskFactory.h b/third_party/WebKit/Source/platform/scheduler/CancellableTaskFactory.h
index e379fed..4a5075e5 100644
--- a/third_party/WebKit/Source/platform/scheduler/CancellableTaskFactory.h
+++ b/third_party/WebKit/Source/platform/scheduler/CancellableTaskFactory.h
@@ -63,7 +63,7 @@
     // Only intended used by unit tests wanting to stack allocate and/or pass in a closure value.
     // Please use the create() factory method elsewhere.
     explicit CancellableTaskFactory(PassOwnPtr<Closure> closure)
-        : m_closure(closure)
+        : m_closure(std::move(closure))
         , m_weakPtrFactory(this)
     {
     }
diff --git a/third_party/WebKit/Source/web/PageOverlayTest.cpp b/third_party/WebKit/Source/web/PageOverlayTest.cpp
index a0f5536..859081da 100644
--- a/third_party/WebKit/Source/web/PageOverlayTest.cpp
+++ b/third_party/WebKit/Source/web/PageOverlayTest.cpp
@@ -125,15 +125,14 @@
 
     // Paint the layer with a null canvas to get a display list, and then
     // replay that onto the mock canvas for examination.
-    PaintController* paintController = graphicsLayer->paintController();
-    ASSERT(paintController);
-    GraphicsContext graphicsContext(*paintController);
+    PaintController& paintController = graphicsLayer->paintController();
+    GraphicsContext graphicsContext(paintController);
     IntRect intRect = rect;
     graphicsLayer->paint(graphicsContext, &intRect);
 
     graphicsContext.beginRecording(intRect);
-    paintController->commitNewDisplayItems();
-    paintController->paintArtifact().replay(graphicsContext);
+    paintController.commitNewDisplayItems();
+    paintController.paintArtifact().replay(graphicsContext);
     graphicsContext.endRecording()->playback(&canvas);
 }
 
diff --git a/third_party/WebKit/Source/web/WebLeakDetector.cpp b/third_party/WebKit/Source/web/WebLeakDetector.cpp
index 54c16242..e334b9f 100644
--- a/third_party/WebKit/Source/web/WebLeakDetector.cpp
+++ b/third_party/WebKit/Source/web/WebLeakDetector.cpp
@@ -38,7 +38,6 @@
 #include "core/dom/ActiveDOMObject.h"
 #include "core/dom/Document.h"
 #include "core/fetch/MemoryCache.h"
-#include "core/fetch/ResourceFetcher.h"
 #include "core/inspector/InstanceCounters.h"
 #include "core/layout/LayoutObject.h"
 #include "core/workers/WorkerThread.h"
@@ -93,12 +92,6 @@
     WorkerThread::terminateAndWaitForAllWorkers();
     memoryCache()->evictResources();
 
-    {
-        RefPtrWillBeRawPtr<Document> document = PassRefPtrWillBeRawPtr<Document>(frame->document());
-        if (ResourceFetcher* fetcher = document->fetcher())
-            fetcher->garbageCollectDocumentResources();
-    }
-
     // FIXME: HTML5 Notification should be closed because notification affects the result of number of DOM objects.
 
     V8PerIsolateData::from(isolate)->clearScriptRegexpContext();
diff --git a/third_party/WebKit/Source/web/tests/ActivityLoggerTest.cpp b/third_party/WebKit/Source/web/tests/ActivityLoggerTest.cpp
index bbe111d..83a3d91 100644
--- a/third_party/WebKit/Source/web/tests/ActivityLoggerTest.cpp
+++ b/third_party/WebKit/Source/web/tests/ActivityLoggerTest.cpp
@@ -518,12 +518,12 @@
     const char* expectedActivities =
         "blinkAddElement | iframe | data:text/html;charset=utf-8,A\n"
         "blinkRequestResource | Main resource | data:text/html;charset=utf-8,A\n"
+        "blinkRequestResource | Image | data:text/html;charset=utf-8,B\n"
         "blinkAddElement | link | stylesheet | data:text/html;charset=utf-8,C\n"
         "blinkRequestResource | CSS stylesheet | data:text/html;charset=utf-8,C\n"
         "blinkAddElement | script | data:text/html;charset=utf-8,D\n"
         "blinkRequestResource | Script | data:text/html;charset=utf-8,D\n"
-        "blinkRequestResource | XMLHttpRequest | data:text/html;charset=utf-8,E\n"
-        "blinkRequestResource | Image | data:text/html;charset=utf-8,B";
+        "blinkRequestResource | XMLHttpRequest | data:text/html;charset=utf-8,E";
     executeScriptInMainWorld(code);
     ASSERT_TRUE(verifyActivities(""));
     executeScriptInIsolatedWorld(code);
diff --git a/third_party/WebKit/Source/wtf/Assertions.cpp b/third_party/WebKit/Source/wtf/Assertions.cpp
index 08b03cd1..30da047 100644
--- a/third_party/WebKit/Source/wtf/Assertions.cpp
+++ b/third_party/WebKit/Source/wtf/Assertions.cpp
@@ -358,7 +358,7 @@
 
 ScopedLogger*& ScopedLogger::current()
 {
-    AtomicallyInitializedStaticReference(ThreadSpecific<ScopedLogger*>, ref, new ThreadSpecific<ScopedLogger*>);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(ThreadSpecific<ScopedLogger*>, ref, new ThreadSpecific<ScopedLogger*>);
     return *ref;
 }
 
@@ -427,4 +427,3 @@
     vprintf_stderr_with_trailing_newline(format, args);
     va_end(args);
 }
-
diff --git a/third_party/WebKit/Source/wtf/HashTable.cpp b/third_party/WebKit/Source/wtf/HashTable.cpp
index a233650..0c58cab9 100644
--- a/third_party/WebKit/Source/wtf/HashTable.cpp
+++ b/third_party/WebKit/Source/wtf/HashTable.cpp
@@ -36,7 +36,7 @@
 
 static Mutex& hashTableStatsMutex()
 {
-    AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(Mutex, mutex, new Mutex);
     return mutex;
 }
 
diff --git a/third_party/WebKit/Source/wtf/Threading.h b/third_party/WebKit/Source/wtf/Threading.h
index 81aeb6c..ddcc436 100644
--- a/third_party/WebKit/Source/wtf/Threading.h
+++ b/third_party/WebKit/Source/wtf/Threading.h
@@ -37,32 +37,21 @@
 
 // For portability, we do not make use of C++11 thread-safe statics, as supported
 // by some toolchains. Make use of double-checked locking to reduce overhead.
-#define AtomicallyInitializedStaticReferenceInternal(T, name, initializer, LOCK, UNLOCK) \
+// Note that this uses system-wide default lock, and cannot be used before
+// WTF::initializeThreading() is called.
+#define DEFINE_STATIC_LOCAL_THREAD_SAFE(T, name, initializer) \
     /* Init to nullptr is thread-safe on all implementations. */        \
     static void* name##Pointer = nullptr;                               \
     if (!WTF::acquireLoad(&name##Pointer)) {                            \
-        LOCK;                                                           \
+        WTF::lockAtomicallyInitializedStaticMutex();                    \
         if (!WTF::acquireLoad(&name##Pointer)) {                        \
             std::remove_const<T>::type* initializerResult = initializer; \
             WTF::releaseStore(&name##Pointer, initializerResult);       \
         }                                                               \
-        UNLOCK;                                                         \
+        WTF::unlockAtomicallyInitializedStaticMutex();                  \
     }                                                                   \
     T& name = *static_cast<T*>(name##Pointer)
 
-// Uses system-wide default lock. This version cannot be used before
-// WTF::initializeThreading() is called.
-#define AtomicallyInitializedStaticReference(T, name, initializer)      \
-    AtomicallyInitializedStaticReferenceInternal(                       \
-        T, name, initializer, \
-        WTF::lockAtomicallyInitializedStaticMutex(),                    \
-        WTF::unlockAtomicallyInitializedStaticMutex())
-
-// Same as above but uses a given lock.
-#define AtomicallyInitializedStaticReferenceWithLock(T, name, initializer, lockable)  \
-    AtomicallyInitializedStaticReferenceInternal(                       \
-        T, name, initializer, lockable.lock(), lockable.unlock());
-
 namespace WTF {
 
 #if OS(WIN)
diff --git a/third_party/WebKit/Source/wtf/text/TextEncoding.cpp b/third_party/WebKit/Source/wtf/text/TextEncoding.cpp
index 3b05638..ca1dd404 100644
--- a/third_party/WebKit/Source/wtf/text/TextEncoding.cpp
+++ b/third_party/WebKit/Source/wtf/text/TextEncoding.cpp
@@ -39,7 +39,7 @@
 
 static const TextEncoding& UTF7Encoding()
 {
-    AtomicallyInitializedStaticReference(const TextEncoding, globalUTF7Encoding, new TextEncoding("UTF-7"));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(const TextEncoding, globalUTF7Encoding, new TextEncoding("UTF-7"));
     return globalUTF7Encoding;
 }
 
@@ -135,50 +135,50 @@
 
 const TextEncoding& ASCIIEncoding()
 {
-    AtomicallyInitializedStaticReference(const TextEncoding, globalASCIIEncoding, new TextEncoding("ASCII"));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(const TextEncoding, globalASCIIEncoding, new TextEncoding("ASCII"));
     return globalASCIIEncoding;
 }
 
 const TextEncoding& Latin1Encoding()
 {
-    AtomicallyInitializedStaticReference(const TextEncoding, globalLatin1Encoding, new TextEncoding("latin1"));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(const TextEncoding, globalLatin1Encoding, new TextEncoding("latin1"));
     return globalLatin1Encoding;
 }
 
 const TextEncoding& UTF16BigEndianEncoding()
 {
-    AtomicallyInitializedStaticReference(const TextEncoding, globalUTF16BigEndianEncoding, new TextEncoding("UTF-16BE"));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(const TextEncoding, globalUTF16BigEndianEncoding, new TextEncoding("UTF-16BE"));
     return globalUTF16BigEndianEncoding;
 }
 
 const TextEncoding& UTF16LittleEndianEncoding()
 {
-    AtomicallyInitializedStaticReference(const TextEncoding, globalUTF16LittleEndianEncoding, new TextEncoding("UTF-16LE"));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(const TextEncoding, globalUTF16LittleEndianEncoding, new TextEncoding("UTF-16LE"));
     return globalUTF16LittleEndianEncoding;
 }
 
 const TextEncoding& UTF32BigEndianEncoding()
 {
-    AtomicallyInitializedStaticReference(const TextEncoding, globalUTF32BigEndianEncoding, new TextEncoding("UTF-32BE"));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(const TextEncoding, globalUTF32BigEndianEncoding, new TextEncoding("UTF-32BE"));
     return globalUTF32BigEndianEncoding;
 }
 
 const TextEncoding& UTF32LittleEndianEncoding()
 {
-    AtomicallyInitializedStaticReference(const TextEncoding, globalUTF32LittleEndianEncoding, new TextEncoding("UTF-32LE"));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(const TextEncoding, globalUTF32LittleEndianEncoding, new TextEncoding("UTF-32LE"));
     return globalUTF32LittleEndianEncoding;
 }
 
 const TextEncoding& UTF8Encoding()
 {
-    AtomicallyInitializedStaticReference(const TextEncoding, globalUTF8Encoding, new TextEncoding("UTF-8"));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(const TextEncoding, globalUTF8Encoding, new TextEncoding("UTF-8"));
     ASSERT(globalUTF8Encoding.isValid());
     return globalUTF8Encoding;
 }
 
 const TextEncoding& WindowsLatin1Encoding()
 {
-    AtomicallyInitializedStaticReference(const TextEncoding, globalWindowsLatin1Encoding, new TextEncoding("WinLatin1"));
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(const TextEncoding, globalWindowsLatin1Encoding, new TextEncoding("WinLatin1"));
     return globalWindowsLatin1Encoding;
 }
 
diff --git a/third_party/WebKit/Source/wtf/text/icu/CollatorICU.cpp b/third_party/WebKit/Source/wtf/text/icu/CollatorICU.cpp
index 40df3f8..19025c3 100644
--- a/third_party/WebKit/Source/wtf/text/icu/CollatorICU.cpp
+++ b/third_party/WebKit/Source/wtf/text/icu/CollatorICU.cpp
@@ -43,7 +43,7 @@
 static char cachedEquivalentLocale[Collator::ulocFullnameCapacity];
 static Mutex& cachedCollatorMutex()
 {
-    AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex);
+    DEFINE_STATIC_LOCAL_THREAD_SAFE(Mutex, mutex, new Mutex);
     return mutex;
 }
 
diff --git a/third_party/re2/.gitignore b/third_party/re2/.gitignore
deleted file mode 100644
index a671fe2c..0000000
--- a/third_party/re2/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-*.pyc
-*.orig
-core
-obj/
-benchlog.*
diff --git a/third_party/re2/AUTHORS b/third_party/re2/AUTHORS
index 0754006..e17d9bf 100644
--- a/third_party/re2/AUTHORS
+++ b/third_party/re2/AUTHORS
@@ -8,6 +8,6 @@
 
 # Please keep the list sorted.
 
+Brian Gunlogson <unixman83@gmail.com>
 Google Inc.
-Samsung Electronics
 Stefano Rivera <stefano.rivera@gmail.com>
diff --git a/third_party/re2/BUILD b/third_party/re2/BUILD
deleted file mode 100644
index 9ab54b3f..0000000
--- a/third_party/re2/BUILD
+++ /dev/null
@@ -1,121 +0,0 @@
-# Copyright 2009 The RE2 Authors.  All Rights Reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# Bazel (http://bazel.io/) BUILD file for RE2.
-
-licenses(["notice"])
-
-cc_library(
-    name = "re2",
-    srcs = [
-        "re2/bitstate.cc",
-        "re2/compile.cc",
-        "re2/dfa.cc",
-        "re2/filtered_re2.cc",
-        "re2/mimics_pcre.cc",
-        "re2/nfa.cc",
-        "re2/onepass.cc",
-        "re2/parse.cc",
-        "re2/perl_groups.cc",
-        "re2/prefilter.cc",
-        "re2/prefilter.h",
-        "re2/prefilter_tree.cc",
-        "re2/prefilter_tree.h",
-        "re2/prog.cc",
-        "re2/prog.h",
-        "re2/re2.cc",
-        "re2/regexp.cc",
-        "re2/regexp.h",
-        "re2/set.cc",
-        "re2/simplify.cc",
-        "re2/stringpiece.cc",
-        "re2/tostring.cc",
-        "re2/unicode_casefold.cc",
-        "re2/unicode_casefold.h",
-        "re2/unicode_groups.cc",
-        "re2/unicode_groups.h",
-        "re2/walker-inl.h",
-        "util/atomicops.h",
-        "util/flags.h",
-        "util/hash.cc",
-        "util/logging.cc",
-        "util/logging.h",
-        "util/mutex.h",
-        "util/rune.cc",
-        "util/sparse_array.h",
-        "util/sparse_set.h",
-        "util/stringprintf.cc",
-        "util/strutil.cc",
-        "util/utf.h",
-        "util/util.h",
-        "util/valgrind.cc",
-        "util/valgrind.h",
-    ],
-    hdrs = [
-        "re2/filtered_re2.h",
-        "re2/re2.h",
-        "re2/set.h",
-        "re2/stringpiece.h",
-        "re2/variadic_function.h",
-    ],
-    includes = ["."],
-    linkopts = ["-pthread"],
-    visibility = ["//visibility:public"],
-)
-
-cc_library(
-    name = "test",
-    testonly = 1,
-    srcs = [
-        "re2/testing/backtrack.cc",
-        "re2/testing/dump.cc",
-        "re2/testing/exhaustive_tester.cc",
-        "re2/testing/null_walker.cc",
-        "re2/testing/regexp_generator.cc",
-        "re2/testing/string_generator.cc",
-        "re2/testing/tester.cc",
-        "util/pcre.cc",
-        "util/random.cc",
-        "util/test.cc",
-        "util/thread.cc",
-    ],
-    hdrs = [
-        "re2/testing/exhaustive_tester.h",
-        "re2/testing/regexp_generator.h",
-        "re2/testing/string_generator.h",
-        "re2/testing/tester.h",
-        "util/pcre.h",
-        "util/random.h",
-        "util/test.h",
-        "util/thread.h",
-    ],
-    includes = ["."],
-    deps = [":re2"],
-)
-
-load("re2_test", "re2_test")
-
-re2_test("charclass_test")
-re2_test("compile_test")
-re2_test("filtered_re2_test")
-re2_test("mimics_pcre_test")
-re2_test("parse_test")
-re2_test("possible_match_test")
-re2_test("re2_test")
-re2_test("re2_arg_test")
-re2_test("regexp_test")
-re2_test("required_prefix_test")
-re2_test("search_test")
-re2_test("set_test")
-re2_test("simplify_test")
-re2_test("string_generator_test")
-
-re2_test("dfa_test")
-re2_test("exhaustive1_test")
-re2_test("exhaustive2_test")
-re2_test("exhaustive3_test")
-re2_test("exhaustive_test")
-re2_test("random_test")
-
-# TODO: Add support for regexp_benchmark.
diff --git a/third_party/re2/BUILD.gn b/third_party/re2/BUILD.gn
index e95451c..ca1f7a2 100644
--- a/third_party/re2/BUILD.gn
+++ b/third_party/re2/BUILD.gn
@@ -8,6 +8,7 @@
 
 static_library("re2") {
   sources = [
+    "mswin/stdint.h",
     "re2/bitstate.cc",
     "re2/compile.cc",
     "re2/dfa.cc",
@@ -31,7 +32,6 @@
     "re2/set.cc",
     "re2/set.h",
     "re2/simplify.cc",
-    "re2/stringpiece.cc",
     "re2/stringpiece.h",
     "re2/tostring.cc",
     "re2/unicode_casefold.cc",
@@ -40,21 +40,21 @@
     "re2/unicode_groups.h",
     "re2/variadic_function.h",
     "re2/walker-inl.h",
+    "util/arena.cc",
+    "util/arena.h",
     "util/atomicops.h",
     "util/flags.h",
     "util/hash.cc",
-    "util/logging.cc",
     "util/logging.h",
     "util/mutex.h",
     "util/rune.cc",
     "util/sparse_array.h",
     "util/sparse_set.h",
+    "util/stringpiece.cc",
     "util/stringprintf.cc",
     "util/strutil.cc",
     "util/utf.h",
     "util/util.h",
-    "util/valgrind.cc",
-    "util/valgrind.h",
   ]
 
   configs -= [ "//build/config/compiler:chromium_code" ]
@@ -66,9 +66,12 @@
   ]
 
   if (is_win) {
+    include_dirs = [ "mswin" ]
     cflags = [
       "/wd4018",  # Signed/unsigned mismatch in comparison.
       "/wd4722",  # Destructor never terminates.
     ]
+  } else {
+    sources -= [ "mswin/stdint.h" ]
   }
 }
diff --git a/third_party/re2/CMakeLists.txt b/third_party/re2/CMakeLists.txt
deleted file mode 100644
index c6c6060..0000000
--- a/third_party/re2/CMakeLists.txt
+++ /dev/null
@@ -1,112 +0,0 @@
-# Copyright 2015 The RE2 Authors.  All Rights Reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# Old enough to support Ubuntu Precise.
-cmake_minimum_required(VERSION 2.8.7)
-
-project(RE2 CXX)
-option(BUILD_SHARED_LIBS "build shared libraries" OFF)
-option(USEPCRE "use PCRE in tests and benchmarks" OFF)
-
-set(EXTRA_TARGET_LINK_LIBRARIES)
-
-if(WIN32)
-  add_definitions(-DUNICODE -D_UNICODE -DSTRICT -DNOMINMAX)
-  set(THREADING threadwin)
-else()
-  set(THREADING thread)
-  list(APPEND EXTRA_TARGET_LINK_LIBRARIES -pthread)
-endif()
-
-if(USEPCRE)
-  add_definitions(-DUSEPCRE)
-  list(APPEND EXTRA_TARGET_LINK_LIBRARIES pcre)
-endif()
-
-include_directories(${CMAKE_SOURCE_DIR})
-
-set(RE2_LIBRARY_SOURCES
-    re2/bitstate.cc
-    re2/compile.cc
-    re2/dfa.cc
-    re2/filtered_re2.cc
-    re2/mimics_pcre.cc
-    re2/nfa.cc
-    re2/onepass.cc
-    re2/parse.cc
-    re2/perl_groups.cc
-    re2/prefilter.cc
-    re2/prefilter_tree.cc
-    re2/prog.cc
-    re2/re2.cc
-    re2/regexp.cc
-    re2/set.cc
-    re2/simplify.cc
-    re2/stringpiece.cc
-    re2/tostring.cc
-    re2/unicode_casefold.cc
-    re2/unicode_groups.cc
-    util/hash.cc
-    util/logging.cc
-    util/rune.cc
-    util/stringprintf.cc
-    util/strutil.cc
-    util/valgrind.cc
-    )
-
-add_library(re2 ${RE2_LIBRARY_SOURCES})
-
-set(TEST_LIBRARY_SOURCES
-    re2/testing/backtrack.cc
-    re2/testing/dump.cc
-    re2/testing/exhaustive_tester.cc
-    re2/testing/null_walker.cc
-    re2/testing/regexp_generator.cc
-    re2/testing/string_generator.cc
-    re2/testing/tester.cc
-    util/pcre.cc
-    util/random.cc
-    util/${THREADING}.cc
-    )
-
-add_library(test STATIC ${TEST_LIBRARY_SOURCES} util/test.cc)
-add_library(benchmark STATIC ${TEST_LIBRARY_SOURCES} util/benchmark.cc)
-
-set(TEST_TARGETS
-    charclass_test
-    compile_test
-    filtered_re2_test
-    mimics_pcre_test
-    parse_test
-    possible_match_test
-    re2_test
-    re2_arg_test
-    regexp_test
-    required_prefix_test
-    search_test
-    set_test
-    simplify_test
-    string_generator_test
-
-    dfa_test
-    exhaustive1_test
-    exhaustive2_test
-    exhaustive3_test
-    exhaustive_test
-    random_test
-    )
-
-set(BENCHMARK_TARGETS
-    regexp_benchmark
-    )
-
-foreach(target ${TEST_TARGETS})
-  add_executable(${target} re2/testing/${target}.cc)
-  target_link_libraries(${target} test re2 ${EXTRA_TARGET_LINK_LIBRARIES})
-endforeach(target)
-
-foreach(target ${BENCHMARK_TARGETS})
-  add_executable(${target} re2/testing/${target}.cc)
-  target_link_libraries(${target} benchmark re2 ${EXTRA_TARGET_LINK_LIBRARIES})
-endforeach(target)
diff --git a/third_party/re2/CONTRIBUTING.md b/third_party/re2/CONTRIBUTING.md
deleted file mode 100644
index 3af2b0a7..0000000
--- a/third_party/re2/CONTRIBUTING.md
+++ /dev/null
@@ -1,2 +0,0 @@
-RE2 uses Gerrit instead of GitHub pull requests.
-See the [Contributing](https://github.com/google/re2/wiki/Contribute) wiki page.
diff --git a/third_party/re2/CONTRIBUTORS b/third_party/re2/CONTRIBUTORS
index 1a1c8482..7f6a93d 100644
--- a/third_party/re2/CONTRIBUTORS
+++ b/third_party/re2/CONTRIBUTORS
@@ -26,16 +26,11 @@
 
 # Please keep the list sorted.
 
+Brian Gunlogson <unixman83@gmail.com>
 Dominic Battré <battre@chromium.org>
-Doug Kwan <dougkwan@google.com>
-Dmitriy Vyukov <dvyukov@google.com>
 John Millikin <jmillikin@gmail.com>
-Mike Nazarewicz <mpn@google.com>
-Nico Weber <thakis@chromium.org>
-Pawel Hajdan <phajdan.jr@gmail.com>
 Rob Pike <r@google.com>
 Russ Cox <rsc@swtch.com>
 Sanjay Ghemawat <sanjay@google.com>
 Stefano Rivera <stefano.rivera@gmail.com>
 Srinivasan Venkatachary <vsri@google.com>
-Viatcheslav Ostapenko <sl.ostapenko@samsung.com>
diff --git a/third_party/re2/Makefile b/third_party/re2/Makefile
index 5068459..4ded8ec 100644
--- a/third_party/re2/Makefile
+++ b/third_party/re2/Makefile
@@ -2,19 +2,21 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
+all: obj/libre2.a obj/so/libre2.so
+
 # to build against PCRE for testing or benchmarking,
 # uncomment the next two lines
 # CCPCRE=-I/usr/local/include -DUSEPCRE
 # LDPCRE=-L/usr/local/lib -lpcre
 
-CXX?=g++
-CXXFLAGS?=-O3 -g  # can override
-RE2_CXXFLAGS?=-Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -I. $(CCPCRE)  # required
-LDFLAGS?=-pthread
-AR?=ar
-ARFLAGS?=rsc
-NM?=nm
-NMFLAGS?=-p
+CXX=g++
+CXXFLAGS=-Wall -O3 -g -pthread  # can override
+RE2_CXXFLAGS=-Wno-sign-compare -c -I. $(CCPCRE)  # required
+LDFLAGS=-pthread
+AR=ar
+ARFLAGS=rsc
+NM=nm
+NMFLAGS=-p
 
 # Variables mandated by GNU, the arbiter of all good taste on the internet.
 # http://www.gnu.org/prep/standards/standards.html
@@ -36,24 +38,11 @@
 # REBUILD_TABLES=1
 
 ifeq ($(shell uname),Darwin)
-SOEXT=dylib
-SOEXTVER=$(SONAME).$(SOEXT)
-SOEXTVER00=$(SONAME).0.0.$(SOEXT)
-MAKE_SHARED_LIBRARY=$(CXX) -dynamiclib $(LDFLAGS) -Wl,-install_name,@rpath/libre2.$(SOEXTVER) -exported_symbols_list libre2.symbols.darwin
-else ifeq ($(shell uname),SunOS)
-SOEXT=so
-SOEXTVER=$(SOEXT).$(SONAME)
-SOEXTVER00=$(SOEXT).$(SONAME).0.0
-MAKE_SHARED_LIBRARY=$(CXX) -shared -Wl,-soname,libre2.$(SOEXTVER),-M,libre2.symbols $(LDFLAGS)
+MAKE_SHARED_LIBRARY=$(CXX) -dynamiclib $(LDFLAGS) -exported_symbols_list libre2.symbols.darwin
 else
-SOEXT=so
-SOEXTVER=$(SOEXT).$(SONAME)
-SOEXTVER00=$(SOEXT).$(SONAME).0.0
-MAKE_SHARED_LIBRARY=$(CXX) -shared -Wl,-soname,libre2.$(SOEXTVER),--version-script,libre2.symbols $(LDFLAGS)
+MAKE_SHARED_LIBRARY=$(CXX) -shared -Wl,-soname,libre2.so.$(SONAME),--version-script=libre2.symbols $(LDFLAGS)
 endif
 
-all: obj/libre2.a obj/so/libre2.$(SOEXT)
-
 INSTALL_HFILES=\
 	re2/filtered_re2.h\
 	re2/re2.h\
@@ -62,6 +51,7 @@
 	re2/variadic_function.h\
 
 HFILES=\
+	util/arena.h\
 	util/atomicops.h\
 	util/benchmark.h\
 	util/flags.h\
@@ -72,7 +62,6 @@
 	util/sparse_array.h\
 	util/sparse_set.h\
 	util/test.h\
-	util/thread.h\
 	util/utf.h\
 	util/util.h\
 	util/valgrind.h\
@@ -94,9 +83,10 @@
 	re2/walker-inl.h\
 
 OFILES=\
+	obj/util/arena.o\
 	obj/util/hash.o\
-	obj/util/logging.o\
 	obj/util/rune.o\
+	obj/util/stringpiece.o\
 	obj/util/stringprintf.o\
 	obj/util/strutil.o\
 	obj/util/valgrind.o\
@@ -116,7 +106,6 @@
 	obj/re2/regexp.o\
 	obj/re2/set.o\
 	obj/re2/simplify.o\
-	obj/re2/stringpiece.o\
 	obj/re2/tostring.o\
 	obj/re2/unicode_casefold.o\
 	obj/re2/unicode_groups.o\
@@ -169,15 +158,15 @@
 
 obj/%.o: %.cc $(HFILES)
 	@mkdir -p $$(dirname $@)
-	$(CXX) -c -o $@ $(CPPFLAGS) $(CXXFLAGS) $(RE2_CXXFLAGS) -DNDEBUG $*.cc
+	$(CXX) -o $@ $(CPPFLAGS) $(CXXFLAGS) $(RE2_CXXFLAGS) -DNDEBUG $*.cc
 
 obj/dbg/%.o: %.cc $(HFILES)
 	@mkdir -p $$(dirname $@)
-	$(CXX) -c -o $@ $(CPPFLAGS) $(CXXFLAGS) $(RE2_CXXFLAGS) $*.cc
+	$(CXX) -o $@ -fPIC $(CPPFLAGS) $(CXXFLAGS) $(RE2_CXXFLAGS) $*.cc
 
 obj/so/%.o: %.cc $(HFILES)
 	@mkdir -p $$(dirname $@)
-	$(CXX) -c -o $@ -fPIC $(CPPFLAGS) $(CXXFLAGS) $(RE2_CXXFLAGS) -DNDEBUG $*.cc
+	$(CXX) -o $@ -fPIC $(CPPFLAGS) $(CXXFLAGS) $(RE2_CXXFLAGS) -DNDEBUG $*.cc
 
 obj/libre2.a: $(OFILES)
 	@mkdir -p obj
@@ -187,10 +176,10 @@
 	@mkdir -p obj/dbg
 	$(AR) $(ARFLAGS) obj/dbg/libre2.a $(DOFILES)
 
-obj/so/libre2.$(SOEXT): $(SOFILES)
+obj/so/libre2.so: $(SOFILES)
 	@mkdir -p obj/so
-	$(MAKE_SHARED_LIBRARY) -o obj/so/libre2.$(SOEXTVER) $(SOFILES)
-	ln -sf libre2.$(SOEXTVER) $@
+	$(MAKE_SHARED_LIBRARY) -o $@.$(SONAME) $(SOFILES)
+	ln -sf libre2.so.$(SONAME) $@
 
 obj/test/%: obj/libre2.a obj/re2/testing/%.o $(TESTOFILES) obj/util/test.o
 	@mkdir -p obj/test
@@ -200,7 +189,7 @@
 	@mkdir -p obj/dbg/test
 	$(CXX) -o $@ obj/dbg/re2/testing/$*.o $(DTESTOFILES) obj/dbg/util/test.o obj/dbg/libre2.a $(LDFLAGS) $(LDPCRE)
 
-obj/so/test/%: obj/so/libre2.$(SOEXT) obj/libre2.a obj/so/re2/testing/%.o $(STESTOFILES) obj/so/util/test.o
+obj/so/test/%: obj/so/libre2.so obj/libre2.a obj/so/re2/testing/%.o $(STESTOFILES) obj/so/util/test.o
 	@mkdir -p obj/so/test
 	$(CXX) -o $@ obj/so/re2/testing/$*.o $(STESTOFILES) obj/so/util/test.o -Lobj/so -lre2 obj/libre2.a $(LDFLAGS) $(LDPCRE)
 
@@ -214,8 +203,6 @@
 
 re2/unicode_%.cc: re2/make_unicode_%.py
 	python $< > $@
-
-.PRECIOUS: re2/perl_groups.cc re2/unicode_casefold.cc re2/unicode_groups.cc
 endif
 
 distclean: clean
@@ -258,28 +245,23 @@
 
 benchmark: obj/test/regexp_benchmark
 
-install: obj/libre2.a obj/so/libre2.$(SOEXT)
-	mkdir -p $(DESTDIR)$(includedir)/re2 $(DESTDIR)$(libdir)/pkgconfig
+install: obj/libre2.a obj/so/libre2.so
+	mkdir -p $(DESTDIR)$(includedir)/re2 $(DESTDIR)$(libdir)
 	$(INSTALL_DATA) $(INSTALL_HFILES) $(DESTDIR)$(includedir)/re2
 	$(INSTALL) obj/libre2.a $(DESTDIR)$(libdir)/libre2.a
-	$(INSTALL) obj/so/libre2.$(SOEXT) $(DESTDIR)$(libdir)/libre2.$(SOEXTVER00)
-	ln -sf libre2.$(SOEXTVER00) $(DESTDIR)$(libdir)/libre2.$(SOEXTVER)
-	ln -sf libre2.$(SOEXTVER00) $(DESTDIR)$(libdir)/libre2.$(SOEXT)
-	sed -e "s#@prefix@#${prefix}#" re2.pc >$(DESTDIR)$(libdir)/pkgconfig/re2.pc
+	$(INSTALL) obj/so/libre2.so $(DESTDIR)$(libdir)/libre2.so.$(SONAME).0.0
+	ln -sf libre2.so.$(SONAME).0.0 $(DESTDIR)$(libdir)/libre2.so.$(SONAME)
+	ln -sf libre2.so.$(SONAME).0.0 $(DESTDIR)$(libdir)/libre2.so
 
 testinstall:
 	@mkdir -p obj
 	cp testinstall.cc obj
-ifneq ($(shell uname),Darwin)
-	(cd obj && $(CXX) -I$(DESTDIR)$(includedir) -L$(DESTDIR)$(libdir) testinstall.cc -lre2 -pthread -static -o testinstall)
-	obj/testinstall
-endif
 	(cd obj && $(CXX) -I$(DESTDIR)$(includedir) -L$(DESTDIR)$(libdir) testinstall.cc -lre2 -pthread -o testinstall)
 	LD_LIBRARY_PATH=$(DESTDIR)$(libdir) obj/testinstall
 
 benchlog: obj/test/regexp_benchmark
 	(echo '==BENCHMARK==' `hostname` `date`; \
-	  (uname -a; $(CXX) --version; git rev-parse --short HEAD; file obj/test/regexp_benchmark) | sed 's/^/# /'; \
+	  (uname -a; $(CXX) --version; hg identify; file obj/test/regexp_benchmark) | sed 's/^/# /'; \
 	  echo; \
 	  ./obj/test/regexp_benchmark 'PCRE|RE2') | tee -a benchlog.$$(hostname | sed 's/\..*//')
 
@@ -291,9 +273,8 @@
 	obj/test/% obj/so/test/% obj/dbg/test/%
 
 log:
-	$(MAKE) clean
-	$(MAKE) CXXFLAGS="$(CXXFLAGS) -DLOGGING=1" \
-		$(filter obj/test/exhaustive%_test,$(BIGTESTS))
+	make clean
+	make CXXFLAGS="$(CXXFLAGS) -DLOGGING=1" obj/test/exhaustive{,1,2,3}_test
 	echo '#' RE2 exhaustive tests built by make log >re2-exhaustive.txt
 	echo '#' $$(date) >>re2-exhaustive.txt
 	obj/test/exhaustive_test |grep -v '^PASS$$' >>re2-exhaustive.txt
@@ -301,10 +282,7 @@
 	obj/test/exhaustive2_test |grep -v '^PASS$$' >>re2-exhaustive.txt
 	obj/test/exhaustive3_test |grep -v '^PASS$$' >>re2-exhaustive.txt
 
-	$(MAKE) CXXFLAGS="$(CXXFLAGS) -DLOGGING=1" obj/test/search_test
+	make CXXFLAGS="$(CXXFLAGS) -DLOGGING=1" obj/test/search_test
 	echo '#' RE2 basic search tests built by make $@ >re2-search.txt
 	echo '#' $$(date) >>re2-search.txt
 	obj/test/search_test |grep -v '^PASS$$' >>re2-search.txt
-
-x: x.cc obj/libre2.a
-	g++ -I. -o x x.cc obj/libre2.a
diff --git a/third_party/re2/README b/third_party/re2/README
index 2c236606..57b3181 100644
--- a/third_party/re2/README
+++ b/third_party/re2/README
@@ -1,7 +1,7 @@
 This is the source code repository for RE2, a regular expression library.
 
 For documentation about how to install and use RE2,
-visit https://github.com/google/re2/.
+visit http://code.google.com/p/re2/.
 
 The short version is:
 
@@ -10,23 +10,10 @@
 make install
 make testinstall
 
-More information can be found on the wiki:
-https://github.com/google/re2/wiki
-
-Issue tracker:
-https://github.com/google/re2/issues
-
-Mailing list:
-https://groups.google.com/group/re2-dev
-
 Unless otherwise noted, the RE2 source files are distributed
 under the BSD-style license found in the LICENSE file.
 
 RE2's native language is C++.
-An Erlang wrapper is at https://github.com/tuncer/re2/.
-An Inferno wrapper is at https://github.com/powerman/inferno-re2/.
-A Node.js wrapper is at https://github.com/uhop/node-re2/ and on NPM.
-An OCaml wrapper is at https://github.com/janestreet/re2/ and on OPAM.
-A Perl wrapper is at https://github.com/dgl/re-engine-RE2/ and on CPAN.
-A Python wrapper is at https://github.com/facebook/pyre2/.
-A Ruby wrapper is at https://github.com/axic/rre2/.
+An Inferno wrapper is at http://code.google.com/p/inferno-re2/.
+A Python wrapper is at http://github.com/facebook/pyre2/.
+A Ruby wrapper is at http://github.com/axic/rre2/.
diff --git a/third_party/re2/README.chromium b/third_party/re2/README.chromium
index f7d576d..3522d4c 100644
--- a/third_party/re2/README.chromium
+++ b/third_party/re2/README.chromium
@@ -1,8 +1,9 @@
 Name: re2 - an efficient, principled regular expression library
 Short Name: re2
 URL: https://github.com/google/re2
-Version: dba3349aba83b5588e85e5ecf2b56c97f2d259b7
-Date: 2015-12-10
+Version: 7f91923f3ad4
+Date: 2012-06-20
+Revision: 100:7f91923f3ad4
 License: BSD 3-Clause
 License File: LICENSE
 Security Critical: yes
@@ -11,11 +12,23 @@
 RE2 is a fast, safe, thread-friendly alternative to backtracking regular
 expression engines like those used in PCRE, Perl, and Python.
 
-To update RE2, execute the following commands from your Chromium checkout:
-$ git clone https://github.com/google/re2 third_party/re2_new
-$ cp third_party/re2/OWNERS third_party/re2/BUILD.gn third_party/re2/re2.gyp \
-third_party/re2/README.chromium third_party/re2/DEPS third_party/re2_new
-$ rm -rf third_party/re2_new/.git
-$ rm -rf third_party/re2
-$ mv third_party/re2_new third_party/re2
-Then update third_party/re2/BUILD.gn and third_party/re2/re2.gyp.
+Local Modifications (to be applied in this order):
+- Remove valgrind specific code that exists in chromium already
+  (patches/remove-valgrind-code.patch)
+- Support for Windows (patches/re2-msvc9-chrome.patch)
+- Support Android (patches/re2-android.patch)
+- Remove static initializers (patches/remove-static-initializers.patch)
+- Support libcxx (patches/re2-libcxx.patch)
+  https://code.google.com/p/re2/issues/detail?id=76
+- Memory optimization for filtered trees
+  (patches/re2-memory-optimization.patch)
+- Prevent unwanted reports from MemorySanitizer. Note: there's an upstream fix
+  for this (https://code.google.com/p/re2/issues/detail?id=77) which is rendered
+  ineffective by patches/remove-valgrind-code.patch
+  (patches/re2-msan.patch)
+- Remove comparisons of this with NULL, merges upstream b92ce81f1e25
+- Let COMPILE_ASSERT use static_assert if available, merges upstream
+  2225f94df8ec
+- Merge upstream cc56ba02d9d2bdafa614ad5ebf564dde287625bb.
+- Suppress more unwanted reports from MemorySanitizer.
+  (patches/sparse-array-valgrind.patch)
diff --git a/third_party/re2/WORKSPACE b/third_party/re2/WORKSPACE
deleted file mode 100644
index 393f5e6d..0000000
--- a/third_party/re2/WORKSPACE
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2009 The RE2 Authors.  All Rights Reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# Bazel (http://bazel.io/) WORKSPACE file for RE2.
diff --git a/third_party/re2/benchlog/benchplot.py b/third_party/re2/benchlog/benchplot.py
deleted file mode 100755
index 104abe8..0000000
--- a/third_party/re2/benchlog/benchplot.py
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/usr/bin/env python
-
-import argparse     # for ArgumentParser
-import subprocess   # for Popen
-import tempfile     # for NamedTemporaryFile
-import os           # for remove
-
-class gnuplot(object):
-
-    output = "result.png"
-
-    script = """
-             set terminal png size 1024, 768
-             set output "{}.png"
-             set title "re2 benchlog"
-             set datafile separator ";"
-             set grid x y
-             set ylabel "MB/s"
-             set autoscale
-             plot """
-
-    template = """'{}' using 1:5:xticlabels(2) with linespoints linewidth 3 title "{}",\\\n"""
-
-    benchdata = dict()
-    tempfiles = []
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, type, value, traceback):
-        """
-        remove all temporary files
-        """
-
-        for filename in self.tempfiles:
-            os.remove(filename)
-
-    def parse_re2_benchlog(self, filename):
-        """
-        parse the input benchlog and return a dictionary contain bench data
-        """
-
-        benchdata = self.benchdata
-
-        with open(filename) as f:
-
-            for raw in f.readlines():
-
-                data = raw.split('\t')
-
-                if len(data) == 4:
-
-                    data = data[0].split('/') + data[1:]
-                    data = list(map(str.strip, data))
-
-                    if not benchdata.get(data[0]):
-                        benchdata[data[0]] = [ data[1:] ]
-                    else:
-                        benchdata[data[0]].append(data[1:])
-
-    def gen_csv(self):
-        """
-        generate temporary csv files
-        """
-
-        for name, data in self.benchdata.items():
-
-            with tempfile.NamedTemporaryFile(delete=False) as f:
-
-                for index, line in enumerate(data):
-                    f.write('{};{}\n'.format(index, ';'.join(line)).encode())
-
-                self.tempfiles.append(f.name)
-                self.script = self.script + self.template.format(f.name, name)
-
-    def run(self):
-        self.gen_csv()
-        script = self.script[:-3].format(self.output)
-        command = subprocess.Popen(['gnuplot'], stdin=subprocess.PIPE)
-        command.communicate(script.encode())
-
-
-if __name__ == '__main__':
-
-    parser = argparse.ArgumentParser(description='generate plots for benchlog')
-    parser.add_argument('benchlog', type=str, help='benchlog generated by re2')
-    args = parser.parse_args()
-
-    try:
-        subprocess.Popen(['gnuplot'], stdin=subprocess.PIPE)
-    except FileNotFoundError:
-        print('you can install "gnuplot" to generate plots automatically')
-        exit(1)
-
-    with gnuplot() as plot:
-        plot.output = args.benchlog
-        plot.parse_re2_benchlog(args.benchlog)
-        plot.run()
diff --git a/third_party/re2/doc/mksyntaxgo b/third_party/re2/doc/mksyntaxgo
index caad9b6..42e87d6 100755
--- a/third_party/re2/doc/mksyntaxgo
+++ b/third_party/re2/doc/mksyntaxgo
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 set -e
-out=$GOROOT/src/regexp/syntax/doc.go
+out=$GOROOT/src/pkg/regexp/syntax/doc.go
 cp syntax.txt $out
 sam -d $out <<'!'
 ,x g/NOT SUPPORTED/d
diff --git a/third_party/re2/doc/syntax.html b/third_party/re2/doc/syntax.html
index aa08b11..7f5e15a1 100644
--- a/third_party/re2/doc/syntax.html
+++ b/third_party/re2/doc/syntax.html
@@ -11,15 +11,16 @@
 <tr><td colspan=2>This page lists the regular expression syntax accepted by RE2.</td></tr>
 <tr><td colspan=2>It also lists syntax accepted by PCRE, PERL, and VIM.</td></tr>
 <tr><td colspan=2>Grayed out expressions are not supported by RE2.</td></tr>
+<tr><td colspan=2>See <a href="http://go/re2">http://go/re2</a> and <a href="http://go/re2quick">http://go/re2quick</a>.</td></tr>
 <tr><td></td></tr>
 <tr><td colspan=2><b>Single characters:</b></td></tr>
-<tr><td><code>.</code></td><td>any character, possibly including newline (s=true)</td></tr>
+<tr><td><code>.</code></td><td>any character, including newline (s=true)</td></tr>
 <tr><td><code>[xyz]</code></td><td>character class</td></tr>
 <tr><td><code>[^xyz]</code></td><td>negated character class</td></tr>
 <tr><td><code>\d</code></td><td>Perl character class</td></tr>
 <tr><td><code>\D</code></td><td>negated Perl character class</td></tr>
-<tr><td><code>[[:alpha:]]</code></td><td>ASCII character class</td></tr>
-<tr><td><code>[[:^alpha:]]</code></td><td>negated ASCII character class</td></tr>
+<tr><td><code>[:alpha:]</code></td><td>ASCII character class</td></tr>
+<tr><td><code>[:^alpha:]</code></td><td>negated ASCII character class</td></tr>
 <tr><td><code>\pN</code></td><td>Unicode character class (one-letter name)</td></tr>
 <tr><td><code>\p{Greek}</code></td><td>Unicode character class</td></tr>
 <tr><td><code>\PN</code></td><td>negated Unicode character class (one-letter name)</td></tr>
@@ -61,7 +62,7 @@
 <tr><td><code><font color=#808080>(?&lt;name&gt;re)</font></code></td><td>named &amp; numbered capturing group </td></tr>
 <tr><td><code><font color=#808080>(?'name're)</font></code></td><td>named &amp; numbered capturing group </td></tr>
 <tr><td><code>(?:re)</code></td><td>non-capturing group</td></tr>
-<tr><td><code>(?flags)</code></td><td>set flags within current group; non-capturing</td></tr>
+<tr><td><code>(?flags)</code></td><td>set flags until outer paren closes; non-capturing</td></tr>
 <tr><td><code>(?flags:re)</code></td><td>set flags during re; non-capturing</td></tr>
 <tr><td><code><font color=#808080>(?#text)</font></code></td><td>comment </td></tr>
 <tr><td><code><font color=#808080>(?|x|y|z)</font></code></td><td>branch numbering reset </td></tr>
@@ -71,16 +72,16 @@
 <tr><td></td></tr>
 <tr><td colspan=2><b>Flags:</b></td></tr>
 <tr><td><code>i</code></td><td>case-insensitive (default false)</td></tr>
-<tr><td><code>m</code></td><td>multi-line mode: <code>^</code> and <code>$</code> match begin/end line in addition to begin/end text (default false)</td></tr>
+<tr><td><code>m</code></td><td>multi-line mode (default false)</td></tr>
 <tr><td><code>s</code></td><td>let <code>.</code> match <code>\n</code> (default false)</td></tr>
 <tr><td><code>U</code></td><td>ungreedy: swap meaning of <code>x*</code> and <code>x*?</code>, <code>x+</code> and <code>x+?</code>, etc (default false)</td></tr>
 <tr><td colspan=2>Flag syntax is <code>xyz</code> (set) or <code>-xyz</code> (clear) or <code>xy-z</code> (set <code>xy</code>, clear <code>z</code>).</td></tr>
 <tr><td></td></tr>
 <tr><td colspan=2><b>Empty strings:</b></td></tr>
 <tr><td><code>^</code></td><td>at beginning of text or line (<code>m</code>=true)</td></tr>
-<tr><td><code>$</code></td><td>at end of text (like <code>\z</code> not <code>\Z</code>) or line (<code>m</code>=true)</td></tr>
+<tr><td><code>$</code></td><td>at end of text or line (<code>m</code>=true)</td></tr>
 <tr><td><code>\A</code></td><td>at beginning of text</td></tr>
-<tr><td><code>\b</code></td><td>at word boundary (<code>\w</code> on one side and <code>\W</code>, <code>\A</code>, or <code>\z</code> on the other)</td></tr>
+<tr><td><code>\b</code></td><td>at word boundary (<code>\w</code> to left and <code>\W</code> to right or vice versa)</td></tr>
 <tr><td><code>\B</code></td><td>not a word boundary</td></tr>
 <tr><td><code><font color=#808080>\G</font></code></td><td>at beginning of subtext being searched  <font size=-2>PCRE</font></td></tr>
 <tr><td><code><font color=#808080>\G</font></code></td><td>at end of last match  <font size=-2>PERL</font></td></tr>
@@ -180,20 +181,20 @@
 <tr><td><code><font color=#808080>\V</font></code></td><td>not vertical space </td></tr>
 <tr><td></td></tr>
 <tr><td colspan=2><b>ASCII character classes:</b></td></tr>
-<tr><td><code>[[:alnum:]]</code></td><td>alphanumeric (≡ <code>[0-9A-Za-z]</code>)</td></tr>
-<tr><td><code>[[:alpha:]]</code></td><td>alphabetic (≡ <code>[A-Za-z]</code>)</td></tr>
-<tr><td><code>[[:ascii:]]</code></td><td>ASCII (≡ <code>[\x00-\x7F]</code>)</td></tr>
-<tr><td><code>[[:blank:]]</code></td><td>blank (≡ <code>[\t ]</code>)</td></tr>
-<tr><td><code>[[:cntrl:]]</code></td><td>control (≡ <code>[\x00-\x1F\x7F]</code>)</td></tr>
-<tr><td><code>[[:digit:]]</code></td><td>digits (≡ <code>[0-9]</code>)</td></tr>
-<tr><td><code>[[:graph:]]</code></td><td>graphical (≡ <code>[!-~] == [A-Za-z0-9!"#$%&amp;'()*+,\-./:;&lt;=&gt;?@[\\\]^_`{|}~]</code>)</td></tr>
-<tr><td><code>[[:lower:]]</code></td><td>lower case (≡ <code>[a-z]</code>)</td></tr>
-<tr><td><code>[[:print:]]</code></td><td>printable (≡ <code>[ -~] == [ [:graph:]]</code>)</td></tr>
-<tr><td><code>[[:punct:]]</code></td><td>punctuation (≡ <code>[!-/:-@[-`{-~]</code>)</td></tr>
-<tr><td><code>[[:space:]]</code></td><td>whitespace (≡ <code>[\t\n\v\f\r ]</code>)</td></tr>
-<tr><td><code>[[:upper:]]</code></td><td>upper case (≡ <code>[A-Z]</code>)</td></tr>
-<tr><td><code>[[:word:]]</code></td><td>word characters (≡ <code>[0-9A-Za-z_]</code>)</td></tr>
-<tr><td><code>[[:xdigit:]]</code></td><td>hex digit (≡ <code>[0-9A-Fa-f]</code>)</td></tr>
+<tr><td><code>[:alnum:]</code></td><td>alphanumeric (≡ <code>[0-9A-Za-z]</code>)</td></tr>
+<tr><td><code>[:alpha:]</code></td><td>alphabetic (≡ <code>[A-Za-z]</code>)</td></tr>
+<tr><td><code>[:ascii:]</code></td><td>ASCII (≡ <code>[\x00-\x7F]</code>)</td></tr>
+<tr><td><code>[:blank:]</code></td><td>blank (≡ <code>[\t ]</code>)</td></tr>
+<tr><td><code>[:cntrl:]</code></td><td>control (≡ <code>[\x00-\x1F\x7F]</code>)</td></tr>
+<tr><td><code>[:digit:]</code></td><td>digits (≡ <code>[0-9]</code>)</td></tr>
+<tr><td><code>[:graph:]</code></td><td>graphical (≡ <code>[!-~] == [A-Za-z0-9!"#$%&amp;'()*+,\-./:;&lt;=&gt;?@[\\\]^_`{|}~]</code>)</td></tr>
+<tr><td><code>[:lower:]</code></td><td>lower case (≡ <code>[a-z]</code>)</td></tr>
+<tr><td><code>[:print:]</code></td><td>printable (≡ <code>[ -~] == [ [:graph:]]</code>)</td></tr>
+<tr><td><code>[:punct:]</code></td><td>punctuation (≡ <code>[!-/:-@[-`{-~]</code>)</td></tr>
+<tr><td><code>[:space:]</code></td><td>whitespace (≡ <code>[\t\n\v\f\r ]</code>)</td></tr>
+<tr><td><code>[:upper:]</code></td><td>upper case (≡ <code>[A-Z]</code>)</td></tr>
+<tr><td><code>[:word:]</code></td><td>word characters (≡ <code>[0-9A-Za-z_]</code>)</td></tr>
+<tr><td><code>[:xdigit:]</code></td><td>hex digit (≡ <code>[0-9A-Fa-f]</code>)</td></tr>
 <tr><td></td></tr>
 <tr><td colspan=2><b>Unicode character class names--general category:</b></td></tr>
 <tr><td><code>C</code></td><td>other</td></tr>
@@ -240,17 +241,13 @@
 <tr><td><code>Arabic</code></td><td>Arabic</td></tr>
 <tr><td><code>Armenian</code></td><td>Armenian</td></tr>
 <tr><td><code>Balinese</code></td><td>Balinese</td></tr>
-<tr><td><code>Bamum</code></td><td>Bamum</td></tr>
-<tr><td><code>Batak</code></td><td>Batak</td></tr>
 <tr><td><code>Bengali</code></td><td>Bengali</td></tr>
 <tr><td><code>Bopomofo</code></td><td>Bopomofo</td></tr>
-<tr><td><code>Brahmi</code></td><td>Brahmi</td></tr>
 <tr><td><code>Braille</code></td><td>Braille</td></tr>
 <tr><td><code>Buginese</code></td><td>Buginese</td></tr>
 <tr><td><code>Buhid</code></td><td>Buhid</td></tr>
 <tr><td><code>Canadian_Aboriginal</code></td><td>Canadian Aboriginal</td></tr>
 <tr><td><code>Carian</code></td><td>Carian</td></tr>
-<tr><td><code>Chakma</code></td><td>Chakma</td></tr>
 <tr><td><code>Cham</code></td><td>Cham</td></tr>
 <tr><td><code>Cherokee</code></td><td>Cherokee</td></tr>
 <tr><td><code>Common</code></td><td>characters not specific to one script</td></tr>
@@ -260,7 +257,6 @@
 <tr><td><code>Cyrillic</code></td><td>Cyrillic</td></tr>
 <tr><td><code>Deseret</code></td><td>Deseret</td></tr>
 <tr><td><code>Devanagari</code></td><td>Devanagari</td></tr>
-<tr><td><code>Egyptian_Hieroglyphs</code></td><td>Egyptian Hieroglyphs</td></tr>
 <tr><td><code>Ethiopic</code></td><td>Ethiopic</td></tr>
 <tr><td><code>Georgian</code></td><td>Georgian</td></tr>
 <tr><td><code>Glagolitic</code></td><td>Glagolitic</td></tr>
@@ -273,12 +269,7 @@
 <tr><td><code>Hanunoo</code></td><td>Hanunoo</td></tr>
 <tr><td><code>Hebrew</code></td><td>Hebrew</td></tr>
 <tr><td><code>Hiragana</code></td><td>Hiragana</td></tr>
-<tr><td><code>Imperial_Aramaic</code></td><td>Imperial Aramaic</td></tr>
 <tr><td><code>Inherited</code></td><td>inherit script from previous character</td></tr>
-<tr><td><code>Inscriptional_Pahlavi</code></td><td>Inscriptional Pahlavi</td></tr>
-<tr><td><code>Inscriptional_Parthian</code></td><td>Inscriptional Parthian</td></tr>
-<tr><td><code>Javanese</code></td><td>Javanese</td></tr>
-<tr><td><code>Kaithi</code></td><td>Kaithi</td></tr>
 <tr><td><code>Kannada</code></td><td>Kannada</td></tr>
 <tr><td><code>Katakana</code></td><td>Katakana</td></tr>
 <tr><td><code>Kayah_Li</code></td><td>Kayah Li</td></tr>
@@ -292,11 +283,6 @@
 <tr><td><code>Lycian</code></td><td>Lycian</td></tr>
 <tr><td><code>Lydian</code></td><td>Lydian</td></tr>
 <tr><td><code>Malayalam</code></td><td>Malayalam</td></tr>
-<tr><td><code>Mandaic</code></td><td>Mandaic</td></tr>
-<tr><td><code>Meetei_Mayek</code></td><td>Meetei Mayek</td></tr>
-<tr><td><code>Meroitic_Cursive</code></td><td>Meroitic Cursive</td></tr>
-<tr><td><code>Meroitic_Hieroglyphs</code></td><td>Meroitic Hieroglyphs</td></tr>
-<tr><td><code>Miao</code></td><td>Miao</td></tr>
 <tr><td><code>Mongolian</code></td><td>Mongolian</td></tr>
 <tr><td><code>Myanmar</code></td><td>Myanmar</td></tr>
 <tr><td><code>New_Tai_Lue</code></td><td>New Tai Lue (aka Simplified Tai Lue)</td></tr>
@@ -305,8 +291,6 @@
 <tr><td><code>Ol_Chiki</code></td><td>Ol Chiki</td></tr>
 <tr><td><code>Old_Italic</code></td><td>Old Italic</td></tr>
 <tr><td><code>Old_Persian</code></td><td>Old Persian</td></tr>
-<tr><td><code>Old_South_Arabian</code></td><td>Old South Arabian</td></tr>
-<tr><td><code>Old_Turkic</code></td><td>Old Turkic</td></tr>
 <tr><td><code>Oriya</code></td><td>Oriya</td></tr>
 <tr><td><code>Osmanya</code></td><td>Osmanya</td></tr>
 <tr><td><code>Phags_Pa</code></td><td>'Phags Pa</td></tr>
@@ -314,19 +298,14 @@
 <tr><td><code>Rejang</code></td><td>Rejang</td></tr>
 <tr><td><code>Runic</code></td><td>Runic</td></tr>
 <tr><td><code>Saurashtra</code></td><td>Saurashtra</td></tr>
-<tr><td><code>Sharada</code></td><td>Sharada</td></tr>
 <tr><td><code>Shavian</code></td><td>Shavian</td></tr>
 <tr><td><code>Sinhala</code></td><td>Sinhala</td></tr>
-<tr><td><code>Sora_Sompeng</code></td><td>Sora Sompeng</td></tr>
 <tr><td><code>Sundanese</code></td><td>Sundanese</td></tr>
 <tr><td><code>Syloti_Nagri</code></td><td>Syloti Nagri</td></tr>
 <tr><td><code>Syriac</code></td><td>Syriac</td></tr>
 <tr><td><code>Tagalog</code></td><td>Tagalog</td></tr>
 <tr><td><code>Tagbanwa</code></td><td>Tagbanwa</td></tr>
 <tr><td><code>Tai_Le</code></td><td>Tai Le</td></tr>
-<tr><td><code>Tai_Tham</code></td><td>Tai Tham</td></tr>
-<tr><td><code>Tai_Viet</code></td><td>Tai Viet</td></tr>
-<tr><td><code>Takri</code></td><td>Takri</td></tr>
 <tr><td><code>Tamil</code></td><td>Tamil</td></tr>
 <tr><td><code>Telugu</code></td><td>Telugu</td></tr>
 <tr><td><code>Thaana</code></td><td>Thaana</td></tr>
diff --git a/third_party/re2/doc/syntax.txt b/third_party/re2/doc/syntax.txt
index e9c6ff4..f9407509 100644
--- a/third_party/re2/doc/syntax.txt
+++ b/third_party/re2/doc/syntax.txt
@@ -7,8 +7,8 @@
 [^xyz]	negated character class
 \d	Perl character class
 \D	negated Perl character class
-[[:alpha:]]	ASCII character class
-[[:^alpha:]]	negated ASCII character class
+[:alpha:]	ASCII character class
+[:^alpha:]	negated ASCII character class
 \pN	Unicode character class (one-letter name)
 \p{Greek}	Unicode character class
 \PN	negated Unicode character class (one-letter name)
@@ -36,10 +36,6 @@
 x{-n}	(== x{n}?) NOT SUPPORTED vim
 x=	(== x?) NOT SUPPORTED vim
 
-Implementation restriction: The counting forms «x{n,m}», «x{n,}», and «x{n}»
-reject forms that create a minimum or maximum repetition count above 1000.
-Unlimited repetitions are not subject to this restriction.
-
 Possessive repetitions:
 x*+	zero or more «x», possessive NOT SUPPORTED
 x++	one or more «x», possessive NOT SUPPORTED
@@ -49,10 +45,10 @@
 x{n}+	exactly «n» «x», possessive NOT SUPPORTED
 
 Grouping:
-(re)	numbered capturing group (submatch)
-(?P<name>re)	named & numbered capturing group (submatch)
-(?<name>re)	named & numbered capturing group (submatch) NOT SUPPORTED
-(?'name're)	named & numbered capturing group (submatch) NOT SUPPORTED
+(re)	numbered capturing group
+(?P<name>re)	named & numbered capturing group
+(?<name>re)	named & numbered capturing group NOT SUPPORTED
+(?'name're)	named & numbered capturing group NOT SUPPORTED
 (?:re)	non-capturing group
 (?flags)	set flags within current group; non-capturing
 (?flags:re)	set flags during re; non-capturing
@@ -73,8 +69,8 @@
 ^	at beginning of text or line («m»=true)
 $	at end of text (like «\z» not «\Z») or line («m»=true)
 \A	at beginning of text
-\b	at ASCII word boundary («\w» on one side and «\W», «\A», or «\z» on the other)
-\B	not at ASCII word boundary
+\b	at word boundary («\w» on one side and «\W», «\A», or «\z» on the other)
+\B	not a word boundary
 \G	at beginning of subtext being searched NOT SUPPORTED pcre
 \G	at end of last match NOT SUPPORTED perl
 \Z	at end of text, or before newline at end of text NOT SUPPORTED
@@ -159,7 +155,7 @@
 [\p{Name}]	named Unicode property inside character class (== \p{Name})
 [^\p{Name}]	named Unicode property inside negated character class (== \P{Name})
 
-Perl character classes (all ASCII-only):
+Perl character classes:
 \d	digits (== [0-9])
 \D	not digits (== [^0-9])
 \s	whitespace (== [\t\n\f\r ])
@@ -173,20 +169,20 @@
 \V	not vertical space NOT SUPPORTED
 
 ASCII character classes:
-[[:alnum:]]	alphanumeric (== [0-9A-Za-z])
-[[:alpha:]]	alphabetic (== [A-Za-z])
-[[:ascii:]]	ASCII (== [\x00-\x7F])
-[[:blank:]]	blank (== [\t ])
-[[:cntrl:]]	control (== [\x00-\x1F\x7F])
-[[:digit:]]	digits (== [0-9])
-[[:graph:]]	graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])
-[[:lower:]]	lower case (== [a-z])
-[[:print:]]	printable (== [ -~] == [ [:graph:]])
-[[:punct:]]	punctuation (== [!-/:-@[-`{-~])
-[[:space:]]	whitespace (== [\t\n\v\f\r ])
-[[:upper:]]	upper case (== [A-Z])
-[[:word:]]	word characters (== [0-9A-Za-z_])
-[[:xdigit:]]	hex digit (== [0-9A-Fa-f])
+[:alnum:]	alphanumeric (== [0-9A-Za-z])
+[:alpha:]	alphabetic (== [A-Za-z])
+[:ascii:]	ASCII (== [\x00-\x7F])
+[:blank:]	blank (== [\t ])
+[:cntrl:]	control (== [\x00-\x1F\x7F])
+[:digit:]	digits (== [0-9])
+[:graph:]	graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])
+[:lower:]	lower case (== [a-z])
+[:print:]	printable (== [ -~] == [ [:graph:]])
+[:punct:]	punctuation (== [!-/:-@[-`{-~])
+[:space:]	whitespace (== [\t\n\v\f\r ])
+[:upper:]	upper case (== [A-Z])
+[:word:]	word characters (== [0-9A-Za-z_])
+[:xdigit:]	hex digit (== [0-9A-Fa-f])
 
 Unicode character class names--general category:
 C	other
@@ -233,17 +229,13 @@
 Arabic	Arabic
 Armenian	Armenian
 Balinese	Balinese
-Bamum	Bamum
-Batak	Batak
 Bengali	Bengali
 Bopomofo	Bopomofo
-Brahmi	Brahmi
 Braille	Braille
 Buginese	Buginese
 Buhid	Buhid
 Canadian_Aboriginal	Canadian Aboriginal
 Carian	Carian
-Chakma	Chakma
 Cham	Cham
 Cherokee	Cherokee
 Common	characters not specific to one script
@@ -253,7 +245,6 @@
 Cyrillic	Cyrillic
 Deseret	Deseret
 Devanagari	Devanagari
-Egyptian_Hieroglyphs	Egyptian Hieroglyphs
 Ethiopic	Ethiopic
 Georgian	Georgian
 Glagolitic	Glagolitic
@@ -266,12 +257,7 @@
 Hanunoo	Hanunoo
 Hebrew	Hebrew
 Hiragana	Hiragana
-Imperial_Aramaic	Imperial Aramaic
 Inherited	inherit script from previous character
-Inscriptional_Pahlavi	Inscriptional Pahlavi
-Inscriptional_Parthian	Inscriptional Parthian
-Javanese	Javanese
-Kaithi	Kaithi
 Kannada	Kannada
 Katakana	Katakana
 Kayah_Li	Kayah Li
@@ -285,11 +271,6 @@
 Lycian	Lycian
 Lydian	Lydian
 Malayalam	Malayalam
-Mandaic	Mandaic
-Meetei_Mayek	Meetei Mayek
-Meroitic_Cursive	Meroitic Cursive
-Meroitic_Hieroglyphs	Meroitic Hieroglyphs
-Miao	Miao
 Mongolian	Mongolian
 Myanmar	Myanmar
 New_Tai_Lue	New Tai Lue (aka Simplified Tai Lue)
@@ -298,8 +279,6 @@
 Ol_Chiki	Ol Chiki
 Old_Italic	Old Italic
 Old_Persian	Old Persian
-Old_South_Arabian	Old South Arabian
-Old_Turkic	Old Turkic
 Oriya	Oriya
 Osmanya	Osmanya
 Phags_Pa	'Phags Pa
@@ -307,19 +286,14 @@
 Rejang	Rejang
 Runic	Runic
 Saurashtra	Saurashtra
-Sharada	Sharada
 Shavian	Shavian
 Sinhala	Sinhala
-Sora_Sompeng	Sora Sompeng
 Sundanese	Sundanese
 Syloti_Nagri	Syloti Nagri
 Syriac	Syriac
 Tagalog	Tagalog
 Tagbanwa	Tagbanwa
 Tai_Le	Tai Le
-Tai_Tham	Tai Tham
-Tai_Viet	Tai Viet
-Takri	Takri
 Tamil	Tamil
 Telugu	Telugu
 Thaana	Thaana
diff --git a/third_party/re2/lib/codereview/codereview.cfg b/third_party/re2/lib/codereview/codereview.cfg
new file mode 100644
index 0000000..9581920
--- /dev/null
+++ b/third_party/re2/lib/codereview/codereview.cfg
@@ -0,0 +1 @@
+defaultcc: re2-dev@googlegroups.com
diff --git a/third_party/re2/lib/codereview/codereview.py b/third_party/re2/lib/codereview/codereview.py
new file mode 100644
index 0000000..b892727
--- /dev/null
+++ b/third_party/re2/lib/codereview/codereview.py
@@ -0,0 +1,3565 @@
+# coding=utf-8
+# (The line above is necessary so that I can use 世界 in the
+# *comment* below without Python getting all bent out of shape.)
+
+# Copyright 2007-2009 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+'''Mercurial interface to codereview.appspot.com.
+
+To configure, set the following options in
+your repository's .hg/hgrc file.
+
+	[extensions]
+	codereview = /path/to/codereview.py
+
+	[codereview]
+	server = codereview.appspot.com
+
+The server should be running Rietveld; see http://code.google.com/p/rietveld/.
+
+In addition to the new commands, this extension introduces
+the file pattern syntax @nnnnnn, where nnnnnn is a change list
+number, to mean the files included in that change list, which
+must be associated with the current client.
+
+For example, if change 123456 contains the files x.go and y.go,
+"hg diff @123456" is equivalent to"hg diff x.go y.go".
+'''
+
+import sys
+
+if __name__ == "__main__":
+	print >>sys.stderr, "This is a Mercurial extension and should not be invoked directly."
+	sys.exit(2)
+
+# We require Python 2.6 for the json package.
+if sys.version < '2.6':
+	print >>sys.stderr, "The codereview extension requires Python 2.6 or newer."
+	print >>sys.stderr, "You are running Python " + sys.version
+	sys.exit(2)
+
+import json
+import os
+import re
+import stat
+import subprocess
+import threading
+import time
+
+from mercurial import commands as hg_commands
+from mercurial import util as hg_util
+
+defaultcc = None
+codereview_disabled = None
+real_rollback = None
+releaseBranch = None
+server = "codereview.appspot.com"
+server_url_base = None
+
+#######################################################################
+# Normally I would split this into multiple files, but it simplifies
+# import path headaches to keep it all in one file.  Sorry.
+# The different parts of the file are separated by banners like this one.
+
+#######################################################################
+# Helpers
+
+def RelativePath(path, cwd):
+	n = len(cwd)
+	if path.startswith(cwd) and path[n] == '/':
+		return path[n+1:]
+	return path
+
+def Sub(l1, l2):
+	return [l for l in l1 if l not in l2]
+
+def Add(l1, l2):
+	l = l1 + Sub(l2, l1)
+	l.sort()
+	return l
+
+def Intersect(l1, l2):
+	return [l for l in l1 if l in l2]
+
+#######################################################################
+# RE: UNICODE STRING HANDLING
+#
+# Python distinguishes between the str (string of bytes)
+# and unicode (string of code points) types.  Most operations
+# work on either one just fine, but some (like regexp matching)
+# require unicode, and others (like write) require str.
+#
+# As befits the language, Python hides the distinction between
+# unicode and str by converting between them silently, but
+# *only* if all the bytes/code points involved are 7-bit ASCII.
+# This means that if you're not careful, your program works
+# fine on "hello, world" and fails on "hello, 世界".  And of course,
+# the obvious way to be careful - use static types - is unavailable.
+# So the only way is trial and error to find where to put explicit
+# conversions.
+#
+# Because more functions do implicit conversion to str (string of bytes)
+# than do implicit conversion to unicode (string of code points),
+# the convention in this module is to represent all text as str,
+# converting to unicode only when calling a unicode-only function
+# and then converting back to str as soon as possible.
+
+def typecheck(s, t):
+	if type(s) != t:
+		raise hg_util.Abort("type check failed: %s has type %s != %s" % (repr(s), type(s), t))
+
+# If we have to pass unicode instead of str, ustr does that conversion clearly.
+def ustr(s):
+	typecheck(s, str)
+	return s.decode("utf-8")
+
+# Even with those, Mercurial still sometimes turns unicode into str
+# and then tries to use it as ascii.  Change Mercurial's default.
+def set_mercurial_encoding_to_utf8():
+	from mercurial import encoding
+	encoding.encoding = 'utf-8'
+
+set_mercurial_encoding_to_utf8()
+
+# Even with those we still run into problems.
+# I tried to do things by the book but could not convince
+# Mercurial to let me check in a change with UTF-8 in the
+# CL description or author field, no matter how many conversions
+# between str and unicode I inserted and despite changing the
+# default encoding.  I'm tired of this game, so set the default
+# encoding for all of Python to 'utf-8', not 'ascii'.
+def default_to_utf8():
+	import sys
+	stdout, __stdout__ = sys.stdout, sys.__stdout__
+	reload(sys)  # site.py deleted setdefaultencoding; get it back
+	sys.stdout, sys.__stdout__ = stdout, __stdout__
+	sys.setdefaultencoding('utf-8')
+
+default_to_utf8()
+
+#######################################################################
+# Status printer for long-running commands
+
+global_status = None
+
+def set_status(s):
+	# print >>sys.stderr, "\t", time.asctime(), s
+	global global_status
+	global_status = s
+
+class StatusThread(threading.Thread):
+	def __init__(self):
+		threading.Thread.__init__(self)
+	def run(self):
+		# pause a reasonable amount of time before
+		# starting to display status messages, so that
+		# most hg commands won't ever see them.
+		time.sleep(30)
+
+		# now show status every 15 seconds
+		while True:
+			time.sleep(15 - time.time() % 15)
+			s = global_status
+			if s is None:
+				continue
+			if s == "":
+				s = "(unknown status)"
+			print >>sys.stderr, time.asctime(), s
+
+def start_status_thread():
+	t = StatusThread()
+	t.setDaemon(True)  # allowed to exit if t is still running
+	t.start()
+
+#######################################################################
+# Change list parsing.
+#
+# Change lists are stored in .hg/codereview/cl.nnnnnn
+# where nnnnnn is the number assigned by the code review server.
+# Most data about a change list is stored on the code review server
+# too: the description, reviewer, and cc list are all stored there.
+# The only thing in the cl.nnnnnn file is the list of relevant files.
+# Also, the existence of the cl.nnnnnn file marks this repository
+# as the one where the change list lives.
+
+emptydiff = """Index: ~rietveld~placeholder~
+===================================================================
+diff --git a/~rietveld~placeholder~ b/~rietveld~placeholder~
+new file mode 100644
+"""
+
+class CL(object):
+	def __init__(self, name):
+		typecheck(name, str)
+		self.name = name
+		self.desc = ''
+		self.files = []
+		self.reviewer = []
+		self.cc = []
+		self.url = ''
+		self.local = False
+		self.web = False
+		self.copied_from = None	# None means current user
+		self.mailed = False
+		self.private = False
+		self.lgtm = []
+
+	def DiskText(self):
+		cl = self
+		s = ""
+		if cl.copied_from:
+			s += "Author: " + cl.copied_from + "\n\n"
+		if cl.private:
+			s += "Private: " + str(self.private) + "\n"
+		s += "Mailed: " + str(self.mailed) + "\n"
+		s += "Description:\n"
+		s += Indent(cl.desc, "\t")
+		s += "Files:\n"
+		for f in cl.files:
+			s += "\t" + f + "\n"
+		typecheck(s, str)
+		return s
+
+	def EditorText(self):
+		cl = self
+		s = _change_prolog
+		s += "\n"
+		if cl.copied_from:
+			s += "Author: " + cl.copied_from + "\n"
+		if cl.url != '':
+			s += 'URL: ' + cl.url + '	# cannot edit\n\n'
+		if cl.private:
+			s += "Private: True\n"
+		s += "Reviewer: " + JoinComma(cl.reviewer) + "\n"
+		s += "CC: " + JoinComma(cl.cc) + "\n"
+		s += "\n"
+		s += "Description:\n"
+		if cl.desc == '':
+			s += "\t<enter description here>\n"
+		else:
+			s += Indent(cl.desc, "\t")
+		s += "\n"
+		if cl.local or cl.name == "new":
+			s += "Files:\n"
+			for f in cl.files:
+				s += "\t" + f + "\n"
+			s += "\n"
+		typecheck(s, str)
+		return s
+
+	def PendingText(self, quick=False):
+		cl = self
+		s = cl.name + ":" + "\n"
+		s += Indent(cl.desc, "\t")
+		s += "\n"
+		if cl.copied_from:
+			s += "\tAuthor: " + cl.copied_from + "\n"
+		if not quick:
+			s += "\tReviewer: " + JoinComma(cl.reviewer) + "\n"
+			for (who, line) in cl.lgtm:
+				s += "\t\t" + who + ": " + line + "\n"
+			s += "\tCC: " + JoinComma(cl.cc) + "\n"
+		s += "\tFiles:\n"
+		for f in cl.files:
+			s += "\t\t" + f + "\n"
+		typecheck(s, str)
+		return s
+
+	def Flush(self, ui, repo):
+		if self.name == "new":
+			self.Upload(ui, repo, gofmt_just_warn=True, creating=True)
+		dir = CodeReviewDir(ui, repo)
+		path = dir + '/cl.' + self.name
+		f = open(path+'!', "w")
+		f.write(self.DiskText())
+		f.close()
+		if sys.platform == "win32" and os.path.isfile(path):
+			os.remove(path)
+		os.rename(path+'!', path)
+		if self.web and not self.copied_from:
+			EditDesc(self.name, desc=self.desc,
+				reviewers=JoinComma(self.reviewer), cc=JoinComma(self.cc),
+				private=self.private)
+
+	def Delete(self, ui, repo):
+		dir = CodeReviewDir(ui, repo)
+		os.unlink(dir + "/cl." + self.name)
+
+	def Subject(self):
+		s = line1(self.desc)
+		if len(s) > 60:
+			s = s[0:55] + "..."
+		if self.name != "new":
+			s = "code review %s: %s" % (self.name, s)
+		typecheck(s, str)
+		return s
+
+	def Upload(self, ui, repo, send_mail=False, gofmt=True, gofmt_just_warn=False, creating=False, quiet=False):
+		if not self.files and not creating:
+			ui.warn("no files in change list\n")
+		if ui.configbool("codereview", "force_gofmt", True) and gofmt:
+			CheckFormat(ui, repo, self.files, just_warn=gofmt_just_warn)
+		set_status("uploading CL metadata + diffs")
+		os.chdir(repo.root)
+		form_fields = [
+			("content_upload", "1"),
+			("reviewers", JoinComma(self.reviewer)),
+			("cc", JoinComma(self.cc)),
+			("description", self.desc),
+			("base_hashes", ""),
+		]
+
+		if self.name != "new":
+			form_fields.append(("issue", self.name))
+		vcs = None
+		# We do not include files when creating the issue,
+		# because we want the patch sets to record the repository
+		# and base revision they are diffs against.  We use the patch
+		# set message for that purpose, but there is no message with
+		# the first patch set.  Instead the message gets used as the
+		# new CL's overall subject.  So omit the diffs when creating
+		# and then we'll run an immediate upload.
+		# This has the effect that every CL begins with an empty "Patch set 1".
+		if self.files and not creating:
+			vcs = MercurialVCS(upload_options, ui, repo)
+			data = vcs.GenerateDiff(self.files)
+			files = vcs.GetBaseFiles(data)
+			if len(data) > MAX_UPLOAD_SIZE:
+				uploaded_diff_file = []
+				form_fields.append(("separate_patches", "1"))
+			else:
+				uploaded_diff_file = [("data", "data.diff", data)]
+		else:
+			uploaded_diff_file = [("data", "data.diff", emptydiff)]
+		
+		if vcs and self.name != "new":
+			form_fields.append(("subject", "diff -r " + vcs.base_rev + " " + ui.expandpath("default")))
+		else:
+			# First upload sets the subject for the CL itself.
+			form_fields.append(("subject", self.Subject()))
+		ctype, body = EncodeMultipartFormData(form_fields, uploaded_diff_file)
+		response_body = MySend("/upload", body, content_type=ctype)
+		patchset = None
+		msg = response_body
+		lines = msg.splitlines()
+		if len(lines) >= 2:
+			msg = lines[0]
+			patchset = lines[1].strip()
+			patches = [x.split(" ", 1) for x in lines[2:]]
+		if response_body.startswith("Issue updated.") and quiet:
+			pass
+		else:
+			ui.status(msg + "\n")
+		set_status("uploaded CL metadata + diffs")
+		if not response_body.startswith("Issue created.") and not response_body.startswith("Issue updated."):
+			raise hg_util.Abort("failed to update issue: " + response_body)
+		issue = msg[msg.rfind("/")+1:]
+		self.name = issue
+		if not self.url:
+			self.url = server_url_base + self.name
+		if not uploaded_diff_file:
+			set_status("uploading patches")
+			patches = UploadSeparatePatches(issue, rpc, patchset, data, upload_options)
+		if vcs:
+			set_status("uploading base files")
+			vcs.UploadBaseFiles(issue, rpc, patches, patchset, upload_options, files)
+		if send_mail:
+			set_status("sending mail")
+			MySend("/" + issue + "/mail", payload="")
+		self.web = True
+		set_status("flushing changes to disk")
+		self.Flush(ui, repo)
+		return
+
+	def Mail(self, ui, repo):
+		pmsg = "Hello " + JoinComma(self.reviewer)
+		if self.cc:
+			pmsg += " (cc: %s)" % (', '.join(self.cc),)
+		pmsg += ",\n"
+		pmsg += "\n"
+		repourl = ui.expandpath("default")
+		if not self.mailed:
+			pmsg += "I'd like you to review this change to\n" + repourl + "\n"
+		else:
+			pmsg += "Please take another look.\n"
+		typecheck(pmsg, str)
+		PostMessage(ui, self.name, pmsg, subject=self.Subject())
+		self.mailed = True
+		self.Flush(ui, repo)
+
+def GoodCLName(name):
+	typecheck(name, str)
+	return re.match("^[0-9]+$", name)
+
+def ParseCL(text, name):
+	typecheck(text, str)
+	typecheck(name, str)
+	sname = None
+	lineno = 0
+	sections = {
+		'Author': '',
+		'Description': '',
+		'Files': '',
+		'URL': '',
+		'Reviewer': '',
+		'CC': '',
+		'Mailed': '',
+		'Private': '',
+	}
+	for line in text.split('\n'):
+		lineno += 1
+		line = line.rstrip()
+		if line != '' and line[0] == '#':
+			continue
+		if line == '' or line[0] == ' ' or line[0] == '\t':
+			if sname == None and line != '':
+				return None, lineno, 'text outside section'
+			if sname != None:
+				sections[sname] += line + '\n'
+			continue
+		p = line.find(':')
+		if p >= 0:
+			s, val = line[:p].strip(), line[p+1:].strip()
+			if s in sections:
+				sname = s
+				if val != '':
+					sections[sname] += val + '\n'
+				continue
+		return None, lineno, 'malformed section header'
+
+	for k in sections:
+		sections[k] = StripCommon(sections[k]).rstrip()
+
+	cl = CL(name)
+	if sections['Author']:
+		cl.copied_from = sections['Author']
+	cl.desc = sections['Description']
+	for line in sections['Files'].split('\n'):
+		i = line.find('#')
+		if i >= 0:
+			line = line[0:i].rstrip()
+		line = line.strip()
+		if line == '':
+			continue
+		cl.files.append(line)
+	cl.reviewer = SplitCommaSpace(sections['Reviewer'])
+	cl.cc = SplitCommaSpace(sections['CC'])
+	cl.url = sections['URL']
+	if sections['Mailed'] != 'False':
+		# Odd default, but avoids spurious mailings when
+		# reading old CLs that do not have a Mailed: line.
+		# CLs created with this update will always have 
+		# Mailed: False on disk.
+		cl.mailed = True
+	if sections['Private'] in ('True', 'true', 'Yes', 'yes'):
+		cl.private = True
+	if cl.desc == '<enter description here>':
+		cl.desc = ''
+	return cl, 0, ''
+
+def SplitCommaSpace(s):
+	typecheck(s, str)
+	s = s.strip()
+	if s == "":
+		return []
+	return re.split(", *", s)
+
+def CutDomain(s):
+	typecheck(s, str)
+	i = s.find('@')
+	if i >= 0:
+		s = s[0:i]
+	return s
+
+def JoinComma(l):
+	for s in l:
+		typecheck(s, str)
+	return ", ".join(l)
+
+def ExceptionDetail():
+	s = str(sys.exc_info()[0])
+	if s.startswith("<type '") and s.endswith("'>"):
+		s = s[7:-2]
+	elif s.startswith("<class '") and s.endswith("'>"):
+		s = s[8:-2]
+	arg = str(sys.exc_info()[1])
+	if len(arg) > 0:
+		s += ": " + arg
+	return s
+
+def IsLocalCL(ui, repo, name):
+	return GoodCLName(name) and os.access(CodeReviewDir(ui, repo) + "/cl." + name, 0)
+
+# Load CL from disk and/or the web.
+def LoadCL(ui, repo, name, web=True):
+	typecheck(name, str)
+	set_status("loading CL " + name)
+	if not GoodCLName(name):
+		return None, "invalid CL name"
+	dir = CodeReviewDir(ui, repo)
+	path = dir + "cl." + name
+	if os.access(path, 0):
+		ff = open(path)
+		text = ff.read()
+		ff.close()
+		cl, lineno, err = ParseCL(text, name)
+		if err != "":
+			return None, "malformed CL data: "+err
+		cl.local = True
+	else:
+		cl = CL(name)
+	if web:
+		set_status("getting issue metadata from web")
+		d = JSONGet(ui, "/api/" + name + "?messages=true")
+		set_status(None)
+		if d is None:
+			return None, "cannot load CL %s from server" % (name,)
+		if 'owner_email' not in d or 'issue' not in d or str(d['issue']) != name:
+			return None, "malformed response loading CL data from code review server"
+		cl.dict = d
+		cl.reviewer = d.get('reviewers', [])
+		cl.cc = d.get('cc', [])
+		if cl.local and cl.copied_from and cl.desc:
+			# local copy of CL written by someone else
+			# and we saved a description.  use that one,
+			# so that committers can edit the description
+			# before doing hg submit.
+			pass
+		else:
+			cl.desc = d.get('description', "")
+		cl.url = server_url_base + name
+		cl.web = True
+		cl.private = d.get('private', False) != False
+		cl.lgtm = []
+		for m in d.get('messages', []):
+			if m.get('approval', False) == True:
+				who = re.sub('@.*', '', m.get('sender', ''))
+				text = re.sub("\n(.|\n)*", '', m.get('text', ''))
+				cl.lgtm.append((who, text))
+
+	set_status("loaded CL " + name)
+	return cl, ''
+
+class LoadCLThread(threading.Thread):
+	def __init__(self, ui, repo, dir, f, web):
+		threading.Thread.__init__(self)
+		self.ui = ui
+		self.repo = repo
+		self.dir = dir
+		self.f = f
+		self.web = web
+		self.cl = None
+	def run(self):
+		cl, err = LoadCL(self.ui, self.repo, self.f[3:], web=self.web)
+		if err != '':
+			self.ui.warn("loading "+self.dir+self.f+": " + err + "\n")
+			return
+		self.cl = cl
+
+# Load all the CLs from this repository.
+def LoadAllCL(ui, repo, web=True):
+	dir = CodeReviewDir(ui, repo)
+	m = {}
+	files = [f for f in os.listdir(dir) if f.startswith('cl.')]
+	if not files:
+		return m
+	active = []
+	first = True
+	for f in files:
+		t = LoadCLThread(ui, repo, dir, f, web)
+		t.start()
+		if web and first:
+			# first request: wait in case it needs to authenticate
+			# otherwise we get lots of user/password prompts
+			# running in parallel.
+			t.join()
+			if t.cl:
+				m[t.cl.name] = t.cl
+			first = False
+		else:
+			active.append(t)
+	for t in active:
+		t.join()
+		if t.cl:
+			m[t.cl.name] = t.cl
+	return m
+
+# Find repository root.  On error, ui.warn and return None
+def RepoDir(ui, repo):
+	url = repo.url();
+	if not url.startswith('file:'):
+		ui.warn("repository %s is not in local file system\n" % (url,))
+		return None
+	url = url[5:]
+	if url.endswith('/'):
+		url = url[:-1]
+	typecheck(url, str)
+	return url
+
+# Find (or make) code review directory.  On error, ui.warn and return None
+def CodeReviewDir(ui, repo):
+	dir = RepoDir(ui, repo)
+	if dir == None:
+		return None
+	dir += '/.hg/codereview/'
+	if not os.path.isdir(dir):
+		try:
+			os.mkdir(dir, 0700)
+		except:
+			ui.warn('cannot mkdir %s: %s\n' % (dir, ExceptionDetail()))
+			return None
+	typecheck(dir, str)
+	return dir
+
+# Turn leading tabs into spaces, so that the common white space
+# prefix doesn't get confused when people's editors write out 
+# some lines with spaces, some with tabs.  Only a heuristic
+# (some editors don't use 8 spaces either) but a useful one.
+def TabsToSpaces(line):
+	i = 0
+	while i < len(line) and line[i] == '\t':
+		i += 1
+	return ' '*(8*i) + line[i:]
+
+# Strip maximal common leading white space prefix from text
+def StripCommon(text):
+	typecheck(text, str)
+	ws = None
+	for line in text.split('\n'):
+		line = line.rstrip()
+		if line == '':
+			continue
+		line = TabsToSpaces(line)
+		white = line[:len(line)-len(line.lstrip())]
+		if ws == None:
+			ws = white
+		else:
+			common = ''
+			for i in range(min(len(white), len(ws))+1):
+				if white[0:i] == ws[0:i]:
+					common = white[0:i]
+			ws = common
+		if ws == '':
+			break
+	if ws == None:
+		return text
+	t = ''
+	for line in text.split('\n'):
+		line = line.rstrip()
+		line = TabsToSpaces(line)
+		if line.startswith(ws):
+			line = line[len(ws):]
+		if line == '' and t == '':
+			continue
+		t += line + '\n'
+	while len(t) >= 2 and t[-2:] == '\n\n':
+		t = t[:-1]
+	typecheck(t, str)
+	return t
+
+# Indent text with indent.
+def Indent(text, indent):
+	typecheck(text, str)
+	typecheck(indent, str)
+	t = ''
+	for line in text.split('\n'):
+		t += indent + line + '\n'
+	typecheck(t, str)
+	return t
+
+# Return the first line of l
+def line1(text):
+	typecheck(text, str)
+	return text.split('\n')[0]
+
+_change_prolog = """# Change list.
+# Lines beginning with # are ignored.
+# Multi-line values should be indented.
+"""
+
+desc_re = '^(.+: |(tag )?(release|weekly)\.|fix build|undo CL)'
+
+desc_msg = '''Your CL description appears not to use the standard form.
+
+The first line of your change description is conventionally a
+one-line summary of the change, prefixed by the primary affected package,
+and is used as the subject for code review mail; the rest of the description
+elaborates.
+
+Examples:
+
+	encoding/rot13: new package
+
+	math: add IsInf, IsNaN
+	
+	net: fix cname in LookupHost
+
+	unicode: update to Unicode 5.0.2
+
+'''
+
+def promptyesno(ui, msg):
+	if hgversion >= "2.7":
+		return ui.promptchoice(msg + " $$ &yes $$ &no", 0) == 0
+	else:
+		return ui.promptchoice(msg, ["&yes", "&no"], 0) == 0
+
+def promptremove(ui, repo, f):
+	if promptyesno(ui, "hg remove %s (y/n)?" % (f,)):
+		if hg_commands.remove(ui, repo, 'path:'+f) != 0:
+			ui.warn("error removing %s" % (f,))
+
+def promptadd(ui, repo, f):
+	if promptyesno(ui, "hg add %s (y/n)?" % (f,)):
+		if hg_commands.add(ui, repo, 'path:'+f) != 0:
+			ui.warn("error adding %s" % (f,))
+
+def EditCL(ui, repo, cl):
+	set_status(None)	# do not show status
+	s = cl.EditorText()
+	while True:
+		s = ui.edit(s, ui.username())
+		
+		# We can't trust Mercurial + Python not to die before making the change,
+		# so, by popular demand, just scribble the most recent CL edit into
+		# $(hg root)/last-change so that if Mercurial does die, people
+		# can look there for their work.
+		try:
+			f = open(repo.root+"/last-change", "w")
+			f.write(s)
+			f.close()
+		except:
+			pass
+
+		clx, line, err = ParseCL(s, cl.name)
+		if err != '':
+			if not promptyesno(ui, "error parsing change list: line %d: %s\nre-edit (y/n)?" % (line, err)):
+				return "change list not modified"
+			continue
+		
+		# Check description.
+		if clx.desc == '':
+			if promptyesno(ui, "change list should have a description\nre-edit (y/n)?"):
+				continue
+		elif re.search('<enter reason for undo>', clx.desc):
+			if promptyesno(ui, "change list description omits reason for undo\nre-edit (y/n)?"):
+				continue
+		elif not re.match(desc_re, clx.desc.split('\n')[0]):
+			if promptyesno(ui, desc_msg + "re-edit (y/n)?"):
+				continue
+
+		# Check file list for files that need to be hg added or hg removed
+		# or simply aren't understood.
+		pats = ['path:'+f for f in clx.files]
+		changed = hg_matchPattern(ui, repo, *pats, modified=True, added=True, removed=True)
+		deleted = hg_matchPattern(ui, repo, *pats, deleted=True)
+		unknown = hg_matchPattern(ui, repo, *pats, unknown=True)
+		ignored = hg_matchPattern(ui, repo, *pats, ignored=True)
+		clean = hg_matchPattern(ui, repo, *pats, clean=True)
+		files = []
+		for f in clx.files:
+			if f in changed:
+				files.append(f)
+				continue
+			if f in deleted:
+				promptremove(ui, repo, f)
+				files.append(f)
+				continue
+			if f in unknown:
+				promptadd(ui, repo, f)
+				files.append(f)
+				continue
+			if f in ignored:
+				ui.warn("error: %s is excluded by .hgignore; omitting\n" % (f,))
+				continue
+			if f in clean:
+				ui.warn("warning: %s is listed in the CL but unchanged\n" % (f,))
+				files.append(f)
+				continue
+			p = repo.root + '/' + f
+			if os.path.isfile(p):
+				ui.warn("warning: %s is a file but not known to hg\n" % (f,))
+				files.append(f)
+				continue
+			if os.path.isdir(p):
+				ui.warn("error: %s is a directory, not a file; omitting\n" % (f,))
+				continue
+			ui.warn("error: %s does not exist; omitting\n" % (f,))
+		clx.files = files
+
+		cl.desc = clx.desc
+		cl.reviewer = clx.reviewer
+		cl.cc = clx.cc
+		cl.files = clx.files
+		cl.private = clx.private
+		break
+	return ""
+
+# For use by submit, etc. (NOT by change)
+# Get change list number or list of files from command line.
+# If files are given, make a new change list.
+def CommandLineCL(ui, repo, pats, opts, defaultcc=None):
+	if len(pats) > 0 and GoodCLName(pats[0]):
+		if len(pats) != 1:
+			return None, "cannot specify change number and file names"
+		if opts.get('message'):
+			return None, "cannot use -m with existing CL"
+		cl, err = LoadCL(ui, repo, pats[0], web=True)
+		if err != "":
+			return None, err
+	else:
+		cl = CL("new")
+		cl.local = True
+		cl.files = ChangedFiles(ui, repo, pats, taken=Taken(ui, repo))
+		if not cl.files:
+			return None, "no files changed"
+	if opts.get('reviewer'):
+		cl.reviewer = Add(cl.reviewer, SplitCommaSpace(opts.get('reviewer')))
+	if opts.get('cc'):
+		cl.cc = Add(cl.cc, SplitCommaSpace(opts.get('cc')))
+	if defaultcc:
+		cl.cc = Add(cl.cc, defaultcc)
+	if cl.name == "new":
+		if opts.get('message'):
+			cl.desc = opts.get('message')
+		else:
+			err = EditCL(ui, repo, cl)
+			if err != '':
+				return None, err
+	return cl, ""
+
+#######################################################################
+# Change list file management
+
+# Return list of changed files in repository that match pats.
+# The patterns came from the command line, so we warn
+# if they have no effect or cannot be understood.
+def ChangedFiles(ui, repo, pats, taken=None):
+	taken = taken or {}
+	# Run each pattern separately so that we can warn about
+	# patterns that didn't do anything useful.
+	for p in pats:
+		for f in hg_matchPattern(ui, repo, p, unknown=True):
+			promptadd(ui, repo, f)
+		for f in hg_matchPattern(ui, repo, p, removed=True):
+			promptremove(ui, repo, f)
+		files = hg_matchPattern(ui, repo, p, modified=True, added=True, removed=True)
+		for f in files:
+			if f in taken:
+				ui.warn("warning: %s already in CL %s\n" % (f, taken[f].name))
+		if not files:
+			ui.warn("warning: %s did not match any modified files\n" % (p,))
+
+	# Again, all at once (eliminates duplicates)
+	l = hg_matchPattern(ui, repo, *pats, modified=True, added=True, removed=True)
+	l.sort()
+	if taken:
+		l = Sub(l, taken.keys())
+	return l
+
+# Return list of changed files in repository that match pats and still exist.
+def ChangedExistingFiles(ui, repo, pats, opts):
+	l = hg_matchPattern(ui, repo, *pats, modified=True, added=True)
+	l.sort()
+	return l
+
+# Return list of files claimed by existing CLs
+def Taken(ui, repo):
+	all = LoadAllCL(ui, repo, web=False)
+	taken = {}
+	for _, cl in all.items():
+		for f in cl.files:
+			taken[f] = cl
+	return taken
+
+# Return list of changed files that are not claimed by other CLs
+def DefaultFiles(ui, repo, pats):
+	return ChangedFiles(ui, repo, pats, taken=Taken(ui, repo))
+
+#######################################################################
+# File format checking.
+
+def CheckFormat(ui, repo, files, just_warn=False):
+	set_status("running gofmt")
+	CheckGofmt(ui, repo, files, just_warn)
+	CheckTabfmt(ui, repo, files, just_warn)
+
+# Check that gofmt run on the list of files does not change them
+def CheckGofmt(ui, repo, files, just_warn):
+	files = gofmt_required(files)
+	if not files:
+		return
+	cwd = os.getcwd()
+	files = [RelativePath(repo.root + '/' + f, cwd) for f in files]
+	files = [f for f in files if os.access(f, 0)]
+	if not files:
+		return
+	try:
+		cmd = subprocess.Popen(["gofmt", "-l"] + files, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=sys.platform != "win32")
+		cmd.stdin.close()
+	except:
+		raise hg_util.Abort("gofmt: " + ExceptionDetail())
+	data = cmd.stdout.read()
+	errors = cmd.stderr.read()
+	cmd.wait()
+	set_status("done with gofmt")
+	if len(errors) > 0:
+		ui.warn("gofmt errors:\n" + errors.rstrip() + "\n")
+		return
+	if len(data) > 0:
+		msg = "gofmt needs to format these files (run hg gofmt):\n" + Indent(data, "\t").rstrip()
+		if just_warn:
+			ui.warn("warning: " + msg + "\n")
+		else:
+			raise hg_util.Abort(msg)
+	return
+
+# Check that *.[chys] files indent using tabs.
+def CheckTabfmt(ui, repo, files, just_warn):
+	files = [f for f in files if f.startswith('src/') and re.search(r"\.[chys]$", f) and not re.search(r"\.tab\.[ch]$", f)]
+	if not files:
+		return
+	cwd = os.getcwd()
+	files = [RelativePath(repo.root + '/' + f, cwd) for f in files]
+	files = [f for f in files if os.access(f, 0)]
+	badfiles = []
+	for f in files:
+		try:
+			for line in open(f, 'r'):
+				# Four leading spaces is enough to complain about,
+				# except that some Plan 9 code uses four spaces as the label indent,
+				# so allow that.
+				if line.startswith('    ') and not re.match('    [A-Za-z0-9_]+:', line):
+					badfiles.append(f)
+					break
+		except:
+			# ignore cannot open file, etc.
+			pass
+	if len(badfiles) > 0:
+		msg = "these files use spaces for indentation (use tabs instead):\n\t" + "\n\t".join(badfiles)
+		if just_warn:
+			ui.warn("warning: " + msg + "\n")
+		else:
+			raise hg_util.Abort(msg)
+	return
+
+#######################################################################
+# CONTRIBUTORS file parsing
+
+contributorsCache = None
+contributorsURL = None
+
+def ReadContributors(ui, repo):
+	global contributorsCache
+	if contributorsCache is not None:
+		return contributorsCache
+
+	try:
+		if contributorsURL is not None:
+			opening = contributorsURL
+			f = urllib2.urlopen(contributorsURL)
+		else:
+			opening = repo.root + '/CONTRIBUTORS'
+			f = open(repo.root + '/CONTRIBUTORS', 'r')
+	except:
+		ui.write("warning: cannot open %s: %s\n" % (opening, ExceptionDetail()))
+		return
+
+	contributors = {}
+	for line in f:
+		# CONTRIBUTORS is a list of lines like:
+		#	Person <email>
+		#	Person <email> <alt-email>
+		# The first email address is the one used in commit logs.
+		if line.startswith('#'):
+			continue
+		m = re.match(r"([^<>]+\S)\s+(<[^<>\s]+>)((\s+<[^<>\s]+>)*)\s*$", line)
+		if m:
+			name = m.group(1)
+			email = m.group(2)[1:-1]
+			contributors[email.lower()] = (name, email)
+			for extra in m.group(3).split():
+				contributors[extra[1:-1].lower()] = (name, email)
+
+	contributorsCache = contributors
+	return contributors
+
+def CheckContributor(ui, repo, user=None):
+	set_status("checking CONTRIBUTORS file")
+	user, userline = FindContributor(ui, repo, user, warn=False)
+	if not userline:
+		raise hg_util.Abort("cannot find %s in CONTRIBUTORS" % (user,))
+	return userline
+
+def FindContributor(ui, repo, user=None, warn=True):
+	if not user:
+		user = ui.config("ui", "username")
+		if not user:
+			raise hg_util.Abort("[ui] username is not configured in .hgrc")
+	user = user.lower()
+	m = re.match(r".*<(.*)>", user)
+	if m:
+		user = m.group(1)
+
+	contributors = ReadContributors(ui, repo)
+	if user not in contributors:
+		if warn:
+			ui.warn("warning: cannot find %s in CONTRIBUTORS\n" % (user,))
+		return user, None
+	
+	user, email = contributors[user]
+	return email, "%s <%s>" % (user, email)
+
+#######################################################################
+# Mercurial helper functions.
+# Read http://mercurial.selenic.com/wiki/MercurialApi before writing any of these.
+# We use the ui.pushbuffer/ui.popbuffer + hg_commands.xxx tricks for all interaction
+# with Mercurial.  It has proved the most stable as they make changes.
+
+hgversion = hg_util.version()
+
+# We require Mercurial 1.9 and suggest Mercurial 2.0.
+# The details of the scmutil package changed then,
+# so allowing earlier versions would require extra band-aids below.
+# Ubuntu 11.10 ships with Mercurial 1.9.1 as the default version.
+hg_required = "1.9"
+hg_suggested = "2.0"
+
+old_message = """
+
+The code review extension requires Mercurial """+hg_required+""" or newer.
+You are using Mercurial """+hgversion+""".
+
+To install a new Mercurial, use
+
+	sudo easy_install mercurial=="""+hg_suggested+"""
+
+or visit http://mercurial.selenic.com/downloads/.
+"""
+
+linux_message = """
+You may need to clear your current Mercurial installation by running:
+
+	sudo apt-get remove mercurial mercurial-common
+	sudo rm -rf /etc/mercurial
+"""
+
+if hgversion < hg_required:
+	msg = old_message
+	if os.access("/etc/mercurial", 0):
+		msg += linux_message
+	raise hg_util.Abort(msg)
+
+from mercurial.hg import clean as hg_clean
+from mercurial import cmdutil as hg_cmdutil
+from mercurial import error as hg_error
+from mercurial import match as hg_match
+from mercurial import node as hg_node
+
+class uiwrap(object):
+	def __init__(self, ui):
+		self.ui = ui
+		ui.pushbuffer()
+		self.oldQuiet = ui.quiet
+		ui.quiet = True
+		self.oldVerbose = ui.verbose
+		ui.verbose = False
+	def output(self):
+		ui = self.ui
+		ui.quiet = self.oldQuiet
+		ui.verbose = self.oldVerbose
+		return ui.popbuffer()
+
+def to_slash(path):
+	if sys.platform == "win32":
+		return path.replace('\\', '/')
+	return path
+
+def hg_matchPattern(ui, repo, *pats, **opts):
+	w = uiwrap(ui)
+	hg_commands.status(ui, repo, *pats, **opts)
+	text = w.output()
+	ret = []
+	prefix = to_slash(os.path.realpath(repo.root))+'/'
+	for line in text.split('\n'):
+		f = line.split()
+		if len(f) > 1:
+			if len(pats) > 0:
+				# Given patterns, Mercurial shows relative to cwd
+				p = to_slash(os.path.realpath(f[1]))
+				if not p.startswith(prefix):
+					print >>sys.stderr, "File %s not in repo root %s.\n" % (p, prefix)
+				else:
+					ret.append(p[len(prefix):])
+			else:
+				# Without patterns, Mercurial shows relative to root (what we want)
+				ret.append(to_slash(f[1]))
+	return ret
+
+def hg_heads(ui, repo):
+	w = uiwrap(ui)
+	hg_commands.heads(ui, repo)
+	return w.output()
+
+noise = [
+	"",
+	"resolving manifests",
+	"searching for changes",
+	"couldn't find merge tool hgmerge",
+	"adding changesets",
+	"adding manifests",
+	"adding file changes",
+	"all local heads known remotely",
+]
+
+def isNoise(line):
+	line = str(line)
+	for x in noise:
+		if line == x:
+			return True
+	return False
+
+def hg_incoming(ui, repo):
+	w = uiwrap(ui)
+	ret = hg_commands.incoming(ui, repo, force=False, bundle="")
+	if ret and ret != 1:
+		raise hg_util.Abort(ret)
+	return w.output()
+
+def hg_log(ui, repo, **opts):
+	for k in ['date', 'keyword', 'rev', 'user']:
+		if not opts.has_key(k):
+			opts[k] = ""
+	w = uiwrap(ui)
+	ret = hg_commands.log(ui, repo, **opts)
+	if ret:
+		raise hg_util.Abort(ret)
+	return w.output()
+
+def hg_outgoing(ui, repo, **opts):
+	w = uiwrap(ui)
+	ret = hg_commands.outgoing(ui, repo, **opts)
+	if ret and ret != 1:
+		raise hg_util.Abort(ret)
+	return w.output()
+
+def hg_pull(ui, repo, **opts):
+	w = uiwrap(ui)
+	ui.quiet = False
+	ui.verbose = True  # for file list
+	err = hg_commands.pull(ui, repo, **opts)
+	for line in w.output().split('\n'):
+		if isNoise(line):
+			continue
+		if line.startswith('moving '):
+			line = 'mv ' + line[len('moving '):]
+		if line.startswith('getting ') and line.find(' to ') >= 0:
+			line = 'mv ' + line[len('getting '):]
+		if line.startswith('getting '):
+			line = '+ ' + line[len('getting '):]
+		if line.startswith('removing '):
+			line = '- ' + line[len('removing '):]
+		ui.write(line + '\n')
+	return err
+
+def hg_push(ui, repo, **opts):
+	w = uiwrap(ui)
+	ui.quiet = False
+	ui.verbose = True
+	err = hg_commands.push(ui, repo, **opts)
+	for line in w.output().split('\n'):
+		if not isNoise(line):
+			ui.write(line + '\n')
+	return err
+
+def hg_commit(ui, repo, *pats, **opts):
+	return hg_commands.commit(ui, repo, *pats, **opts)
+
+#######################################################################
+# Mercurial precommit hook to disable commit except through this interface.
+
+commit_okay = False
+
+def precommithook(ui, repo, **opts):
+	if commit_okay:
+		return False  # False means okay.
+	ui.write("\ncodereview extension enabled; use mail, upload, or submit instead of commit\n\n")
+	return True
+
+#######################################################################
+# @clnumber file pattern support
+
+# We replace scmutil.match with the MatchAt wrapper to add the @clnumber pattern.
+
+match_repo = None
+match_ui = None
+match_orig = None
+
+def InstallMatch(ui, repo):
+	global match_repo
+	global match_ui
+	global match_orig
+
+	match_ui = ui
+	match_repo = repo
+
+	from mercurial import scmutil
+	match_orig = scmutil.match
+	scmutil.match = MatchAt
+
+def MatchAt(ctx, pats=None, opts=None, globbed=False, default='relpath'):
+	taken = []
+	files = []
+	pats = pats or []
+	opts = opts or {}
+	
+	for p in pats:
+		if p.startswith('@'):
+			taken.append(p)
+			clname = p[1:]
+			if clname == "default":
+				files = DefaultFiles(match_ui, match_repo, [])
+			else:
+				if not GoodCLName(clname):
+					raise hg_util.Abort("invalid CL name " + clname)
+				cl, err = LoadCL(match_repo.ui, match_repo, clname, web=False)
+				if err != '':
+					raise hg_util.Abort("loading CL " + clname + ": " + err)
+				if not cl.files:
+					raise hg_util.Abort("no files in CL " + clname)
+				files = Add(files, cl.files)
+	pats = Sub(pats, taken) + ['path:'+f for f in files]
+
+	# work-around for http://selenic.com/hg/rev/785bbc8634f8
+	if not hasattr(ctx, 'match'):
+		ctx = ctx[None]
+	return match_orig(ctx, pats=pats, opts=opts, globbed=globbed, default=default)
+
+#######################################################################
+# Commands added by code review extension.
+
+# As of Mercurial 2.1 the commands are all required to return integer
+# exit codes, whereas earlier versions allowed returning arbitrary strings
+# to be printed as errors.  We wrap the old functions to make sure we
+# always return integer exit codes now.  Otherwise Mercurial dies
+# with a TypeError traceback (unsupported operand type(s) for &: 'str' and 'int').
+# Introduce a Python decorator to convert old functions to the new
+# stricter convention.
+
+def hgcommand(f):
+	def wrapped(ui, repo, *pats, **opts):
+		err = f(ui, repo, *pats, **opts)
+		if type(err) is int:
+			return err
+		if not err:
+			return 0
+		raise hg_util.Abort(err)
+	wrapped.__doc__ = f.__doc__
+	return wrapped
+
+#######################################################################
+# hg change
+
+@hgcommand
+def change(ui, repo, *pats, **opts):
+	"""create, edit or delete a change list
+
+	Create, edit or delete a change list.
+	A change list is a group of files to be reviewed and submitted together,
+	plus a textual description of the change.
+	Change lists are referred to by simple alphanumeric names.
+
+	Changes must be reviewed before they can be submitted.
+
+	In the absence of options, the change command opens the
+	change list for editing in the default editor.
+
+	Deleting a change with the -d or -D flag does not affect
+	the contents of the files listed in that change.  To revert
+	the files listed in a change, use
+
+		hg revert @123456
+
+	before running hg change -d 123456.
+	"""
+
+	if codereview_disabled:
+		return codereview_disabled
+	
+	dirty = {}
+	if len(pats) > 0 and GoodCLName(pats[0]):
+		name = pats[0]
+		if len(pats) != 1:
+			return "cannot specify CL name and file patterns"
+		pats = pats[1:]
+		cl, err = LoadCL(ui, repo, name, web=True)
+		if err != '':
+			return err
+		if not cl.local and (opts["stdin"] or not opts["stdout"]):
+			return "cannot change non-local CL " + name
+	else:
+		name = "new"
+		cl = CL("new")
+		if repo[None].branch() != "default":
+			return "cannot create CL outside default branch; switch with 'hg update default'"
+		dirty[cl] = True
+		files = ChangedFiles(ui, repo, pats, taken=Taken(ui, repo))
+
+	if opts["delete"] or opts["deletelocal"]:
+		if opts["delete"] and opts["deletelocal"]:
+			return "cannot use -d and -D together"
+		flag = "-d"
+		if opts["deletelocal"]:
+			flag = "-D"
+		if name == "new":
+			return "cannot use "+flag+" with file patterns"
+		if opts["stdin"] or opts["stdout"]:
+			return "cannot use "+flag+" with -i or -o"
+		if not cl.local:
+			return "cannot change non-local CL " + name
+		if opts["delete"]:
+			if cl.copied_from:
+				return "original author must delete CL; hg change -D will remove locally"
+			PostMessage(ui, cl.name, "*** Abandoned ***", send_mail=cl.mailed)
+			EditDesc(cl.name, closed=True, private=cl.private)
+		cl.Delete(ui, repo)
+		return
+
+	if opts["stdin"]:
+		s = sys.stdin.read()
+		clx, line, err = ParseCL(s, name)
+		if err != '':
+			return "error parsing change list: line %d: %s" % (line, err)
+		if clx.desc is not None:
+			cl.desc = clx.desc;
+			dirty[cl] = True
+		if clx.reviewer is not None:
+			cl.reviewer = clx.reviewer
+			dirty[cl] = True
+		if clx.cc is not None:
+			cl.cc = clx.cc
+			dirty[cl] = True
+		if clx.files is not None:
+			cl.files = clx.files
+			dirty[cl] = True
+		if clx.private != cl.private:
+			cl.private = clx.private
+			dirty[cl] = True
+
+	if not opts["stdin"] and not opts["stdout"]:
+		if name == "new":
+			cl.files = files
+		err = EditCL(ui, repo, cl)
+		if err != "":
+			return err
+		dirty[cl] = True
+
+	for d, _ in dirty.items():
+		name = d.name
+		d.Flush(ui, repo)
+		if name == "new":
+			d.Upload(ui, repo, quiet=True)
+
+	if opts["stdout"]:
+		ui.write(cl.EditorText())
+	elif opts["pending"]:
+		ui.write(cl.PendingText())
+	elif name == "new":
+		if ui.quiet:
+			ui.write(cl.name)
+		else:
+			ui.write("CL created: " + cl.url + "\n")
+	return
+
+#######################################################################
+# hg code-login (broken?)
+
+@hgcommand
+def code_login(ui, repo, **opts):
+	"""log in to code review server
+
+	Logs in to the code review server, saving a cookie in
+	a file in your home directory.
+	"""
+	if codereview_disabled:
+		return codereview_disabled
+
+	MySend(None)
+
+#######################################################################
+# hg clpatch / undo / release-apply / download
+# All concerned with applying or unapplying patches to the repository.
+
+@hgcommand
+def clpatch(ui, repo, clname, **opts):
+	"""import a patch from the code review server
+
+	Imports a patch from the code review server into the local client.
+	If the local client has already modified any of the files that the
+	patch modifies, this command will refuse to apply the patch.
+
+	Submitting an imported patch will keep the original author's
+	name as the Author: line but add your own name to a Committer: line.
+	"""
+	if repo[None].branch() != "default":
+		return "cannot run hg clpatch outside default branch"
+	return clpatch_or_undo(ui, repo, clname, opts, mode="clpatch")
+
+@hgcommand
+def undo(ui, repo, clname, **opts):
+	"""undo the effect of a CL
+	
+	Creates a new CL that undoes an earlier CL.
+	After creating the CL, opens the CL text for editing so that
+	you can add the reason for the undo to the description.
+	"""
+	if repo[None].branch() != "default":
+		return "cannot run hg undo outside default branch"
+	return clpatch_or_undo(ui, repo, clname, opts, mode="undo")
+
+@hgcommand
+def release_apply(ui, repo, clname, **opts):
+	"""apply a CL to the release branch
+
+	Creates a new CL copying a previously committed change
+	from the main branch to the release branch.
+	The current client must either be clean or already be in
+	the release branch.
+	
+	The release branch must be created by starting with a
+	clean client, disabling the code review plugin, and running:
+	
+		hg update weekly.YYYY-MM-DD
+		hg branch release-branch.rNN
+		hg commit -m 'create release-branch.rNN'
+		hg push --new-branch
+	
+	Then re-enable the code review plugin.
+	
+	People can test the release branch by running
+	
+		hg update release-branch.rNN
+	
+	in a clean client.  To return to the normal tree,
+	
+		hg update default
+	
+	Move changes since the weekly into the release branch 
+	using hg release-apply followed by the usual code review
+	process and hg submit.
+
+	When it comes time to tag the release, record the
+	final long-form tag of the release-branch.rNN
+	in the *default* branch's .hgtags file.  That is, run
+	
+		hg update default
+	
+	and then edit .hgtags as you would for a weekly.
+		
+	"""
+	c = repo[None]
+	if not releaseBranch:
+		return "no active release branches"
+	if c.branch() != releaseBranch:
+		if c.modified() or c.added() or c.removed():
+			raise hg_util.Abort("uncommitted local changes - cannot switch branches")
+		err = hg_clean(repo, releaseBranch)
+		if err:
+			return err
+	try:
+		err = clpatch_or_undo(ui, repo, clname, opts, mode="backport")
+		if err:
+			raise hg_util.Abort(err)
+	except Exception, e:
+		hg_clean(repo, "default")
+		raise e
+	return None
+
+def rev2clname(rev):
+	# Extract CL name from revision description.
+	# The last line in the description that is a codereview URL is the real one.
+	# Earlier lines might be part of the user-written description.
+	all = re.findall('(?m)^http://codereview.appspot.com/([0-9]+)$', rev.description())
+	if len(all) > 0:
+		return all[-1]
+	return ""
+
+undoHeader = """undo CL %s / %s
+
+<enter reason for undo>
+
+««« original CL description
+"""
+
+undoFooter = """
+»»»
+"""
+
+backportHeader = """[%s] %s
+
+««« CL %s / %s
+"""
+
+backportFooter = """
+»»»
+"""
+
+# Implementation of clpatch/undo.
+def clpatch_or_undo(ui, repo, clname, opts, mode):
+	if codereview_disabled:
+		return codereview_disabled
+
+	if mode == "undo" or mode == "backport":
+		# Find revision in Mercurial repository.
+		# Assume CL number is 7+ decimal digits.
+		# Otherwise is either change log sequence number (fewer decimal digits),
+		# hexadecimal hash, or tag name.
+		# Mercurial will fall over long before the change log
+		# sequence numbers get to be 7 digits long.
+		if re.match('^[0-9]{7,}$', clname):
+			found = False
+			for r in hg_log(ui, repo, keyword="codereview.appspot.com/"+clname, limit=100, template="{node}\n").split():
+				rev = repo[r]
+				# Last line with a code review URL is the actual review URL.
+				# Earlier ones might be part of the CL description.
+				n = rev2clname(rev)
+				if n == clname:
+					found = True
+					break
+			if not found:
+				return "cannot find CL %s in local repository" % clname
+		else:
+			rev = repo[clname]
+			if not rev:
+				return "unknown revision %s" % clname
+			clname = rev2clname(rev)
+			if clname == "":
+				return "cannot find CL name in revision description"
+		
+		# Create fresh CL and start with patch that would reverse the change.
+		vers = hg_node.short(rev.node())
+		cl = CL("new")
+		desc = str(rev.description())
+		if mode == "undo":
+			cl.desc = (undoHeader % (clname, vers)) + desc + undoFooter
+		else:
+			cl.desc = (backportHeader % (releaseBranch, line1(desc), clname, vers)) + desc + undoFooter
+		v1 = vers
+		v0 = hg_node.short(rev.parents()[0].node())
+		if mode == "undo":
+			arg = v1 + ":" + v0
+		else:
+			vers = v0
+			arg = v0 + ":" + v1
+		patch = RunShell(["hg", "diff", "--git", "-r", arg])
+
+	else:  # clpatch
+		cl, vers, patch, err = DownloadCL(ui, repo, clname)
+		if err != "":
+			return err
+		if patch == emptydiff:
+			return "codereview issue %s has no diff" % clname
+
+	# find current hg version (hg identify)
+	ctx = repo[None]
+	parents = ctx.parents()
+	id = '+'.join([hg_node.short(p.node()) for p in parents])
+
+	# if version does not match the patch version,
+	# try to update the patch line numbers.
+	if vers != "" and id != vers:
+		# "vers in repo" gives the wrong answer
+		# on some versions of Mercurial.  Instead, do the actual
+		# lookup and catch the exception.
+		try:
+			repo[vers].description()
+		except:
+			return "local repository is out of date; sync to get %s" % (vers)
+		patch1, err = portPatch(repo, patch, vers, id)
+		if err != "":
+			if not opts["ignore_hgpatch_failure"]:
+				return "codereview issue %s is out of date: %s (%s->%s)" % (clname, err, vers, id)
+		else:
+			patch = patch1
+	argv = ["hgpatch"]
+	if opts["no_incoming"] or mode == "backport":
+		argv += ["--checksync=false"]
+	try:
+		cmd = subprocess.Popen(argv, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None, close_fds=sys.platform != "win32")
+	except:
+		return "hgpatch: " + ExceptionDetail() + "\nInstall hgpatch with:\n$ go get code.google.com/p/go.codereview/cmd/hgpatch\n"
+
+	out, err = cmd.communicate(patch)
+	if cmd.returncode != 0 and not opts["ignore_hgpatch_failure"]:
+		return "hgpatch failed"
+	cl.local = True
+	cl.files = out.strip().split()
+	if not cl.files and not opts["ignore_hgpatch_failure"]:
+		return "codereview issue %s has no changed files" % clname
+	files = ChangedFiles(ui, repo, [])
+	extra = Sub(cl.files, files)
+	if extra:
+		ui.warn("warning: these files were listed in the patch but not changed:\n\t" + "\n\t".join(extra) + "\n")
+	cl.Flush(ui, repo)
+	if mode == "undo":
+		err = EditCL(ui, repo, cl)
+		if err != "":
+			return "CL created, but error editing: " + err
+		cl.Flush(ui, repo)
+	else:
+		ui.write(cl.PendingText() + "\n")
+
+# portPatch rewrites patch from being a patch against
+# oldver to being a patch against newver.
+def portPatch(repo, patch, oldver, newver):
+	lines = patch.splitlines(True) # True = keep \n
+	delta = None
+	for i in range(len(lines)):
+		line = lines[i]
+		if line.startswith('--- a/'):
+			file = line[6:-1]
+			delta = fileDeltas(repo, file, oldver, newver)
+		if not delta or not line.startswith('@@ '):
+			continue
+		# @@ -x,y +z,w @@ means the patch chunk replaces
+		# the original file's line numbers x up to x+y with the
+		# line numbers z up to z+w in the new file.
+		# Find the delta from x in the original to the same
+		# line in the current version and add that delta to both
+		# x and z.
+		m = re.match('@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@', line)
+		if not m:
+			return None, "error parsing patch line numbers"
+		n1, len1, n2, len2 = int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4))
+		d, err = lineDelta(delta, n1, len1)
+		if err != "":
+			return "", err
+		n1 += d
+		n2 += d
+		lines[i] = "@@ -%d,%d +%d,%d @@\n" % (n1, len1, n2, len2)
+		
+	newpatch = ''.join(lines)
+	return newpatch, ""
+
+# fileDelta returns the line number deltas for the given file's
+# changes from oldver to newver.
+# The deltas are a list of (n, len, newdelta) triples that say
+# lines [n, n+len) were modified, and after that range the
+# line numbers are +newdelta from what they were before.
+def fileDeltas(repo, file, oldver, newver):
+	cmd = ["hg", "diff", "--git", "-r", oldver + ":" + newver, "path:" + file]
+	data = RunShell(cmd, silent_ok=True)
+	deltas = []
+	for line in data.splitlines():
+		m = re.match('@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@', line)
+		if not m:
+			continue
+		n1, len1, n2, len2 = int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4))
+		deltas.append((n1, len1, n2+len2-(n1+len1)))
+	return deltas
+
+# lineDelta finds the appropriate line number delta to apply to the lines [n, n+len).
+# It returns an error if those lines were rewritten by the patch.
+def lineDelta(deltas, n, len):
+	d = 0
+	for (old, oldlen, newdelta) in deltas:
+		if old >= n+len:
+			break
+		if old+len > n:
+			return 0, "patch and recent changes conflict"
+		d = newdelta
+	return d, ""
+
+@hgcommand
+def download(ui, repo, clname, **opts):
+	"""download a change from the code review server
+
+	Download prints a description of the given change list
+	followed by its diff, downloaded from the code review server.
+	"""
+	if codereview_disabled:
+		return codereview_disabled
+
+	cl, vers, patch, err = DownloadCL(ui, repo, clname)
+	if err != "":
+		return err
+	ui.write(cl.EditorText() + "\n")
+	ui.write(patch + "\n")
+	return
+
+#######################################################################
+# hg file
+
+@hgcommand
+def file(ui, repo, clname, pat, *pats, **opts):
+	"""assign files to or remove files from a change list
+
+	Assign files to or (with -d) remove files from a change list.
+
+	The -d option only removes files from the change list.
+	It does not edit them or remove them from the repository.
+	"""
+	if codereview_disabled:
+		return codereview_disabled
+
+	pats = tuple([pat] + list(pats))
+	if not GoodCLName(clname):
+		return "invalid CL name " + clname
+
+	dirty = {}
+	cl, err = LoadCL(ui, repo, clname, web=False)
+	if err != '':
+		return err
+	if not cl.local:
+		return "cannot change non-local CL " + clname
+
+	files = ChangedFiles(ui, repo, pats)
+
+	if opts["delete"]:
+		oldfiles = Intersect(files, cl.files)
+		if oldfiles:
+			if not ui.quiet:
+				ui.status("# Removing files from CL.  To undo:\n")
+				ui.status("#	cd %s\n" % (repo.root))
+				for f in oldfiles:
+					ui.status("#	hg file %s %s\n" % (cl.name, f))
+			cl.files = Sub(cl.files, oldfiles)
+			cl.Flush(ui, repo)
+		else:
+			ui.status("no such files in CL")
+		return
+
+	if not files:
+		return "no such modified files"
+
+	files = Sub(files, cl.files)
+	taken = Taken(ui, repo)
+	warned = False
+	for f in files:
+		if f in taken:
+			if not warned and not ui.quiet:
+				ui.status("# Taking files from other CLs.  To undo:\n")
+				ui.status("#	cd %s\n" % (repo.root))
+				warned = True
+			ocl = taken[f]
+			if not ui.quiet:
+				ui.status("#	hg file %s %s\n" % (ocl.name, f))
+			if ocl not in dirty:
+				ocl.files = Sub(ocl.files, files)
+				dirty[ocl] = True
+	cl.files = Add(cl.files, files)
+	dirty[cl] = True
+	for d, _ in dirty.items():
+		d.Flush(ui, repo)
+	return
+
+#######################################################################
+# hg gofmt
+
+@hgcommand
+def gofmt(ui, repo, *pats, **opts):
+	"""apply gofmt to modified files
+
+	Applies gofmt to the modified files in the repository that match
+	the given patterns.
+	"""
+	if codereview_disabled:
+		return codereview_disabled
+
+	files = ChangedExistingFiles(ui, repo, pats, opts)
+	files = gofmt_required(files)
+	if not files:
+		return "no modified go files"
+	cwd = os.getcwd()
+	files = [RelativePath(repo.root + '/' + f, cwd) for f in files]
+	try:
+		cmd = ["gofmt", "-l"]
+		if not opts["list"]:
+			cmd += ["-w"]
+		if os.spawnvp(os.P_WAIT, "gofmt", cmd + files) != 0:
+			raise hg_util.Abort("gofmt did not exit cleanly")
+	except hg_error.Abort, e:
+		raise
+	except:
+		raise hg_util.Abort("gofmt: " + ExceptionDetail())
+	return
+
+def gofmt_required(files):
+	return [f for f in files if (not f.startswith('test/') or f.startswith('test/bench/')) and f.endswith('.go')]
+
+#######################################################################
+# hg mail
+
+@hgcommand
+def mail(ui, repo, *pats, **opts):
+	"""mail a change for review
+
+	Uploads a patch to the code review server and then sends mail
+	to the reviewer and CC list asking for a review.
+	"""
+	if codereview_disabled:
+		return codereview_disabled
+
+	cl, err = CommandLineCL(ui, repo, pats, opts, defaultcc=defaultcc)
+	if err != "":
+		return err
+	cl.Upload(ui, repo, gofmt_just_warn=True)
+	if not cl.reviewer:
+		# If no reviewer is listed, assign the review to defaultcc.
+		# This makes sure that it appears in the 
+		# codereview.appspot.com/user/defaultcc
+		# page, so that it doesn't get dropped on the floor.
+		if not defaultcc:
+			return "no reviewers listed in CL"
+		cl.cc = Sub(cl.cc, defaultcc)
+		cl.reviewer = defaultcc
+		cl.Flush(ui, repo)
+
+	if cl.files == []:
+		return "no changed files, not sending mail"
+
+	cl.Mail(ui, repo)		
+
+#######################################################################
+# hg p / hg pq / hg ps / hg pending
+
+@hgcommand
+def ps(ui, repo, *pats, **opts):
+	"""alias for hg p --short
+	"""
+	opts['short'] = True
+	return pending(ui, repo, *pats, **opts)
+
+@hgcommand
+def pq(ui, repo, *pats, **opts):
+	"""alias for hg p --quick
+	"""
+	opts['quick'] = True
+	return pending(ui, repo, *pats, **opts)
+
+@hgcommand
+def pending(ui, repo, *pats, **opts):
+	"""show pending changes
+
+	Lists pending changes followed by a list of unassigned but modified files.
+	"""
+	if codereview_disabled:
+		return codereview_disabled
+
+	quick = opts.get('quick', False)
+	short = opts.get('short', False)
+	m = LoadAllCL(ui, repo, web=not quick and not short)
+	names = m.keys()
+	names.sort()
+	for name in names:
+		cl = m[name]
+		if short:
+			ui.write(name + "\t" + line1(cl.desc) + "\n")
+		else:
+			ui.write(cl.PendingText(quick=quick) + "\n")
+
+	if short:
+		return
+	files = DefaultFiles(ui, repo, [])
+	if len(files) > 0:
+		s = "Changed files not in any CL:\n"
+		for f in files:
+			s += "\t" + f + "\n"
+		ui.write(s)
+
+#######################################################################
+# hg submit
+
+def need_sync():
+	raise hg_util.Abort("local repository out of date; must sync before submit")
+
+@hgcommand
+def submit(ui, repo, *pats, **opts):
+	"""submit change to remote repository
+
+	Submits change to remote repository.
+	Bails out if the local repository is not in sync with the remote one.
+	"""
+	if codereview_disabled:
+		return codereview_disabled
+
+	# We already called this on startup but sometimes Mercurial forgets.
+	set_mercurial_encoding_to_utf8()
+
+	if not opts["no_incoming"] and hg_incoming(ui, repo):
+		need_sync()
+
+	cl, err = CommandLineCL(ui, repo, pats, opts, defaultcc=defaultcc)
+	if err != "":
+		return err
+
+	user = None
+	if cl.copied_from:
+		user = cl.copied_from
+	userline = CheckContributor(ui, repo, user)
+	typecheck(userline, str)
+
+	about = ""
+	if cl.reviewer:
+		about += "R=" + JoinComma([CutDomain(s) for s in cl.reviewer]) + "\n"
+	if opts.get('tbr'):
+		tbr = SplitCommaSpace(opts.get('tbr'))
+		cl.reviewer = Add(cl.reviewer, tbr)
+		about += "TBR=" + JoinComma([CutDomain(s) for s in tbr]) + "\n"
+	if cl.cc:
+		about += "CC=" + JoinComma([CutDomain(s) for s in cl.cc]) + "\n"
+
+	if not cl.reviewer:
+		return "no reviewers listed in CL"
+
+	if not cl.local:
+		return "cannot submit non-local CL"
+
+	# upload, to sync current patch and also get change number if CL is new.
+	if not cl.copied_from:
+		cl.Upload(ui, repo, gofmt_just_warn=True)
+
+	# check gofmt for real; allowed upload to warn in order to save CL.
+	cl.Flush(ui, repo)
+	CheckFormat(ui, repo, cl.files)
+
+	about += "%s%s\n" % (server_url_base, cl.name)
+
+	if cl.copied_from:
+		about += "\nCommitter: " + CheckContributor(ui, repo, None) + "\n"
+	typecheck(about, str)
+
+	if not cl.mailed and not cl.copied_from:		# in case this is TBR
+		cl.Mail(ui, repo)
+
+	# submit changes locally
+	message = cl.desc.rstrip() + "\n\n" + about
+	typecheck(message, str)
+
+	set_status("pushing " + cl.name + " to remote server")
+
+	if hg_outgoing(ui, repo):
+		raise hg_util.Abort("local repository corrupt or out-of-phase with remote: found outgoing changes")
+	
+	old_heads = len(hg_heads(ui, repo).split())
+
+	global commit_okay
+	commit_okay = True
+	ret = hg_commit(ui, repo, *['path:'+f for f in cl.files], message=message, user=userline)
+	commit_okay = False
+	if ret:
+		return "nothing changed"
+	node = repo["-1"].node()
+	# push to remote; if it fails for any reason, roll back
+	try:
+		new_heads = len(hg_heads(ui, repo).split())
+		if old_heads != new_heads and not (old_heads == 0 and new_heads == 1):
+			# Created new head, so we weren't up to date.
+			need_sync()
+
+		# Push changes to remote.  If it works, we're committed.  If not, roll back.
+		try:
+			hg_push(ui, repo)
+		except hg_error.Abort, e:
+			if e.message.find("push creates new heads") >= 0:
+				# Remote repository had changes we missed.
+				need_sync()
+			raise
+	except:
+		real_rollback()
+		raise
+
+	# We're committed. Upload final patch, close review, add commit message.
+	changeURL = hg_node.short(node)
+	url = ui.expandpath("default")
+	m = re.match("(^https?://([^@/]+@)?([^.]+)\.googlecode\.com/hg/?)" + "|" +
+		"(^https?://([^@/]+@)?code\.google\.com/p/([^/.]+)(\.[^./]+)?/?)", url)
+	if m:
+		if m.group(1): # prj.googlecode.com/hg/ case
+			changeURL = "http://code.google.com/p/%s/source/detail?r=%s" % (m.group(3), changeURL)
+		elif m.group(4) and m.group(7): # code.google.com/p/prj.subrepo/ case
+			changeURL = "http://code.google.com/p/%s/source/detail?r=%s&repo=%s" % (m.group(6), changeURL, m.group(7)[1:])
+		elif m.group(4): # code.google.com/p/prj/ case
+			changeURL = "http://code.google.com/p/%s/source/detail?r=%s" % (m.group(6), changeURL)
+		else:
+			print >>sys.stderr, "URL: ", url
+	else:
+		print >>sys.stderr, "URL: ", url
+	pmsg = "*** Submitted as " + changeURL + " ***\n\n" + message
+
+	# When posting, move reviewers to CC line,
+	# so that the issue stops showing up in their "My Issues" page.
+	PostMessage(ui, cl.name, pmsg, reviewers="", cc=JoinComma(cl.reviewer+cl.cc))
+
+	if not cl.copied_from:
+		EditDesc(cl.name, closed=True, private=cl.private)
+	cl.Delete(ui, repo)
+
+	c = repo[None]
+	if c.branch() == releaseBranch and not c.modified() and not c.added() and not c.removed():
+		ui.write("switching from %s to default branch.\n" % releaseBranch)
+		err = hg_clean(repo, "default")
+		if err:
+			return err
+	return None
+
+#######################################################################
+# hg sync
+
+@hgcommand
+def sync(ui, repo, **opts):
+	"""synchronize with remote repository
+
+	Incorporates recent changes from the remote repository
+	into the local repository.
+	"""
+	if codereview_disabled:
+		return codereview_disabled
+
+	if not opts["local"]:
+		err = hg_pull(ui, repo, update=True)
+		if err:
+			return err
+	sync_changes(ui, repo)
+
+def sync_changes(ui, repo):
+	# Look through recent change log descriptions to find
+	# potential references to http://.*/our-CL-number.
+	# Double-check them by looking at the Rietveld log.
+	for rev in hg_log(ui, repo, limit=100, template="{node}\n").split():
+		desc = repo[rev].description().strip()
+		for clname in re.findall('(?m)^http://(?:[^\n]+)/([0-9]+)$', desc):
+			if IsLocalCL(ui, repo, clname) and IsRietveldSubmitted(ui, clname, repo[rev].hex()):
+				ui.warn("CL %s submitted as %s; closing\n" % (clname, repo[rev]))
+				cl, err = LoadCL(ui, repo, clname, web=False)
+				if err != "":
+					ui.warn("loading CL %s: %s\n" % (clname, err))
+					continue
+				if not cl.copied_from:
+					EditDesc(cl.name, closed=True, private=cl.private)
+				cl.Delete(ui, repo)
+
+	# Remove files that are not modified from the CLs in which they appear.
+	all = LoadAllCL(ui, repo, web=False)
+	changed = ChangedFiles(ui, repo, [])
+	for cl in all.values():
+		extra = Sub(cl.files, changed)
+		if extra:
+			ui.warn("Removing unmodified files from CL %s:\n" % (cl.name,))
+			for f in extra:
+				ui.warn("\t%s\n" % (f,))
+			cl.files = Sub(cl.files, extra)
+			cl.Flush(ui, repo)
+		if not cl.files:
+			if not cl.copied_from:
+				ui.warn("CL %s has no files; delete (abandon) with hg change -d %s\n" % (cl.name, cl.name))
+			else:
+				ui.warn("CL %s has no files; delete locally with hg change -D %s\n" % (cl.name, cl.name))
+	return
+
+#######################################################################
+# hg upload
+
+@hgcommand
+def upload(ui, repo, name, **opts):
+	"""upload diffs to the code review server
+
+	Uploads the current modifications for a given change to the server.
+	"""
+	if codereview_disabled:
+		return codereview_disabled
+
+	repo.ui.quiet = True
+	cl, err = LoadCL(ui, repo, name, web=True)
+	if err != "":
+		return err
+	if not cl.local:
+		return "cannot upload non-local change"
+	cl.Upload(ui, repo)
+	print "%s%s\n" % (server_url_base, cl.name)
+	return
+
+#######################################################################
+# Table of commands, supplied to Mercurial for installation.
+
+review_opts = [
+	('r', 'reviewer', '', 'add reviewer'),
+	('', 'cc', '', 'add cc'),
+	('', 'tbr', '', 'add future reviewer'),
+	('m', 'message', '', 'change description (for new change)'),
+]
+
+cmdtable = {
+	# The ^ means to show this command in the help text that
+	# is printed when running hg with no arguments.
+	"^change": (
+		change,
+		[
+			('d', 'delete', None, 'delete existing change list'),
+			('D', 'deletelocal', None, 'delete locally, but do not change CL on server'),
+			('i', 'stdin', None, 'read change list from standard input'),
+			('o', 'stdout', None, 'print change list to standard output'),
+			('p', 'pending', None, 'print pending summary to standard output'),
+		],
+		"[-d | -D] [-i] [-o] change# or FILE ..."
+	),
+	"^clpatch": (
+		clpatch,
+		[
+			('', 'ignore_hgpatch_failure', None, 'create CL metadata even if hgpatch fails'),
+			('', 'no_incoming', None, 'disable check for incoming changes'),
+		],
+		"change#"
+	),
+	# Would prefer to call this codereview-login, but then
+	# hg help codereview prints the help for this command
+	# instead of the help for the extension.
+	"code-login": (
+		code_login,
+		[],
+		"",
+	),
+	"^download": (
+		download,
+		[],
+		"change#"
+	),
+	"^file": (
+		file,
+		[
+			('d', 'delete', None, 'delete files from change list (but not repository)'),
+		],
+		"[-d] change# FILE ..."
+	),
+	"^gofmt": (
+		gofmt,
+		[
+			('l', 'list', None, 'list files that would change, but do not edit them'),
+		],
+		"FILE ..."
+	),
+	"^pending|p": (
+		pending,
+		[
+			('s', 'short', False, 'show short result form'),
+			('', 'quick', False, 'do not consult codereview server'),
+		],
+		"[FILE ...]"
+	),
+	"^ps": (
+		ps,
+		[],
+		"[FILE ...]"
+	),
+	"^pq": (
+		pq,
+		[],
+		"[FILE ...]"
+	),
+	"^mail": (
+		mail,
+		review_opts + [
+		] + hg_commands.walkopts,
+		"[-r reviewer] [--cc cc] [change# | file ...]"
+	),
+	"^release-apply": (
+		release_apply,
+		[
+			('', 'ignore_hgpatch_failure', None, 'create CL metadata even if hgpatch fails'),
+			('', 'no_incoming', None, 'disable check for incoming changes'),
+		],
+		"change#"
+	),
+	# TODO: release-start, release-tag, weekly-tag
+	"^submit": (
+		submit,
+		review_opts + [
+			('', 'no_incoming', None, 'disable initial incoming check (for testing)'),
+		] + hg_commands.walkopts + hg_commands.commitopts + hg_commands.commitopts2,
+		"[-r reviewer] [--cc cc] [change# | file ...]"
+	),
+	"^sync": (
+		sync,
+		[
+			('', 'local', None, 'do not pull changes from remote repository')
+		],
+		"[--local]",
+	),
+	"^undo": (
+		undo,
+		[
+			('', 'ignore_hgpatch_failure', None, 'create CL metadata even if hgpatch fails'),
+			('', 'no_incoming', None, 'disable check for incoming changes'),
+		],
+		"change#"
+	),
+	"^upload": (
+		upload,
+		[],
+		"change#"
+	),
+}
+
+#######################################################################
+# Mercurial extension initialization
+
+def norollback(*pats, **opts):
+	"""(disabled when using this extension)"""
+	raise hg_util.Abort("codereview extension enabled; use undo instead of rollback")
+
+codereview_init = False
+
+def reposetup(ui, repo):
+	global codereview_disabled
+	global defaultcc
+	
+	# reposetup gets called both for the local repository
+	# and also for any repository we are pulling or pushing to.
+	# Only initialize the first time.
+	global codereview_init
+	if codereview_init:
+		return
+	codereview_init = True
+
+	# Read repository-specific options from lib/codereview/codereview.cfg or codereview.cfg.
+	root = ''
+	try:
+		root = repo.root
+	except:
+		# Yes, repo might not have root; see issue 959.
+		codereview_disabled = 'codereview disabled: repository has no root'
+		return
+	
+	repo_config_path = ''
+	p1 = root + '/lib/codereview/codereview.cfg'
+	p2 = root + '/codereview.cfg'
+	if os.access(p1, os.F_OK):
+		repo_config_path = p1
+	else:
+		repo_config_path = p2
+	try:
+		f = open(repo_config_path)
+		for line in f:
+			if line.startswith('defaultcc:'):
+				defaultcc = SplitCommaSpace(line[len('defaultcc:'):])
+			if line.startswith('contributors:'):
+				global contributorsURL
+				contributorsURL = line[len('contributors:'):].strip()
+	except:
+		codereview_disabled = 'codereview disabled: cannot open ' + repo_config_path
+		return
+
+	remote = ui.config("paths", "default", "")
+	if remote.find("://") < 0:
+		raise hg_util.Abort("codereview: default path '%s' is not a URL" % (remote,))
+
+	InstallMatch(ui, repo)
+	RietveldSetup(ui, repo)
+
+	# Disable the Mercurial commands that might change the repository.
+	# Only commands in this extension are supposed to do that.
+	ui.setconfig("hooks", "precommit.codereview", precommithook)
+
+	# Rollback removes an existing commit.  Don't do that either.
+	global real_rollback
+	real_rollback = repo.rollback
+	repo.rollback = norollback
+	
+
+#######################################################################
+# Wrappers around upload.py for interacting with Rietveld
+
+from HTMLParser import HTMLParser
+
+# HTML form parser
+class FormParser(HTMLParser):
+	def __init__(self):
+		self.map = {}
+		self.curtag = None
+		self.curdata = None
+		HTMLParser.__init__(self)
+	def handle_starttag(self, tag, attrs):
+		if tag == "input":
+			key = None
+			value = ''
+			for a in attrs:
+				if a[0] == 'name':
+					key = a[1]
+				if a[0] == 'value':
+					value = a[1]
+			if key is not None:
+				self.map[key] = value
+		if tag == "textarea":
+			key = None
+			for a in attrs:
+				if a[0] == 'name':
+					key = a[1]
+			if key is not None:
+				self.curtag = key
+				self.curdata = ''
+	def handle_endtag(self, tag):
+		if tag == "textarea" and self.curtag is not None:
+			self.map[self.curtag] = self.curdata
+			self.curtag = None
+			self.curdata = None
+	def handle_charref(self, name):
+		self.handle_data(unichr(int(name)))
+	def handle_entityref(self, name):
+		import htmlentitydefs
+		if name in htmlentitydefs.entitydefs:
+			self.handle_data(htmlentitydefs.entitydefs[name])
+		else:
+			self.handle_data("&" + name + ";")
+	def handle_data(self, data):
+		if self.curdata is not None:
+			self.curdata += data
+
+def JSONGet(ui, path):
+	try:
+		data = MySend(path, force_auth=False)
+		typecheck(data, str)
+		d = fix_json(json.loads(data))
+	except:
+		ui.warn("JSONGet %s: %s\n" % (path, ExceptionDetail()))
+		return None
+	return d
+
+# Clean up json parser output to match our expectations:
+#   * all strings are UTF-8-encoded str, not unicode.
+#   * missing fields are missing, not None,
+#     so that d.get("foo", defaultvalue) works.
+def fix_json(x):
+	if type(x) in [str, int, float, bool, type(None)]:
+		pass
+	elif type(x) is unicode:
+		x = x.encode("utf-8")
+	elif type(x) is list:
+		for i in range(len(x)):
+			x[i] = fix_json(x[i])
+	elif type(x) is dict:
+		todel = []
+		for k in x:
+			if x[k] is None:
+				todel.append(k)
+			else:
+				x[k] = fix_json(x[k])
+		for k in todel:
+			del x[k]
+	else:
+		raise hg_util.Abort("unknown type " + str(type(x)) + " in fix_json")
+	if type(x) is str:
+		x = x.replace('\r\n', '\n')
+	return x
+
+def IsRietveldSubmitted(ui, clname, hex):
+	dict = JSONGet(ui, "/api/" + clname + "?messages=true")
+	if dict is None:
+		return False
+	for msg in dict.get("messages", []):
+		text = msg.get("text", "")
+		m = re.match('\*\*\* Submitted as [^*]*?([0-9a-f]+) \*\*\*', text)
+		if m is not None and len(m.group(1)) >= 8 and hex.startswith(m.group(1)):
+			return True
+	return False
+
+def IsRietveldMailed(cl):
+	for msg in cl.dict.get("messages", []):
+		if msg.get("text", "").find("I'd like you to review this change") >= 0:
+			return True
+	return False
+
+def DownloadCL(ui, repo, clname):
+	set_status("downloading CL " + clname)
+	cl, err = LoadCL(ui, repo, clname, web=True)
+	if err != "":
+		return None, None, None, "error loading CL %s: %s" % (clname, err)
+
+	# Find most recent diff
+	diffs = cl.dict.get("patchsets", [])
+	if not diffs:
+		return None, None, None, "CL has no patch sets"
+	patchid = diffs[-1]
+
+	patchset = JSONGet(ui, "/api/" + clname + "/" + str(patchid))
+	if patchset is None:
+		return None, None, None, "error loading CL patchset %s/%d" % (clname, patchid)
+	if patchset.get("patchset", 0) != patchid:
+		return None, None, None, "malformed patchset information"
+	
+	vers = ""
+	msg = patchset.get("message", "").split()
+	if len(msg) >= 3 and msg[0] == "diff" and msg[1] == "-r":
+		vers = msg[2]
+	diff = "/download/issue" + clname + "_" + str(patchid) + ".diff"
+
+	diffdata = MySend(diff, force_auth=False)
+	
+	# Print warning if email is not in CONTRIBUTORS file.
+	email = cl.dict.get("owner_email", "")
+	if not email:
+		return None, None, None, "cannot find owner for %s" % (clname)
+	him = FindContributor(ui, repo, email)
+	me = FindContributor(ui, repo, None)
+	if him == me:
+		cl.mailed = IsRietveldMailed(cl)
+	else:
+		cl.copied_from = email
+
+	return cl, vers, diffdata, ""
+
+def MySend(request_path, payload=None,
+		content_type="application/octet-stream",
+		timeout=None, force_auth=True,
+		**kwargs):
+	"""Run MySend1 maybe twice, because Rietveld is unreliable."""
+	try:
+		return MySend1(request_path, payload, content_type, timeout, force_auth, **kwargs)
+	except Exception, e:
+		if type(e) != urllib2.HTTPError or e.code != 500:	# only retry on HTTP 500 error
+			raise
+		print >>sys.stderr, "Loading "+request_path+": "+ExceptionDetail()+"; trying again in 2 seconds."
+		time.sleep(2)
+		return MySend1(request_path, payload, content_type, timeout, force_auth, **kwargs)
+
+# Like upload.py Send but only authenticates when the
+# redirect is to www.google.com/accounts.  This keeps
+# unnecessary redirects from happening during testing.
+def MySend1(request_path, payload=None,
+				content_type="application/octet-stream",
+				timeout=None, force_auth=True,
+				**kwargs):
+	"""Sends an RPC and returns the response.
+
+	Args:
+		request_path: The path to send the request to, eg /api/appversion/create.
+		payload: The body of the request, or None to send an empty request.
+		content_type: The Content-Type header to use.
+		timeout: timeout in seconds; default None i.e. no timeout.
+			(Note: for large requests on OS X, the timeout doesn't work right.)
+		kwargs: Any keyword arguments are converted into query string parameters.
+
+	Returns:
+		The response body, as a string.
+	"""
+	# TODO: Don't require authentication.  Let the server say
+	# whether it is necessary.
+	global rpc
+	if rpc == None:
+		rpc = GetRpcServer(upload_options)
+	self = rpc
+	if not self.authenticated and force_auth:
+		self._Authenticate()
+	if request_path is None:
+		return
+
+	old_timeout = socket.getdefaulttimeout()
+	socket.setdefaulttimeout(timeout)
+	try:
+		tries = 0
+		while True:
+			tries += 1
+			args = dict(kwargs)
+			url = "http://%s%s" % (self.host, request_path)
+			if args:
+				url += "?" + urllib.urlencode(args)
+			req = self._CreateRequest(url=url, data=payload)
+			req.add_header("Content-Type", content_type)
+			try:
+				f = self.opener.open(req)
+				response = f.read()
+				f.close()
+				# Translate \r\n into \n, because Rietveld doesn't.
+				response = response.replace('\r\n', '\n')
+				# who knows what urllib will give us
+				if type(response) == unicode:
+					response = response.encode("utf-8")
+				typecheck(response, str)
+				return response
+			except urllib2.HTTPError, e:
+				if tries > 3:
+					raise
+				elif e.code == 401:
+					self._Authenticate()
+				elif e.code == 302:
+					loc = e.info()["location"]
+					if not loc.startswith('https://www.google.com/a') or loc.find('/ServiceLogin') < 0:
+						return ''
+					self._Authenticate()
+				else:
+					raise
+	finally:
+		socket.setdefaulttimeout(old_timeout)
+
+def GetForm(url):
+	f = FormParser()
+	f.feed(ustr(MySend(url)))	# f.feed wants unicode
+	f.close()
+	# convert back to utf-8 to restore sanity
+	m = {}
+	for k,v in f.map.items():
+		m[k.encode("utf-8")] = v.replace("\r\n", "\n").encode("utf-8")
+	return m
+
+def EditDesc(issue, subject=None, desc=None, reviewers=None, cc=None, closed=False, private=False):
+	set_status("uploading change to description")
+	form_fields = GetForm("/" + issue + "/edit")
+	if subject is not None:
+		form_fields['subject'] = subject
+	if desc is not None:
+		form_fields['description'] = desc
+	if reviewers is not None:
+		form_fields['reviewers'] = reviewers
+	if cc is not None:
+		form_fields['cc'] = cc
+	if closed:
+		form_fields['closed'] = "checked"
+	if private:
+		form_fields['private'] = "checked"
+	ctype, body = EncodeMultipartFormData(form_fields.items(), [])
+	response = MySend("/" + issue + "/edit", body, content_type=ctype)
+	if response != "":
+		print >>sys.stderr, "Error editing description:\n" + "Sent form: \n", form_fields, "\n", response
+		sys.exit(2)
+
+def PostMessage(ui, issue, message, reviewers=None, cc=None, send_mail=True, subject=None):
+	set_status("uploading message")
+	form_fields = GetForm("/" + issue + "/publish")
+	if reviewers is not None:
+		form_fields['reviewers'] = reviewers
+	if cc is not None:
+		form_fields['cc'] = cc
+	if send_mail:
+		form_fields['send_mail'] = "checked"
+	else:
+		del form_fields['send_mail']
+	if subject is not None:
+		form_fields['subject'] = subject
+	form_fields['message'] = message
+	
+	form_fields['message_only'] = '1'	# Don't include draft comments
+	if reviewers is not None or cc is not None:
+		form_fields['message_only'] = ''	# Must set '' in order to override cc/reviewer
+	ctype = "applications/x-www-form-urlencoded"
+	body = urllib.urlencode(form_fields)
+	response = MySend("/" + issue + "/publish", body, content_type=ctype)
+	if response != "":
+		print response
+		sys.exit(2)
+
+class opt(object):
+	pass
+
+def RietveldSetup(ui, repo):
+	global force_google_account
+	global rpc
+	global server
+	global server_url_base
+	global upload_options
+	global verbosity
+
+	if not ui.verbose:
+		verbosity = 0
+
+	# Config options.
+	x = ui.config("codereview", "server")
+	if x is not None:
+		server = x
+
+	# TODO(rsc): Take from ui.username?
+	email = None
+	x = ui.config("codereview", "email")
+	if x is not None:
+		email = x
+
+	server_url_base = "http://" + server + "/"
+
+	testing = ui.config("codereview", "testing")
+	force_google_account = ui.configbool("codereview", "force_google_account", False)
+
+	upload_options = opt()
+	upload_options.email = email
+	upload_options.host = None
+	upload_options.verbose = 0
+	upload_options.description = None
+	upload_options.description_file = None
+	upload_options.reviewers = None
+	upload_options.cc = None
+	upload_options.message = None
+	upload_options.issue = None
+	upload_options.download_base = False
+	upload_options.revision = None
+	upload_options.send_mail = False
+	upload_options.vcs = None
+	upload_options.server = server
+	upload_options.save_cookies = True
+
+	if testing:
+		upload_options.save_cookies = False
+		upload_options.email = "test@example.com"
+
+	rpc = None
+	
+	global releaseBranch
+	tags = repo.branchmap().keys()
+	if 'release-branch.go10' in tags:
+		# NOTE(rsc): This tags.sort is going to get the wrong
+		# answer when comparing release-branch.go9 with
+		# release-branch.go10.  It will be a while before we care.
+		raise hg_util.Abort('tags.sort needs to be fixed for release-branch.go10')
+	tags.sort()
+	for t in tags:
+		if t.startswith('release-branch.go'):
+			releaseBranch = t			
+
+#######################################################################
+# http://codereview.appspot.com/static/upload.py, heavily edited.
+
+#!/usr/bin/env python
+#
+# Copyright 2007 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Tool for uploading diffs from a version control system to the codereview app.
+
+Usage summary: upload.py [options] [-- diff_options]
+
+Diff options are passed to the diff command of the underlying system.
+
+Supported version control systems:
+	Git
+	Mercurial
+	Subversion
+
+It is important for Git/Mercurial users to specify a tree/node/branch to diff
+against by using the '--rev' option.
+"""
+# This code is derived from appcfg.py in the App Engine SDK (open source),
+# and from ASPN recipe #146306.
+
+import cookielib
+import getpass
+import logging
+import mimetypes
+import optparse
+import os
+import re
+import socket
+import subprocess
+import sys
+import urllib
+import urllib2
+import urlparse
+
+# The md5 module was deprecated in Python 2.5.
+try:
+	from hashlib import md5
+except ImportError:
+	from md5 import md5
+
+try:
+	import readline
+except ImportError:
+	pass
+
+# The logging verbosity:
+#  0: Errors only.
+#  1: Status messages.
+#  2: Info logs.
+#  3: Debug logs.
+verbosity = 1
+
+# Max size of patch or base file.
+MAX_UPLOAD_SIZE = 900 * 1024
+
+# whitelist for non-binary filetypes which do not start with "text/"
+# .mm (Objective-C) shows up as application/x-freemind on my Linux box.
+TEXT_MIMETYPES = [
+	'application/javascript',
+	'application/x-javascript',
+	'application/x-freemind'
+]
+
+def GetEmail(prompt):
+	"""Prompts the user for their email address and returns it.
+
+	The last used email address is saved to a file and offered up as a suggestion
+	to the user. If the user presses enter without typing in anything the last
+	used email address is used. If the user enters a new address, it is saved
+	for next time we prompt.
+
+	"""
+	last_email_file_name = os.path.expanduser("~/.last_codereview_email_address")
+	last_email = ""
+	if os.path.exists(last_email_file_name):
+		try:
+			last_email_file = open(last_email_file_name, "r")
+			last_email = last_email_file.readline().strip("\n")
+			last_email_file.close()
+			prompt += " [%s]" % last_email
+		except IOError, e:
+			pass
+	email = raw_input(prompt + ": ").strip()
+	if email:
+		try:
+			last_email_file = open(last_email_file_name, "w")
+			last_email_file.write(email)
+			last_email_file.close()
+		except IOError, e:
+			pass
+	else:
+		email = last_email
+	return email
+
+
+def StatusUpdate(msg):
+	"""Print a status message to stdout.
+
+	If 'verbosity' is greater than 0, print the message.
+
+	Args:
+		msg: The string to print.
+	"""
+	if verbosity > 0:
+		print msg
+
+
+def ErrorExit(msg):
+	"""Print an error message to stderr and exit."""
+	print >>sys.stderr, msg
+	sys.exit(1)
+
+
+class ClientLoginError(urllib2.HTTPError):
+	"""Raised to indicate there was an error authenticating with ClientLogin."""
+
+	def __init__(self, url, code, msg, headers, args):
+		urllib2.HTTPError.__init__(self, url, code, msg, headers, None)
+		self.args = args
+		self.reason = args["Error"]
+
+
+class AbstractRpcServer(object):
+	"""Provides a common interface for a simple RPC server."""
+
+	def __init__(self, host, auth_function, host_override=None, extra_headers={}, save_cookies=False):
+		"""Creates a new HttpRpcServer.
+
+		Args:
+			host: The host to send requests to.
+			auth_function: A function that takes no arguments and returns an
+				(email, password) tuple when called. Will be called if authentication
+				is required.
+			host_override: The host header to send to the server (defaults to host).
+			extra_headers: A dict of extra headers to append to every request.
+			save_cookies: If True, save the authentication cookies to local disk.
+				If False, use an in-memory cookiejar instead.  Subclasses must
+				implement this functionality.  Defaults to False.
+		"""
+		self.host = host
+		self.host_override = host_override
+		self.auth_function = auth_function
+		self.authenticated = False
+		self.extra_headers = extra_headers
+		self.save_cookies = save_cookies
+		self.opener = self._GetOpener()
+		if self.host_override:
+			logging.info("Server: %s; Host: %s", self.host, self.host_override)
+		else:
+			logging.info("Server: %s", self.host)
+
+	def _GetOpener(self):
+		"""Returns an OpenerDirector for making HTTP requests.
+
+		Returns:
+			A urllib2.OpenerDirector object.
+		"""
+		raise NotImplementedError()
+
+	def _CreateRequest(self, url, data=None):
+		"""Creates a new urllib request."""
+		logging.debug("Creating request for: '%s' with payload:\n%s", url, data)
+		req = urllib2.Request(url, data=data)
+		if self.host_override:
+			req.add_header("Host", self.host_override)
+		for key, value in self.extra_headers.iteritems():
+			req.add_header(key, value)
+		return req
+
+	def _GetAuthToken(self, email, password):
+		"""Uses ClientLogin to authenticate the user, returning an auth token.
+
+		Args:
+			email:    The user's email address
+			password: The user's password
+
+		Raises:
+			ClientLoginError: If there was an error authenticating with ClientLogin.
+			HTTPError: If there was some other form of HTTP error.
+
+		Returns:
+			The authentication token returned by ClientLogin.
+		"""
+		account_type = "GOOGLE"
+		if self.host.endswith(".google.com") and not force_google_account:
+			# Needed for use inside Google.
+			account_type = "HOSTED"
+		req = self._CreateRequest(
+				url="https://www.google.com/accounts/ClientLogin",
+				data=urllib.urlencode({
+						"Email": email,
+						"Passwd": password,
+						"service": "ah",
+						"source": "rietveld-codereview-upload",
+						"accountType": account_type,
+				}),
+		)
+		try:
+			response = self.opener.open(req)
+			response_body = response.read()
+			response_dict = dict(x.split("=") for x in response_body.split("\n") if x)
+			return response_dict["Auth"]
+		except urllib2.HTTPError, e:
+			if e.code == 403:
+				body = e.read()
+				response_dict = dict(x.split("=", 1) for x in body.split("\n") if x)
+				raise ClientLoginError(req.get_full_url(), e.code, e.msg, e.headers, response_dict)
+			else:
+				raise
+
+	def _GetAuthCookie(self, auth_token):
+		"""Fetches authentication cookies for an authentication token.
+
+		Args:
+			auth_token: The authentication token returned by ClientLogin.
+
+		Raises:
+			HTTPError: If there was an error fetching the authentication cookies.
+		"""
+		# This is a dummy value to allow us to identify when we're successful.
+		continue_location = "http://localhost/"
+		args = {"continue": continue_location, "auth": auth_token}
+		req = self._CreateRequest("http://%s/_ah/login?%s" % (self.host, urllib.urlencode(args)))
+		try:
+			response = self.opener.open(req)
+		except urllib2.HTTPError, e:
+			response = e
+		if (response.code != 302 or
+				response.info()["location"] != continue_location):
+			raise urllib2.HTTPError(req.get_full_url(), response.code, response.msg, response.headers, response.fp)
+		self.authenticated = True
+
+	def _Authenticate(self):
+		"""Authenticates the user.
+
+		The authentication process works as follows:
+		1) We get a username and password from the user
+		2) We use ClientLogin to obtain an AUTH token for the user
+				(see http://code.google.com/apis/accounts/AuthForInstalledApps.html).
+		3) We pass the auth token to /_ah/login on the server to obtain an
+				authentication cookie. If login was successful, it tries to redirect
+				us to the URL we provided.
+
+		If we attempt to access the upload API without first obtaining an
+		authentication cookie, it returns a 401 response (or a 302) and
+		directs us to authenticate ourselves with ClientLogin.
+		"""
+		for i in range(3):
+			credentials = self.auth_function()
+			try:
+				auth_token = self._GetAuthToken(credentials[0], credentials[1])
+			except ClientLoginError, e:
+				if e.reason == "BadAuthentication":
+					print >>sys.stderr, "Invalid username or password."
+					continue
+				if e.reason == "CaptchaRequired":
+					print >>sys.stderr, (
+						"Please go to\n"
+						"https://www.google.com/accounts/DisplayUnlockCaptcha\n"
+						"and verify you are a human.  Then try again.")
+					break
+				if e.reason == "NotVerified":
+					print >>sys.stderr, "Account not verified."
+					break
+				if e.reason == "TermsNotAgreed":
+					print >>sys.stderr, "User has not agreed to TOS."
+					break
+				if e.reason == "AccountDeleted":
+					print >>sys.stderr, "The user account has been deleted."
+					break
+				if e.reason == "AccountDisabled":
+					print >>sys.stderr, "The user account has been disabled."
+					break
+				if e.reason == "ServiceDisabled":
+					print >>sys.stderr, "The user's access to the service has been disabled."
+					break
+				if e.reason == "ServiceUnavailable":
+					print >>sys.stderr, "The service is not available; try again later."
+					break
+				raise
+			self._GetAuthCookie(auth_token)
+			return
+
+	def Send(self, request_path, payload=None,
+					content_type="application/octet-stream",
+					timeout=None,
+					**kwargs):
+		"""Sends an RPC and returns the response.
+
+		Args:
+			request_path: The path to send the request to, eg /api/appversion/create.
+			payload: The body of the request, or None to send an empty request.
+			content_type: The Content-Type header to use.
+			timeout: timeout in seconds; default None i.e. no timeout.
+				(Note: for large requests on OS X, the timeout doesn't work right.)
+			kwargs: Any keyword arguments are converted into query string parameters.
+
+		Returns:
+			The response body, as a string.
+		"""
+		# TODO: Don't require authentication.  Let the server say
+		# whether it is necessary.
+		if not self.authenticated:
+			self._Authenticate()
+
+		old_timeout = socket.getdefaulttimeout()
+		socket.setdefaulttimeout(timeout)
+		try:
+			tries = 0
+			while True:
+				tries += 1
+				args = dict(kwargs)
+				url = "http://%s%s" % (self.host, request_path)
+				if args:
+					url += "?" + urllib.urlencode(args)
+				req = self._CreateRequest(url=url, data=payload)
+				req.add_header("Content-Type", content_type)
+				try:
+					f = self.opener.open(req)
+					response = f.read()
+					f.close()
+					return response
+				except urllib2.HTTPError, e:
+					if tries > 3:
+						raise
+					elif e.code == 401 or e.code == 302:
+						self._Authenticate()
+					else:
+						raise
+		finally:
+			socket.setdefaulttimeout(old_timeout)
+
+
+class HttpRpcServer(AbstractRpcServer):
+	"""Provides a simplified RPC-style interface for HTTP requests."""
+
+	def _Authenticate(self):
+		"""Save the cookie jar after authentication."""
+		super(HttpRpcServer, self)._Authenticate()
+		if self.save_cookies:
+			StatusUpdate("Saving authentication cookies to %s" % self.cookie_file)
+			self.cookie_jar.save()
+
+	def _GetOpener(self):
+		"""Returns an OpenerDirector that supports cookies and ignores redirects.
+
+		Returns:
+			A urllib2.OpenerDirector object.
+		"""
+		opener = urllib2.OpenerDirector()
+		opener.add_handler(urllib2.ProxyHandler())
+		opener.add_handler(urllib2.UnknownHandler())
+		opener.add_handler(urllib2.HTTPHandler())
+		opener.add_handler(urllib2.HTTPDefaultErrorHandler())
+		opener.add_handler(urllib2.HTTPSHandler())
+		opener.add_handler(urllib2.HTTPErrorProcessor())
+		if self.save_cookies:
+			self.cookie_file = os.path.expanduser("~/.codereview_upload_cookies_" + server)
+			self.cookie_jar = cookielib.MozillaCookieJar(self.cookie_file)
+			if os.path.exists(self.cookie_file):
+				try:
+					self.cookie_jar.load()
+					self.authenticated = True
+					StatusUpdate("Loaded authentication cookies from %s" % self.cookie_file)
+				except (cookielib.LoadError, IOError):
+					# Failed to load cookies - just ignore them.
+					pass
+			else:
+				# Create an empty cookie file with mode 600
+				fd = os.open(self.cookie_file, os.O_CREAT, 0600)
+				os.close(fd)
+			# Always chmod the cookie file
+			os.chmod(self.cookie_file, 0600)
+		else:
+			# Don't save cookies across runs of update.py.
+			self.cookie_jar = cookielib.CookieJar()
+		opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar))
+		return opener
+
+
+def GetRpcServer(options):
+	"""Returns an instance of an AbstractRpcServer.
+
+	Returns:
+		A new AbstractRpcServer, on which RPC calls can be made.
+	"""
+
+	rpc_server_class = HttpRpcServer
+
+	def GetUserCredentials():
+		"""Prompts the user for a username and password."""
+		# Disable status prints so they don't obscure the password prompt.
+		global global_status
+		st = global_status
+		global_status = None
+
+		email = options.email
+		if email is None:
+			email = GetEmail("Email (login for uploading to %s)" % options.server)
+		password = getpass.getpass("Password for %s: " % email)
+
+		# Put status back.
+		global_status = st
+		return (email, password)
+
+	# If this is the dev_appserver, use fake authentication.
+	host = (options.host or options.server).lower()
+	if host == "localhost" or host.startswith("localhost:"):
+		email = options.email
+		if email is None:
+			email = "test@example.com"
+			logging.info("Using debug user %s.  Override with --email" % email)
+		server = rpc_server_class(
+				options.server,
+				lambda: (email, "password"),
+				host_override=options.host,
+				extra_headers={"Cookie": 'dev_appserver_login="%s:False"' % email},
+				save_cookies=options.save_cookies)
+		# Don't try to talk to ClientLogin.
+		server.authenticated = True
+		return server
+
+	return rpc_server_class(options.server, GetUserCredentials,
+		host_override=options.host, save_cookies=options.save_cookies)
+
+
+def EncodeMultipartFormData(fields, files):
+	"""Encode form fields for multipart/form-data.
+
+	Args:
+		fields: A sequence of (name, value) elements for regular form fields.
+		files: A sequence of (name, filename, value) elements for data to be
+					uploaded as files.
+	Returns:
+		(content_type, body) ready for httplib.HTTP instance.
+
+	Source:
+		http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306
+	"""
+	BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-'
+	CRLF = '\r\n'
+	lines = []
+	for (key, value) in fields:
+		typecheck(key, str)
+		typecheck(value, str)
+		lines.append('--' + BOUNDARY)
+		lines.append('Content-Disposition: form-data; name="%s"' % key)
+		lines.append('')
+		lines.append(value)
+	for (key, filename, value) in files:
+		typecheck(key, str)
+		typecheck(filename, str)
+		typecheck(value, str)
+		lines.append('--' + BOUNDARY)
+		lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
+		lines.append('Content-Type: %s' % GetContentType(filename))
+		lines.append('')
+		lines.append(value)
+	lines.append('--' + BOUNDARY + '--')
+	lines.append('')
+	body = CRLF.join(lines)
+	content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
+	return content_type, body
+
+
+def GetContentType(filename):
+	"""Helper to guess the content-type from the filename."""
+	return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
+
+
+# Use a shell for subcommands on Windows to get a PATH search.
+use_shell = sys.platform.startswith("win")
+
+def RunShellWithReturnCode(command, print_output=False,
+		universal_newlines=True, env=os.environ):
+	"""Executes a command and returns the output from stdout and the return code.
+
+	Args:
+		command: Command to execute.
+		print_output: If True, the output is printed to stdout.
+			If False, both stdout and stderr are ignored.
+		universal_newlines: Use universal_newlines flag (default: True).
+
+	Returns:
+		Tuple (output, return code)
+	"""
+	logging.info("Running %s", command)
+	p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+		shell=use_shell, universal_newlines=universal_newlines, env=env)
+	if print_output:
+		output_array = []
+		while True:
+			line = p.stdout.readline()
+			if not line:
+				break
+			print line.strip("\n")
+			output_array.append(line)
+		output = "".join(output_array)
+	else:
+		output = p.stdout.read()
+	p.wait()
+	errout = p.stderr.read()
+	if print_output and errout:
+		print >>sys.stderr, errout
+	p.stdout.close()
+	p.stderr.close()
+	return output, p.returncode
+
+
+def RunShell(command, silent_ok=False, universal_newlines=True,
+		print_output=False, env=os.environ):
+	data, retcode = RunShellWithReturnCode(command, print_output, universal_newlines, env)
+	if retcode:
+		ErrorExit("Got error status from %s:\n%s" % (command, data))
+	if not silent_ok and not data:
+		ErrorExit("No output from %s" % command)
+	return data
+
+
+class VersionControlSystem(object):
+	"""Abstract base class providing an interface to the VCS."""
+
+	def __init__(self, options):
+		"""Constructor.
+
+		Args:
+			options: Command line options.
+		"""
+		self.options = options
+
+	def GenerateDiff(self, args):
+		"""Return the current diff as a string.
+
+		Args:
+			args: Extra arguments to pass to the diff command.
+		"""
+		raise NotImplementedError(
+				"abstract method -- subclass %s must override" % self.__class__)
+
+	def GetUnknownFiles(self):
+		"""Return a list of files unknown to the VCS."""
+		raise NotImplementedError(
+				"abstract method -- subclass %s must override" % self.__class__)
+
+	def CheckForUnknownFiles(self):
+		"""Show an "are you sure?" prompt if there are unknown files."""
+		unknown_files = self.GetUnknownFiles()
+		if unknown_files:
+			print "The following files are not added to version control:"
+			for line in unknown_files:
+				print line
+			prompt = "Are you sure to continue?(y/N) "
+			answer = raw_input(prompt).strip()
+			if answer != "y":
+				ErrorExit("User aborted")
+
+	def GetBaseFile(self, filename):
+		"""Get the content of the upstream version of a file.
+
+		Returns:
+			A tuple (base_content, new_content, is_binary, status)
+				base_content: The contents of the base file.
+				new_content: For text files, this is empty.  For binary files, this is
+					the contents of the new file, since the diff output won't contain
+					information to reconstruct the current file.
+				is_binary: True iff the file is binary.
+				status: The status of the file.
+		"""
+
+		raise NotImplementedError(
+				"abstract method -- subclass %s must override" % self.__class__)
+
+
+	def GetBaseFiles(self, diff):
+		"""Helper that calls GetBase file for each file in the patch.
+
+		Returns:
+			A dictionary that maps from filename to GetBaseFile's tuple.  Filenames
+			are retrieved based on lines that start with "Index:" or
+			"Property changes on:".
+		"""
+		files = {}
+		for line in diff.splitlines(True):
+			if line.startswith('Index:') or line.startswith('Property changes on:'):
+				unused, filename = line.split(':', 1)
+				# On Windows if a file has property changes its filename uses '\'
+				# instead of '/'.
+				filename = to_slash(filename.strip())
+				files[filename] = self.GetBaseFile(filename)
+		return files
+
+
+	def UploadBaseFiles(self, issue, rpc_server, patch_list, patchset, options,
+											files):
+		"""Uploads the base files (and if necessary, the current ones as well)."""
+
+		def UploadFile(filename, file_id, content, is_binary, status, is_base):
+			"""Uploads a file to the server."""
+			set_status("uploading " + filename)
+			file_too_large = False
+			if is_base:
+				type = "base"
+			else:
+				type = "current"
+			if len(content) > MAX_UPLOAD_SIZE:
+				print ("Not uploading the %s file for %s because it's too large." %
+							(type, filename))
+				file_too_large = True
+				content = ""
+			checksum = md5(content).hexdigest()
+			if options.verbose > 0 and not file_too_large:
+				print "Uploading %s file for %s" % (type, filename)
+			url = "/%d/upload_content/%d/%d" % (int(issue), int(patchset), file_id)
+			form_fields = [
+				("filename", filename),
+				("status", status),
+				("checksum", checksum),
+				("is_binary", str(is_binary)),
+				("is_current", str(not is_base)),
+			]
+			if file_too_large:
+				form_fields.append(("file_too_large", "1"))
+			if options.email:
+				form_fields.append(("user", options.email))
+			ctype, body = EncodeMultipartFormData(form_fields, [("data", filename, content)])
+			response_body = rpc_server.Send(url, body, content_type=ctype)
+			if not response_body.startswith("OK"):
+				StatusUpdate("  --> %s" % response_body)
+				sys.exit(1)
+
+		# Don't want to spawn too many threads, nor do we want to
+		# hit Rietveld too hard, or it will start serving 500 errors.
+		# When 8 works, it's no better than 4, and sometimes 8 is
+		# too many for Rietveld to handle.
+		MAX_PARALLEL_UPLOADS = 4
+
+		sema = threading.BoundedSemaphore(MAX_PARALLEL_UPLOADS)
+		upload_threads = []
+		finished_upload_threads = []
+		
+		class UploadFileThread(threading.Thread):
+			def __init__(self, args):
+				threading.Thread.__init__(self)
+				self.args = args
+			def run(self):
+				UploadFile(*self.args)
+				finished_upload_threads.append(self)
+				sema.release()
+
+		def StartUploadFile(*args):
+			sema.acquire()
+			while len(finished_upload_threads) > 0:
+				t = finished_upload_threads.pop()
+				upload_threads.remove(t)
+				t.join()
+			t = UploadFileThread(args)
+			upload_threads.append(t)
+			t.start()
+
+		def WaitForUploads():			
+			for t in upload_threads:
+				t.join()
+
+		patches = dict()
+		[patches.setdefault(v, k) for k, v in patch_list]
+		for filename in patches.keys():
+			base_content, new_content, is_binary, status = files[filename]
+			file_id_str = patches.get(filename)
+			if file_id_str.find("nobase") != -1:
+				base_content = None
+				file_id_str = file_id_str[file_id_str.rfind("_") + 1:]
+			file_id = int(file_id_str)
+			if base_content != None:
+				StartUploadFile(filename, file_id, base_content, is_binary, status, True)
+			if new_content != None:
+				StartUploadFile(filename, file_id, new_content, is_binary, status, False)
+		WaitForUploads()
+
+	def IsImage(self, filename):
+		"""Returns true if the filename has an image extension."""
+		mimetype =  mimetypes.guess_type(filename)[0]
+		if not mimetype:
+			return False
+		return mimetype.startswith("image/")
+
+	def IsBinary(self, filename):
+		"""Returns true if the guessed mimetyped isnt't in text group."""
+		mimetype = mimetypes.guess_type(filename)[0]
+		if not mimetype:
+			return False  # e.g. README, "real" binaries usually have an extension
+		# special case for text files which don't start with text/
+		if mimetype in TEXT_MIMETYPES:
+			return False
+		return not mimetype.startswith("text/")
+
+
+class FakeMercurialUI(object):
+	def __init__(self):
+		self.quiet = True
+		self.output = ''
+	
+	def write(self, *args, **opts):
+		self.output += ' '.join(args)
+	def copy(self):
+		return self
+	def status(self, *args, **opts):
+		pass
+
+	def formatter(self, topic, opts):
+		from mercurial.formatter import plainformatter
+		return plainformatter(self, topic, opts)
+	
+	def readconfig(self, *args, **opts):
+		pass
+	def expandpath(self, *args, **opts):
+		return global_ui.expandpath(*args, **opts)
+	def configitems(self, *args, **opts):
+		return global_ui.configitems(*args, **opts)
+	def config(self, *args, **opts):
+		return global_ui.config(*args, **opts)
+
+use_hg_shell = False	# set to True to shell out to hg always; slower
+
+class MercurialVCS(VersionControlSystem):
+	"""Implementation of the VersionControlSystem interface for Mercurial."""
+
+	def __init__(self, options, ui, repo):
+		super(MercurialVCS, self).__init__(options)
+		self.ui = ui
+		self.repo = repo
+		self.status = None
+		# Absolute path to repository (we can be in a subdir)
+		self.repo_dir = os.path.normpath(repo.root)
+		# Compute the subdir
+		cwd = os.path.normpath(os.getcwd())
+		assert cwd.startswith(self.repo_dir)
+		self.subdir = cwd[len(self.repo_dir):].lstrip(r"\/")
+		if self.options.revision:
+			self.base_rev = self.options.revision
+		else:
+			mqparent, err = RunShellWithReturnCode(['hg', 'log', '--rev', 'qparent', '--template={node}'])
+			if not err and mqparent != "":
+				self.base_rev = mqparent
+			else:
+				out = RunShell(["hg", "parents", "-q"], silent_ok=True).strip()
+				if not out:
+					# No revisions; use 0 to mean a repository with nothing.
+					out = "0:0"
+				self.base_rev = out.split(':')[1].strip()
+	def _GetRelPath(self, filename):
+		"""Get relative path of a file according to the current directory,
+		given its logical path in the repo."""
+		assert filename.startswith(self.subdir), (filename, self.subdir)
+		return filename[len(self.subdir):].lstrip(r"\/")
+
+	def GenerateDiff(self, extra_args):
+		# If no file specified, restrict to the current subdir
+		extra_args = extra_args or ["."]
+		cmd = ["hg", "diff", "--git", "-r", self.base_rev] + extra_args
+		data = RunShell(cmd, silent_ok=True)
+		svndiff = []
+		filecount = 0
+		for line in data.splitlines():
+			m = re.match("diff --git a/(\S+) b/(\S+)", line)
+			if m:
+				# Modify line to make it look like as it comes from svn diff.
+				# With this modification no changes on the server side are required
+				# to make upload.py work with Mercurial repos.
+				# NOTE: for proper handling of moved/copied files, we have to use
+				# the second filename.
+				filename = m.group(2)
+				svndiff.append("Index: %s" % filename)
+				svndiff.append("=" * 67)
+				filecount += 1
+				logging.info(line)
+			else:
+				svndiff.append(line)
+		if not filecount:
+			ErrorExit("No valid patches found in output from hg diff")
+		return "\n".join(svndiff) + "\n"
+
+	def GetUnknownFiles(self):
+		"""Return a list of files unknown to the VCS."""
+		args = []
+		status = RunShell(["hg", "status", "--rev", self.base_rev, "-u", "."],
+				silent_ok=True)
+		unknown_files = []
+		for line in status.splitlines():
+			st, fn = line.split(" ", 1)
+			if st == "?":
+				unknown_files.append(fn)
+		return unknown_files
+
+	def get_hg_status(self, rev, path):
+		# We'd like to use 'hg status -C path', but that is buggy
+		# (see http://mercurial.selenic.com/bts/issue3023).
+		# Instead, run 'hg status -C' without a path
+		# and skim the output for the path we want.
+		if self.status is None:
+			if use_hg_shell:
+				out = RunShell(["hg", "status", "-C", "--rev", rev])
+			else:
+				fui = FakeMercurialUI()
+				ret = hg_commands.status(fui, self.repo, *[], **{'rev': [rev], 'copies': True})
+				if ret:
+					raise hg_util.Abort(ret)
+				out = fui.output
+			self.status = out.splitlines()
+		for i in range(len(self.status)):
+			# line is
+			#	A path
+			#	M path
+			# etc
+			line = to_slash(self.status[i])
+			if line[2:] == path:
+				if i+1 < len(self.status) and self.status[i+1][:2] == '  ':
+					return self.status[i:i+2]
+				return self.status[i:i+1]
+		raise hg_util.Abort("no status for " + path)
+	
+	def GetBaseFile(self, filename):
+		set_status("inspecting " + filename)
+		# "hg status" and "hg cat" both take a path relative to the current subdir
+		# rather than to the repo root, but "hg diff" has given us the full path
+		# to the repo root.
+		base_content = ""
+		new_content = None
+		is_binary = False
+		oldrelpath = relpath = self._GetRelPath(filename)
+		out = self.get_hg_status(self.base_rev, relpath)
+		status, what = out[0].split(' ', 1)
+		if len(out) > 1 and status == "A" and what == relpath:
+			oldrelpath = out[1].strip()
+			status = "M"
+		if ":" in self.base_rev:
+			base_rev = self.base_rev.split(":", 1)[0]
+		else:
+			base_rev = self.base_rev
+		if status != "A":
+			if use_hg_shell:
+				base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath], silent_ok=True)
+			else:
+				base_content = str(self.repo[base_rev][oldrelpath].data())
+			is_binary = "\0" in base_content  # Mercurial's heuristic
+		if status != "R":
+			new_content = open(relpath, "rb").read()
+			is_binary = is_binary or "\0" in new_content
+		if is_binary and base_content and use_hg_shell:
+			# Fetch again without converting newlines
+			base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath],
+				silent_ok=True, universal_newlines=False)
+		if not is_binary or not self.IsImage(relpath):
+			new_content = None
+		return base_content, new_content, is_binary, status
+
+
+# NOTE: The SplitPatch function is duplicated in engine.py, keep them in sync.
+def SplitPatch(data):
+	"""Splits a patch into separate pieces for each file.
+
+	Args:
+		data: A string containing the output of svn diff.
+
+	Returns:
+		A list of 2-tuple (filename, text) where text is the svn diff output
+			pertaining to filename.
+	"""
+	patches = []
+	filename = None
+	diff = []
+	for line in data.splitlines(True):
+		new_filename = None
+		if line.startswith('Index:'):
+			unused, new_filename = line.split(':', 1)
+			new_filename = new_filename.strip()
+		elif line.startswith('Property changes on:'):
+			unused, temp_filename = line.split(':', 1)
+			# When a file is modified, paths use '/' between directories, however
+			# when a property is modified '\' is used on Windows.  Make them the same
+			# otherwise the file shows up twice.
+			temp_filename = to_slash(temp_filename.strip())
+			if temp_filename != filename:
+				# File has property changes but no modifications, create a new diff.
+				new_filename = temp_filename
+		if new_filename:
+			if filename and diff:
+				patches.append((filename, ''.join(diff)))
+			filename = new_filename
+			diff = [line]
+			continue
+		if diff is not None:
+			diff.append(line)
+	if filename and diff:
+		patches.append((filename, ''.join(diff)))
+	return patches
+
+
+def UploadSeparatePatches(issue, rpc_server, patchset, data, options):
+	"""Uploads a separate patch for each file in the diff output.
+
+	Returns a list of [patch_key, filename] for each file.
+	"""
+	patches = SplitPatch(data)
+	rv = []
+	for patch in patches:
+		set_status("uploading patch for " + patch[0])
+		if len(patch[1]) > MAX_UPLOAD_SIZE:
+			print ("Not uploading the patch for " + patch[0] +
+				" because the file is too large.")
+			continue
+		form_fields = [("filename", patch[0])]
+		if not options.download_base:
+			form_fields.append(("content_upload", "1"))
+		files = [("data", "data.diff", patch[1])]
+		ctype, body = EncodeMultipartFormData(form_fields, files)
+		url = "/%d/upload_patch/%d" % (int(issue), int(patchset))
+		print "Uploading patch for " + patch[0]
+		response_body = rpc_server.Send(url, body, content_type=ctype)
+		lines = response_body.splitlines()
+		if not lines or lines[0] != "OK":
+			StatusUpdate("  --> %s" % response_body)
+			sys.exit(1)
+		rv.append([lines[1], patch[0]])
+	return rv
diff --git a/third_party/re2/lib/git/commit-msg.hook b/third_party/re2/lib/git/commit-msg.hook
deleted file mode 100755
index 985016b..0000000
--- a/third_party/re2/lib/git/commit-msg.hook
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/bin/sh
-# From Gerrit Code Review 2.2.1
-#
-# Part of Gerrit Code Review (http://code.google.com/p/gerrit/)
-#
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-CHANGE_ID_AFTER="Bug|Issue"
-MSG="$1"
-
-# Check for, and add if missing, a unique Change-Id
-#
-add_ChangeId() {
-	clean_message=`sed -e '
-		/^diff --git a\/.*/{
-			s///
-			q
-		}
-		/^Signed-off-by:/d
-		/^#/d
-	' "$MSG" | git stripspace`
-	if test -z "$clean_message"
-	then
-		return
-	fi
-
-	if grep -i '^Change-Id:' "$MSG" >/dev/null
-	then
-		return
-	fi
-
-	id=`_gen_ChangeId`
-	perl -e '
-		$MSG = shift;
-		$id = shift;
-		$CHANGE_ID_AFTER = shift;
-
-		undef $/;
-		open(I, $MSG); $_ = <I>; close I;
-		s|^diff --git a/.*||ms;
-		s|^#.*$||mg;
-		exit unless $_;
-
-		@message = split /\n/;
-		$haveFooter = 0;
-		$startFooter = @message;
-		for($line = @message - 1; $line >= 0; $line--) {
-			$_ = $message[$line];
-
-			if (/^[a-zA-Z0-9-]+:/ && !m,^[a-z0-9-]+://,) {
-				$haveFooter++;
-				next;
-			}
-			next if /^[ []/;
-			$startFooter = $line if ($haveFooter && /^\r?$/);
-			last;
-		}
-
-		@footer = @message[$startFooter+1..@message];
-		@message = @message[0..$startFooter];
-		push(@footer, "") unless @footer;
-
-		for ($line = 0; $line < @footer; $line++) {
-			$_ = $footer[$line];
-			next if /^($CHANGE_ID_AFTER):/i;
-			last;
-		}
-		splice(@footer, $line, 0, "Change-Id: I$id");
-
-		$_ = join("\n", @message, @footer);
-		open(O, ">$MSG"); print O; close O;
-	' "$MSG" "$id" "$CHANGE_ID_AFTER"
-}
-_gen_ChangeIdInput() {
-	echo "tree `git write-tree`"
-	if parent=`git rev-parse HEAD^0 2>/dev/null`
-	then
-		echo "parent $parent"
-	fi
-	echo "author `git var GIT_AUTHOR_IDENT`"
-	echo "committer `git var GIT_COMMITTER_IDENT`"
-	echo
-	printf '%s' "$clean_message"
-}
-_gen_ChangeId() {
-	_gen_ChangeIdInput |
-	git hash-object -t commit --stdin
-}
-
-
-add_ChangeId
diff --git a/third_party/re2/libre2.symbols b/third_party/re2/libre2.symbols
index 90a10205..1a9cae3b 100644
--- a/third_party/re2/libre2.symbols
+++ b/third_party/re2/libre2.symbols
@@ -10,9 +10,6 @@
 		_ZlsRSoRKN3re211StringPieceE;
 		# re2::FilteredRE2*
 		_ZN3re211FilteredRE2*;
-		_ZNK3re211FilteredRE2*;
-		# flags
-		_ZN3re2*FLAGS_*;
 	local:
 		*;
 };
diff --git a/third_party/re2/libre2.symbols.darwin b/third_party/re2/libre2.symbols.darwin
index 4207f87..93eab3e9 100644
--- a/third_party/re2/libre2.symbols.darwin
+++ b/third_party/re2/libre2.symbols.darwin
@@ -6,14 +6,6 @@
 __ZN3re211StringPiece*
 __ZNK3re211StringPiece*
 # operator<<(std::ostream&, re2::StringPiece const&)
-# Seen with libstdc++ on 10.8 and below:
-# __ZlsRSoRKN3re211StringPieceE
-# Seen with libc++ on 10.9 and above:
-# __ZlsRNSt3__113basic_ostreamIcNS_11char_traitsIcEEEERKN3re211StringPieceE
-# Note that "ls" means operator<<, so this is not overly broad.
-__Zls*RKN3re211StringPieceE
+__ZlsRSoRKN3re211StringPieceE
 # re2::FilteredRE2*
 __ZN3re211FilteredRE2*
-__ZNK3re211FilteredRE2*
-# flags
-__ZN3re2*FLAGS_*
diff --git a/third_party/re2/patches/re2-android.patch b/third_party/re2/patches/re2-android.patch
new file mode 100644
index 0000000..67e9816
--- /dev/null
+++ b/third_party/re2/patches/re2-android.patch
@@ -0,0 +1,30 @@
+diff --git a/util/util.h b/util/util.h
+index 17ef824..8f54040 100644
+--- a/util/util.h
++++ b/util/util.h
+@@ -29,6 +29,7 @@
+ #include <utility>
+ #include <set>
+ 
++#include "build/build_config.h"
+ #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
+ 
+ // Use std names.
+@@ -45,7 +46,7 @@ using std::sort;
+ using std::swap;
+ using std::make_pair;
+ 
+-#if defined(__GNUC__) && !defined(USE_CXX0X)
++#if defined(__GNUC__) && !defined(USE_CXX0X) && !defined(OS_ANDROID)
+ 
+ #include <tr1/unordered_set>
+ using std::tr1::unordered_set;
+@@ -53,7 +54,7 @@ using std::tr1::unordered_set;
+ #else
+ 
+ #include <unordered_set>
+-#ifdef WIN32
++#if defined(WIN32) || defined(OS_ANDROID)
+ using std::tr1::unordered_set;
+ #else
+ using std::unordered_set;
diff --git a/third_party/re2/patches/re2-libcxx.patch b/third_party/re2/patches/re2-libcxx.patch
new file mode 100644
index 0000000..54f3b6b
--- /dev/null
+++ b/third_party/re2/patches/re2-libcxx.patch
@@ -0,0 +1,23 @@
+diff --git a/third_party/re2/util/util.h b/third_party/re2/util/util.h
+index 8f54040..de1ef5b 100644
+--- a/third_party/re2/util/util.h
++++ b/third_party/re2/util/util.h
+@@ -46,7 +46,8 @@ using std::sort;
+ using std::swap;
+ using std::make_pair;
+ 
+-#if defined(__GNUC__) && !defined(USE_CXX0X) && !defined(OS_ANDROID)
++#if defined(__GNUC__) && !defined(USE_CXX0X) && !defined(OS_ANDROID) && \
++    !defined(_LIBCPP_ABI_VERSION)
+ 
+ #include <tr1/unordered_set>
+ using std::tr1::unordered_set;
+@@ -54,1 +55,1 @@ using std::tr1::unordered_set;
+ #else
+
+ #include <unordered_set>
+-#if defined(WIN32) || defined(OS_ANDROID)
++#if defined(WIN32) || (defined(OS_ANDROID) && !defined(_LIBCPP_ABI_VERSION))
+ using std::tr1::unordered_set;
+ #else
+ using std::unordered_set;
\ No newline at end of file
diff --git a/third_party/re2/patches/re2-msan.patch b/third_party/re2/patches/re2-msan.patch
new file mode 100644
index 0000000..8577669
--- /dev/null
+++ b/third_party/re2/patches/re2-msan.patch
@@ -0,0 +1,63 @@
+diff --git a/third_party/re2/util/sparse_array.h b/third_party/re2/util/sparse_array.h
+index 3e33f89..4ee5c94 100644
+--- a/third_party/re2/util/sparse_array.h
++++ b/third_party/re2/util/sparse_array.h
+@@ -231,7 +231,8 @@ class SparseArray {
+ 
+ template<typename Value>
+ SparseArray<Value>::SparseArray()
+-    : size_(0), max_size_(0), sparse_to_dense_(NULL), dense_(), valgrind_(RunningOnValgrind()) {}
++    : size_(0), max_size_(0), sparse_to_dense_(NULL), dense_(),
++      valgrind_(RunningOnValgrindOrMemorySanitizer()) {}
+ 
+ // IndexValue pairs: exposed in SparseArray::iterator.
+ template<typename Value>
+@@ -418,7 +419,7 @@ void SparseArray<Value>::create_index(int i) {
+ template<typename Value> SparseArray<Value>::SparseArray(int max_size) {
+   max_size_ = max_size;
+   sparse_to_dense_ = new int[max_size];
+-  valgrind_ = RunningOnValgrind();
++  valgrind_ = RunningOnValgrindOrMemorySanitizer();
+   dense_.resize(max_size);
+   // Don't need to zero the new memory, but appease Valgrind.
+   if (valgrind_) {
+diff --git a/third_party/re2/util/sparse_set.h b/third_party/re2/util/sparse_set.h
+index 165dd09..4a324d7 100644
+--- a/third_party/re2/util/sparse_set.h
++++ b/third_party/re2/util/sparse_set.h
+@@ -54,13 +54,14 @@ namespace re2 {
+ class SparseSet {
+  public:
+   SparseSet()
+-    : size_(0), max_size_(0), sparse_to_dense_(NULL), dense_(NULL), valgrind_(RunningOnValgrind()) {}
++    : size_(0), max_size_(0), sparse_to_dense_(NULL), dense_(NULL),
++      valgrind_(RunningOnValgrindOrMemorySanitizer()) {}
+ 
+   SparseSet(int max_size) {
+     max_size_ = max_size;
+     sparse_to_dense_ = new int[max_size];
+     dense_ = new int[max_size];
+-    valgrind_ = RunningOnValgrind();
++    valgrind_ = RunningOnValgrindOrMemorySanitizer();
+     // Don't need to zero the memory, but do so anyway
+     // to appease Valgrind.
+     if (valgrind_) {
+diff --git a/third_party/re2/util/util.h b/third_party/re2/util/util.h
+index de1ef5b..49159c2 100644
+--- a/third_party/re2/util/util.h
++++ b/third_party/re2/util/util.h
+@@ -129,6 +129,14 @@ static inline uint64 Hash64StringWithSeed(const char* s, int len, uint32 seed) {
+   return ((uint64)x << 32) | y;
+ }
+ 
++inline bool RunningOnValgrindOrMemorySanitizer() {
++#if defined(MEMORY_SANITIZER)
++  return true;
++#else
++  return RunningOnValgrind();
++#endif
++}
++
+ }  // namespace re2
+ 
+ #include "util/arena.h"
diff --git a/third_party/re2/patches/re2-msvc9-chrome.patch b/third_party/re2/patches/re2-msvc9-chrome.patch
new file mode 100644
index 0000000..49a2b75
--- /dev/null
+++ b/third_party/re2/patches/re2-msvc9-chrome.patch
@@ -0,0 +1,344 @@
+diff --git a/AUTHORS b/AUTHORS
+index 3c0f928..e17d9bf 100644
+--- a/AUTHORS
++++ b/AUTHORS
+@@ -8,5 +8,6 @@
+ 
+ # Please keep the list sorted.
+ 
++Brian Gunlogson <unixman83@gmail.com>
+ Google Inc.
+ Stefano Rivera <stefano.rivera@gmail.com>
+diff --git a/CONTRIBUTORS b/CONTRIBUTORS
+index 7b44e04..7f6a93d 100644
+--- a/CONTRIBUTORS
++++ b/CONTRIBUTORS
+@@ -26,6 +26,7 @@
+ 
+ # Please keep the list sorted.
+ 
++Brian Gunlogson <unixman83@gmail.com>
+ Dominic Battré <battre@chromium.org>
+ John Millikin <jmillikin@gmail.com>
+ Rob Pike <r@google.com>
+diff --git a/re2/compile.cc b/re2/compile.cc
+index 9cddb71..adb45fd 100644
+--- a/re2/compile.cc
++++ b/re2/compile.cc
+@@ -502,7 +502,7 @@ int Compiler::RuneByteSuffix(uint8 lo, uint8 hi, bool foldcase, int next) {
+     return UncachedRuneByteSuffix(lo, hi, foldcase, next);
+   }
+ 
+-  uint64 key = ((uint64)next << 17) | (lo<<9) | (hi<<1) | foldcase;
++  uint64 key = ((uint64)next << 17) | (lo<<9) | (hi<<1) | (foldcase ? 1ULL : 0ULL);
+   map<uint64, int>::iterator it = rune_cache_.find(key);
+   if (it != rune_cache_.end())
+     return it->second;
+diff --git a/re2/prefilter_tree.cc b/re2/prefilter_tree.cc
+index d8bc37a..cdcf77e 100644
+--- a/re2/prefilter_tree.cc
++++ b/re2/prefilter_tree.cc
+@@ -8,6 +8,11 @@
+ #include "re2/prefilter_tree.h"
+ #include "re2/re2.h"
+ 
++#ifdef WIN32
++#include <stdio.h>
++#define snprintf _snprintf
++#endif
++
+ DEFINE_int32(filtered_re2_min_atom_len,
+              3,
+              "Strings less than this length are not stored as atoms");
+diff --git a/re2/re2.cc b/re2/re2.cc
+index 8d1d468..0da886d 100644
+--- a/re2/re2.cc
++++ b/re2/re2.cc
+@@ -11,7 +11,13 @@
+ 
+ #include <stdio.h>
+ #include <string>
++#ifdef WIN32
++#define strtoll _strtoi64
++#define strtoull _strtoui64
++#define strtof strtod
++#else
+ #include <pthread.h>
++#endif
+ #include <errno.h>
+ #include "util/util.h"
+ #include "util/flags.h"
+@@ -31,10 +37,22 @@ const VariadicFunction2<bool, const StringPiece&, const RE2&, RE2::Arg, RE2::Par
+ const VariadicFunction2<bool, StringPiece*, const RE2&, RE2::Arg, RE2::ConsumeN> RE2::Consume;
+ const VariadicFunction2<bool, StringPiece*, const RE2&, RE2::Arg, RE2::FindAndConsumeN> RE2::FindAndConsume;
+ 
+-// This will trigger LNK2005 error in MSVC.
+-#ifndef COMPILER_MSVC
+-const int RE2::Options::kDefaultMaxMem;  // initialized in re2.h
+-#endif  // COMPILER_MSVC
++#define kDefaultMaxMem (8<<20)
++
++RE2::Options::Options()
++  :  encoding_(EncodingUTF8),
++     posix_syntax_(false),
++     longest_match_(false),
++     log_errors_(true),
++     max_mem_(kDefaultMaxMem),
++     literal_(false),
++     never_nl_(false),
++     never_capture_(false),
++     case_sensitive_(true),
++     perl_classes_(false),
++     word_boundary_(false),
++     one_line_(false) {
++}
+ 
+ RE2::Options::Options(RE2::CannedOptions opt)
+   : encoding_(opt == RE2::Latin1 ? EncodingLatin1 : EncodingUTF8),
+diff --git a/re2/re2.h b/re2/re2.h
+index 272028b..c509853 100644
+--- a/re2/re2.h
++++ b/re2/re2.h
+@@ -552,28 +552,16 @@ class RE2 {
+     // If this happens too often, RE2 falls back on the NFA implementation.
+ 
+     // For now, make the default budget something close to Code Search.
++#ifndef WIN32
+     static const int kDefaultMaxMem = 8<<20;
++#endif
+ 
+     enum Encoding {
+       EncodingUTF8 = 1,
+       EncodingLatin1
+     };
+ 
+-    Options() :
+-      encoding_(EncodingUTF8),
+-      posix_syntax_(false),
+-      longest_match_(false),
+-      log_errors_(true),
+-      max_mem_(kDefaultMaxMem),
+-      literal_(false),
+-      never_nl_(false),
+-      never_capture_(false),
+-      case_sensitive_(true),
+-      perl_classes_(false),
+-      word_boundary_(false),
+-      one_line_(false) {
+-    }
+-    
++    Options();
+     /*implicit*/ Options(CannedOptions);
+ 
+     Encoding encoding() const { return encoding_; }
+diff --git a/re2/stringpiece.h b/re2/stringpiece.h
+index ab9297c..38a5150 100644
+--- a/re2/stringpiece.h
++++ b/re2/stringpiece.h
+@@ -23,6 +23,9 @@
+ #include <cstddef>
+ #include <iosfwd>
+ #include <string>
++#ifdef WIN32
++#include <algorithm>
++#endif
+ 
+ namespace re2 {
+ 
+diff --git a/re2/testing/re2_test.cc b/re2/testing/re2_test.cc
+index b99cacf..911e868 100644
+--- a/re2/testing/re2_test.cc
++++ b/re2/testing/re2_test.cc
+@@ -6,7 +6,9 @@
+ // TODO: Test extractions for PartialMatch/Consume
+ 
+ #include <sys/types.h>
++#ifndef WIN32
+ #include <sys/mman.h>
++#endif
+ #include <sys/stat.h>
+ #include <errno.h>
+ #include <vector>
+@@ -14,6 +16,11 @@
+ #include "re2/re2.h"
+ #include "re2/regexp.h"
+ 
++#ifdef WIN32
++#include <stdio.h>
++#define snprintf _snprintf
++#endif
++
+ DECLARE_bool(logtostderr);
+ 
+ namespace re2 {
+@@ -657,6 +664,7 @@ TEST(RE2, FullMatchTypedNullArg) {
+   CHECK(!RE2::FullMatch("hello", "(.*)", (float*)NULL));
+ }
+ 
++#ifndef WIN32
+ // Check that numeric parsing code does not read past the end of
+ // the number being parsed.
+ TEST(RE2, NULTerminated) {
+@@ -678,6 +686,7 @@ TEST(RE2, NULTerminated) {
+   CHECK(RE2::FullMatch(StringPiece(v + pagesize - 1, 1), "(.*)", &x));
+   CHECK_EQ(x, 1);
+ }
++#endif
+ 
+ TEST(RE2, FullMatchTypeTests) {
+   // Type tests
+diff --git a/util/logging.h b/util/logging.h
+index 4443f7c..d0a2d87 100644
+--- a/util/logging.h
++++ b/util/logging.h
+@@ -7,8 +7,13 @@
+ #ifndef RE2_UTIL_LOGGING_H__
+ #define RE2_UTIL_LOGGING_H__
+ 
++#ifndef WIN32
+ #include <unistd.h>  /* for write */
++#endif
+ #include <sstream>
++#ifdef WIN32
++#include <io.h>
++#endif
+ 
+ // Debug-only checking.
+ #define DCHECK(condition) assert(condition)
+diff --git a/util/mutex.h b/util/mutex.h
+index 9787bfb..e321fae 100644
+--- a/util/mutex.h
++++ b/util/mutex.h
+@@ -12,8 +12,10 @@
+ 
+ namespace re2 {
+ 
++#ifndef WIN32
+ #define HAVE_PTHREAD 1
+ #define HAVE_RWLOCK 1
++#endif
+ 
+ #if defined(NO_THREADS)
+   typedef int MutexType;      // to keep a lock-count
+@@ -32,7 +34,9 @@ namespace re2 {
+ # include <pthread.h>
+   typedef pthread_mutex_t MutexType;
+ #elif defined(WIN32)
+-# define WIN32_LEAN_AND_MEAN  // We only need minimal includes
++# ifndef WIN32_LEAN_AND_MEAN
++#  define WIN32_LEAN_AND_MEAN  // We only need minimal includes
++# endif
+ # ifdef GMUTEX_TRYLOCK
+   // We need Windows NT or later for TryEnterCriticalSection().  If you
+   // don't need that functionality, you can remove these _WIN32_WINNT
+diff --git a/util/pcre.cc b/util/pcre.cc
+index 5e67e1f..1602133 100644
+--- a/util/pcre.cc
++++ b/util/pcre.cc
+@@ -11,6 +11,11 @@
+ #include "util/flags.h"
+ #include "util/pcre.h"
+ 
++#ifdef WIN32
++#define strtoll _strtoi64
++#define strtoull _strtoui64
++#endif
++
+ #define PCREPORT(level) LOG(level)
+ 
+ // Default PCRE limits.
+diff --git a/util/pcre.h b/util/pcre.h
+index 4dda95d..771ac91 100644
+--- a/util/pcre.h
++++ b/util/pcre.h
+@@ -180,9 +180,15 @@ struct pcre_extra { int flags, match_limit, match_limit_recursion; };
+ #define PCRE_ERROR_MATCHLIMIT 2
+ #define PCRE_ERROR_RECURSIONLIMIT 3
+ #define PCRE_INFO_CAPTURECOUNT 0
++#ifndef WIN32
+ #define pcre_compile(a,b,c,d,e) ({ (void)(a); (void)(b); *(c)=""; *(d)=0; (void)(e); ((pcre*)0); })
+ #define pcre_exec(a, b, c, d, e, f, g, h) ({ (void)(a); (void)(b); (void)(c); (void)(d); (void)(e); (void)(f); (void)(g); (void)(h); 0; })
+ #define pcre_fullinfo(a, b, c, d) ({ (void)(a); (void)(b); (void)(c); *(d) = 0; 0; })
++#else
++#define pcre_compile(a,b,c,d,e) NULL
++#define pcre_exec(a, b, c, d, e, f, g, h) NULL
++#define pcre_fullinfo(a, b, c, d) NULL
++#endif
+ }  // namespace re2
+ #endif
+ 
+diff --git a/util/test.cc b/util/test.cc
+index 0644829..2fe1bfa 100644
+--- a/util/test.cc
++++ b/util/test.cc
+@@ -3,7 +3,9 @@
+ // license that can be found in the LICENSE file.
+ 
+ #include <stdio.h>
++#ifndef WIN32
+ #include <sys/resource.h>
++#endif
+ #include "util/test.h"
+ 
+ DEFINE_string(test_tmpdir, "/var/tmp", "temp directory");
+@@ -23,9 +25,13 @@ void RegisterTest(void (*fn)(void), const char *name) {
+ 
+ namespace re2 {
+ int64 VirtualProcessSize() {
++#ifndef WIN32
+   struct rusage ru;
+   getrusage(RUSAGE_SELF, &ru);
+   return (int64)ru.ru_maxrss*1024;
++#else
++  return 0;
++#endif
+ }
+ }  // namespace re2
+ 
+diff --git a/util/util.h b/util/util.h
+index c46ab1b..17ef824 100644
+--- a/util/util.h
++++ b/util/util.h
+@@ -12,7 +12,9 @@
+ #include <stddef.h>         // For size_t
+ #include <assert.h>
+ #include <stdarg.h>
++#ifndef WIN32
+ #include <sys/time.h>
++#endif
+ #include <time.h>
+ #include <ctype.h>	// For isdigit, isalpha.
+ 
+@@ -51,7 +53,11 @@ using std::tr1::unordered_set;
+ #else
+ 
+ #include <unordered_set>
++#ifdef WIN32
++using std::tr1::unordered_set;
++#else
+ using std::unordered_set;
++#endif
+ 
+ #endif
+ 
+diff --git a/util/valgrind.h b/util/valgrind.h
+index ca10b1a..d097b0c 100644
+--- a/util/valgrind.h
++++ b/util/valgrind.h
+@@ -4064,6 +4064,7 @@ typedef
+ #endif /* PLAT_ppc64_aix5 */
+ 
+ 
++#ifndef WIN32
+ /* ------------------------------------------------------------------ */
+ /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS.               */
+ /*                                                                    */
+@@ -4170,7 +4171,7 @@ typedef
+                                VG_USERREQ__DISCARD_TRANSLATIONS,  \
+                                _qzz_addr, _qzz_len, 0, 0, 0);     \
+    }
+-
++#endif
+ 
+ /* These requests are for getting Valgrind itself to print something.
+    Possibly with a backtrace.  This is a really ugly hack.  The return value
diff --git a/third_party/re2/patches/remove-valgrind-code.patch b/third_party/re2/patches/remove-valgrind-code.patch
new file mode 100644
index 0000000..ba6007a
--- /dev/null
+++ b/third_party/re2/patches/remove-valgrind-code.patch
@@ -0,0 +1,35 @@
+diff --git a/re2/dfa.cc b/re2/dfa.cc
+index 2556c0f..f1fc7b0 100644
+--- a/re2/dfa.cc
++++ b/re2/dfa.cc
+@@ -27,6 +27,8 @@
+ #include "util/flags.h"
+ #include "util/sparse_set.h"
+ 
++#define NO_THREAD_SAFETY_ANALYSIS
++
+ DEFINE_bool(re2_dfa_bail_when_slow, true,
+             "Whether the RE2 DFA should bail out early "
+             "if the NFA would be faster (for testing).");
+diff --git a/util/util.h b/util/util.h
+index 471c64f..c46ab1b 100644
+--- a/util/util.h
++++ b/util/util.h
+@@ -27,6 +27,8 @@
+ #include <utility>
+ #include <set>
+ 
++#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
++
+ // Use std names.
+ using std::set;
+ using std::pair;
+@@ -119,8 +121,6 @@ static inline uint64 Hash64StringWithSeed(const char* s, int len, uint32 seed) {
+   return ((uint64)x << 32) | y;
+ }
+ 
+-int RunningOnValgrind();
+-
+ }  // namespace re2
+ 
+ #include "util/arena.h"
diff --git a/third_party/re2/patches/sparse-array-valgrind.patch b/third_party/re2/patches/sparse-array-valgrind.patch
new file mode 100644
index 0000000..e2cf0bd
--- /dev/null
+++ b/third_party/re2/patches/sparse-array-valgrind.patch
@@ -0,0 +1,23 @@
+diff --git a/third_party/re2/util/sparse_array.h b/third_party/re2/util/sparse_array.h
+index 4ee5c94..7bc3a86 100644
+--- a/third_party/re2/util/sparse_array.h
++++ b/third_party/re2/util/sparse_array.h
+@@ -273,13 +273,13 @@ void SparseArray<Value>::resize(int new_max_size) {
+     int* a = new int[new_max_size];
+     if (sparse_to_dense_) {
+       memmove(a, sparse_to_dense_, max_size_*sizeof a[0]);
+-      // Don't need to zero the memory but appease Valgrind.
+-      if (valgrind_) {
+-        for (int i = max_size_; i < new_max_size; i++)
+-          a[i] = 0xababababU;
+-      }
+       delete[] sparse_to_dense_;
+     }
++    // Don't need to zero the memory but appease Valgrind.
++    if (valgrind_) {
++      for (int i = max_size_; i < new_max_size; i++)
++        a[i] = 0xababababU;
++    }
+     sparse_to_dense_ = a;
+ 
+     dense_.resize(new_max_size);
diff --git a/third_party/re2/re2.gyp b/third_party/re2/re2.gyp
index 689cd71..8ddfc91 100644
--- a/third_party/re2/re2.gyp
+++ b/third_party/re2/re2.gyp
@@ -44,7 +44,6 @@
         're2/set.cc',
         're2/set.h',
         're2/simplify.cc',
-        're2/stringpiece.cc',
         're2/stringpiece.h',
         're2/tostring.cc',
         're2/unicode_casefold.cc',
@@ -53,21 +52,21 @@
         're2/unicode_groups.h',
         're2/variadic_function.h',
         're2/walker-inl.h',
+        'util/arena.cc',
+        'util/arena.h',
         'util/atomicops.h',
         'util/flags.h',
         'util/hash.cc',
-        'util/logging.cc',
         'util/logging.h',
         'util/mutex.h',
         'util/rune.cc',
         'util/sparse_array.h',
         'util/sparse_set.h',
+        'util/stringpiece.cc',
         'util/stringprintf.cc',
         'util/strutil.cc',
         'util/utf.h',
         'util/util.h',
-        'util/valgrind.cc',
-        'util/valgrind.h',
       ],
       'conditions': [
         ['OS=="win"', {
diff --git a/third_party/re2/re2.pc b/third_party/re2/re2.pc
deleted file mode 100644
index 9e90cdad..0000000
--- a/third_party/re2/re2.pc
+++ /dev/null
@@ -1,10 +0,0 @@
-prefix=@prefix@
-exec_prefix=${prefix}
-includedir=${prefix}/include
-libdir=${exec_prefix}/lib
-
-Name: re2
-Description: RE2 is a fast, safe, thread-friendly regular expression engine.
-Version: 0.0.0
-Cflags: -I${includedir}
-Libs: -L${libdir} -lre2 -pthread
diff --git a/third_party/re2/re2/Makefile b/third_party/re2/re2/Makefile
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/third_party/re2/re2/Makefile
@@ -0,0 +1 @@
+
diff --git a/third_party/re2/re2/bitstate.cc b/third_party/re2/re2/bitstate.cc
index 5740daa4..518d642 100644
--- a/third_party/re2/re2/bitstate.cc
+++ b/third_party/re2/re2/bitstate.cc
@@ -94,7 +94,7 @@
 // If so, remember that it was visited so that the next time,
 // we don't repeat the visit.
 bool BitState::ShouldVisit(int id, const char* p) {
-  size_t n = id * (text_.size() + 1) + (p - text_.begin());
+  uint n = id * (text_.size() + 1) + (p - text_.begin());
   if (visited_[n/VisitedBits] & (1 << (n & (VisitedBits-1))))
     return false;
   visited_[n/VisitedBits] |= 1 << (n & (VisitedBits-1));
@@ -170,8 +170,6 @@
     Prog::Inst* ip = prog_->inst(id);
     switch (ip->opcode()) {
       case kInstFail:
-        return false;
-
       default:
         LOG(DFATAL) << "Unexpected opcode: " << ip->opcode() << " arg " << arg;
         return false;
@@ -272,8 +270,7 @@
         if (submatch_[0].data() == NULL ||
             (longest_ && p > submatch_[0].end())) {
           for (int i = 0; i < nsubmatch_; i++)
-            submatch_[i].set(cap_[2*i],
-                             static_cast<int>(cap_[2*i+1] - cap_[2*i]));
+            submatch_[i] = StringPiece(cap_[2*i], cap_[2*i+1] - cap_[2*i]);
         }
 
         // If going for first match, we're done.
diff --git a/third_party/re2/re2/compile.cc b/third_party/re2/re2/compile.cc
index 5037524..9a59f13 100644
--- a/third_party/re2/re2/compile.cc
+++ b/third_party/re2/re2/compile.cc
@@ -230,7 +230,7 @@
 
   RE2::Anchor anchor_;  // anchor mode for RE2::Set
 
-  DISALLOW_COPY_AND_ASSIGN(Compiler);
+  DISALLOW_EVIL_CONSTRUCTORS(Compiler);
 };
 
 Compiler::Compiler() {
@@ -371,8 +371,6 @@
 
 // Given a fragment for a, returns a fragment for a? or a?? (if nongreedy)
 Frag Compiler::Quest(Frag a, bool nongreedy) {
-  if (IsNoMatch(a))
-    return Nop();
   int id = AllocInst(1);
   if (id < 0)
     return NoMatch();
@@ -435,10 +433,7 @@
   if (empty & (kEmptyWordBoundary|kEmptyNonWordBoundary)) {
     int j;
     for (int i = 0; i < 256; i = j) {
-      for (j = i + 1; j < 256 &&
-                      Prog::IsWordChar(static_cast<uint8>(i)) ==
-                          Prog::IsWordChar(static_cast<uint8>(j));
-           j++)
+      for (j = i+1; j < 256 && Prog::IsWordChar(i) == Prog::IsWordChar(j); j++)
         ;
       prog_->MarkByteRange(i, j-1);
     }
@@ -448,8 +443,6 @@
 
 // Given a fragment a, returns a fragment with capturing parens around a.
 Frag Compiler::Capture(Frag a, int n) {
-  if (IsNoMatch(a))
-    return NoMatch();
   int id = AllocInst(2);
   if (id < 0)
     return NoMatch();
@@ -506,10 +499,7 @@
     return UncachedRuneByteSuffix(lo, hi, foldcase, next);
   }
 
-  uint64 key = (uint64)next << 17 |
-               (uint64)lo   <<  9 |
-               (uint64)hi   <<  1 |
-               (uint64)foldcase;
+  uint64 key = ((uint64)next << 17) | (lo<<9) | (hi<<1) | (foldcase ? 1ULL : 0ULL);
   map<uint64, int>::iterator it = rune_cache_.find(key);
   if (it != rune_cache_.end())
     return it->second;
@@ -561,8 +551,7 @@
     return;
   if (hi > 0xFF)
     hi = 0xFF;
-  AddSuffix(RuneByteSuffix(static_cast<uint8>(lo), static_cast<uint8>(hi),
-                           foldcase, 0));
+  AddSuffix(RuneByteSuffix(lo, hi, foldcase, 0));
 }
 
 // Table describing how to make a UTF-8 matching machine
@@ -603,8 +592,7 @@
     int next = 0;
     if (p.next >= 0)
       next = inst[p.next];
-    inst[i] = UncachedRuneByteSuffix(static_cast<uint8>(p.lo),
-                                     static_cast<uint8>(p.hi), false, next);
+    inst[i] = UncachedRuneByteSuffix(p.lo, p.hi, false, next);
     if ((p.lo & 0xC0) != 0x80)
       AddSuffix(inst[i]);
   }
@@ -633,8 +621,7 @@
 
   // ASCII range is always a special case.
   if (hi < Runeself) {
-    AddSuffix(RuneByteSuffix(static_cast<uint8>(lo), static_cast<uint8>(hi),
-                             foldcase, 0));
+    AddSuffix(RuneByteSuffix(lo, hi, foldcase, 0));
     return;
   }
 
@@ -762,16 +749,16 @@
     }
 
     case kRegexpStar:
-      return Star(child_frags[0], (re->parse_flags()&Regexp::NonGreedy) != 0);
+      return Star(child_frags[0], re->parse_flags()&Regexp::NonGreedy);
 
     case kRegexpPlus:
-      return Plus(child_frags[0], (re->parse_flags()&Regexp::NonGreedy) != 0);
+      return Plus(child_frags[0], re->parse_flags()&Regexp::NonGreedy);
 
     case kRegexpQuest:
-      return Quest(child_frags[0], (re->parse_flags()&Regexp::NonGreedy) != 0);
+      return Quest(child_frags[0], re->parse_flags()&Regexp::NonGreedy);
 
     case kRegexpLiteral:
-      return Literal(re->rune(), (re->parse_flags()&Regexp::FoldCase) != 0);
+      return Literal(re->rune(), re->parse_flags()&Regexp::FoldCase);
 
     case kRegexpLiteralString: {
       // Concatenation of literals.
@@ -779,8 +766,7 @@
         return Nop();
       Frag f;
       for (int i = 0; i < re->nrunes(); i++) {
-        Frag f1 = Literal(re->runes()[i],
-                          (re->parse_flags()&Regexp::FoldCase) != 0);
+        Frag f1 = Literal(re->runes()[i], re->parse_flags()&Regexp::FoldCase);
         if (i == 0)
           f = f1;
         else
@@ -825,8 +811,7 @@
         // If this range contains all of A-Za-z or none of it,
         // the fold flag is unnecessary; don't bother.
         bool fold = foldascii;
-        if ((i->lo <= 'A' && 'z' <= i->hi) || i->hi < 'A' || 'z' < i->lo ||
-            ('Z' < i->lo && i->hi < 'a'))
+        if ((i->lo <= 'A' && 'z' <= i->hi) || i->hi < 'A' || 'z' < i->lo)
           fold = false;
 
         AddRuneRange(i->lo, i->hi, fold);
@@ -969,7 +954,7 @@
   max_mem_ = max_mem;
   if (max_mem <= 0) {
     max_inst_ = 100000;  // more than enough
-  } else if (max_mem <= static_cast<int64>(sizeof(Prog))) {
+  } else if (max_mem <= sizeof(Prog)) {
     // No room for anything.
     max_inst_ = 0;
   } else {
@@ -989,7 +974,7 @@
     if (m > Prog::Inst::kMaxInst)
       m = Prog::Inst::kMaxInst;
 
-    max_inst_ = static_cast<int>(m);
+    max_inst_ = m;
   }
 
   anchor_ = anchor;
diff --git a/third_party/re2/re2/dfa.cc b/third_party/re2/re2/dfa.cc
index 1f54b9f..f1fc7b0 100644
--- a/third_party/re2/re2/dfa.cc
+++ b/third_party/re2/re2/dfa.cc
@@ -21,11 +21,13 @@
 //
 // See http://swtch.com/~rsc/regexp/ for a very bare-bones equivalent.
 
+#include "re2/prog.h"
+#include "re2/stringpiece.h"
 #include "util/atomicops.h"
 #include "util/flags.h"
 #include "util/sparse_set.h"
-#include "re2/prog.h"
-#include "re2/stringpiece.h"
+
+#define NO_THREAD_SAFETY_ANALYSIS
 
 DEFINE_bool(re2_dfa_bail_when_slow, true,
             "Whether the RE2 DFA should bail out early "
@@ -94,7 +96,7 @@
   // States, linked by the next_ pointers.  If in state s and reading
   // byte c, the next state should be s->next_[c].
   struct State {
-    inline bool IsMatch() const { return (flag_ & kFlagMatch) != 0; }
+    inline bool IsMatch() const { return flag_ & kFlagMatch; }
     void SaveMatch(vector<int>* v);
 
     int* inst_;         // Instruction pointers in the state.
@@ -143,7 +145,7 @@
       if (sizeof(size_t) == sizeof(uint32))
         return Hash32StringWithSeed(s, len, a->flag_);
       else
-        return static_cast<size_t>(Hash64StringWithSeed(s, len, a->flag_));
+        return Hash64StringWithSeed(s, len, a->flag_);
     }
 #ifdef STL_MSVC
     // Less than operator.
@@ -228,8 +230,9 @@
   // sets *ismatch to true.
   // L >= mutex_
   void RunWorkqOnByte(Workq* q, Workq* nq,
-                      int c, uint flag, bool* ismatch,
-                      Prog::MatchKind kind);
+                             int c, uint flag, bool* ismatch,
+                             Prog::MatchKind kind,
+                             int new_byte_loop);
 
   // Runs a Workq on a set of empty-string flags, producing a new Workq in nq.
   // L >= mutex_
@@ -274,7 +277,7 @@
     vector<int>* matches;
 
    private:
-    DISALLOW_COPY_AND_ASSIGN(SearchParams);
+    DISALLOW_EVIL_CONSTRUCTORS(SearchParams);
   };
 
   // Before each search, the parameters to Search are analyzed by
@@ -339,6 +342,7 @@
   // Constant after initialization.
   Prog* prog_;              // The regular expression program to run.
   Prog::MatchKind kind_;    // The kind of DFA.
+  int start_unanchored_;  // start of unanchored program
   bool init_failed_;        // initialization failed (out of memory)
 
   Mutex mutex_;  // mutex_ >= cache_mutex_.r
@@ -426,7 +430,7 @@
   int maxmark_;          // maximum number of marks
   int nextmark_;         // id of next mark
   bool last_was_mark_;   // last inserted was mark
-  DISALLOW_COPY_AND_ASSIGN(Workq);
+  DISALLOW_EVIL_CONSTRUCTORS(Workq);
 };
 
 DFA::DFA(Prog* prog, Prog::MatchKind kind, int64 max_mem)
@@ -441,8 +445,11 @@
   if (DebugDFA)
     fprintf(stderr, "\nkind %d\n%s\n", (int)kind_, prog_->DumpUnanchored().c_str());
   int nmark = 0;
-  if (kind_ == Prog::kLongestMatch)
+  start_unanchored_ = 0;
+  if (kind_ == Prog::kLongestMatch) {
     nmark = prog->size();
+    start_unanchored_ = prog->start_unanchored();
+  }
   nastack_ = 2 * prog->size() + nmark;
 
   // Account for space needed for DFA, q0, q1, astack.
@@ -451,7 +458,7 @@
                  (sizeof(int)+sizeof(int)) * 2;  // q0, q1
   mem_budget_ -= nastack_ * sizeof(int);  // astack
   if (mem_budget_ < 0) {
-    LOG(INFO) << StringPrintf("DFA out of memory: prog size %d mem %lld",
+    LOG(INFO) << StringPrintf("DFA out of memory: prog size %lld mem %lld",
                               prog_->size(), max_mem);
     init_failed_ = true;
     return;
@@ -466,7 +473,7 @@
   int64 one_state = sizeof(State) + (prog_->size()+nmark)*sizeof(int) +
                     (prog_->bytemap_range()+1)*sizeof(State*);
   if (state_budget_ < 20*one_state) {
-    LOG(INFO) << StringPrintf("DFA out of memory: prog size %d mem %lld",
+    LOG(INFO) << StringPrintf("DFA out of memory: prog size %lld mem %lld",
                               prog_->size(), max_mem);
     init_failed_ = true;
     return;
@@ -782,7 +789,7 @@
        it != state_cache_.end(); ++it)
     v.push_back(*it);
   state_cache_.clear();
-  for (size_t i = 0; i < v.size(); i++)
+  for (int i = 0; i < v.size(); i++)
     delete[] reinterpret_cast<const char*>(v[i]);
 }
 
@@ -864,10 +871,8 @@
         break;
 
       case kInstEmptyWidth:
-        // Continue on if we have all the right flag bits.
-        if (ip->empty() & ~flag)
-          break;
-        stk[nstk++] = ip->out();
+        if ((ip->empty() & flag) == ip->empty())
+          stk[nstk++] = ip->out();
         break;
     }
   }
@@ -905,7 +910,8 @@
 // regular expression program has been reached (the regexp has matched).
 void DFA::RunWorkqOnByte(Workq* oldq, Workq* newq,
                          int c, uint flag, bool* ismatch,
-                         Prog::MatchKind kind) {
+                         Prog::MatchKind kind,
+                         int new_byte_loop) {
   if (DEBUG_MODE)
     mutex_.AssertHeld();
 
@@ -984,8 +990,9 @@
   }
 
   // If someone else already computed this, return it.
-  State* ns;
-  ATOMIC_LOAD_CONSUME(ns, &state->next_[ByteMap(c)]);
+  MaybeReadMemoryBarrier(); // On alpha we need to ensure read ordering
+  State* ns = state->next_[ByteMap(c)];
+  ANNOTATE_HAPPENS_AFTER(ns);
   if (ns != NULL)
     return ns;
 
@@ -1015,8 +1022,8 @@
   // The state flag kFlagLastWord says whether the last
   // byte processed was a word character.  Use that info to
   // insert empty-width (non-)word boundaries.
-  bool islastword = (state->flag_ & kFlagLastWord) != 0;
-  bool isword = (c != kByteEndText && Prog::IsWordChar(static_cast<uint8>(c)));
+  bool islastword = state->flag_ & kFlagLastWord;
+  bool isword = (c != kByteEndText && Prog::IsWordChar(c));
   if (isword == islastword)
     beforeflag |= kEmptyNonWordBoundary;
   else
@@ -1029,8 +1036,8 @@
     swap(q0_, q1_);
   }
   bool ismatch = false;
-  RunWorkqOnByte(q0_, q1_, c, afterflag, &ismatch, kind_);
-
+  RunWorkqOnByte(q0_, q1_, c, afterflag, &ismatch, kind_, start_unanchored_);
+  
   // Most of the time, we build the state from the output of
   // RunWorkqOnByte, so swap q0_ and q1_ here.  However, so that
   // RE2::Set can tell exactly which match instructions
@@ -1051,11 +1058,18 @@
 
   ns = WorkqToCachedState(q0_, flag);
 
-  // Flush ns before linking to it.
   // Write barrier before updating state->next_ so that the
   // main search loop can proceed without any locking, for speed.
   // (Otherwise it would need one mutex operation per input byte.)
-  ATOMIC_STORE_RELEASE(&state->next_[ByteMap(c)], ns);
+  // The annotations below tell race detectors that:
+  //   a) the access to next_ should be ignored,
+  //   b) 'ns' is properly published.
+  WriteMemoryBarrier();  // Flush ns before linking to it.
+
+  ANNOTATE_IGNORE_WRITES_BEGIN();
+  ANNOTATE_HAPPENS_BEFORE(ns);
+  state->next_[ByteMap(c)] = ns;
+  ANNOTATE_IGNORE_WRITES_END();
   return ns;
 }
 
@@ -1098,7 +1112,7 @@
   Mutex* mu_;
   bool writing_;
 
-  DISALLOW_COPY_AND_ASSIGN(RWLocker);
+  DISALLOW_EVIL_CONSTRUCTORS(RWLocker);
 };
 
 DFA::RWLocker::RWLocker(Mutex* mu)
@@ -1198,7 +1212,7 @@
   bool is_special_;  // whether original state was special
   State* special_;   // if is_special_, the original state
 
-  DISALLOW_COPY_AND_ASSIGN(StateSaver);
+  DISALLOW_EVIL_CONSTRUCTORS(StateSaver);
 };
 
 DFA::StateSaver::StateSaver(DFA* dfa, State* state) {
@@ -1376,8 +1390,9 @@
     // Okay to use bytemap[] not ByteMap() here, because
     // c is known to be an actual byte and not kByteEndText.
 
-    State* ns;
-    ATOMIC_LOAD_CONSUME(ns, &s->next_[bytemap[c]]);
+    MaybeReadMemoryBarrier(); // On alpha we need to ensure read ordering
+    State* ns = s->next_[bytemap[c]];
+    ANNOTATE_HAPPENS_AFTER(ns);
     if (ns == NULL) {
       ns = RunStateOnByteUnlocked(s, c);
       if (ns == NULL) {
@@ -1390,7 +1405,7 @@
         // of 10 bytes per state computation, fail so that RE2 can
         // fall back to the NFA.
         if (FLAGS_re2_dfa_bail_when_slow && resetp != NULL &&
-            static_cast<unsigned long>(p - resetp) < 10*state_cache_.size()) {
+            (p - resetp) < 10*state_cache_.size()) {
           params->failed = true;
           return false;
         }
@@ -1464,8 +1479,9 @@
       lastbyte = params->text.begin()[-1] & 0xFF;
   }
 
-  State* ns;
-  ATOMIC_LOAD_CONSUME(ns, &s->next_[ByteMap(lastbyte)]);
+  MaybeReadMemoryBarrier(); // On alpha we need to ensure read ordering
+  State* ns = s->next_[ByteMap(lastbyte)];
+  ANNOTATE_HAPPENS_AFTER(ns);
   if (ns == NULL) {
     ns = RunStateOnByteUnlocked(s, lastbyte);
     if (ns == NULL) {
@@ -1653,16 +1669,13 @@
     }
   }
 
-  if (DebugDFA) {
-    int fb;
-    ATOMIC_LOAD_RELAXED(fb, &info->firstbyte);
+  if (DebugDFA)
     fprintf(stderr, "anchored=%d fwd=%d flags=%#x state=%s firstbyte=%d\n",
             params->anchored, params->run_forward, flags,
-            DumpState(info->start).c_str(), fb);
-  }
+            DumpState(info->start).c_str(), info->firstbyte);
 
   params->start = info->start;
-  ATOMIC_LOAD_ACQUIRE(params->firstbyte, &info->firstbyte);
+  params->firstbyte = ANNOTATE_UNPROTECTED_READ(info->firstbyte);
 
   return true;
 }
@@ -1670,15 +1683,17 @@
 // Fills in info if needed.  Returns true on success, false on failure.
 bool DFA::AnalyzeSearchHelper(SearchParams* params, StartInfo* info,
                               uint flags) {
-  // Quick check.
-  int fb;
-  ATOMIC_LOAD_ACQUIRE(fb, &info->firstbyte);
-  if (fb != kFbUnknown)
+  // Quick check; okay because of memory barriers below.
+  if (ANNOTATE_UNPROTECTED_READ(info->firstbyte) != kFbUnknown) {
+    ANNOTATE_HAPPENS_AFTER(&info->firstbyte);
     return true;
+  }
 
   MutexLock l(&mutex_);
-  if (info->firstbyte != kFbUnknown)
+  if (info->firstbyte != kFbUnknown) {
+    ANNOTATE_HAPPENS_AFTER(&info->firstbyte);
     return true;
+  }
 
   q0_->clear();
   AddToQueue(q0_,
@@ -1689,14 +1704,16 @@
     return false;
 
   if (info->start == DeadState) {
-    // Synchronize with "quick check" above.
-    ATOMIC_STORE_RELEASE(&info->firstbyte, kFbNone);
+    ANNOTATE_HAPPENS_BEFORE(&info->firstbyte);
+    WriteMemoryBarrier();  // Synchronize with "quick check" above.
+    info->firstbyte = kFbNone;
     return true;
   }
 
   if (info->start == FullMatchState) {
-    // Synchronize with "quick check" above.
-    ATOMIC_STORE_RELEASE(&info->firstbyte, kFbNone);	// will be ignored
+    ANNOTATE_HAPPENS_BEFORE(&info->firstbyte);
+    WriteMemoryBarrier();  // Synchronize with "quick check" above.
+    info->firstbyte = kFbNone;	// will be ignored
     return true;
   }
 
@@ -1707,8 +1724,9 @@
   for (int i = 0; i < 256; i++) {
     State* s = RunStateOnByte(info->start, i);
     if (s == NULL) {
-      // Synchronize with "quick check" above.
-      ATOMIC_STORE_RELEASE(&info->firstbyte, firstbyte);
+      ANNOTATE_HAPPENS_BEFORE(&info->firstbyte);
+      WriteMemoryBarrier();  // Synchronize with "quick check" above.
+      info->firstbyte = firstbyte;
       return false;
     }
     if (s == info->start)
@@ -1721,8 +1739,9 @@
       break;
     }
   }
-  // Synchronize with "quick check" above.
-  ATOMIC_STORE_RELEASE(&info->firstbyte, firstbyte);
+  ANNOTATE_HAPPENS_BEFORE(&info->firstbyte);
+  WriteMemoryBarrier();  // Synchronize with "quick check" above.
+  info->firstbyte = firstbyte;
   return true;
 }
 
@@ -1802,16 +1821,19 @@
     pdfa = &dfa_longest_;
   }
 
-  // Quick check.
-  DFA *dfa;
-  ATOMIC_LOAD_ACQUIRE(dfa, pdfa);
-  if (dfa != NULL)
+  // Quick check; okay because of memory barrier below.
+  DFA *dfa = ANNOTATE_UNPROTECTED_READ(*pdfa);
+  if (dfa != NULL) {
+    ANNOTATE_HAPPENS_AFTER(dfa);
     return dfa;
+  }
 
   MutexLock l(&dfa_mutex_);
   dfa = *pdfa;
-  if (dfa != NULL)
+  if (dfa != NULL) {
+    ANNOTATE_HAPPENS_AFTER(dfa);
     return dfa;
+  }
 
   // For a forward DFA, half the memory goes to each DFA.
   // For a reverse DFA, all the memory goes to the
@@ -1828,7 +1850,9 @@
   delete_dfa_ = DeleteDFA;
 
   // Synchronize with "quick check" above.
-  ATOMIC_STORE_RELEASE(pdfa, dfa);
+  ANNOTATE_HAPPENS_BEFORE(dfa);
+  WriteMemoryBarrier();
+  *pdfa = dfa;
 
   return dfa;
 }
@@ -1901,9 +1925,9 @@
   // as the beginning.
   if (match0) {
     if (reversed_)
-      match0->set(ep, static_cast<int>(text.end() - ep));
+      *match0 = StringPiece(ep, text.end() - ep);
     else
-      match0->set(text.begin(), static_cast<int>(ep - text.begin()));
+      *match0 = StringPiece(text.begin(), ep - text.begin());
   }
   return true;
 }
@@ -1928,7 +1952,7 @@
   q.push_back(params.start);
 
   // Flood to expand every state.
-  for (size_t i = 0; i < q.size(); i++) {
+  for (int i = 0; i < q.size(); i++) {
     State* s = q[i];
     for (int c = 0; c < 257; c++) {
       State* ns = RunStateOnByteUnlocked(s, c);
@@ -1939,7 +1963,7 @@
     }
   }
 
-  return static_cast<int>(q.size());
+  return q.size();
 }
 
 // Build out all states in DFA for kind.  Returns number of states.
@@ -2011,7 +2035,6 @@
   // Build minimum prefix.
   State* s = params.start;
   min->clear();
-  MutexLock lock(&mutex_);
   for (int i = 0; i < maxlen; i++) {
     if (previously_visited_states[s] > kMaxEltRepetitions) {
       VLOG(2) << "Hit kMaxEltRepetitions=" << kMaxEltRepetitions
@@ -2021,7 +2044,7 @@
     previously_visited_states[s]++;
 
     // Stop if min is a match.
-    State* ns = RunStateOnByte(s, kByteEndText);
+    State* ns = RunStateOnByteUnlocked(s, kByteEndText);
     if (ns == NULL)  // DFA out of memory
       return false;
     if (ns != DeadState && (ns == FullMatchState || ns->IsMatch()))
@@ -2030,13 +2053,13 @@
     // Try to extend the string with low bytes.
     bool extended = false;
     for (int j = 0; j < 256; j++) {
-      ns = RunStateOnByte(s, j);
+      ns = RunStateOnByteUnlocked(s, j);
       if (ns == NULL)  // DFA out of memory
         return false;
       if (ns == FullMatchState ||
           (ns > SpecialStateMax && ns->ninst_ > 0)) {
         extended = true;
-        min->append(1, static_cast<char>(j));
+        min->append(1, j);
         s = ns;
         break;
       }
@@ -2060,13 +2083,13 @@
     // Try to extend the string with high bytes.
     bool extended = false;
     for (int j = 255; j >= 0; j--) {
-      State* ns = RunStateOnByte(s, j);
+      State* ns = RunStateOnByteUnlocked(s, j);
       if (ns == NULL)
         return false;
       if (ns == FullMatchState ||
           (ns > SpecialStateMax && ns->ninst_ > 0)) {
         extended = true;
-        max->append(1, static_cast<char>(j));
+        max->append(1, j);
         s = ns;
         break;
       }
@@ -2099,12 +2122,11 @@
     MutexLock l(&dfa_mutex_);
     // Have to use dfa_longest_ to get all strings for full matches.
     // For example, (a|aa) never matches aa in first-match mode.
-    dfa = dfa_longest_;
-    if (dfa == NULL) {
-      dfa = new DFA(this, Prog::kLongestMatch, dfa_mem_/2);
-      ATOMIC_STORE_RELEASE(&dfa_longest_, dfa);
+    if (dfa_longest_ == NULL) {
+      dfa_longest_ = new DFA(this, Prog::kLongestMatch, dfa_mem_/2);
       delete_dfa_ = DeleteDFA;
     }
+    dfa = dfa_longest_;
   }
   return dfa->PossibleMatchRange(min, max, maxlen);
 }
diff --git a/third_party/re2/re2/filtered_re2.cc b/third_party/re2/re2/filtered_re2.cc
index 5dd65d5..f576258 100644
--- a/third_party/re2/re2/filtered_re2.cc
+++ b/third_party/re2/re2/filtered_re2.cc
@@ -16,7 +16,7 @@
 }
 
 FilteredRE2::~FilteredRE2() {
-  for (size_t i = 0; i < re2_vec_.size(); i++)
+  for (int i = 0; i < re2_vec_.size(); i++)
     delete re2_vec_[i];
   delete prefilter_tree_;
 }
@@ -33,7 +33,7 @@
     }
     delete re;
   } else {
-    *id = static_cast<int>(re2_vec_.size());
+    *id = re2_vec_.size();
     re2_vec_.push_back(re);
   }
 
@@ -46,7 +46,7 @@
     return;
   }
 
-  for (size_t i = 0; i < re2_vec_.size(); i++) {
+  for (int i = 0; i < re2_vec_.size(); i++) {
     Prefilter* prefilter = Prefilter::FromRE2(re2_vec_[i]);
     prefilter_tree_->Add(prefilter);
   }
@@ -56,9 +56,9 @@
 }
 
 int FilteredRE2::SlowFirstMatch(const StringPiece& text) const {
-  for (size_t i = 0; i < re2_vec_.size(); i++)
+  for (int i = 0; i < re2_vec_.size(); i++)
     if (RE2::PartialMatch(text, *re2_vec_[i]))
-      return static_cast<int>(i);
+      return i;
   return -1;
 }
 
@@ -70,7 +70,7 @@
   }
   vector<int> regexps;
   prefilter_tree_->RegexpsGivenStrings(atoms, &regexps);
-  for (size_t i = 0; i < regexps.size(); i++)
+  for (int i = 0; i < regexps.size(); i++)
     if (RE2::PartialMatch(text, *re2_vec_[regexps[i]]))
       return regexps[i];
   return -1;
@@ -83,23 +83,18 @@
   matching_regexps->clear();
   vector<int> regexps;
   prefilter_tree_->RegexpsGivenStrings(atoms, &regexps);
-  for (size_t i = 0; i < regexps.size(); i++)
+  for (int i = 0; i < regexps.size(); i++)
     if (RE2::PartialMatch(text, *re2_vec_[regexps[i]]))
       matching_regexps->push_back(regexps[i]);
   return !matching_regexps->empty();
 }
 
-void FilteredRE2::AllPotentials(
-    const vector<int>& atoms,
-    vector<int>* potential_regexps) const {
-  prefilter_tree_->RegexpsGivenStrings(atoms, potential_regexps);
-}
-
 void FilteredRE2::RegexpsGivenStrings(const vector<int>& matched_atoms,
                                       vector<int>* passed_regexps) {
   prefilter_tree_->RegexpsGivenStrings(matched_atoms, passed_regexps);
 }
 
+
 void FilteredRE2::PrintPrefilter(int regexpid) {
   prefilter_tree_->PrintPrefilter(regexpid);
 }
diff --git a/third_party/re2/re2/filtered_re2.h b/third_party/re2/re2/filtered_re2.h
index f4b2be48..64b35be6 100644
--- a/third_party/re2/re2/filtered_re2.h
+++ b/third_party/re2/re2/filtered_re2.h
@@ -67,16 +67,8 @@
                   const vector<int>& atoms,
                   vector<int>* matching_regexps) const;
 
-  // Returns the indices of all potentially matching regexps after first
-  // clearing potential_regexps.
-  // A regexp is potentially matching if it passes the filter.
-  // If a regexp passes the filter it may still not match.
-  // A regexp that does not pass the filter is guaranteed to not match.
-  void AllPotentials(const vector<int>& atoms,
-                     vector<int>* potential_regexps) const;
-
   // The number of regexps added.
-  int NumRegexps() const { return static_cast<int>(re2_vec_.size()); }
+  int NumRegexps() const { return re2_vec_.size(); }
 
  private:
 
@@ -99,7 +91,7 @@
   // An AND-OR tree of string atoms used for filtering regexps.
   PrefilterTree* prefilter_tree_;
 
-  //DISALLOW_COPY_AND_ASSIGN(FilteredRE2);
+  //DISALLOW_EVIL_CONSTRUCTORS(FilteredRE2);
   FilteredRE2(const FilteredRE2&);
   void operator=(const FilteredRE2&);
 };
diff --git a/third_party/re2/re2/make_perl_groups.pl b/third_party/re2/re2/make_perl_groups.pl
index d9fcdafa..d5eaa59 100755
--- a/third_party/re2/re2/make_perl_groups.pl
+++ b/third_party/re2/re2/make_perl_groups.pl
@@ -32,20 +32,14 @@
 	"\\w",
 );
 
-%overrides = (
-	# Prior to Perl 5.18, \s did not match vertical tab.
-	# RE2 preserves that original behaviour.
-	"\\s:11" => 0,
-);
-
 sub ComputeClass($) {
-  my ($cname) = @_;
   my @ranges;
-  my $regexp = qr/[$cname]/;
+  my ($class) = @_;
+  my $regexp = "[$class]";
   my $start = -1;
   for (my $i=0; $i<=129; $i++) {
     if ($i == 129) { $i = 256; }
-    if ($i <= 128 && ($overrides{"$cname:$i"} // chr($i) =~ $regexp)) {
+    if ($i <= 128 && chr($i) =~ $regexp) {
       if ($start < 0) {
         $start = $i;
       }
@@ -60,15 +54,15 @@
 }
 
 sub PrintClass($$@) {
-  my ($cnum, $cname, @ranges) = @_;
-  print "static const URange16 code${cnum}[] = {  /* $cname */\n";
+  my ($cname, $name, @ranges) = @_;
+  print "static URange16 code${cname}[] = {  /* $name */\n";
   for (my $i=0; $i<@ranges; $i++) {
     my @a = @{$ranges[$i]};
     printf "\t{ 0x%x, 0x%x },\n", $a[0], $a[1];
   }
   print "};\n";
   my $n = @ranges;
-  my $escname = $cname;
+  my $escname = $name;
   $escname =~ s/\\/\\\\/g;
   $negname = $escname;
   if ($negname =~ /:/) {
@@ -76,25 +70,25 @@
   } else {
     $negname =~ y/a-z/A-Z/;
   }
-  return "{ \"$escname\", +1, code$cnum, $n }", "{ \"$negname\", -1, code$cnum, $n }";
+  return "{ \"$escname\", +1, code$cname, $n }", "{ \"$negname\", -1, code$cname, $n }";
 }
 
-my $cnum = 0;
+my $gen = 0;
 
 sub PrintClasses($@) {
-  my ($pname, @classes) = @_;
+  my ($cname, @classes) = @_;
   my @entries;
-  foreach my $cname (@classes) {
-    my @ranges = ComputeClass($cname);
-    push @entries, PrintClass(++$cnum, $cname, @ranges);
+  foreach my $cl (@classes) {
+    my @ranges = ComputeClass($cl);
+    push @entries, PrintClass(++$gen, $cl, @ranges);
   }
-  print "const UGroup ${pname}_groups[] = {\n";
+  print "UGroup ${cname}_groups[] = {\n";
   foreach my $e (@entries) {
     print "\t$e,\n";
   }
   print "};\n";
   my $count = @entries;
-  print "const int num_${pname}_groups = $count;\n";
+  print "int num_${cname}_groups = $count;\n";
 }
 
 print <<EOF;
diff --git a/third_party/re2/re2/make_unicode_casefold.py b/third_party/re2/re2/make_unicode_casefold.py
index d215eb1..3375d2e 100755
--- a/third_party/re2/re2/make_unicode_casefold.py
+++ b/third_party/re2/re2/make_unicode_casefold.py
@@ -9,8 +9,7 @@
 
 """Generate C++ table for Unicode case folding."""
 
-import sys
-import unicode
+import unicode, sys
 
 _header = """
 // GENERATED BY make_unicode_casefold.py; DO NOT EDIT.
@@ -131,11 +130,11 @@
     foldpairs.sort()
     foldranges = _MakeRanges(foldpairs)
     print "// %d groups, %d pairs, %d ranges" % (len(casegroups), len(foldpairs), len(foldranges))
-    print "const CaseFold unicode_%s[] = {" % (name,)
+    print "CaseFold unicode_%s[] = {" % (name,)
     for lo, hi, delta in foldranges:
       print "\t{ %d, %d, %s }," % (lo, hi, delta)
     print "};"
-    print "const int num_unicode_%s = %d;" % (name, len(foldranges),)
+    print "int num_unicode_%s = %d;" % (name, len(foldranges),)
     print ""
 
   print _header
diff --git a/third_party/re2/re2/make_unicode_groups.py b/third_party/re2/re2/make_unicode_groups.py
index 8499793..c2e25c1 100755
--- a/third_party/re2/re2/make_unicode_groups.py
+++ b/third_party/re2/re2/make_unicode_groups.py
@@ -41,7 +41,7 @@
 
 def PrintRanges(type, name, ranges):
   """Print the ranges as an array of type named name."""
-  print "static const %s %s[] = {" % (type, name,)
+  print "static %s %s[] = {" % (type, name,)
   for lo, hi in ranges:
     print "\t{ %d, %d }," % (lo, hi)
   print "};"
@@ -99,12 +99,12 @@
   for name, codes in unicode.Scripts().iteritems():
     ugroups.append(PrintGroup(name, codes))
   print "// %d 16-bit ranges, %d 32-bit ranges" % (n16, n32)
-  print "const UGroup unicode_groups[] = {";
+  print "UGroup unicode_groups[] = {";
   ugroups.sort()
   for ug in ugroups:
     print "\t%s," % (ug,)
   print "};"
-  print "const int num_unicode_groups = %d;" % (len(ugroups),)
+  print "int num_unicode_groups = %d;" % (len(ugroups),)
   print _trailer
 
 if __name__ == '__main__':
diff --git a/third_party/re2/re2/mimics_pcre.cc b/third_party/re2/re2/mimics_pcre.cc
index 0a55004..fc6dd4a 100644
--- a/third_party/re2/re2/mimics_pcre.cc
+++ b/third_party/re2/re2/mimics_pcre.cc
@@ -124,7 +124,7 @@
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(EmptyStringWalker);
+  DISALLOW_EVIL_CONSTRUCTORS(EmptyStringWalker);
 };
 
 // Called after visiting re's children.  child_args contains the return
diff --git a/third_party/re2/re2/nfa.cc b/third_party/re2/re2/nfa.cc
index bc8996c..8c4f761 100644
--- a/third_party/re2/re2/nfa.cc
+++ b/third_party/re2/re2/nfa.cc
@@ -122,7 +122,7 @@
 
   Thread* free_threads_;  // free list
 
-  DISALLOW_COPY_AND_ASSIGN(NFA);
+  DISALLOW_EVIL_CONSTRUCTORS(NFA);
 };
 
 NFA::NFA(Prog* prog) {
@@ -468,7 +468,7 @@
 
   if (text.begin() > context.begin()) {
     c = text.begin()[-1] & 0xFF;
-    wasword = Prog::IsWordChar(static_cast<uint8>(c));
+    wasword = Prog::IsWordChar(c);
   }
 
   // Loop over the text, stepping the machine.
@@ -529,8 +529,7 @@
             break;
 
           case kInstCapture:
-            if (ip->cap() < ncapture_)
-              match_[ip->cap()] = p;
+            match_[ip->cap()] = p;
             id = ip->out();
             continue;
 
@@ -608,8 +607,7 @@
 
   if (matched_) {
     for (int i = 0; i < nsubmatch; i++)
-      submatch[i].set(match_[2*i],
-                      static_cast<int>(match_[2*i+1] - match_[2*i]));
+      submatch[i].set(match_[2*i], match_[2*i+1] - match_[2*i]);
     if (Debug)
       fprintf(stderr, "match (%d,%d)\n",
               static_cast<int>(match_[0] - btext_),
@@ -707,52 +705,5 @@
   return true;
 }
 
-// For each instruction i in the program reachable from the start, compute the
-// number of instructions reachable from i by following only empty transitions
-// and record that count as fanout[i].
-//
-// fanout holds the results and is also the work queue for the outer iteration.
-// reachable holds the reached nodes for the inner iteration.
-void Prog::Fanout(SparseArray<int>* fanout) {
-  DCHECK_EQ(fanout->max_size(), size());
-  SparseSet reachable(size());
-  fanout->clear();
-  fanout->set_new(start(), 0);
-  for (SparseArray<int>::iterator i = fanout->begin(); i != fanout->end(); ++i) {
-    int* count = &i->second;
-    reachable.clear();
-    reachable.insert(i->index());
-    for (SparseSet::iterator j = reachable.begin(); j != reachable.end(); ++j) {
-      Prog::Inst* ip = inst(*j);
-      switch (ip->opcode()) {
-        default:
-          LOG(DFATAL) << "unhandled " << ip->opcode() << " in Prog::Fanout()";
-          break;
-
-        case kInstByteRange:
-          (*count)++;
-          if (!fanout->has_index(ip->out())) {
-            fanout->set_new(ip->out(), 0);
-          }
-          break;
-
-        case kInstAlt:
-        case kInstAltMatch:
-          reachable.insert(ip->out1());
-          // fall through
-
-        case kInstCapture:
-        case kInstEmptyWidth:
-        case kInstNop:
-          reachable.insert(ip->out());
-          break;
-
-        case kInstMatch:
-        case kInstFail:
-          break;
-      }
-    }
-  }
-}
-
 }  // namespace re2
+
diff --git a/third_party/re2/re2/onepass.cc b/third_party/re2/re2/onepass.cc
index 73acdc8..1c49988 100644
--- a/third_party/re2/re2/onepass.cc
+++ b/third_party/re2/re2/onepass.cc
@@ -53,6 +53,7 @@
 #include <string.h>
 #include <map>
 #include "util/util.h"
+#include "util/arena.h"
 #include "util/sparse_set.h"
 #include "re2/prog.h"
 #include "re2/stringpiece.h"
@@ -125,6 +126,9 @@
 // whether a set of conditions required to finish a match at that
 // point in the input rather than process the next byte.
 
+// A state in the one-pass NFA (aka DFA) - just an array of actions.
+struct OneState;
+
 // A state in the one-pass NFA - just an array of actions indexed
 // by the bytemap_[] of the next input byte.  (The bytemap
 // maps next input bytes into equivalence classes, to reduce
@@ -331,8 +335,7 @@
   if (!matched)
     return false;
   for (int i = 0; i < nmatch; i++)
-    match[i].set(matchcap[2*i],
-                 static_cast<int>(matchcap[2*i+1] - matchcap[2*i]));
+    match[i].set(matchcap[2*i], matchcap[2*i+1] - matchcap[2*i]);
   return true;
 }
 
diff --git a/third_party/re2/re2/parse.cc b/third_party/re2/re2/parse.cc
index cf74f5a1a..0cf4ab4 100644
--- a/third_party/re2/re2/parse.cc
+++ b/third_party/re2/re2/parse.cc
@@ -21,7 +21,6 @@
 #include "re2/stringpiece.h"
 #include "re2/unicode_casefold.h"
 #include "re2/unicode_groups.h"
-#include "re2/walker-inl.h"
 
 namespace re2 {
 
@@ -157,7 +156,7 @@
   int ncap_;  // number of capturing parens seen
   int rune_max_;  // maximum char value for this encoding
 
-  DISALLOW_COPY_AND_ASSIGN(ParseState);
+  DISALLOW_EVIL_CONSTRUCTORS(ParseState);
 };
 
 // Pseudo-operators - only on parse stack.
@@ -215,8 +214,7 @@
   // single characters (e.g., [.] instead of \.), and some
   // analysis does better with fewer character classes.
   // Similarly, [Aa] can be rewritten as a literal A with ASCII case folding.
-  if (re->op_ == kRegexpCharClass && re->ccb_ != NULL) {
-    re->ccb_->RemoveAbove(rune_max_);
+  if (re->op_ == kRegexpCharClass) {
     if (re->ccb_->size() == 1) {
       Rune r = re->ccb_->begin()->lo;
       re->Decref();
@@ -242,8 +240,8 @@
 // Searches the case folding tables and returns the CaseFold* that contains r.
 // If there isn't one, returns the CaseFold* with smallest f->lo bigger than r.
 // If there isn't one, returns NULL.
-const CaseFold* LookupCaseFold(const CaseFold *f, int n, Rune r) {
-  const CaseFold* ef = f + n;
+CaseFold* LookupCaseFold(CaseFold *f, int n, Rune r) {
+  CaseFold* ef = f + n;
 
   // Binary search for entry containing r.
   while (n > 0) {
@@ -270,7 +268,7 @@
 }
 
 // Returns the result of applying the fold f to the rune r.
-Rune ApplyFold(const CaseFold *f, Rune r) {
+Rune ApplyFold(CaseFold *f, Rune r) {
   switch (f->delta) {
     default:
       return r + f->delta;
@@ -306,7 +304,7 @@
 //
 //   CycleFoldRune('?') = '?'
 Rune CycleFoldRune(Rune r) {
-  const CaseFold* f = LookupCaseFold(unicode_casefold, num_unicode_casefold, r);
+  CaseFold* f = LookupCaseFold(unicode_casefold, num_unicode_casefold, r);
   if (f == NULL || r < f->lo)
     return r;
   return ApplyFold(f, r);
@@ -329,7 +327,7 @@
     return;
 
   while (lo <= hi) {
-    const CaseFold* f = LookupCaseFold(unicode_casefold, num_unicode_casefold, lo);
+    CaseFold* f = LookupCaseFold(unicode_casefold, num_unicode_casefold, lo);
     if (f == NULL)  // lo has no fold, nor does anything above lo
       break;
     if (lo < f->lo) {  // lo has no fold; next rune with a fold is f->lo
@@ -379,6 +377,7 @@
       }
       r = CycleFoldRune(r);
     } while (r != r1);
+    re->ccb_->RemoveAbove(rune_max_);
     return PushRegexp(re);
   }
 
@@ -464,59 +463,6 @@
   return true;
 }
 
-// RepetitionWalker reports whether the repetition regexp is valid.
-// Valid means that the combination of the top-level repetition
-// and any inner repetitions does not exceed n copies of the
-// innermost thing.
-// This rewalks the regexp tree and is called for every repetition,
-// so we have to worry about inducing quadratic behavior in the parser.
-// We avoid this by only using RepetitionWalker when min or max >= 2.
-// In that case the depth of any >= 2 nesting can only get to 9 without
-// triggering a parse error, so each subtree can only be rewalked 9 times.
-class RepetitionWalker : public Regexp::Walker<int> {
- public:
-  RepetitionWalker() {}
-  virtual int PreVisit(Regexp* re, int parent_arg, bool* stop);
-  virtual int PostVisit(Regexp* re, int parent_arg, int pre_arg,
-                        int* child_args, int nchild_args);
-  virtual int ShortVisit(Regexp* re, int parent_arg);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(RepetitionWalker);
-};
-
-int RepetitionWalker::PreVisit(Regexp* re, int parent_arg, bool* stop) {
-  int arg = parent_arg;
-  if (re->op() == kRegexpRepeat) {
-    int m = re->max();
-    if (m < 0) {
-      m = re->min();
-    }
-    if (m > 0) {
-      arg /= m;
-    }
-  }
-  return arg;
-}
-
-int RepetitionWalker::PostVisit(Regexp* re, int parent_arg, int pre_arg,
-                                int* child_args, int nchild_args) {
-  int arg = pre_arg;
-  for (int i = 0; i < nchild_args; i++) {
-    if (child_args[i] < arg) {
-      arg = child_args[i];
-    }
-  }
-  return arg;
-}
-
-int RepetitionWalker::ShortVisit(Regexp* re, int parent_arg) {
-  // This should never be called, since we use Walk and not
-  // WalkExponential.
-  LOG(DFATAL) << "RepetitionWalker::ShortVisit called";
-  return 0;
-}
-
 // Pushes a repetition regexp onto the stack.
 // A valid argument for the operator must already be on the stack.
 bool Regexp::ParseState::PushRepetition(int min, int max,
@@ -542,15 +488,8 @@
   re->down_ = stacktop_->down_;
   re->sub()[0] = FinishRegexp(stacktop_);
   re->simple_ = re->ComputeSimple();
+
   stacktop_ = re;
-  if (min >= 2 || max >= 2) {
-    RepetitionWalker w;
-    if (w.Walk(stacktop_, 1000) == 0) {
-      status_->set_code(kRegexpRepeatSize);
-      status_->set_error_arg(s);
-      return false;
-    }
-  }
   return true;
 }
 
@@ -576,6 +515,13 @@
   return PushRegexp(re);
 }
 
+// Adds r to cc, along with r's upper case if foldascii is set.
+static void AddLiteral(CharClassBuilder* cc, Rune r, bool foldascii) {
+  cc->AddRange(r, r);
+  if (foldascii && 'a' <= r && r <= 'z')
+    cc->AddRange(r + 'A' - 'a', r + 'A' - 'a');
+}
+
 // Processes a vertical bar in the input.
 bool Regexp::ParseState::DoVerticalBar() {
   MaybeConcatString(-1, NoParseFlags);
@@ -589,34 +535,46 @@
   Regexp* r1;
   Regexp* r2;
   if ((r1 = stacktop_) != NULL &&
-      (r2 = r1->down_) != NULL &&
+      (r2 = stacktop_->down_) != NULL &&
       r2->op() == kVerticalBar) {
+    // If above and below vertical bar are literal or char class,
+    // can merge into a single char class.
     Regexp* r3;
-    if ((r3 = r2->down_) != NULL &&
-        (r1->op() == kRegexpAnyChar || r3->op() == kRegexpAnyChar)) {
-      // AnyChar is above or below the vertical bar. Let it subsume
-      // the other when the other is Literal, CharClass or AnyChar.
-      if (r3->op() == kRegexpAnyChar &&
-          (r1->op() == kRegexpLiteral ||
-           r1->op() == kRegexpCharClass ||
-           r1->op() == kRegexpAnyChar)) {
-        // Discard r1.
-        stacktop_ = r2;
-        r1->Decref();
-        return true;
-      }
-      if (r1->op() == kRegexpAnyChar &&
-          (r3->op() == kRegexpLiteral ||
-           r3->op() == kRegexpCharClass ||
-           r3->op() == kRegexpAnyChar)) {
-        // Rearrange the stack and discard r3.
-        r1->down_ = r3->down_;
-        r2->down_ = r1;
-        stacktop_ = r2;
-        r3->Decref();
-        return true;
+    if ((r1->op() == kRegexpLiteral ||
+         r1->op() == kRegexpCharClass ||
+         r1->op() == kRegexpAnyChar) &&
+        (r3 = r2->down_) != NULL) {
+      Rune rune;
+      switch (r3->op()) {
+        case kRegexpLiteral:  // convert to char class
+          rune = r3->rune_;
+          r3->op_ = kRegexpCharClass;
+          r3->cc_ = NULL;
+          r3->ccb_ = new CharClassBuilder;
+          AddLiteral(r3->ccb_, rune, r3->parse_flags_ & Regexp::FoldCase);
+          // fall through
+        case kRegexpCharClass:
+          if (r1->op() == kRegexpLiteral)
+            AddLiteral(r3->ccb_, r1->rune_,
+                       r1->parse_flags_ & Regexp::FoldCase);
+          else if (r1->op() == kRegexpCharClass)
+            r3->ccb_->AddCharClass(r1->ccb_);
+          if (r1->op() == kRegexpAnyChar || r3->ccb_->full()) {
+            delete r3->ccb_;
+            r3->ccb_ = NULL;
+            r3->op_ = kRegexpAnyChar;
+          }
+          // fall through
+        case kRegexpAnyChar:
+          // pop r1
+          stacktop_ = r2;
+          r1->Decref();
+          return true;
+        default:
+          break;
       }
     }
+
     // Swap r1 below vertical bar (r2).
     r1->down_ = r2->down_;
     r2->down_ = r1;
@@ -1147,7 +1105,7 @@
   if (r >= 0) {
     re1->op_ = kRegexpLiteral;
     re1->rune_ = r;
-    re1->parse_flags_ = static_cast<uint16>(flags);
+    re1->parse_flags_ = flags;
     return true;
   }
 
@@ -1230,14 +1188,6 @@
   int n;
   if (fullrune(sp->data(), sp->size())) {
     n = chartorune(r, sp->data());
-    // Some copies of chartorune have a bug that accepts
-    // encodings of values in (10FFFF, 1FFFFF] as valid.
-    // Those values break the character class algorithm,
-    // which assumes Runemax is the largest rune.
-    if (*r > Runemax) {
-      n = 1;
-      *r = Runeerror;
-    }
     if (!(n == 1 && *r == Runeerror)) {  // no decoding error
       sp->remove_prefix(n);
       return n;
@@ -1340,8 +1290,6 @@
           }
         }
       }
-      if (code > rune_max)
-        goto BadEscape;
       *rp = code;
       return true;
 
@@ -1427,8 +1375,7 @@
 BadEscape:
   // Unrecognized escape sequence.
   status->set_code(kRegexpBadEscape);
-  status->set_error_arg(
-      StringPiece(begin, static_cast<int>(s->data() - begin)));
+  status->set_error_arg(StringPiece(begin, s->data() - begin));
   return false;
 }
 
@@ -1456,8 +1403,8 @@
 }
 
 // Look for a group with the given name.
-static const UGroup* LookupGroup(const StringPiece& name,
-                                 const UGroup *groups, int ngroups) {
+static UGroup* LookupGroup(const StringPiece& name,
+                           UGroup *groups, int ngroups) {
   // Simple name lookup.
   for (int i = 0; i < ngroups; i++)
     if (StringPiece(groups[i].name) == name)
@@ -1471,16 +1418,16 @@
 static UGroup anygroup = { "Any", +1, any16, 1, any32, 1 };
 
 // Look for a POSIX group with the given name (e.g., "[:^alpha:]")
-static const UGroup* LookupPosixGroup(const StringPiece& name) {
+static UGroup* LookupPosixGroup(const StringPiece& name) {
   return LookupGroup(name, posix_groups, num_posix_groups);
 }
 
-static const UGroup* LookupPerlGroup(const StringPiece& name) {
+static UGroup* LookupPerlGroup(const StringPiece& name) {
   return LookupGroup(name, perl_groups, num_perl_groups);
 }
 
 // Look for a Unicode group with the given name (e.g., "Han")
-static const UGroup* LookupUnicodeGroup(const StringPiece& name) {
+static UGroup* LookupUnicodeGroup(const StringPiece& name) {
   // Special case: "Any" means any.
   if (name == StringPiece("Any"))
     return &anygroup;
@@ -1488,7 +1435,7 @@
 }
 
 // Add a UGroup or its negation to the character class.
-static void AddUGroup(CharClassBuilder *cc, const UGroup *g, int sign,
+static void AddUGroup(CharClassBuilder *cc, UGroup *g, int sign,
                       Regexp::ParseFlags parse_flags) {
   if (sign == +1) {
     for (int i = 0; i < g->nr16; i++) {
@@ -1539,7 +1486,7 @@
 // On success, sets *s to span the remainder of the string
 // and returns the corresponding UGroup.
 // The StringPiece must *NOT* be edited unless the call succeeds.
-const UGroup* MaybeParsePerlCCEscape(StringPiece* s, Regexp::ParseFlags parse_flags) {
+UGroup* MaybeParsePerlCCEscape(StringPiece* s, Regexp::ParseFlags parse_flags) {
   if (!(parse_flags & Regexp::PerlClasses))
     return NULL;
   if (s->size() < 2 || (*s)[0] != '\\')
@@ -1547,7 +1494,7 @@
   // Could use StringPieceToRune, but there aren't
   // any non-ASCII Perl group names.
   StringPiece name(s->begin(), 2);
-  const UGroup *g = LookupPerlGroup(name);
+  UGroup *g = LookupPerlGroup(name);
   if (g == NULL)
     return NULL;
   s->remove_prefix(name.size());
@@ -1587,10 +1534,10 @@
   if (c != '{') {
     // Name is the bit of string we just skipped over for c.
     const char* p = seq.begin() + 2;
-    name = StringPiece(p, static_cast<int>(s->begin() - p));
+    name = StringPiece(p, s->begin() - p);
   } else {
     // Name is in braces. Look for closing }
-    size_t end = s->find('}', 0);
+    int end = s->find('}', 0);
     if (end == s->npos) {
       if (!IsValidUTF8(seq, status))
         return kParseError;
@@ -1598,21 +1545,21 @@
       status->set_error_arg(seq);
       return kParseError;
     }
-    name = StringPiece(s->begin(), static_cast<int>(end));  // without '}'
-    s->remove_prefix(static_cast<int>(end) + 1);  // with '}'
+    name = StringPiece(s->begin(), end);  // without '}'
+    s->remove_prefix(end + 1);  // with '}'
     if (!IsValidUTF8(name, status))
       return kParseError;
   }
 
   // Chop seq where s now begins.
-  seq = StringPiece(seq.begin(), static_cast<int>(s->begin() - seq.begin()));
+  seq = StringPiece(seq.begin(), s->begin() - seq.begin());
 
   // Look up group
   if (name.size() > 0 && name[0] == '^') {
     sign = -sign;
     name.remove_prefix(1);  // '^'
   }
-  const UGroup *g = LookupUnicodeGroup(name);
+  UGroup *g = LookupUnicodeGroup(name);
   if (g == NULL) {
     status->set_code(kRegexpBadCharRange);
     status->set_error_arg(seq);
@@ -1646,9 +1593,9 @@
 
   // Got it.  Check that it's valid.
   q += 2;
-  StringPiece name(p, static_cast<int>(q-p));
+  StringPiece name(p, q-p);
 
-  const UGroup *g = LookupPosixGroup(name);
+  UGroup *g = LookupPosixGroup(name);
   if (g == NULL) {
     status->set_code(kRegexpBadCharRange);
     status->set_error_arg(name);
@@ -1700,8 +1647,7 @@
       return false;
     if (rr->hi < rr->lo) {
       status->set_code(kRegexpBadCharRange);
-      status->set_error_arg(
-          StringPiece(os.data(), static_cast<int>(s->data() - os.data())));
+      status->set_error_arg(StringPiece(os.data(), s->data() - os.data()));
       return false;
     }
   } else {
@@ -1786,7 +1732,7 @@
     }
 
     // Look for Perl character class symbols (extension).
-    const UGroup *g = MaybeParsePerlCCEscape(s, flags_);
+    UGroup *g = MaybeParsePerlCCEscape(s, flags_);
     if (g != NULL) {
       AddUGroup(re->ccb_, g, g->sign, flags_);
       continue;
@@ -1815,6 +1761,7 @@
 
   if (negated)
     re->ccb_->Negate();
+  re->ccb_->RemoveAbove(rune_max_);
 
   *out_re = re;
   return true;
@@ -1873,7 +1820,7 @@
   // so that's the one we implement.  One is enough.
   if (t.size() > 2 && t[0] == 'P' && t[1] == '<') {
     // Pull out name.
-    size_t end = t.find('>', 2);
+    int end = t.find('>', 2);
     if (end == t.npos) {
       if (!IsValidUTF8(*s, status_))
         return false;
@@ -1883,8 +1830,8 @@
     }
 
     // t is "P<name>...", t[end] == '>'
-    StringPiece capture(t.begin()-2, static_cast<int>(end)+3);  // "(?P<name>"
-    StringPiece name(t.begin()+2, static_cast<int>(end)-2);     // "name"
+    StringPiece capture(t.begin()-2, end+3);  // "(?P<name>"
+    StringPiece name(t.begin()+2, end-2);     // "name"
     if (!IsValidUTF8(name, status_))
       return false;
     if (!IsValidCaptureName(name)) {
@@ -1898,7 +1845,7 @@
       return false;
     }
 
-    s->remove_prefix(static_cast<int>(capture.end() - s->begin()));
+    s->remove_prefix(capture.end() - s->begin());
     return true;
   }
 
@@ -1981,8 +1928,7 @@
 
 BadPerlOp:
   status_->set_code(kRegexpBadPerlOp);
-  status_->set_error_arg(
-      StringPiece(s->begin(), static_cast<int>(t.begin() - s->begin())));
+  status_->set_error_arg(StringPiece(s->begin(), t.begin() - s->begin()));
   return false;
 }
 
@@ -2129,13 +2075,12 @@
             //   a** is a syntax error, not a double-star.
             // (and a++ means something else entirely, which we don't support!)
             status->set_code(kRegexpRepeatOp);
-            status->set_error_arg(
-                StringPiece(lastunary.begin(),
-                            static_cast<int>(t.begin() - lastunary.begin())));
+            status->set_error_arg(StringPiece(lastunary.begin(),
+                                              t.begin() - lastunary.begin()));
             return NULL;
           }
         }
-        opstr.set(opstr.data(), static_cast<int>(t.data() - opstr.data()));
+        opstr.set(opstr.data(), t.data() - opstr.data());
         if (!ps.PushRepeatOp(op, opstr, nongreedy))
           return NULL;
         isunary = opstr;
@@ -2161,13 +2106,12 @@
           if (lastunary.size() > 0) {
             // Not allowed to stack repetition operators.
             status->set_code(kRegexpRepeatOp);
-            status->set_error_arg(
-                StringPiece(lastunary.begin(),
-                            static_cast<int>(t.begin() - lastunary.begin())));
+            status->set_error_arg(StringPiece(lastunary.begin(),
+                                              t.begin() - lastunary.begin()));
             return NULL;
           }
         }
-        opstr.set(opstr.data(), static_cast<int>(t.data() - opstr.data()));
+        opstr.set(opstr.data(), t.data() - opstr.data());
         if (!ps.PushRepetition(lo, hi, opstr, nongreedy))
           return NULL;
         isunary = opstr;
@@ -2243,7 +2187,7 @@
           }
         }
 
-        const UGroup *g = MaybeParsePerlCCEscape(&t, ps.flags());
+        UGroup *g = MaybeParsePerlCCEscape(&t, ps.flags());
         if (g != NULL) {
           Regexp* re = new Regexp(kRegexpCharClass, ps.flags() & ~FoldCase);
           re->ccb_ = new CharClassBuilder;
diff --git a/third_party/re2/re2/perl_groups.cc b/third_party/re2/re2/perl_groups.cc
index 422b388..1af5b43 100644
--- a/third_party/re2/re2/perl_groups.cc
+++ b/third_party/re2/re2/perl_groups.cc
@@ -5,21 +5,21 @@
 
 namespace re2 {
 
-static const URange16 code1[] = {  /* \d */
+static URange16 code1[] = {  /* \d */
 	{ 0x30, 0x39 },
 };
-static const URange16 code2[] = {  /* \s */
+static URange16 code2[] = {  /* \s */
 	{ 0x9, 0xa },
 	{ 0xc, 0xd },
 	{ 0x20, 0x20 },
 };
-static const URange16 code3[] = {  /* \w */
+static URange16 code3[] = {  /* \w */
 	{ 0x30, 0x39 },
 	{ 0x41, 0x5a },
 	{ 0x5f, 0x5f },
 	{ 0x61, 0x7a },
 };
-const UGroup perl_groups[] = {
+UGroup perl_groups[] = {
 	{ "\\d", +1, code1, 1 },
 	{ "\\D", -1, code1, 1 },
 	{ "\\s", +1, code2, 3 },
@@ -27,64 +27,64 @@
 	{ "\\w", +1, code3, 4 },
 	{ "\\W", -1, code3, 4 },
 };
-const int num_perl_groups = 6;
-static const URange16 code4[] = {  /* [:alnum:] */
+int num_perl_groups = 6;
+static URange16 code4[] = {  /* [:alnum:] */
 	{ 0x30, 0x39 },
 	{ 0x41, 0x5a },
 	{ 0x61, 0x7a },
 };
-static const URange16 code5[] = {  /* [:alpha:] */
+static URange16 code5[] = {  /* [:alpha:] */
 	{ 0x41, 0x5a },
 	{ 0x61, 0x7a },
 };
-static const URange16 code6[] = {  /* [:ascii:] */
+static URange16 code6[] = {  /* [:ascii:] */
 	{ 0x0, 0x7f },
 };
-static const URange16 code7[] = {  /* [:blank:] */
+static URange16 code7[] = {  /* [:blank:] */
 	{ 0x9, 0x9 },
 	{ 0x20, 0x20 },
 };
-static const URange16 code8[] = {  /* [:cntrl:] */
+static URange16 code8[] = {  /* [:cntrl:] */
 	{ 0x0, 0x1f },
 	{ 0x7f, 0x7f },
 };
-static const URange16 code9[] = {  /* [:digit:] */
+static URange16 code9[] = {  /* [:digit:] */
 	{ 0x30, 0x39 },
 };
-static const URange16 code10[] = {  /* [:graph:] */
+static URange16 code10[] = {  /* [:graph:] */
 	{ 0x21, 0x7e },
 };
-static const URange16 code11[] = {  /* [:lower:] */
+static URange16 code11[] = {  /* [:lower:] */
 	{ 0x61, 0x7a },
 };
-static const URange16 code12[] = {  /* [:print:] */
+static URange16 code12[] = {  /* [:print:] */
 	{ 0x20, 0x7e },
 };
-static const URange16 code13[] = {  /* [:punct:] */
+static URange16 code13[] = {  /* [:punct:] */
 	{ 0x21, 0x2f },
 	{ 0x3a, 0x40 },
 	{ 0x5b, 0x60 },
 	{ 0x7b, 0x7e },
 };
-static const URange16 code14[] = {  /* [:space:] */
+static URange16 code14[] = {  /* [:space:] */
 	{ 0x9, 0xd },
 	{ 0x20, 0x20 },
 };
-static const URange16 code15[] = {  /* [:upper:] */
+static URange16 code15[] = {  /* [:upper:] */
 	{ 0x41, 0x5a },
 };
-static const URange16 code16[] = {  /* [:word:] */
+static URange16 code16[] = {  /* [:word:] */
 	{ 0x30, 0x39 },
 	{ 0x41, 0x5a },
 	{ 0x5f, 0x5f },
 	{ 0x61, 0x7a },
 };
-static const URange16 code17[] = {  /* [:xdigit:] */
+static URange16 code17[] = {  /* [:xdigit:] */
 	{ 0x30, 0x39 },
 	{ 0x41, 0x46 },
 	{ 0x61, 0x66 },
 };
-const UGroup posix_groups[] = {
+UGroup posix_groups[] = {
 	{ "[:alnum:]", +1, code4, 3 },
 	{ "[:^alnum:]", -1, code4, 3 },
 	{ "[:alpha:]", +1, code5, 2 },
@@ -114,6 +114,6 @@
 	{ "[:xdigit:]", +1, code17, 3 },
 	{ "[:^xdigit:]", -1, code17, 3 },
 };
-const int num_posix_groups = 28;
+int num_posix_groups = 28;
 
 }  // namespace re2
diff --git a/third_party/re2/re2/prefilter.cc b/third_party/re2/re2/prefilter.cc
index 45e43c9..77e0cbd 100644
--- a/third_party/re2/re2/prefilter.cc
+++ b/third_party/re2/re2/prefilter.cc
@@ -15,7 +15,6 @@
 typedef set<string>::iterator SSIter;
 typedef set<string>::const_iterator ConstSSIter;
 
-GLOBAL_MUTEX(alloc_id_mutex);
 static int alloc_id = 100000;  // Used for debugging.
 // Initializes a Prefilter, allocating subs_ as necessary.
 Prefilter::Prefilter(Op op) {
@@ -24,9 +23,7 @@
   if (op_ == AND || op_ == OR)
     subs_ = new vector<Prefilter*>;
 
-  GLOBAL_MUTEX_LOCK(alloc_id_mutex);
   alloc_id_ = alloc_id++;
-  GLOBAL_MUTEX_UNLOCK(alloc_id_mutex);
   VLOG(10) << "alloc_id: " << alloc_id_;
 }
 
@@ -34,7 +31,7 @@
 Prefilter::~Prefilter() {
   VLOG(10) << "Deleted: " << alloc_id_;
   if (subs_) {
-    for (size_t i = 0; i < subs_->size(); i++)
+    for (int i = 0; i < subs_->size(); i++)
       delete (*subs_)[i];
     delete subs_;
     subs_ = NULL;
@@ -103,7 +100,7 @@
 
   // If a and b match op, merge their contents.
   if (a->op() == op && b->op() == op) {
-    for (size_t i = 0; i < b->subs()->size(); i++) {
+    for (int i = 0; i < b->subs()->size(); i++) {
       Prefilter* bb = (*b->subs())[i];
       a->subs()->push_back(bb);
     }
@@ -178,7 +175,7 @@
     return r;
   }
 
-  const CaseFold *f = LookupCaseFold(unicode_tolower, num_unicode_tolower, r);
+  CaseFold *f = LookupCaseFold(unicode_tolower, num_unicode_tolower, r);
   if (f == NULL || r < f->lo)
     return r;
   return ApplyFold(f, r);
@@ -495,7 +492,7 @@
   bool latin1() { return latin1_; }
  private:
   bool latin1_;
-  DISALLOW_COPY_AND_ASSIGN(Walker);
+  DISALLOW_EVIL_CONSTRUCTORS(Walker);
 };
 
 Prefilter::Info* Prefilter::BuildInfo(Regexp* re) {
@@ -503,7 +500,7 @@
     LOG(INFO) << "BuildPrefilter::Info: " << re->ToString();
   }
 
-  bool latin1 = (re->parse_flags() & Regexp::Latin1) != 0;
+  bool latin1 = re->parse_flags() & Regexp::Latin1;
   Prefilter::Info::Walker w(latin1);
   Prefilter::Info* info = w.WalkExponential(re, NULL, 100000);
 
@@ -672,7 +669,7 @@
       return "";
     case AND: {
       string s = "";
-      for (size_t i = 0; i < subs_->size(); i++) {
+      for (int i = 0; i < subs_->size(); i++) {
         if (i > 0)
           s += " ";
         Prefilter* sub = (*subs_)[i];
@@ -682,7 +679,7 @@
     }
     case OR: {
       string s = "(";
-      for (size_t i = 0; i < subs_->size(); i++) {
+      for (int i = 0; i < subs_->size(); i++) {
         if (i > 0)
           s += "|";
         Prefilter* sub = (*subs_)[i];
diff --git a/third_party/re2/re2/prefilter.h b/third_party/re2/re2/prefilter.h
index 2bc1676..c2f9dddd 100644
--- a/third_party/re2/re2/prefilter.h
+++ b/third_party/re2/re2/prefilter.h
@@ -97,7 +97,7 @@
   // Used for debugging, helps in tracking memory leaks.
   int alloc_id_;
 
-  DISALLOW_COPY_AND_ASSIGN(Prefilter);
+  DISALLOW_EVIL_CONSTRUCTORS(Prefilter);
 };
 
 }  // namespace re2
diff --git a/third_party/re2/re2/prefilter_tree.cc b/third_party/re2/re2/prefilter_tree.cc
index be9b5844..e5c465b 100644
--- a/third_party/re2/re2/prefilter_tree.cc
+++ b/third_party/re2/re2/prefilter_tree.cc
@@ -8,6 +8,11 @@
 #include "re2/prefilter_tree.h"
 #include "re2/re2.h"
 
+#ifdef WIN32
+#include <stdio.h>
+#define snprintf _snprintf
+#endif
+
 DEFINE_int32(filtered_re2_min_atom_len,
              3,
              "Strings less than this length are not stored as atoms");
@@ -19,10 +24,10 @@
 }
 
 PrefilterTree::~PrefilterTree() {
-  for (size_t i = 0; i < prefilter_vec_.size(); i++)
+  for (int i = 0; i < prefilter_vec_.size(); i++)
     delete prefilter_vec_[i];
 
-  for (size_t i = 0; i < entries_.size(); i++)
+  for (int i = 0; i < entries_.size(); i++)
     delete entries_[i].parents;
 }
 
@@ -43,12 +48,12 @@
 
     case Prefilter::ATOM:
       return prefilter->atom().size() >=
-          static_cast<size_t>(FLAGS_filtered_re2_min_atom_len);
+          FLAGS_filtered_re2_min_atom_len;
 
     case Prefilter::AND: {
       int j = 0;
       vector<Prefilter*>* subs = prefilter->subs();
-      for (size_t i = 0; i < subs->size(); i++)
+      for (int i = 0; i < subs->size(); i++)
         if (KeepPart((*subs)[i], level + 1))
           (*subs)[j++] = (*subs)[i];
         else
@@ -59,7 +64,7 @@
     }
 
     case Prefilter::OR:
-      for (size_t i = 0; i < prefilter->subs()->size(); i++)
+      for (int i = 0; i < prefilter->subs()->size(); i++)
         if (!KeepPart((*prefilter->subs())[i], level + 1))
           return false;
       return true;
@@ -101,7 +106,7 @@
   // no longer necessary for their parent to trigger; that is, we do
   // not miss out on any regexps triggering by getting rid of a
   // prefilter node.
-  for (size_t i = 0; i < entries_.size(); i++) {
+  for (int i = 0; i < entries_.size(); i++) {
     StdIntMap* parents = entries_[i].parents;
     if (parents->size() > 8) {
       // This one triggers too many things. If all the parents are AND
@@ -148,7 +153,7 @@
   if (node->op() == Prefilter::ATOM) {
     s += node->atom();
   } else {
-    for (size_t i = 0; i < node->subs()->size(); i++) {
+    for (int i = 0; i < node->subs()->size() ; i++) {
       if (i > 0)
         s += ',';
       s += Itoa((*node->subs())[i]->unique_id());
@@ -165,10 +170,10 @@
   vector<Prefilter*> v;
 
   // Add the top level nodes of each regexp prefilter.
-  for (size_t i = 0; i < prefilter_vec_.size(); i++) {
+  for (int i = 0; i < prefilter_vec_.size(); i++) {
     Prefilter* f = prefilter_vec_[i];
     if (f == NULL)
-      unfiltered_.push_back(static_cast<int>(i));
+      unfiltered_.push_back(i);
 
     // We push NULL also on to v, so that we maintain the
     // mapping of index==regexpid for level=0 prefilter nodes.
@@ -176,20 +181,20 @@
   }
 
   // Now add all the descendant nodes.
-  for (size_t i = 0; i < v.size(); i++) {
+  for (int i = 0; i < v.size(); i++) {
     Prefilter* f = v[i];
     if (f == NULL)
       continue;
     if (f->op() == Prefilter::AND || f->op() == Prefilter::OR) {
       const vector<Prefilter*>& subs = *f->subs();
-      for (size_t j = 0; j < subs.size(); j++)
+      for (int j = 0; j < subs.size(); j++)
         v.push_back(subs[j]);
     }
   }
 
   // Identify unique nodes.
   int unique_id = 0;
-  for (int i = static_cast<int>(v.size()) - 1; i >= 0; i--) {
+  for (int i = v.size() - 1; i >= 0; i--) {
     Prefilter *node = v[i];
     if (node == NULL)
       continue;
@@ -211,7 +216,7 @@
   entries_.resize(node_map_.size());
 
   // Create parent StdIntMap for the entries.
-  for (int i = static_cast<int>(v.size()) - 1; i >= 0; i--) {
+  for (int i = v.size()  - 1; i >= 0; i--) {
     Prefilter* prefilter = v[i];
     if (prefilter == NULL)
       continue;
@@ -224,7 +229,7 @@
   }
 
   // Fill the entries.
-  for (int i = static_cast<int>(v.size()) - 1; i >= 0; i--) {
+  for (int i = v.size()  - 1; i >= 0; i--) {
     Prefilter* prefilter = v[i];
     if (prefilter == NULL)
       continue;
@@ -246,8 +251,8 @@
 
       case Prefilter::OR:
       case Prefilter::AND: {
-        set<int> uniq_child;
-        for (size_t j = 0; j < prefilter->subs()->size(); j++) {
+        std::set<int> uniq_child;
+        for (int j = 0; j < prefilter->subs()->size() ; j++) {
           Prefilter* child = (*prefilter->subs())[j];
           Prefilter* canonical = CanonicalNode(child);
           if (canonical == NULL) {
@@ -259,13 +264,11 @@
           // To the child, we want to add to parent indices.
           Entry* child_entry = &entries_[child_id];
           if (child_entry->parents->find(prefilter->unique_id()) ==
-              child_entry->parents->end()) {
+              child_entry->parents->end())
             (*child_entry->parents)[prefilter->unique_id()] = 1;
-          }
         }
-        entry->propagate_up_at_count = prefilter->op() == Prefilter::AND
-                                           ? static_cast<int>(uniq_child.size())
-                                           : 1;
+        entry->propagate_up_at_count =
+            prefilter->op() == Prefilter::AND ? uniq_child.size() : 1;
 
         break;
       }
@@ -273,13 +276,13 @@
   }
 
   // For top level nodes, populate regexp id.
-  for (size_t i = 0; i < prefilter_vec_.size(); i++) {
+  for (int i = 0; i < prefilter_vec_.size(); i++) {
     if (prefilter_vec_[i] == NULL)
       continue;
     int id = CanonicalNode(prefilter_vec_[i])->unique_id();
     DCHECK_LE(0, id);
     Entry* entry = &entries_[id];
-    entry->regexps.push_back(static_cast<int>(i));
+    entry->regexps.push_back(i);
   }
 }
 
@@ -290,13 +293,13 @@
   regexps->clear();
   if (!compiled_) {
     LOG(WARNING) << "Compile() not called";
-    for (size_t i = 0; i < prefilter_vec_.size(); ++i)
-      regexps->push_back(static_cast<int>(i));
+    for (int i = 0; i < prefilter_vec_.size(); ++i)
+      regexps->push_back(i);
   } else {
     if (!prefilter_vec_.empty()) {
-      IntMap regexps_map(static_cast<int>(prefilter_vec_.size()));
+      IntMap regexps_map(prefilter_vec_.size());
       vector<int> matched_atom_ids;
-      for (size_t j = 0; j < matched_atoms.size(); j++) {
+      for (int j = 0; j < matched_atoms.size(); j++) {
         matched_atom_ids.push_back(atom_index_to_id_[matched_atoms[j]]);
         VLOG(10) << "Atom id:" << atom_index_to_id_[matched_atoms[j]];
       }
@@ -314,15 +317,15 @@
 
 void PrefilterTree::PropagateMatch(const vector<int>& atom_ids,
                                    IntMap* regexps) const {
-  IntMap count(static_cast<int>(entries_.size()));
-  IntMap work(static_cast<int>(entries_.size()));
-  for (size_t i = 0; i < atom_ids.size(); i++)
+  IntMap count(entries_.size());
+  IntMap work(entries_.size());
+  for (int i = 0; i < atom_ids.size(); i++)
     work.set(atom_ids[i], 1);
   for (IntMap::iterator it = work.begin(); it != work.end(); ++it) {
     const Entry& entry = entries_[it->index()];
     VLOG(10) << "Processing: " << it->index();
     // Record regexps triggered.
-    for (size_t i = 0; i < entry.regexps.size(); i++) {
+    for (int i = 0; i < entry.regexps.size(); i++) {
       VLOG(10) << "Regexp triggered: " << entry.regexps[i];
       regexps->set(entry.regexps[i], 1);
     }
@@ -362,7 +365,7 @@
   VLOG(10) << "#Unique Atoms: " << atom_index_to_id_.size();
   VLOG(10) << "#Unique Nodes: " << entries_.size();
 
-  for (size_t i = 0; i < entries_.size(); ++i) {
+  for (int i = 0; i < entries_.size(); ++i) {
     StdIntMap* parents = entries_[i].parents;
     const vector<int>& regexps = entries_[i].regexps;
     VLOG(10) << "EntryId: " << i
@@ -387,7 +390,7 @@
     // Adding the operation disambiguates AND and OR nodes.
     node_string +=  node->op() == Prefilter::AND ? "AND" : "OR";
     node_string += "(";
-    for (size_t i = 0; i < node->subs()->size(); i++) {
+    for (int i = 0; i < node->subs()->size() ; i++) {
       if (i > 0)
         node_string += ',';
       node_string += Itoa((*node->subs())[i]->unique_id());
diff --git a/third_party/re2/re2/prefilter_tree.h b/third_party/re2/re2/prefilter_tree.h
index abea55d..94eb183 100644
--- a/third_party/re2/re2/prefilter_tree.h
+++ b/third_party/re2/re2/prefilter_tree.h
@@ -16,13 +16,15 @@
 #ifndef RE2_PREFILTER_TREE_H_
 #define RE2_PREFILTER_TREE_H_
 
+#include <map>
+
 #include "util/util.h"
 #include "util/sparse_array.h"
 
 namespace re2 {
 
 typedef SparseArray<int> IntMap;
-typedef map<int, int> StdIntMap;
+typedef std::map<int, int> StdIntMap;
 
 class Prefilter;
 
@@ -123,7 +125,7 @@
   // Has the prefilter tree been compiled.
   bool compiled_;
 
-  DISALLOW_COPY_AND_ASSIGN(PrefilterTree);
+  DISALLOW_EVIL_CONSTRUCTORS(PrefilterTree);
 };
 
 }  // namespace
diff --git a/third_party/re2/re2/prog.cc b/third_party/re2/re2/prog.cc
index 499f560..ef9ef23 100644
--- a/third_party/re2/re2/prog.cc
+++ b/third_party/re2/re2/prog.cc
@@ -25,7 +25,7 @@
   set_out_opcode(out, kInstByteRange);
   lo_ = lo & 0xFF;
   hi_ = hi & 0xFF;
-  foldcase_ = foldcase & 0xFF;
+  foldcase_ = foldcase;
 }
 
 void Prog::Inst::InitCapture(int cap, uint32 out) {
@@ -295,15 +295,13 @@
 }
 
 void Prog::MarkByteRange(int lo, int hi) {
-  DCHECK_GE(lo, 0);
-  DCHECK_GE(hi, 0);
-  DCHECK_LE(lo, 255);
-  DCHECK_LE(hi, 255);
-  DCHECK_LE(lo, hi);
-  if (0 < lo && lo <= 255)
+  CHECK_GE(lo, 0);
+  CHECK_GE(hi, 0);
+  CHECK_LE(lo, 255);
+  CHECK_LE(hi, 255);
+  if (lo > 0)
     byterange_.Set(lo - 1);
-  if (0 <= hi && hi <= 255)
-    byterange_.Set(hi);
+  byterange_.Set(hi);
 }
 
 void Prog::ComputeByteMap() {
@@ -327,12 +325,12 @@
   bytemap_range_ = bytemap_[255] + 1;
   unbytemap_ = new uint8[bytemap_range_];
   for (int i = 0; i < 256; i++)
-    unbytemap_[bytemap_[i]] = static_cast<uint8>(i);
+    unbytemap_[bytemap_[i]] = i;
 
   if (0) {  // For debugging: use trivial byte map.
     for (int i = 0; i < 256; i++) {
-      bytemap_[i] = static_cast<uint8>(i);
-      unbytemap_[i] = static_cast<uint8>(i);
+      bytemap_[i] = i;
+      unbytemap_[i] = i;
     }
     bytemap_range_ = 256;
     LOG(INFO) << "Using trivial bytemap.";
diff --git a/third_party/re2/re2/prog.h b/third_party/re2/re2/prog.h
index 8c5b2c4..2cf65bc7 100644
--- a/third_party/re2/re2/prog.h
+++ b/third_party/re2/re2/prog.h
@@ -10,7 +10,6 @@
 #define RE2_PROG_H__
 
 #include "util/util.h"
-#include "util/sparse_array.h"
 #include "re2/re2.h"
 
 namespace re2 {
@@ -43,7 +42,7 @@
   static const int WordLog = 5;
   static const int Words = (Bits+31)/32;
   uint32 w_[Words];
-  DISALLOW_COPY_AND_ASSIGN(Bitmap);
+  DISALLOW_EVIL_CONSTRUCTORS(Bitmap);
 };
 
 
@@ -96,7 +95,7 @@
     void InitFail();
 
     // Getters
-    int id(Prog* p) { return static_cast<int>(this - p->inst_); }
+    int id(Prog* p) { return this - p->inst_; }
     InstOp opcode() { return static_cast<InstOp>(out_opcode_&7); }
     int out()     { return out_opcode_>>3; }
     int out1()    { DCHECK(opcode() == kInstAlt || opcode() == kInstAltMatch); return out1_; }
@@ -168,7 +167,7 @@
     friend struct PatchList;
     friend class Prog;
 
-    DISALLOW_COPY_AND_ASSIGN(Inst);
+    DISALLOW_EVIL_CONSTRUCTORS(Inst);
   };
 
   // Whether to anchor the search.
@@ -201,10 +200,10 @@
   int start_unanchored() { return start_unanchored_; }
   void set_start(int start) { start_ = start; }
   void set_start_unanchored(int start) { start_unanchored_ = start; }
-  int size() { return size_; }
+  int64 size() { return size_; }
   bool reversed() { return reversed_; }
   void set_reversed(bool reversed) { reversed_ = reversed; }
-  int byte_inst_count() { return byte_inst_count_; }
+  int64 byte_inst_count() { return byte_inst_count_; }
   const Bitmap<256>& byterange() { return byterange_; }
   void set_dfa_mem(int64 dfa_mem) { dfa_mem_ = dfa_mem; }
   int64 dfa_mem() { return dfa_mem_; }
@@ -330,10 +329,6 @@
   // Returns true on success, false on error.
   bool PossibleMatchRange(string* min, string* max, int maxlen);
 
-  // EXPERIMENTAL! SUBJECT TO CHANGE!
-  // Outputs the program fanout into the given sparse array.
-  void Fanout(SparseArray<int>* fanout);
-
   // Compiles a collection of regexps to Prog.  Each regexp will have
   // its own Match instruction recording the index in the vector.
   static Prog* CompileSet(const RE2::Options& options, RE2::Anchor anchor,
@@ -373,7 +368,7 @@
   uint8* onepass_nodes_;     // data for OnePass nodes
   OneState* onepass_start_;  // start node for OnePass program
 
-  DISALLOW_COPY_AND_ASSIGN(Prog);
+  DISALLOW_EVIL_CONSTRUCTORS(Prog);
 };
 
 }  // namespace re2
diff --git a/third_party/re2/re2/re2.cc b/third_party/re2/re2/re2.cc
index b3e582f..b9e44fc 100644
--- a/third_party/re2/re2/re2.cc
+++ b/third_party/re2/re2/re2.cc
@@ -11,10 +11,16 @@
 
 #include <stdio.h>
 #include <string>
+#ifdef WIN32
+#define strtoll _strtoi64
+#define strtoull _strtoui64
+#define strtof strtod
+#else
+#include <pthread.h>
+#endif
 #include <errno.h>
 #include "util/util.h"
 #include "util/flags.h"
-#include "util/sparse_array.h"
 #include "re2/prog.h"
 #include "re2/regexp.h"
 
@@ -31,10 +37,22 @@
 const VariadicFunction2<bool, StringPiece*, const RE2&, RE2::Arg, RE2::ConsumeN> RE2::Consume = {};
 const VariadicFunction2<bool, StringPiece*, const RE2&, RE2::Arg, RE2::FindAndConsumeN> RE2::FindAndConsume = {};
 
-// This will trigger LNK2005 error in MSVC.
-#ifndef _MSC_VER
-const int RE2::Options::kDefaultMaxMem;  // initialized in re2.h
-#endif
+#define kDefaultMaxMem (8<<20)
+
+RE2::Options::Options()
+  :  encoding_(EncodingUTF8),
+     posix_syntax_(false),
+     longest_match_(false),
+     log_errors_(true),
+     max_mem_(kDefaultMaxMem),
+     literal_(false),
+     never_nl_(false),
+     never_capture_(false),
+     case_sensitive_(true),
+     perl_classes_(false),
+     word_boundary_(false),
+     one_line_(false) {
+}
 
 RE2::Options::Options(RE2::CannedOptions opt)
   : encoding_(opt == RE2::Latin1 ? EncodingLatin1 : EncodingUTF8),
@@ -44,7 +62,6 @@
     max_mem_(kDefaultMaxMem),
     literal_(false),
     never_nl_(false),
-    dot_nl_(false),
     never_capture_(false),
     case_sensitive_(true),
     perl_classes_(false),
@@ -152,9 +169,6 @@
   if (never_nl())
     flags |= Regexp::NeverNL;
 
-  if (dot_nl())
-    flags |= Regexp::DotNL;
-
   if (never_capture())
     flags |= Regexp::NeverCapture;
 
@@ -271,36 +285,8 @@
   return prog_->size();
 }
 
-int RE2::ProgramFanout(map<int, int>* histogram) const {
-  if (prog_ == NULL)
-    return -1;
-  SparseArray<int> fanout(prog_->size());
-  prog_->Fanout(&fanout);
-  histogram->clear();
-  for (SparseArray<int>::iterator i = fanout.begin(); i != fanout.end(); ++i) {
-    // TODO(junyer): Optimise this?
-    int bucket = 0;
-    while (1 << bucket < i->second) {
-      bucket++;
-    }
-    (*histogram)[bucket]++;
-  }
-  return histogram->rbegin()->first;
-}
-
-// Returns num_captures_, computing it if needed, or -1 if the
-// regexp wasn't valid on construction.
-int RE2::NumberOfCapturingGroups() const {
-  MutexLock l(mutex_);
-  if (suffix_regexp_ == NULL)
-    return -1;
-  if (num_captures_ == -1)
-    num_captures_ = suffix_regexp_->NumCaptures();
-  return num_captures_;
-}
-
 // Returns named_groups_, computing it if needed.
-const map<string, int>& RE2::NamedCapturingGroups() const {
+const map<string, int>&  RE2::NamedCapturingGroups() const {
   MutexLock l(mutex_);
   if (!ok())
     return *empty_named_groups;
@@ -313,7 +299,7 @@
 }
 
 // Returns group_names_, computing it if needed.
-const map<int, string>& RE2::CapturingGroupNames() const {
+const map<int, string>&  RE2::CapturingGroupNames() const {
   MutexLock l(mutex_);
   if (!ok())
     return *empty_group_names;
@@ -385,7 +371,7 @@
   int nvec = 1 + MaxSubmatch(rewrite);
   if (nvec > arraysize(vec))
     return false;
-  if (!re.Match(*str, 0, static_cast<int>(str->size()), UNANCHORED, vec, nvec))
+  if (!re.Match(*str, 0, str->size(), UNANCHORED, vec, nvec))
     return false;
 
   string s;
@@ -412,8 +398,7 @@
   string out;
   int count = 0;
   while (p <= ep) {
-    if (!re.Match(*str, static_cast<int>(p - str->data()),
-                  static_cast<int>(str->size()), UNANCHORED, vec, nvec))
+    if (!re.Match(*str, p - str->data(), str->size(), UNANCHORED, vec, nvec))
       break;
     if (p < vec[0].begin())
       out.append(p, vec[0].begin() - p);
@@ -497,7 +482,7 @@
   if (prog_ == NULL)
     return false;
 
-  int n = static_cast<int>(prefix_.size());
+  int n = prefix_.size();
   if (n > maxlen)
     n = maxlen;
 
@@ -569,10 +554,7 @@
 
   if (startpos < 0 || startpos > endpos || endpos > text.size()) {
     if (options_.log_errors())
-      LOG(ERROR) << "RE2: invalid startpos, endpos pair. ["
-                 << "startpos: " << startpos << ", "
-                 << "endpos: " << endpos << ", "
-                 << "text size: " << text.size() << "]";
+      LOG(ERROR) << "RE2: invalid startpos, endpos pair.";
     return false;
   }
 
@@ -609,7 +591,7 @@
   if (!prefix_.empty()) {
     if (startpos != 0)
       return false;
-    prefixlen = static_cast<int>(prefix_.size());
+    prefixlen = prefix_.size();
     if (prefixlen > subtext.size())
       return false;
     if (prefix_foldcase_) {
@@ -850,8 +832,8 @@
     return false;
   }
 
-  if (consumed != NULL)
-    *consumed = static_cast<int>(vec[0].end() - text.begin());
+  if(consumed != NULL)
+    *consumed = vec[0].end() - text.begin();
 
   if (n == 0 || args == NULL) {
     // We are not interested in results
@@ -873,7 +855,7 @@
     if (!args[i]->Parse(s.data(), s.size())) {
       // TODO: Should we indicate what the error was?
       VLOG(1) << "Parse error on #" << i << " " << s << " "
-              << (void*)s.data() << "/" << s.size();
+	      << (void*)s.data() << "/" << s.size();
       delete[] heapvec;
       return false;
     }
@@ -889,35 +871,48 @@
                  const StringPiece *vec, int veclen) const {
   for (const char *s = rewrite.data(), *end = s + rewrite.size();
        s < end; s++) {
-    if (*s != '\\') {
-      out->push_back(*s);
-      continue;
-    }
-    s++;
-    int c = (s < end) ? *s : -1;
-    if (isdigit(c)) {
-      int n = (c - '0');
-      if (n >= veclen) {
-        if (options_.log_errors()) {
-          LOG(ERROR) << "requested group " << n
-                     << " in regexp " << rewrite.data();
+    int c = *s;
+    if (c == '\\') {
+      s++;
+      c = (s < end) ? *s : -1;
+      if (isdigit(c)) {
+        int n = (c - '0');
+        if (n >= veclen) {
+          if (options_.log_errors()) {
+            LOG(ERROR) << "requested group " << n
+                       << " in regexp " << rewrite.data();
+          }
+          return false;
         }
+        StringPiece snip = vec[n];
+        if (snip.size() > 0)
+          out->append(snip.data(), snip.size());
+      } else if (c == '\\') {
+        out->push_back('\\');
+      } else {
+        if (options_.log_errors())
+          LOG(ERROR) << "invalid rewrite pattern: " << rewrite.data();
         return false;
       }
-      StringPiece snip = vec[n];
-      if (snip.size() > 0)
-        out->append(snip.data(), snip.size());
-    } else if (c == '\\') {
-      out->push_back('\\');
     } else {
-      if (options_.log_errors())
-        LOG(ERROR) << "invalid rewrite pattern: " << rewrite.data();
-      return false;
+      out->push_back(c);
     }
   }
   return true;
 }
 
+// Return the number of capturing subpatterns, or -1 if the
+// regexp wasn't valid on construction.
+int RE2::NumberOfCapturingGroups() const {
+  if (suffix_regexp_ == NULL)
+    return -1;
+  ANNOTATE_BENIGN_RACE(&num_captures_, "benign race: in the worst case"
+    " multiple threads end up doing the same work in parallel.");
+  if (num_captures_ == -1)
+    num_captures_ = suffix_regexp_->NumCaptures();
+  return num_captures_;
+}
+
 // Checks that the rewrite string is well-formed with respect to this
 // regular expression.
 bool RE2::CheckRewriteString(const StringPiece& rewrite, string* error) const {
@@ -992,23 +987,16 @@
 // Largest number spec that we are willing to parse
 static const int kMaxNumberLength = 32;
 
-// REQUIRES "buf" must have length at least nbuf.
+// REQUIRES "buf" must have length at least kMaxNumberLength+1
 // Copies "str" into "buf" and null-terminates.
 // Overwrites *np with the new length.
-static const char* TerminateNumber(char* buf, int nbuf, const char* str, int* np,
-                                   bool accept_spaces) {
+static const char* TerminateNumber(char* buf, const char* str, int* np) {
   int n = *np;
   if (n <= 0) return "";
   if (n > 0 && isspace(*str)) {
     // We are less forgiving than the strtoxxx() routines and do not
-    // allow leading spaces. We do allow leading spaces for floats.
-    if (!accept_spaces) {
-      return "";
-    }
-    while (n > 0 && isspace(*str)) {
-      n--;
-      str++;
-    }
+    // allow leading spaces.
+    return "";
   }
 
   // Although buf has a fixed maximum size, we can still handle
@@ -1038,7 +1026,7 @@
     str--;
   }
 
-  if (n > nbuf-1) return "";
+  if (n > kMaxNumberLength) return "";
 
   memmove(buf, str, n);
   if (neg) {
@@ -1055,7 +1043,7 @@
                                int radix) {
   if (n == 0) return false;
   char buf[kMaxNumberLength+1];
-  str = TerminateNumber(buf, sizeof buf, str, &n, false);
+  str = TerminateNumber(buf, str, &n);
   char* end;
   errno = 0;
   long r = strtol(str, &end, radix);
@@ -1072,7 +1060,7 @@
                                 int radix) {
   if (n == 0) return false;
   char buf[kMaxNumberLength+1];
-  str = TerminateNumber(buf, sizeof buf, str, &n, false);
+  str = TerminateNumber(buf, str, &n);
   if (str[0] == '-') {
    // strtoul() will silently accept negative numbers and parse
    // them.  This module is more strict and treats them as errors.
@@ -1097,7 +1085,7 @@
   if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse
   if ((short)r != r) return false;       // Out of range
   if (dest == NULL) return true;
-  *(reinterpret_cast<short*>(dest)) = (short)r;
+  *(reinterpret_cast<short*>(dest)) = r;
   return true;
 }
 
@@ -1109,7 +1097,7 @@
   if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse
   if ((ushort)r != r) return false;                      // Out of range
   if (dest == NULL) return true;
-  *(reinterpret_cast<unsigned short*>(dest)) = (ushort)r;
+  *(reinterpret_cast<unsigned short*>(dest)) = r;
   return true;
 }
 
@@ -1137,14 +1125,13 @@
   return true;
 }
 
-#if RE2_HAVE_LONGLONG
 bool RE2::Arg::parse_longlong_radix(const char* str,
                                    int n,
                                    void* dest,
                                    int radix) {
   if (n == 0) return false;
   char buf[kMaxNumberLength+1];
-  str = TerminateNumber(buf, sizeof buf, str, &n, false);
+  str = TerminateNumber(buf, str, &n);
   char* end;
   errno = 0;
   int64 r = strtoll(str, &end, radix);
@@ -1161,7 +1148,7 @@
                                     int radix) {
   if (n == 0) return false;
   char buf[kMaxNumberLength+1];
-  str = TerminateNumber(buf, sizeof buf, str, &n, false);
+  str = TerminateNumber(buf, str, &n);
   if (str[0] == '-') {
     // strtoull() will silently accept negative numbers and parse
     // them.  This module is more strict and treats them as errors.
@@ -1176,26 +1163,27 @@
   *(reinterpret_cast<uint64*>(dest)) = r;
   return true;
 }
-#endif
 
 static bool parse_double_float(const char* str, int n, bool isfloat, void *dest) {
   if (n == 0) return false;
   static const int kMaxLength = 200;
-  char buf[kMaxLength+1];
-  str = TerminateNumber(buf, sizeof buf, str, &n, true);
-  char* end;
+  char buf[kMaxLength];
+  if (n >= kMaxLength) return false;
+  memcpy(buf, str, n);
+  buf[n] = '\0';
   errno = 0;
+  char* end;
   double r;
   if (isfloat) {
-    r = strtof(str, &end);
+    r = strtof(buf, &end);
   } else {
-    r = strtod(str, &end);
+    r = strtod(buf, &end);
   }
-  if (end != str + n) return false;   // Leftover junk
+  if (end != buf + n) return false;   // Leftover junk
   if (errno) return false;
   if (dest == NULL) return true;
   if (isfloat) {
-    *(reinterpret_cast<float*>(dest)) = (float)r;
+    *(reinterpret_cast<float*>(dest)) = r;
   } else {
     *(reinterpret_cast<double*>(dest)) = r;
   }
diff --git a/third_party/re2/re2/re2.h b/third_party/re2/re2/re2.h
index a10d6a0..c509853 100644
--- a/third_party/re2/re2/re2.h
+++ b/third_party/re2/re2/re2.h
@@ -17,7 +17,7 @@
 // some of the more complicated things thrown away.  In particular,
 // backreferences and generalized assertions are not available, nor is \Z.
 //
-// See https://github.com/google/re2/wiki/Syntax for the syntax
+// See http://code.google.com/p/re2/wiki/Syntax for the syntax
 // supported by RE2, and a comparison with PCRE and PERL regexps.
 //
 // For those not familiar with Perl's regular expressions,
@@ -179,16 +179,13 @@
 //         RE2::Octal(&a), RE2::Hex(&b), RE2::CRadix(&c), RE2::CRadix(&d));
 // will leave 64 in a, b, c, and d.
 
+
 #include <stdint.h>
 #include <map>
 #include <string>
 #include "re2/stringpiece.h"
 #include "re2/variadic_function.h"
 
-#ifndef RE2_HAVE_LONGLONG
-#define RE2_HAVE_LONGLONG 1
-#endif
-
 namespace re2 {
 
 using std::string;
@@ -243,7 +240,7 @@
     ErrorBadPerlOp,          // bad perl operator
     ErrorBadUTF8,            // invalid UTF-8 in regexp
     ErrorBadNamedCapture,    // bad named capture group
-    ErrorPatternTooLarge     // pattern too large (compile failed)
+    ErrorPatternTooLarge,    // pattern too large (compile failed)
   };
 
   // Predefined common options.
@@ -293,11 +290,6 @@
   // Larger numbers are more expensive than smaller numbers.
   int ProgramSize() const;
 
-  // EXPERIMENTAL! SUBJECT TO CHANGE!
-  // Outputs the program fanout as a histogram bucketed by powers of 2.
-  // Returns the number of the largest non-empty bucket.
-  int ProgramFanout(map<int, int>* histogram) const;
-
   // Returns the underlying Regexp; not for general use.
   // Returns entire_regexp_ so that callers don't need
   // to know about prefix_ and prefix_foldcase_.
@@ -402,8 +394,6 @@
   //
   // Returns true iff a match occurred and the extraction happened
   // successfully;  if no match occurs, the string is left unaffected.
-  //
-  // REQUIRES: "text" must not alias any part of "*out".
   static bool Extract(const StringPiece &text,
                       const RE2& pattern,
                       const StringPiece &rewrite,
@@ -439,7 +429,7 @@
   enum Anchor {
     UNANCHORED,         // No anchoring
     ANCHOR_START,       // Anchor at start only
-    ANCHOR_BOTH         // Anchor at start and end
+    ANCHOR_BOTH,        // Anchor at start and end
   };
 
   // Return the number of capturing subpatterns, or -1 if the
@@ -447,6 +437,7 @@
   // does not count: if the regexp is "(a)(b)", returns 2.
   int NumberOfCapturingGroups() const;
 
+
   // Return a map from names to capturing indices.
   // The map records the index of the leftmost group
   // with the given name.
@@ -521,7 +512,6 @@
     //   max_mem          (see below)  approx. max memory footprint of RE2
     //   literal          (false) interpret string as literal, not regexp
     //   never_nl         (false) never match \n, even if it is in regexp
-    //   dot_nl           (false) dot matches everything including new line
     //   never_capture    (false) parse all parens as non-capturing
     //   case_sensitive   (true)  match is case-sensitive (regexp can override
     //                              with (?i) unless in posix_syntax mode)
@@ -562,29 +552,16 @@
     // If this happens too often, RE2 falls back on the NFA implementation.
 
     // For now, make the default budget something close to Code Search.
+#ifndef WIN32
     static const int kDefaultMaxMem = 8<<20;
+#endif
 
     enum Encoding {
       EncodingUTF8 = 1,
       EncodingLatin1
     };
 
-    Options() :
-      encoding_(EncodingUTF8),
-      posix_syntax_(false),
-      longest_match_(false),
-      log_errors_(true),
-      max_mem_(kDefaultMaxMem),
-      literal_(false),
-      never_nl_(false),
-      dot_nl_(false),
-      never_capture_(false),
-      case_sensitive_(true),
-      perl_classes_(false),
-      word_boundary_(false),
-      one_line_(false) {
-    }
-
+    Options();
     /*implicit*/ Options(CannedOptions);
 
     Encoding encoding() const { return encoding_; }
@@ -610,8 +587,8 @@
     bool log_errors() const { return log_errors_; }
     void set_log_errors(bool b) { log_errors_ = b; }
 
-    int64_t max_mem() const { return max_mem_; }
-    void set_max_mem(int64_t m) { max_mem_ = m; }
+    int max_mem() const { return max_mem_; }
+    void set_max_mem(int m) { max_mem_ = m; }
 
     bool literal() const { return literal_; }
     void set_literal(bool b) { literal_ = b; }
@@ -619,9 +596,6 @@
     bool never_nl() const { return never_nl_; }
     void set_never_nl(bool b) { never_nl_ = b; }
 
-    bool dot_nl() const { return dot_nl_; }
-    void set_dot_nl(bool b) { dot_nl_ = b; }
-
     bool never_capture() const { return never_capture_; }
     void set_never_capture(bool b) { never_capture_ = b; }
 
@@ -645,7 +619,6 @@
       max_mem_ = src.max_mem_;
       literal_ = src.literal_;
       never_nl_ = src.never_nl_;
-      dot_nl_ = src.dot_nl_;
       never_capture_ = src.never_capture_;
       case_sensitive_ = src.case_sensitive_;
       perl_classes_ = src.perl_classes_;
@@ -663,14 +636,13 @@
     int64_t max_mem_;
     bool literal_;
     bool never_nl_;
-    bool dot_nl_;
     bool never_capture_;
     bool case_sensitive_;
     bool perl_classes_;
     bool word_boundary_;
     bool one_line_;
 
-    //DISALLOW_COPY_AND_ASSIGN(Options);
+    //DISALLOW_EVIL_CONSTRUCTORS(Options);
     Options(const Options&);
     void operator=(const Options&);
   };
@@ -685,10 +657,8 @@
   static inline Arg CRadix(unsigned int* x);
   static inline Arg CRadix(long* x);
   static inline Arg CRadix(unsigned long* x);
-  #if RE2_HAVE_LONGLONG
   static inline Arg CRadix(long long* x);
   static inline Arg CRadix(unsigned long long* x);
-  #endif
 
   static inline Arg Hex(short* x);
   static inline Arg Hex(unsigned short* x);
@@ -696,10 +666,8 @@
   static inline Arg Hex(unsigned int* x);
   static inline Arg Hex(long* x);
   static inline Arg Hex(unsigned long* x);
-  #if RE2_HAVE_LONGLONG
   static inline Arg Hex(long long* x);
   static inline Arg Hex(unsigned long long* x);
-  #endif
 
   static inline Arg Octal(short* x);
   static inline Arg Octal(unsigned short* x);
@@ -707,10 +675,8 @@
   static inline Arg Octal(unsigned int* x);
   static inline Arg Octal(long* x);
   static inline Arg Octal(unsigned long* x);
-  #if RE2_HAVE_LONGLONG
   static inline Arg Octal(long long* x);
   static inline Arg Octal(unsigned long long* x);
-  #endif
 
  private:
   void Init(const StringPiece& pattern, const Options& options);
@@ -745,7 +711,7 @@
   // Map from capture indices to names
   mutable const map<int, string>* group_names_;
 
-  //DISALLOW_COPY_AND_ASSIGN(RE2);
+  //DISALLOW_EVIL_CONSTRUCTORS(RE2);
   RE2(const RE2&);
   void operator=(const RE2&);
 };
@@ -790,10 +756,8 @@
   MAKE_PARSER(unsigned int,       parse_uint);
   MAKE_PARSER(long,               parse_long);
   MAKE_PARSER(unsigned long,      parse_ulong);
-  #if RE2_HAVE_LONGLONG
   MAKE_PARSER(long long,          parse_longlong);
   MAKE_PARSER(unsigned long long, parse_ulonglong);
-  #endif
   MAKE_PARSER(float,              parse_float);
   MAKE_PARSER(double,             parse_double);
   MAKE_PARSER(string,             parse_string);
@@ -801,11 +765,12 @@
 
 #undef MAKE_PARSER
 
-  // Generic constructor templates
+  // Generic constructor
+  template <class T> Arg(T*, Parser parser);
+  // Generic constructor template
   template <class T> Arg(T* p)
-      : arg_(p), parser_(_RE2_MatchObject<T>::Parse) { }
-  template <class T> Arg(T* p, Parser parser)
-      : arg_(p), parser_(parser) { }
+    : arg_(p), parser_(_RE2_MatchObject<T>::Parse) {
+  }
 
   // Parse the data
   bool Parse(const char* str, int n) const;
@@ -838,10 +803,8 @@
   DECLARE_INTEGER_PARSER(uint);
   DECLARE_INTEGER_PARSER(long);
   DECLARE_INTEGER_PARSER(ulong);
-  #if RE2_HAVE_LONGLONG
   DECLARE_INTEGER_PARSER(longlong);
   DECLARE_INTEGER_PARSER(ulonglong);
-  #endif
 
 #undef DECLARE_INTEGER_PARSER
 };
@@ -862,16 +825,14 @@
   inline RE2::Arg RE2::CRadix(type* ptr) { \
     return RE2::Arg(ptr, RE2::Arg::parse_ ## name ## _cradix); }
 
-MAKE_INTEGER_PARSER(short,              short)
-MAKE_INTEGER_PARSER(unsigned short,     ushort)
-MAKE_INTEGER_PARSER(int,                int)
-MAKE_INTEGER_PARSER(unsigned int,       uint)
-MAKE_INTEGER_PARSER(long,               long)
-MAKE_INTEGER_PARSER(unsigned long,      ulong)
-#if RE2_HAVE_LONGLONG
-MAKE_INTEGER_PARSER(long long,          longlong)
-MAKE_INTEGER_PARSER(unsigned long long, ulonglong)
-#endif
+MAKE_INTEGER_PARSER(short,              short);
+MAKE_INTEGER_PARSER(unsigned short,     ushort);
+MAKE_INTEGER_PARSER(int,                int);
+MAKE_INTEGER_PARSER(unsigned int,       uint);
+MAKE_INTEGER_PARSER(long,               long);
+MAKE_INTEGER_PARSER(unsigned long,      ulong);
+MAKE_INTEGER_PARSER(long long,          longlong);
+MAKE_INTEGER_PARSER(unsigned long long, ulonglong);
 
 #undef MAKE_INTEGER_PARSER
 
diff --git a/third_party/re2/re2/regexp.cc b/third_party/re2/re2/regexp.cc
index 99e72e5..ed4c3a0 100644
--- a/third_party/re2/re2/regexp.cc
+++ b/third_party/re2/re2/regexp.cc
@@ -14,7 +14,7 @@
 
 // Constructor.  Allocates vectors as appropriate for operator.
 Regexp::Regexp(RegexpOp op, ParseFlags parse_flags)
-  : op_(static_cast<uint8>(op)),
+  : op_(op),
     simple_(false),
     parse_flags_(static_cast<uint16>(parse_flags)),
     ref_(1),
@@ -43,8 +43,7 @@
       delete[] runes_;
       break;
     case kRegexpCharClass:
-      if (cc_)
-        cc_->Delete();
+      cc_->Delete();
       delete ccb_;
       break;
   }
@@ -107,7 +106,7 @@
     GLOBAL_MUTEX_LOCK(ref_mutex);
     int r = (*ref_map)[this] - 1;
     if (r < kMaxRef) {
-      ref_ = static_cast<uint16>(r);
+      ref_ = r;
       ref_map->erase(this);
     } else {
       (*ref_map)[this] = r;
@@ -212,13 +211,6 @@
   if (nsub == 1)
     return sub[0];
 
-  if (nsub == 0) {
-    if (op == kRegexpAlternate)
-      return new Regexp(kRegexpNoMatch, flags);
-    else
-      return new Regexp(kRegexpEmptyMatch, flags);
-  }
-
   Regexp** subcopy = NULL;
   if (op == kRegexpAlternate && can_factor) {
     // Going to edit sub; make a copy so we don't step on caller.
@@ -453,11 +445,10 @@
         continue;
     }
 
-    size_t n = stk.size();
+    int n = stk.size();
     if (n == 0)
       break;
 
-    DCHECK_GE(n, 2);
     a = stk[n-2];
     b = stk[n-1];
     stk.resize(n-2);
@@ -526,7 +517,7 @@
 
  private:
   int ncapture_;
-  DISALLOW_COPY_AND_ASSIGN(NumCapturesWalker);
+  DISALLOW_EVIL_CONSTRUCTORS(NumCapturesWalker);
 };
 
 int Regexp::NumCaptures() {
@@ -570,7 +561,7 @@
 
  private:
   map<string, int>* map_;
-  DISALLOW_COPY_AND_ASSIGN(NamedCapturesWalker);
+  DISALLOW_EVIL_CONSTRUCTORS(NamedCapturesWalker);
 };
 
 map<string, int>* Regexp::NamedCaptures() {
@@ -610,7 +601,7 @@
 
  private:
   map<int, string>* map_;
-  DISALLOW_COPY_AND_ASSIGN(CaptureNamesWalker);
+  DISALLOW_EVIL_CONSTRUCTORS(CaptureNamesWalker);
 };
 
 map<int, string>* Regexp::CaptureNames() {
@@ -652,7 +643,7 @@
       if (re->parse_flags() & Latin1) {
         prefix->resize(re->nrunes_);
         for (int j = 0; j < re->nrunes_; j++)
-          (*prefix)[j] = static_cast<char>(re->runes_[j]);
+          (*prefix)[j] = re->runes_[j];
       } else {
         // Convert to UTF-8 in place.
         // Assume worst-case space and then trim.
@@ -661,7 +652,7 @@
         for (int j = 0; j < re->nrunes_; j++) {
           Rune r = re->runes_[j];
           if (r < Runeself)
-            *p++ = static_cast<char>(r);
+            *p++ = r;
           else
             p += runetochar(p, &r);
         }
@@ -671,14 +662,14 @@
 
     case kRegexpLiteral:
       if ((re->parse_flags() & Latin1) || re->rune_ < Runeself) {
-        prefix->append(1, static_cast<char>(re->rune_));
+        prefix->append(1, re->rune_);
       } else {
         char buf[UTFmax];
         prefix->append(buf, runetochar(buf, &re->rune_));
       }
       break;
   }
-  *foldcase = (sub[i]->parse_flags() & FoldCase) != 0;
+  *foldcase = (sub[i]->parse_flags() & FoldCase);
   i++;
 
   // The rest.
@@ -858,7 +849,7 @@
   }
 
   ranges_.clear();
-  for (size_t i = 0; i < v.size(); i++)
+  for (int i = 0; i < v.size(); i++)
     ranges_.insert(v[i]);
 
   upper_ = AlphaMask & ~upper_;
@@ -924,12 +915,12 @@
 }
 
 CharClass* CharClassBuilder::GetCharClass() {
-  CharClass* cc = CharClass::New(static_cast<int>(ranges_.size()));
+  CharClass* cc = CharClass::New(ranges_.size());
   int n = 0;
   for (iterator it = begin(); it != end(); ++it)
     cc->ranges_[n++] = *it;
   cc->nranges_ = n;
-  DCHECK_LE(n, static_cast<int>(ranges_.size()));
+  DCHECK_LE(n, ranges_.size());
   cc->nrunes_ = nrunes_;
   cc->folds_ascii_ = FoldsASCII();
   return cc;
diff --git a/third_party/re2/re2/regexp.h b/third_party/re2/re2/regexp.h
index 5f222b7..331c017 100644
--- a/third_party/re2/re2/regexp.h
+++ b/third_party/re2/re2/regexp.h
@@ -208,11 +208,10 @@
   StringPiece error_arg_;       // Piece of regexp containing syntax error.
   string* tmp_;                 // Temporary storage, possibly where error_arg_ is.
 
-  DISALLOW_COPY_AND_ASSIGN(RegexpStatus);
+  DISALLOW_EVIL_CONSTRUCTORS(RegexpStatus);
 };
 
-// Walkers to implement Simplify.
-class CoalesceWalker;
+// Walker to implement Simplify.
 class SimplifyWalker;
 
 // Compiled form; see prog.h
@@ -262,7 +261,7 @@
   int nrunes_;
   RuneRange *ranges_;
   int nranges_;
-  DISALLOW_COPY_AND_ASSIGN(CharClass);
+  DISALLOW_EVIL_CONSTRUCTORS(CharClass);
 };
 
 class Regexp {
@@ -313,7 +312,7 @@
   // Get.  No set, Regexps are logically immutable once created.
   RegexpOp op() { return static_cast<RegexpOp>(op_); }
   int nsub() { return nsub_; }
-  bool simple() { return simple_ != 0; }
+  bool simple() { return simple_; }
   enum ParseFlags parse_flags() { return static_cast<ParseFlags>(parse_flags_); }
   int Ref();  // For testing.
 
@@ -354,7 +353,6 @@
   // removed.  The result will capture exactly the same
   // subexpressions the original did, unless formatted with ToString.
   Regexp* Simplify();
-  friend class CoalesceWalker;
   friend class SimplifyWalker;
 
   // Parses the regexp src and then simplifies it and sets *dst to the
@@ -570,7 +568,7 @@
     void *the_union_[2];  // as big as any other element, for memset
   };
 
-  DISALLOW_COPY_AND_ASSIGN(Regexp);
+  DISALLOW_EVIL_CONSTRUCTORS(Regexp);
 };
 
 // Character class set: contains non-overlapping, non-abutting RuneRanges.
@@ -604,7 +602,7 @@
   uint32 lower_;  // bitmap of a-z
   int nrunes_;
   RuneRangeSet ranges_;
-  DISALLOW_COPY_AND_ASSIGN(CharClassBuilder);
+  DISALLOW_EVIL_CONSTRUCTORS(CharClassBuilder);
 };
 
 // Tell g++ that bitwise ops on ParseFlags produce ParseFlags.
diff --git a/third_party/re2/re2/set.cc b/third_party/re2/re2/set.cc
index a1a84ba..2bcd30ac 100644
--- a/third_party/re2/re2/set.cc
+++ b/third_party/re2/re2/set.cc
@@ -20,7 +20,7 @@
 }
 
 RE2::Set::~Set() {
-  for (size_t i = 0; i < re_.size(); i++)
+  for (int i = 0; i < re_.size(); i++)
     re_[i]->Decref();
   delete prog_;
 }
@@ -45,7 +45,7 @@
   }
 
   // Concatenate with match index and push on vector.
-  int n = static_cast<int>(re_.size());
+  int n = re_.size();
   re2::Regexp* m = re2::Regexp::HaveMatch(n, pf);
   if (re->op() == kRegexpConcat) {
     int nsub = re->nsub();
@@ -75,8 +75,8 @@
 
   Regexp::ParseFlags pf = static_cast<Regexp::ParseFlags>(
     options_.ParseFlags());
-  re2::Regexp* re = re2::Regexp::Alternate(const_cast<re2::Regexp**>(re_.data()),
-                                           static_cast<int>(re_.size()), pf);
+  re2::Regexp* re = re2::Regexp::Alternate(const_cast<re2::Regexp**>(&re_[0]),
+                                           re_.size(), pf);
   re_.clear();
   re2::Regexp* sre = re->Simplify();
   re->Decref();
diff --git a/third_party/re2/re2/set.h b/third_party/re2/re2/set.h
index 1f55b61..d716425 100644
--- a/third_party/re2/re2/set.h
+++ b/third_party/re2/re2/set.h
@@ -45,7 +45,7 @@
   vector<re2::Regexp*> re_;
   re2::Prog* prog_;
   bool compiled_;
-  //DISALLOW_COPY_AND_ASSIGN(Set);
+  //DISALLOW_EVIL_CONSTRUCTORS(Set);
   Set(const Set&);
   void operator=(const Set&);
 };
diff --git a/third_party/re2/re2/simplify.cc b/third_party/re2/re2/simplify.cc
index ecc60e7..faf3208 100644
--- a/third_party/re2/re2/simplify.cc
+++ b/third_party/re2/re2/simplify.cc
@@ -61,7 +61,7 @@
       // These are simple as long as the subpieces are simple.
       subs = sub();
       for (int i = 0; i < nsub_; i++)
-        if (!subs[i]->simple())
+        if (!subs[i]->simple_)
           return false;
       return true;
     case kRegexpCharClass:
@@ -71,12 +71,12 @@
       return !cc_->empty() && !cc_->full();
     case kRegexpCapture:
       subs = sub();
-      return subs[0]->simple();
+      return subs[0]->simple_;
     case kRegexpStar:
     case kRegexpPlus:
     case kRegexpQuest:
       subs = sub();
-      if (!subs[0]->simple())
+      if (!subs[0]->simple_)
         return false;
       switch (subs[0]->op_) {
         case kRegexpStar:
@@ -97,36 +97,6 @@
 }
 
 // Walker subclass used by Simplify.
-// Coalesces runs of star/plus/quest/repeat of the same literal along with any
-// occurrences of that literal into repeats of that literal. It also works for
-// char classes, any char and any byte.
-// PostVisit creates the coalesced result, which should then be simplified.
-class CoalesceWalker : public Regexp::Walker<Regexp*> {
- public:
-  CoalesceWalker() {}
-  virtual Regexp* PostVisit(Regexp* re, Regexp* parent_arg, Regexp* pre_arg,
-                            Regexp** child_args, int nchild_args);
-  virtual Regexp* Copy(Regexp* re);
-  virtual Regexp* ShortVisit(Regexp* re, Regexp* parent_arg);
-
- private:
-  // These functions are declared inside CoalesceWalker so that
-  // they can edit the private fields of the Regexps they construct.
-
-  // Returns true if r1 and r2 can be coalesced. In particular, ensures that
-  // the parse flags are consistent. (They will not be checked again later.)
-  static bool CanCoalesce(Regexp* r1, Regexp* r2);
-
-  // Coalesces *r1ptr and *r2ptr. In most cases, the array elements afterwards
-  // will be empty match and the coalesced op. In other cases, where part of a
-  // literal string was removed to be coalesced, the array elements afterwards
-  // will be the coalesced op and the remainder of the literal string.
-  static void DoCoalesce(Regexp** r1ptr, Regexp** r2ptr);
-
-  DISALLOW_COPY_AND_ASSIGN(CoalesceWalker);
-};
-
-// Walker subclass used by Simplify.
 // The simplify walk is purely post-recursive: given the simplified children,
 // PostVisit creates the simplified result.
 // The child_args are simplified Regexp*s.
@@ -134,7 +104,9 @@
  public:
   SimplifyWalker() {}
   virtual Regexp* PreVisit(Regexp* re, Regexp* parent_arg, bool* stop);
-  virtual Regexp* PostVisit(Regexp* re, Regexp* parent_arg, Regexp* pre_arg,
+  virtual Regexp* PostVisit(Regexp* re,
+                            Regexp* parent_arg,
+                            Regexp* pre_arg,
                             Regexp** child_args, int nchild_args);
   virtual Regexp* Copy(Regexp* re);
   virtual Regexp* ShortVisit(Regexp* re, Regexp* parent_arg);
@@ -158,7 +130,7 @@
   // Caller must Decref return value when done with it.
   static Regexp* SimplifyCharClass(Regexp* re);
 
-  DISALLOW_COPY_AND_ASSIGN(SimplifyWalker);
+  DISALLOW_EVIL_CONSTRUCTORS(SimplifyWalker);
 };
 
 // Simplifies a regular expression, returning a new regexp.
@@ -171,261 +143,14 @@
 // Caller must Decref() return value when done with it.
 
 Regexp* Regexp::Simplify() {
-  CoalesceWalker cw;
-  Regexp* cre = cw.Walk(this, NULL);
-  if (cre == NULL)
-    return cre;
-  SimplifyWalker sw;
-  Regexp* sre = sw.Walk(cre, NULL);
-  cre->Decref();
-  return sre;
+  if (simple_)
+    return Incref();
+  SimplifyWalker w;
+  return w.Walk(this, NULL);
 }
 
 #define Simplify DontCallSimplify  // Avoid accidental recursion
 
-// Utility function for PostVisit implementations that compares re->sub() with
-// child_args to determine whether any child_args changed. In the common case,
-// where nothing changed, calls Decref() for all child_args and returns false,
-// so PostVisit must return re->Incref(). Otherwise, returns true.
-static bool ChildArgsChanged(Regexp* re, Regexp** child_args) {
-  for (int i = 0; i < re->nsub(); i++) {
-    Regexp* sub = re->sub()[i];
-    Regexp* newsub = child_args[i];
-    if (newsub != sub)
-      return true;
-  }
-  for (int i = 0; i < re->nsub(); i++) {
-    Regexp* newsub = child_args[i];
-    newsub->Decref();
-  }
-  return false;
-}
-
-Regexp* CoalesceWalker::Copy(Regexp* re) {
-  return re->Incref();
-}
-
-Regexp* CoalesceWalker::ShortVisit(Regexp* re, Regexp* parent_arg) {
-  // This should never be called, since we use Walk and not
-  // WalkExponential.
-  LOG(DFATAL) << "CoalesceWalker::ShortVisit called";
-  return re->Incref();
-}
-
-Regexp* CoalesceWalker::PostVisit(Regexp* re,
-                                  Regexp* parent_arg,
-                                  Regexp* pre_arg,
-                                  Regexp** child_args,
-                                  int nchild_args) {
-  if (re->nsub() == 0)
-    return re->Incref();
-
-  if (re->op() != kRegexpConcat) {
-    if (!ChildArgsChanged(re, child_args))
-      return re->Incref();
-
-    // Something changed. Build a new op.
-    Regexp* nre = new Regexp(re->op(), re->parse_flags());
-    nre->AllocSub(re->nsub());
-    Regexp** nre_subs = nre->sub();
-    for (int i = 0; i < re->nsub(); i++)
-      nre_subs[i] = child_args[i];
-    // Repeats and Captures have additional data that must be copied.
-    if (re->op() == kRegexpRepeat) {
-      nre->min_ = re->min();
-      nre->max_ = re->max();
-    } else if (re->op() == kRegexpCapture) {
-      nre->cap_ = re->cap();
-    }
-    return nre;
-  }
-
-  bool can_coalesce = false;
-  for (int i = 0; i < re->nsub(); i++) {
-    if (i+1 < re->nsub() &&
-        CanCoalesce(child_args[i], child_args[i+1])) {
-      can_coalesce = true;
-      break;
-    }
-  }
-  if (!can_coalesce) {
-    if (!ChildArgsChanged(re, child_args))
-      return re->Incref();
-
-    // Something changed. Build a new op.
-    Regexp* nre = new Regexp(re->op(), re->parse_flags());
-    nre->AllocSub(re->nsub());
-    Regexp** nre_subs = nre->sub();
-    for (int i = 0; i < re->nsub(); i++)
-      nre_subs[i] = child_args[i];
-    return nre;
-  }
-
-  for (int i = 0; i < re->nsub(); i++) {
-    if (i+1 < re->nsub() &&
-        CanCoalesce(child_args[i], child_args[i+1]))
-      DoCoalesce(&child_args[i], &child_args[i+1]);
-  }
-  // Determine how many empty matches were left by DoCoalesce.
-  int n = 0;
-  for (int i = n; i < re->nsub(); i++) {
-    if (child_args[i]->op() == kRegexpEmptyMatch)
-      n++;
-  }
-  // Build a new op.
-  Regexp* nre = new Regexp(re->op(), re->parse_flags());
-  nre->AllocSub(re->nsub() - n);
-  Regexp** nre_subs = nre->sub();
-  for (int i = 0, j = 0; i < re->nsub(); i++) {
-    if (child_args[i]->op() == kRegexpEmptyMatch) {
-      child_args[i]->Decref();
-      continue;
-    }
-    nre_subs[j] = child_args[i];
-    j++;
-  }
-  return nre;
-}
-
-bool CoalesceWalker::CanCoalesce(Regexp* r1, Regexp* r2) {
-  // r1 must be a star/plus/quest/repeat of a literal, char class, any char or
-  // any byte.
-  if ((r1->op() == kRegexpStar ||
-       r1->op() == kRegexpPlus ||
-       r1->op() == kRegexpQuest ||
-       r1->op() == kRegexpRepeat) &&
-      (r1->sub()[0]->op() == kRegexpLiteral ||
-       r1->sub()[0]->op() == kRegexpCharClass ||
-       r1->sub()[0]->op() == kRegexpAnyChar ||
-       r1->sub()[0]->op() == kRegexpAnyByte)) {
-    // r2 must be a star/plus/quest/repeat of the same literal, char class,
-    // any char or any byte.
-    if ((r2->op() == kRegexpStar ||
-         r2->op() == kRegexpPlus ||
-         r2->op() == kRegexpQuest ||
-         r2->op() == kRegexpRepeat) &&
-        Regexp::Equal(r1->sub()[0], r2->sub()[0]) &&
-        // The parse flags must be consistent.
-        ((r1->parse_flags() & Regexp::NonGreedy) ==
-         (r2->parse_flags() & Regexp::NonGreedy))) {
-      return true;
-    }
-    // ... OR an occurrence of that literal, char class, any char or any byte
-    if (Regexp::Equal(r1->sub()[0], r2)) {
-      return true;
-    }
-    // ... OR a literal string that begins with that literal.
-    if (r1->sub()[0]->op() == kRegexpLiteral &&
-        r2->op() == kRegexpLiteralString &&
-        r2->runes()[0] == r1->sub()[0]->rune() &&
-        // The parse flags must be consistent.
-        ((r1->sub()[0]->parse_flags() & Regexp::FoldCase) ==
-         (r2->parse_flags() & Regexp::FoldCase))) {
-      return true;
-    }
-  }
-  return false;
-}
-
-void CoalesceWalker::DoCoalesce(Regexp** r1ptr, Regexp** r2ptr) {
-  Regexp* r1 = *r1ptr;
-  Regexp* r2 = *r2ptr;
-
-  Regexp* nre = Regexp::Repeat(
-      r1->sub()[0]->Incref(), r1->parse_flags(), 0, 0);
-
-  switch (r1->op()) {
-    case kRegexpStar:
-      nre->min_ = 0;
-      nre->max_ = -1;
-      break;
-
-    case kRegexpPlus:
-      nre->min_ = 1;
-      nre->max_ = -1;
-      break;
-
-    case kRegexpQuest:
-      nre->min_ = 0;
-      nre->max_ = 1;
-      break;
-
-    case kRegexpRepeat:
-      nre->min_ = r1->min();
-      nre->max_ = r1->max();
-      break;
-
-    default:
-      LOG(DFATAL) << "DoCoalesce failed: r1->op() is " << r1->op();
-      nre->Decref();
-      return;
-  }
-
-  switch (r2->op()) {
-    case kRegexpStar:
-      nre->max_ = -1;
-      goto LeaveEmpty;
-
-    case kRegexpPlus:
-      nre->min_++;
-      nre->max_ = -1;
-      goto LeaveEmpty;
-
-    case kRegexpQuest:
-      if (nre->max() != -1)
-        nre->max_++;
-      goto LeaveEmpty;
-
-    case kRegexpRepeat:
-      nre->min_ += r2->min();
-      if (r2->max() == -1)
-        nre->max_ = -1;
-      else if (nre->max() != -1)
-        nre->max_ += r2->max();
-      goto LeaveEmpty;
-
-    case kRegexpLiteral:
-    case kRegexpCharClass:
-    case kRegexpAnyChar:
-    case kRegexpAnyByte:
-      nre->min_++;
-      if (nre->max() != -1)
-        nre->max_++;
-      goto LeaveEmpty;
-
-    LeaveEmpty:
-      *r1ptr = new Regexp(kRegexpEmptyMatch, Regexp::NoParseFlags);
-      *r2ptr = nre;
-      break;
-
-    case kRegexpLiteralString: {
-      Rune r = r1->sub()[0]->rune();
-      // Determine how much of the literal string is removed.
-      // We know that we have at least one rune. :)
-      int n = 1;
-      while (n < r2->nrunes() && r2->runes()[n] == r)
-        n++;
-      nre->min_ += n;
-      if (nre->max() != -1)
-        nre->max_ += n;
-      if (n == r2->nrunes())
-        goto LeaveEmpty;
-      *r1ptr = nre;
-      *r2ptr = Regexp::LiteralString(
-          &r2->runes()[n], r2->nrunes() - n, r2->parse_flags());
-      break;
-    }
-
-    default:
-      LOG(DFATAL) << "DoCoalesce failed: r2->op() is " << r2->op();
-      nre->Decref();
-      return;
-  }
-
-  r1->Decref();
-  r2->Decref();
-}
-
 Regexp* SimplifyWalker::Copy(Regexp* re) {
   return re->Incref();
 }
@@ -438,7 +163,7 @@
 }
 
 Regexp* SimplifyWalker::PreVisit(Regexp* re, Regexp* parent_arg, bool* stop) {
-  if (re->simple()) {
+  if (re->simple_) {
     *stop = true;
     return re->Incref();
   }
@@ -471,14 +196,29 @@
     case kRegexpConcat:
     case kRegexpAlternate: {
       // These are simple as long as the subpieces are simple.
-      if (!ChildArgsChanged(re, child_args)) {
+      // Two passes to avoid allocation in the common case.
+      bool changed = false;
+      Regexp** subs = re->sub();
+      for (int i = 0; i < re->nsub_; i++) {
+        Regexp* sub = subs[i];
+        Regexp* newsub = child_args[i];
+        if (newsub != sub) {
+          changed = true;
+          break;
+        }
+      }
+      if (!changed) {
+        for (int i = 0; i < re->nsub_; i++) {
+          Regexp* newsub = child_args[i];
+          newsub->Decref();
+        }
         re->simple_ = true;
         return re->Incref();
       }
       Regexp* nre = new Regexp(re->op(), re->parse_flags());
-      nre->AllocSub(re->nsub());
+      nre->AllocSub(re->nsub_);
       Regexp** nre_subs = nre->sub();
-      for (int i = 0; i < re->nsub(); i++)
+      for (int i = 0; i <re->nsub_; i++)
         nre_subs[i] = child_args[i];
       nre->simple_ = true;
       return nre;
@@ -494,7 +234,7 @@
       Regexp* nre = new Regexp(kRegexpCapture, re->parse_flags());
       nre->AllocSub(1);
       nre->sub()[0] = newsub;
-      nre->cap_ = re->cap();
+      nre->cap_ = re->cap_;
       nre->simple_ = true;
       return nre;
     }
@@ -585,6 +325,7 @@
     // General case: x{4,} is xxxx+
     Regexp* nre = new Regexp(kRegexpConcat, f);
     nre->AllocSub(min);
+    VLOG(1) << "Simplify " << min;
     Regexp** nre_subs = nre->sub();
     for (int i = 0; i < min-1; i++)
       nre_subs[i] = re->Incref();
diff --git a/third_party/re2/re2/stringpiece.h b/third_party/re2/re2/stringpiece.h
index 1479d1a..38a5150 100644
--- a/third_party/re2/re2/stringpiece.h
+++ b/third_party/re2/re2/stringpiece.h
@@ -20,10 +20,12 @@
 #define STRINGS_STRINGPIECE_H__
 
 #include <string.h>
-#include <algorithm>
 #include <cstddef>
 #include <iosfwd>
 #include <string>
+#ifdef WIN32
+#include <algorithm>
+#endif
 
 namespace re2 {
 
@@ -137,17 +139,15 @@
   int max_size() const { return length_; }
   int capacity() const { return length_; }
 
-  size_type copy(char* buf, size_type n, size_type pos = 0) const;
+  int copy(char* buf, size_type n, size_type pos = 0) const;
 
-  bool contains(StringPiece s) const;
-
-  size_type find(const StringPiece& s, size_type pos = 0) const;
-  size_type find(char c, size_type pos = 0) const;
-  size_type rfind(const StringPiece& s, size_type pos = npos) const;
-  size_type rfind(char c, size_type pos = npos) const;
+  int find(const StringPiece& s, size_type pos = 0) const;
+  int find(char c, size_type pos = 0) const;
+  int rfind(const StringPiece& s, size_type pos = npos) const;
+  int rfind(char c, size_type pos = npos) const;
 
   StringPiece substr(size_type pos, size_type n = npos) const;
-
+  
   static bool _equal(const StringPiece&, const StringPiece&);
 };
 
diff --git a/third_party/re2/re2/testing/backtrack.cc b/third_party/re2/re2/testing/backtrack.cc
index a872840..b2dd6dba 100644
--- a/third_party/re2/re2/testing/backtrack.cc
+++ b/third_party/re2/re2/testing/backtrack.cc
@@ -72,7 +72,7 @@
   // Search state
   const char* cap_[64];     // capture registers
   uint32 *visited_;         // bitmap: (Inst*, char*) pairs already backtracked
-  size_t nvisited_;         //   # of words in bitmap
+  int nvisited_;            //   # of words in bitmap
 };
 
 Backtracker::Backtracker(Prog* prog)
@@ -150,7 +150,7 @@
   // either it didn't match or it did but we're hoping for a better match.
   // Either way, don't go down that road again.
   CHECK(p <= text_.end());
-  size_t n = id*(text_.size()+1) + (p - text_.begin());
+  int n = id*(text_.size()+1) + (p - text_.begin());
   CHECK_LT(n/32, nvisited_);
   if (visited_[n/32] & (1 << (n&31)))
     return false;
@@ -212,8 +212,7 @@
       if (submatch_[0].data() == NULL ||           // First match so far ...
           (longest_ && p > submatch_[0].end())) {  // ... or better match
         for (int i = 0; i < nsubmatch_; i++)
-          submatch_[i].set(cap_[2*i],
-                           static_cast<int>(cap_[2*i+1] - cap_[2*i]));
+          submatch_[i] = StringPiece(cap_[2*i], cap_[2*i+1] - cap_[2*i]);
       }
       return true;
 
diff --git a/third_party/re2/re2/testing/compile_test.cc b/third_party/re2/re2/testing/compile_test.cc
index d438b193..8d92105 100644
--- a/third_party/re2/re2/testing/compile_test.cc
+++ b/third_party/re2/re2/testing/compile_test.cc
@@ -99,10 +99,6 @@
   { "[Aa]",
     "1. byte/i [61-61] -> 2\n"
     "2. match! 0\n" },
-  // Issue 20992936
-  { "[[-`]",
-    "1. byte [5b-60] -> 2\n"
-    "2. match! 0\n" },
 };
 
 TEST(TestRegexpCompileToProg, Simple) {
diff --git a/third_party/re2/re2/testing/dfa_test.cc b/third_party/re2/re2/testing/dfa_test.cc
index e9c7befd..8e95ae4b 100644
--- a/third_party/re2/re2/testing/dfa_test.cc
+++ b/third_party/re2/re2/testing/dfa_test.cc
@@ -2,16 +2,14 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "util/thread.h"
 #include "util/test.h"
+#include "util/thread.h"
 #include "re2/prog.h"
 #include "re2/re2.h"
 #include "re2/regexp.h"
 #include "re2/testing/regexp_generator.h"
 #include "re2/testing/string_generator.h"
 
-static const bool UsingMallocCounter = false;
-
 DECLARE_bool(re2_dfa_bail_when_slow);
 
 DEFINE_int32(size, 8, "log2(number of DFA nodes)");
@@ -44,7 +42,7 @@
   // Check that single-threaded code works.
   {
     //LOG(INFO) << s;
-    Regexp* re = Regexp::Parse(s, Regexp::LikePerl, NULL);
+    Regexp* re = Regexp::Parse(s.c_str(), Regexp::LikePerl, NULL);
     CHECK(re);
     Prog* prog = re->CompileToProg(0);
     CHECK(prog);
@@ -59,7 +57,7 @@
 
   // Build the DFA simultaneously in a bunch of threads.
   for (int i = 0; i < FLAGS_repeat; i++) {
-    Regexp* re = Regexp::Parse(s, Regexp::LikePerl, NULL);
+    Regexp* re = Regexp::Parse(s.c_str(), Regexp::LikePerl, NULL);
     CHECK(re);
     Prog* prog = re->CompileToProg(0);
     CHECK(prog);
@@ -94,13 +92,14 @@
     s += "[ab]";
   s += "b";
 
-  Regexp* re = Regexp::Parse(s, Regexp::LikePerl, NULL);
+  //LOG(INFO) << s;
+  Regexp* re = Regexp::Parse(s.c_str(), Regexp::LikePerl, NULL);
   CHECK(re);
   int max = 24;
   for (int i = 17; i < max; i++) {
-    int64 limit = 1<<i;
-    int64 usage;
-    //int64 progusage, dfamem;
+    int limit = 1<<i;
+    int usage;
+    //int progusage, dfamem;
     {
       testing::MallocCounter m(testing::MallocCounter::THIS_THREAD_ONLY);
       Prog* prog = re->CompileToProg(limit);
@@ -114,13 +113,10 @@
     }
     if (!UsingMallocCounter)
       continue;
-    //LOG(INFO) << "limit " << limit << ", "
-    //          << "prog usage " << progusage << ", "
-    //          << "DFA budget " << dfamem << ", "
-    //          << "total " << usage;
-    // Tolerate +/- 10%.
+    //LOG(INFO) << StringPrintf("Limit %d: prog used %d, DFA budget %d, total %d\n",
+    //                          limit, progusage, dfamem, usage);
     CHECK_GT(usage, limit*9/10);
-    CHECK_LT(usage, limit*11/10);
+    CHECK_LT(usage, limit + (16<<10));  // 16kB of slop okay
   }
   re->Decref();
 }
@@ -136,7 +132,7 @@
 // position in the input, never reusing any states until it gets to the
 // end of the string.  This is the worst possible case for DFA execution.
 static string DeBruijnString(int n) {
-  CHECK_LT(n, static_cast<int>(8*sizeof(int)));
+  CHECK_LT(n, 8*sizeof(int));
   CHECK_GT(n, 0);
 
   vector<bool> did(1<<n);
@@ -225,13 +221,13 @@
     peak_usage = m.PeakHeapGrowth();
     delete prog;
   }
+  re->Decref();
+
   if (!UsingMallocCounter)
     return;
-  //LOG(INFO) << "usage " << usage << ", "
-  //          << "peak usage " << peak_usage;
+  //LOG(INFO) << "usage " << usage << " " << peak_usage;
   CHECK_LT(usage, 1<<n);
   CHECK_LT(peak_usage, 1<<n);
-  re->Decref();
 }
 
 // Helper thread: searches for match, which should match,
diff --git a/third_party/re2/re2/testing/dump.cc b/third_party/re2/re2/testing/dump.cc
index 97030390..4bdf714 100644
--- a/third_party/re2/re2/testing/dump.cc
+++ b/third_party/re2/re2/testing/dump.cc
@@ -120,8 +120,6 @@
       DumpRegexpAppending(re->sub()[0], s);
       break;
     case kRegexpCapture:
-      if (re->cap() == 0)
-        LOG(DFATAL) << "kRegexpCapture cap() == 0";
       if (re->name()) {
         s->append(*re->name());
         s->append(":");
diff --git a/third_party/re2/re2/testing/exhaustive2_test.cc b/third_party/re2/re2/testing/exhaustive2_test.cc
index 6dc5016..c5fec5b 100644
--- a/third_party/re2/re2/testing/exhaustive2_test.cc
+++ b/third_party/re2/re2/testing/exhaustive2_test.cc
@@ -23,7 +23,7 @@
 TEST(Punctuation, Literals) {
   vector<string> alphabet = Explode("()*+?{}[]\\^$.");
   vector<string> escaped = alphabet;
-  for (size_t i = 0; i < escaped.size(); i++)
+  for (int i = 0; i < escaped.size(); i++)
     escaped[i] = "\\" + escaped[i];
   ExhaustiveTest(1, 1, escaped, RegexpGenerator::EgrepOps(),
                  2, alphabet, "", "");
diff --git a/third_party/re2/re2/testing/exhaustive3_test.cc b/third_party/re2/re2/testing/exhaustive3_test.cc
index 6e46bb4e..5613fcb 100644
--- a/third_party/re2/re2/testing/exhaustive3_test.cc
+++ b/third_party/re2/re2/testing/exhaustive3_test.cc
@@ -84,7 +84,7 @@
     "[[:upper:]] [[:xdigit:]] [\\s\\S] [\\d\\D] [^\\w\\W] [^\\d\\D]");
   vector<string> ops;  // no ops
   vector<string> alpha = InterestingUTF8();
-  for (size_t i = 0; i < alpha.size(); i++)
+  for (int i = 0; i < alpha.size(); i++)
     alpha[i] = "a" + alpha[i] + "b";
   ExhaustiveTest(1, 0, atoms, ops,
                  1, alpha, "a%sb", "");
diff --git a/third_party/re2/re2/testing/exhaustive_tester.cc b/third_party/re2/re2/testing/exhaustive_tester.cc
index 0e90f33..54de857 100644
--- a/third_party/re2/re2/testing/exhaustive_tester.cc
+++ b/third_party/re2/re2/testing/exhaustive_tester.cc
@@ -148,7 +148,7 @@
                     int maxstrlen, const vector<string>& stralphabet,
                     const string& wrapper,
                     const string& topwrapper) {
-  if (RE2_DEBUG_MODE && FLAGS_quick_debug_mode) {
+  if (DEBUG_MODE && FLAGS_quick_debug_mode) {
     if (maxatoms > 1)
       maxatoms--;
     if (maxops > 1)
diff --git a/third_party/re2/re2/testing/exhaustive_tester.h b/third_party/re2/re2/testing/exhaustive_tester.h
index 1facb979..38a139f 100644
--- a/third_party/re2/re2/testing/exhaustive_tester.h
+++ b/third_party/re2/re2/testing/exhaustive_tester.h
@@ -13,16 +13,6 @@
 
 namespace re2 {
 
-#if !defined(NDEBUG)
-// We are in a debug build.
-const bool RE2_DEBUG_MODE = true;
-#elif ADDRESS_SANITIZER || MEMORY_SANITIZER || THREAD_SANITIZER
-// Not a debug build, but still under sanitizers.
-const bool RE2_DEBUG_MODE = true;
-#else
-const bool RE2_DEBUG_MODE = false;
-#endif
-
 // Exhaustive regular expression test: generate all regexps within parameters,
 // then generate all strings of a given length over a given alphabet,
 // then check that NFA, DFA, and PCRE agree about whether each regexp matches
@@ -73,7 +63,7 @@
   bool randomstrings_;  // Whether to use random strings
   int32 stringseed_;    // If so, the seed.
   int stringcount_;     // If so, how many to generate.
-  DISALLOW_COPY_AND_ASSIGN(ExhaustiveTester);
+  DISALLOW_EVIL_CONSTRUCTORS(ExhaustiveTester);
 };
 
 // Runs an exhaustive test on the given parameters.
diff --git a/third_party/re2/re2/testing/filtered_re2_test.cc b/third_party/re2/re2/testing/filtered_re2_test.cc
index 76c1284..e3a0dd1 100644
--- a/third_party/re2/re2/testing/filtered_re2_test.cc
+++ b/third_party/re2/re2/testing/filtered_re2_test.cc
@@ -44,7 +44,7 @@
   FilterTestVars v;
   int id;
 
-  v.opts.set_encoding(RE2::Options::EncodingLatin1);
+  v.opts.set_utf8(false);
   v.f.Add("\xde\xadQ\xbe\xef", v.opts, &id);
   v.f.Compile(&v.atoms);
   EXPECT_EQ(1, v.atoms.size());
@@ -158,10 +158,10 @@
   if (!pass) {
     LOG(WARNING) << "Failed " << testname;
     LOG(WARNING) << "Expected #atoms = " << expected.size();
-    for (size_t i = 0; i < expected.size(); i++)
+    for (int i = 0; i < expected.size(); i++)
       LOG(WARNING) << expected[i];
     LOG(WARNING) << "Found #atoms = " << v->atoms.size();
-    for (size_t i = 0; i < v->atoms.size(); i++)
+    for (int i = 0; i < v->atoms.size(); i++)
       LOG(WARNING) << v->atoms[i];
   }
 
@@ -189,16 +189,18 @@
   EXPECT_EQ(0, nfail);
 }
 
-void FindAtomIndices(const vector<string>& atoms,
-                     const vector<string>& matched_atoms,
+void FindAtomIndices(const vector<string> atoms,
+                     const vector<string> matched_atoms,
                      vector<int>* atom_indices) {
   atom_indices->clear();
-  for (size_t i = 0; i < matched_atoms.size(); i++) {
-    for (size_t j = 0; j < atoms.size(); j++) {
+  for (int i = 0; i < matched_atoms.size(); i++) {
+    int j = 0;
+    for (; j < atoms.size(); j++) {
       if (matched_atoms[i] == atoms[j]) {
-        atom_indices->push_back(static_cast<int>(j));
+        atom_indices->push_back(j);
         break;
       }
+      EXPECT_LT(j, atoms.size());
     }
   }
 }
@@ -264,7 +266,7 @@
   atoms.push_back("yyyzzz");
   FindAtomIndices(v.atoms, atoms, &atom_ids);
   LOG(INFO) << "S: " << atom_ids.size();
-  for (size_t i = 0; i < atom_ids.size(); i++)
+  for (int i = 0; i < atom_ids.size(); i++)
     LOG(INFO) << "i: " << i << " : " << atom_ids[i];
   v.f.AllMatches(text, atom_ids, &matching_regexps);
   EXPECT_EQ(2, matching_regexps.size());
diff --git a/third_party/re2/re2/testing/null_walker.cc b/third_party/re2/re2/testing/null_walker.cc
index bc943f4..09b53cb 100644
--- a/third_party/re2/re2/testing/null_walker.cc
+++ b/third_party/re2/re2/testing/null_walker.cc
@@ -23,7 +23,7 @@
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(NullWalker);
+  DISALLOW_EVIL_CONSTRUCTORS(NullWalker);
 };
 
 // Called after visiting re's children.  child_args contains the return
diff --git a/third_party/re2/re2/testing/parse_test.cc b/third_party/re2/re2/testing/parse_test.cc
index 75c02966..f67b477 100644
--- a/third_party/re2/re2/testing/parse_test.cc
+++ b/third_party/re2/re2/testing/parse_test.cc
@@ -118,24 +118,14 @@
   { "(?:a)", "lit{a}" },
   { "(?:ab)(?:cd)", "str{abcd}" },
   { "(?:a|b)|(?:c|d)", "cc{0x61-0x64}" },
-  { "a|c", "cc{0x61 0x63}" },
-  { "a|[cd]", "cc{0x61 0x63-0x64}" },
   { "a|.", "dot{}" },
-  { "[ab]|c", "cc{0x61-0x63}" },
-  { "[ab]|[cd]", "cc{0x61-0x64}" },
-  { "[ab]|.", "dot{}" },
-  { ".|c", "dot{}" },
-  { ".|[cd]", "dot{}" },
-  { ".|.", "dot{}" },
+  { ".|a", "dot{}" },
 
   // Test Perl quoted literals
   { "\\Q+|*?{[\\E", "str{+|*?{[}" },
   { "\\Q+\\E+", "plus{lit{+}}" },
   { "\\Q\\\\E", "lit{\\}" },
   { "\\Q\\\\\\E", "str{\\\\}" },
-  { "\\Qa\\E*", "star{lit{a}}" },
-  { "\\Qab\\E*", "cat{lit{a}star{lit{b}}}" },
-  { "\\Qabc\\E*", "cat{str{ab}star{lit{c}}}" },
 
   // Test Perl \A and \z
   { "(?m)^", "bol{}" },
@@ -222,12 +212,12 @@
                          << status.Text();
     string s = re[i]->Dump();
     EXPECT_EQ(string(tests[i].parse), s) << "Regexp: " << tests[i].regexp
-      << "\nparse: " << string(tests[i].parse) << " s: " << s << " flag=" << f;
+      << "\nparse: " << tests[i].parse << " s: " << s << " flag=" << f;
   }
 
   for (int i = 0; i < ntests; i++) {
     for (int j = 0; j < ntests; j++) {
-      EXPECT_EQ(string(tests[i].parse) == string(tests[j].parse),
+      EXPECT_EQ(string(tests[i].parse) == tests[j].parse,
                 RegexpEqualTestingOnly(re[i], re[j]))
         << "Regexp: " << tests[i].regexp << " " << tests[j].regexp;
     }
@@ -309,14 +299,6 @@
     "cat{rep{2,2 lit{x}}alt{emp{}cc{0x30-0x39}}}" },
   { "x{2}y|x{2}[0-9]y",
     "cat{rep{2,2 lit{x}}alt{lit{y}cat{cc{0x30-0x39}lit{y}}}}" },
-  { "n|r|rs",
-    "alt{lit{n}cat{lit{r}alt{emp{}lit{s}}}}" },
-  { "n|rs|r",
-    "alt{lit{n}cat{lit{r}alt{lit{s}emp{}}}}" },
-  { "r|rs|n",
-    "alt{cat{lit{r}alt{emp{}lit{s}}}lit{n}}" },
-  { "rs|r|n",
-    "alt{cat{lit{r}alt{lit{s}emp{}}}lit{n}}" },
 };
 
 // Test that prefix factoring works.
@@ -324,22 +306,6 @@
   TestParse(prefix_tests, arraysize(prefix_tests), Regexp::PerlX, "prefix");
 }
 
-Test nested_tests[] = {
-  { "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}))",
-    "cap{cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 lit{x}}}}}}}}}}}}}}}}}}}}" },
-  { "((((((((((x{1}){2}){2}){2}){2}){2}){2}){2}){2}){2})",
-    "cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{1,1 lit{x}}}}}}}}}}}}}}}}}}}}}" },
-  { "((((((((((x{0}){2}){2}){2}){2}){2}){2}){2}){2}){2})",
-    "cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 cap{rep{0,0 lit{x}}}}}}}}}}}}}}}}}}}}}" },
-  { "((((((x{2}){2}){2}){5}){5}){5})",
-    "cap{rep{5,5 cap{rep{5,5 cap{rep{5,5 cap{rep{2,2 cap{rep{2,2 cap{rep{2,2 lit{x}}}}}}}}}}}}}" },
-};
-
-// Test that nested repetition works.
-TEST(TestParse, Nested) {
-  TestParse(nested_tests, arraysize(nested_tests), Regexp::PerlX, "nested");
-}
-
 // Invalid regular expressions
 const char* badtests[] = {
   "(",
@@ -363,9 +329,6 @@
   "(?i)[a-Z]",
   "a{100000}",
   "a{100000,}",
-  "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})",
-  "(((x{7}){11}){13})",
-  "\\Q\\E*",
 };
 
 // Valid in Perl, bad in POSIX
diff --git a/third_party/re2/re2/testing/possible_match_test.cc b/third_party/re2/re2/testing/possible_match_test.cc
index 4687165..7c2400eb5b 100644
--- a/third_party/re2/re2/testing/possible_match_test.cc
+++ b/third_party/re2/re2/testing/possible_match_test.cc
@@ -7,7 +7,6 @@
 #include "re2/prog.h"
 #include "re2/re2.h"
 #include "re2/regexp.h"
-#include "re2/testing/exhaustive_tester.h"
 #include "re2/testing/regexp_generator.h"
 #include "re2/testing/string_generator.h"
 
@@ -137,26 +136,26 @@
   // are no valid UTF-8 strings beginning with byte 0xFF.
   EXPECT_FALSE(RE2("[\\s\\S]+", RE2::Latin1).
                PossibleMatchRange(&min, &max, 10))
-      << "min=" << CEscape(min) << ", max=" << CEscape(max);
+    << "min=" << CEscape(min) << ", max=" << CEscape(max);
   EXPECT_FALSE(RE2("[\\0-\xFF]+", RE2::Latin1).
                PossibleMatchRange(&min, &max, 10))
-      << "min=" << CEscape(min) << ", max=" << CEscape(max);
+    << "min=" << CEscape(min) << ", max=" << CEscape(max);
   EXPECT_FALSE(RE2(".+hello", RE2::Latin1).
                PossibleMatchRange(&min, &max, 10))
-      << "min=" << CEscape(min) << ", max=" << CEscape(max);
+    << "min=" << CEscape(min) << ", max=" << CEscape(max);
   EXPECT_FALSE(RE2(".*hello", RE2::Latin1).
                PossibleMatchRange(&min, &max, 10))
-      << "min=" << CEscape(min) << ", max=" << CEscape(max);
+    << "min=" << CEscape(min) << ", max=" << CEscape(max);
   EXPECT_FALSE(RE2(".*", RE2::Latin1).
                PossibleMatchRange(&min, &max, 10))
-      << "min=" << CEscape(min) << ", max=" << CEscape(max);
+    << "min=" << CEscape(min) << ", max=" << CEscape(max);
   EXPECT_FALSE(RE2("\\C*").
                PossibleMatchRange(&min, &max, 10))
-      << "min=" << CEscape(min) << ", max=" << CEscape(max);
+    << "min=" << CEscape(min) << ", max=" << CEscape(max);
 
   // Fails because it's a malformed regexp.
   EXPECT_FALSE(RE2("*hello").PossibleMatchRange(&min, &max, 10))
-      << "min=" << CEscape(min) << ", max=" << CEscape(max);
+    << "min=" << CEscape(min) << ", max=" << CEscape(max);
 }
 
 // Exhaustive test: generate all regexps within parameters,
@@ -187,7 +186,7 @@
   int regexps_;   // Number of HandleRegexp calls
   int tests_;     // Number of regexp tests.
 
-  DISALLOW_COPY_AND_ASSIGN(PossibleMatchTester);
+  DISALLOW_EVIL_CONSTRUCTORS(PossibleMatchTester);
 };
 
 // Processes a single generated regexp.
@@ -225,7 +224,7 @@
   int natom = 3;
   int noperator = 3;
   int stringlen = 5;
-  if (RE2_DEBUG_MODE) {
+  if (DEBUG_MODE) {
     natom = 2;
     noperator = 3;
     stringlen = 3;
diff --git a/third_party/re2/re2/testing/random_test.cc b/third_party/re2/re2/testing/random_test.cc
index d67ae64..91d2b32 100644
--- a/third_party/re2/re2/testing/random_test.cc
+++ b/third_party/re2/re2/testing/random_test.cc
@@ -25,7 +25,7 @@
                        const string& wrapper) {
   // Limit to smaller test cases in debug mode,
   // because everything is so much slower.
-  if (RE2_DEBUG_MODE) {
+  if (DEBUG_MODE) {
     maxatoms--;
     maxops--;
     maxstrlen /= 2;
diff --git a/third_party/re2/re2/testing/re2_arg_test.cc b/third_party/re2/re2/testing/re2_arg_test.cc
index d843ffa5..ae7a7b0 100644
--- a/third_party/re2/re2/testing/re2_arg_test.cc
+++ b/third_party/re2/re2/testing/re2_arg_test.cc
@@ -84,24 +84,24 @@
 { "18446744073709551616", 0,    { false, false, false, false, false, false }},
 };
 
-const int kNumStrings = arraysize(kSuccessTable);
+const int kNumStrings = ARRAYSIZE(kSuccessTable);
 
-// It's ugly to use a macro, but we apparently can't use the EXPECT_EQ
+// It's ugly to use a macro, but we apparently can't use the ASSERT_TRUE_M
 // macro outside of a TEST block and this seems to be the only way to
 // avoid code duplication.  I can also pull off a couple nice tricks
 // using concatenation for the type I'm checking against.
 #define PARSE_FOR_TYPE(type, column) {                                   \
   type r;                                                                \
-  for (int i = 0; i < kNumStrings; ++i) {                                \
+  for ( int i = 0; i < kNumStrings; ++i ) {                              \
     RE2::Arg arg(&r);                                                    \
     const char* const p = kSuccessTable[i].value_string;                 \
-    bool retval = arg.Parse(p, static_cast<int>(strlen(p)));             \
+    bool retval = arg.Parse(p, strlen(p));                               \
     bool success = kSuccessTable[i].success[column];                     \
-    EXPECT_EQ(retval, success)                                           \
-        << "Parsing '" << p << "' for type " #type " should return "     \
-        << success;                                                      \
-    if (success) {                                                       \
-      EXPECT_EQ(r, (type)kSuccessTable[i].value);                        \
+    ASSERT_TRUE_M(retval == success,                                     \
+      StringPrintf("Parsing '%s' for type " #type " should return %d",   \
+                   p, success).c_str());                                 \
+    if ( success ) {                                                     \
+      ASSERT_EQUALS(r, kSuccessTable[i].value);                          \
     }                                                                    \
   }                                                                      \
 }
diff --git a/third_party/re2/re2/testing/re2_test.cc b/third_party/re2/re2/testing/re2_test.cc
index a1d9c57..911e868 100644
--- a/third_party/re2/re2/testing/re2_test.cc
+++ b/third_party/re2/re2/testing/re2_test.cc
@@ -5,18 +5,22 @@
 
 // TODO: Test extractions for PartialMatch/Consume
 
-#include <errno.h>
-#ifndef _MSC_VER
-#include <unistd.h>  /* for sysconf */
+#include <sys/types.h>
+#ifndef WIN32
 #include <sys/mman.h>
 #endif
 #include <sys/stat.h>
-#include <sys/types.h>
+#include <errno.h>
 #include <vector>
 #include "util/test.h"
 #include "re2/re2.h"
 #include "re2/regexp.h"
 
+#ifdef WIN32
+#include <stdio.h>
+#define snprintf _snprintf
+#endif
+
 DECLARE_bool(logtostderr);
 
 namespace re2 {
@@ -176,7 +180,7 @@
     { "", NULL, NULL, NULL, NULL, 0 }
   };
 
-  for (const ReplaceTest* t = tests; t->original != NULL; t++) {
+  for (const ReplaceTest *t = tests; t->original != NULL; ++t) {
     VLOG(1) << StringPrintf("\"%s\" =~ s/%s/%s/g", t->original, t->regexp, t->rewrite);
     string one(t->original);
     CHECK(RE2::Replace(&one, t->regexp, t->rewrite));
@@ -369,12 +373,12 @@
   CHECK_EQ(port, 9000);
 }
 
-static void TestRecursion(int size, const char* pattern) {
+static void TestRecursion(int size, const char *pattern) {
   // Fill up a string repeating the pattern given
   string domain;
   domain.resize(size);
-  size_t patlen = strlen(pattern);
-  for (int i = 0; i < size; i++) {
+  int patlen = strlen(pattern);
+  for (int i = 0; i < size; ++i) {
     domain[i] = pattern[i % patlen];
   }
   // Just make sure it doesn't crash due to too much recursion.
@@ -388,8 +392,8 @@
                           const RE2::Options& options = RE2::DefaultOptions) {
   string quoted = RE2::QuoteMeta(unquoted);
   RE2 re(quoted, options);
-  EXPECT_TRUE(RE2::FullMatch(unquoted, re))
-      << "Unquoted='" << unquoted << "', quoted='" << quoted << "'.";
+  EXPECT_TRUE_M(RE2::FullMatch(unquoted, re),
+                "Unquoted='" + unquoted + "', quoted='" + quoted + "'.");
 }
 
 // A meta-quoted string, interpreted as a pattern, should always match
@@ -398,8 +402,8 @@
                                   const RE2::Options& options = RE2::DefaultOptions) {
   string quoted = RE2::QuoteMeta(unquoted);
   RE2 re(quoted, options);
-  EXPECT_FALSE(RE2::FullMatch(should_not_match, re))
-      << "Unquoted='" << unquoted << "', quoted='" << quoted << "'.";
+  EXPECT_FALSE_M(RE2::FullMatch(should_not_match, re),
+                 "Unquoted='" + unquoted + "', quoted='" + quoted + "'.");
 }
 
 // Tests that quoted meta characters match their original strings,
@@ -465,38 +469,13 @@
 TEST(ProgramSize, BigProgram) {
   RE2 re_simple("simple regexp");
   RE2 re_medium("medium.*regexp");
-  RE2 re_complex("complex.{1,128}regexp");
+  RE2 re_complex("hard.{1,128}regexp");
 
   CHECK_GT(re_simple.ProgramSize(), 0);
   CHECK_GT(re_medium.ProgramSize(), re_simple.ProgramSize());
   CHECK_GT(re_complex.ProgramSize(), re_medium.ProgramSize());
 }
 
-TEST(ProgramFanout, BigProgram) {
-  RE2 re1("(?:(?:(?:(?:(?:.)?){1})*)+)");
-  RE2 re10("(?:(?:(?:(?:(?:.)?){10})*)+)");
-  RE2 re100("(?:(?:(?:(?:(?:.)?){100})*)+)");
-  RE2 re1000("(?:(?:(?:(?:(?:.)?){1000})*)+)");
-
-  map<int, int> histogram;
-
-  // 3 is the largest non-empty bucket and has 1 element.
-  CHECK_EQ(3, re1.ProgramFanout(&histogram));
-  CHECK_EQ(1, histogram[3]);
-
-  // 7 is the largest non-empty bucket and has 10 elements.
-  CHECK_EQ(7, re10.ProgramFanout(&histogram));
-  CHECK_EQ(10, histogram[7]);
-
-  // 10 is the largest non-empty bucket and has 100 elements.
-  CHECK_EQ(10, re100.ProgramFanout(&histogram));
-  CHECK_EQ(100, histogram[10]);
-
-  // 13 is the largest non-empty bucket and has 1000 elements.
-  CHECK_EQ(13, re1000.ProgramFanout(&histogram));
-  CHECK_EQ(1000, histogram[13]);
-}
-
 // Issue 956519: handling empty character sets was
 // causing NULL dereference.  This tests a few empty character sets.
 // (The way to get an empty character set is to negate a full one.)
@@ -511,21 +490,6 @@
     CHECK(!RE2(empties[i]).Match("abc", 0, 3, RE2::UNANCHORED, NULL, 0));
 }
 
-// Bitstate assumes that kInstFail instructions in
-// alternations or capture groups have been "compiled away".
-TEST(EmptyCharset, BitstateAssumptions) {
-  // Captures trigger use of Bitstate.
-  static const char *nop_empties[] = {
-    "((((()))))" "[^\\S\\s]?",
-    "((((()))))" "([^\\S\\s])?",
-    "((((()))))" "([^\\S\\s]|[^\\S\\s])?",
-    "((((()))))" "(([^\\S\\s]|[^\\S\\s])|)"
-  };
-  StringPiece group[6];
-  for (int i = 0; i < arraysize(nop_empties); i++)
-    CHECK(RE2(nop_empties[i]).Match("", 0, 0, RE2::UNANCHORED, group, 6));
-}
-
 // Test that named groups work correctly.
 TEST(Capture, NamedGroups) {
   {
@@ -547,34 +511,6 @@
   }
 }
 
-TEST(RE2, CapturedGroupTest) {
-  RE2 re("directions from (?P<S>.*) to (?P<D>.*)");
-  int num_groups = re.NumberOfCapturingGroups();
-  EXPECT_EQ(2, num_groups);
-  string args[4];
-  RE2::Arg arg0(&args[0]);
-  RE2::Arg arg1(&args[1]);
-  RE2::Arg arg2(&args[2]);
-  RE2::Arg arg3(&args[3]);
-
-  const RE2::Arg* const matches[4] = {&arg0, &arg1, &arg2, &arg3};
-  EXPECT_TRUE(RE2::FullMatchN("directions from mountain view to san jose",
-                              re, matches, num_groups));
-  const map<string, int>& named_groups = re.NamedCapturingGroups();
-  EXPECT_TRUE(named_groups.find("S") != named_groups.end());
-  EXPECT_TRUE(named_groups.find("D") != named_groups.end());
-
-  // The named group index is 1-based.
-  int source_group_index = named_groups.find("S")->second;
-  int destination_group_index = named_groups.find("D")->second;
-  EXPECT_EQ(1, source_group_index);
-  EXPECT_EQ(2, destination_group_index);
-
-  // The args is zero-based.
-  EXPECT_EQ("mountain view", args[source_group_index - 1]);
-  EXPECT_EQ("san jose", args[destination_group_index - 1]);
-}
-
 TEST(RE2, FullMatchWithNoArgs) {
   CHECK(RE2::FullMatch("h", "h"));
   CHECK(RE2::FullMatch("hello", "hello"));
@@ -728,12 +664,10 @@
   CHECK(!RE2::FullMatch("hello", "(.*)", (float*)NULL));
 }
 
+#ifndef WIN32
 // Check that numeric parsing code does not read past the end of
 // the number being parsed.
-// This implementation requires mmap(2) et al. and thus cannot
-// be used unless they are available.
 TEST(RE2, NULTerminated) {
-#if defined(_POSIX_MAPPED_FILES) && _POSIX_MAPPED_FILES > 0
   char *v;
   int x;
   long pagesize = sysconf(_SC_PAGE_SIZE);
@@ -751,12 +685,12 @@
   x = 0;
   CHECK(RE2::FullMatch(StringPiece(v + pagesize - 1, 1), "(.*)", &x));
   CHECK_EQ(x, 1);
-#endif
 }
+#endif
 
 TEST(RE2, FullMatchTypeTests) {
   // Type tests
-  string zeros(1000, '0');
+  string zeros(100, '0');
   {
     char c;
     CHECK(RE2::FullMatch("Hello", "(H)ello", &c));
@@ -858,13 +792,12 @@
 }
 
 TEST(RE2, FloatingPointFullMatchTypes) {
-  string zeros(1000, '0');
+  string zeros(100, '0');
   {
     float v;
     CHECK(RE2::FullMatch("100",   "(.*)", &v));  CHECK_EQ(v, 100);
     CHECK(RE2::FullMatch("-100.", "(.*)", &v));  CHECK_EQ(v, -100);
     CHECK(RE2::FullMatch("1e23",  "(.*)", &v));  CHECK_EQ(v, float(1e23));
-    CHECK(RE2::FullMatch(" 100",  "(.*)", &v));  CHECK_EQ(v, 100);
 
     CHECK(RE2::FullMatch(zeros + "1e23",  "(.*)", &v));
     CHECK_EQ(v, float(1e23));
@@ -1064,14 +997,14 @@
   // Check UTF-8 handling
   // Three Japanese characters (nihongo)
   const char utf8_string[] = {
-       (char)0xe6, (char)0x97, (char)0xa5, // 65e5
-       (char)0xe6, (char)0x9c, (char)0xac, // 627c
-       (char)0xe8, (char)0xaa, (char)0x9e, // 8a9e
+       0xe6, 0x97, 0xa5, // 65e5
+       0xe6, 0x9c, 0xac, // 627c
+       0xe8, 0xaa, 0x9e, // 8a9e
        0
   };
   const char utf8_pattern[] = {
        '.',
-       (char)0xe6, (char)0x9c, (char)0xac, // 627c
+       0xe6, 0x9c, 0xac, // 627c
        '.',
        0
   };
@@ -1320,16 +1253,6 @@
   }
 }
 
-// Check that dot_nl option works.
-TEST(RE2, DotNL) {
-  RE2::Options opt;
-  opt.set_dot_nl(true);
-  EXPECT_TRUE(RE2::PartialMatch("\n", RE2(".", opt)));
-  EXPECT_FALSE(RE2::PartialMatch("\n", RE2("(?-s).", opt)));
-  opt.set_never_nl(true);
-  EXPECT_FALSE(RE2::PartialMatch("\n", RE2(".", opt)));
-}
-
 // Check that there are no capturing groups in "never capture" mode.
 TEST(RE2, NeverCapture) {
   RE2::Options opt;
@@ -1454,79 +1377,4 @@
   EXPECT_EQ(RE2("ca[t-z]$").Regexp()->ToString(), "ca[t-z](?-m:$)");
 }
 
-// Issue 10131674
-TEST(RE2, Bug10131674) {
-  // Some of these escapes describe values that do not fit in a byte.
-  RE2 re("\\140\\440\\174\\271\\150\\656\\106\\201\\004\\332", RE2::Latin1);
-  EXPECT_FALSE(re.ok());
-  EXPECT_FALSE(RE2::FullMatch("hello world", re));
-}
-
-TEST(RE2, Bug18391750) {
-  // Stray write past end of match_ in nfa.cc, caught by fuzzing + address sanitizer.
-  const char t[] = {
-      (char)0x28, (char)0x28, (char)0xfc, (char)0xfc, (char)0x08, (char)0x08,
-      (char)0x26, (char)0x26, (char)0x28, (char)0xc2, (char)0x9b, (char)0xc5,
-      (char)0xc5, (char)0xd4, (char)0x8f, (char)0x8f, (char)0x69, (char)0x69,
-      (char)0xe7, (char)0x29, (char)0x7b, (char)0x37, (char)0x31, (char)0x31,
-      (char)0x7d, (char)0xae, (char)0x7c, (char)0x7c, (char)0xf3, (char)0x29,
-      (char)0xae, (char)0xae, (char)0x2e, (char)0x2a, (char)0x29, (char)0x00,
-  };
-  RE2::Options opt;
-  opt.set_encoding(RE2::Options::EncodingLatin1);
-  opt.set_longest_match(true);
-  opt.set_dot_nl(true);
-  opt.set_case_sensitive(false);
-  RE2 re(t, opt);
-  CHECK(re.ok());
-  RE2::PartialMatch(t, re);
-}
-
-TEST(RE2, Bug18458852) {
-  // Bug in parser accepting invalid (too large) rune,
-  // causing compiler to fail in DCHECK in UTF-8
-  // character class code.
-  const char b[] = {
-      (char)0x28, (char)0x05, (char)0x05, (char)0x41, (char)0x41, (char)0x28,
-      (char)0x24, (char)0x5b, (char)0x5e, (char)0xf5, (char)0x87, (char)0x87,
-      (char)0x90, (char)0x29, (char)0x5d, (char)0x29, (char)0x29, (char)0x00,
-  };
-  RE2 re(b);
-  CHECK(!re.ok());
-}
-
-TEST(RE2, Bug18523943) {
-  // Bug in bitstate: case kFailInst was merged into the default with LOG(DFATAL).
-
-  RE2::Options opt;
-  const char a[] = {
-      (char)0x29, (char)0x29, (char)0x24, (char)0x00,
-  };
-  const char b[] = {
-      (char)0x28, (char)0x0a, (char)0x2a, (char)0x2a, (char)0x29, (char)0x00,
-  };
-  opt.set_log_errors(false);
-  opt.set_encoding(RE2::Options::EncodingLatin1);
-  opt.set_posix_syntax(true);
-  opt.set_longest_match(true);
-  opt.set_literal(false);
-  opt.set_never_nl(true);
-
-  RE2 re((const char*)b, opt);
-  CHECK(re.ok());
-  string s1;
-  CHECK(!RE2::PartialMatch((const char*)a, re, &s1));
-}
-
-TEST(RE2, Bug21371806) {
-  // Bug in parser accepting Unicode groups in Latin-1 mode,
-  // causing compiler to fail in DCHECK in prog.cc.
-
-  RE2::Options opt;
-  opt.set_encoding(RE2::Options::EncodingLatin1);
-
-  RE2 re("g\\p{Zl}]", opt);
-  CHECK(re.ok());
-}
-
 }  // namespace re2
diff --git a/third_party/re2/re2/testing/regexp_benchmark.cc b/third_party/re2/re2/testing/regexp_benchmark.cc
index 6c19858..ca7627f 100644
--- a/third_party/re2/re2/testing/regexp_benchmark.cc
+++ b/third_party/re2/re2/testing/regexp_benchmark.cc
@@ -135,15 +135,13 @@
 // Generate random text that won't contain the search string,
 // to test worst-case search behavior.
 void MakeText(string* text, int nbytes) {
-  srand(1);
   text->resize(nbytes);
+  srand(0);
   for (int i = 0; i < nbytes; i++) {
-    // Generate a one-byte rune that isn't a control character (e.g. '\n').
-    // Clipping to 0x20 introduces some bias, but we don't need uniformity.
-    int byte = rand() & 0x7F;
-    if (byte < 0x20)
-      byte = 0x20;
-    (*text)[i] = byte;
+    if (!rand()%30)
+      (*text)[i] = '\n';
+    else
+      (*text)[i] = rand()%(0x7E + 1 - 0x20)+0x20;
   }
 }
 
@@ -265,7 +263,6 @@
 BENCHMARK_RANGE(Search_BigFixed_CachedRE2,     8, 1<<20)->ThreadRange(1, NumCPUs());
 
 // Benchmark: FindAndConsume
-
 void FindAndConsume(int iters, int nbytes) {
   StopBenchmarkTiming();
   string s;
@@ -287,11 +284,9 @@
 // Benchmark: successful anchored search.
 
 void SearchSuccess(int iters, int nbytes, const char* regexp, SearchImpl* search) {
-  StopBenchmarkTiming();
   string s;
   MakeText(&s, nbytes);
   BenchmarkMemoryUsage();
-  StartBenchmarkTiming();
   search(iters, regexp, s, Prog::kAnchored, true);
   SetBenchmarkBytesProcessed(static_cast<int64>(iters)*nbytes);
 }
@@ -349,9 +344,11 @@
 // Benchmark: use regexp to find phone number.
 
 void SearchDigits(int iters, SearchImpl* search) {
-  StringPiece s("650-253-0001");
+  const char *text = "650-253-0001";
+  int len = strlen(text);
   BenchmarkMemoryUsage();
-  search(iters, "([0-9]+)-([0-9]+)-([0-9]+)", s, Prog::kAnchored, true);
+  search(iters, "([0-9]+)-([0-9]+)-([0-9]+)",
+         StringPiece(text, len), Prog::kAnchored, true);
   SetBenchmarkItemsProcessed(iters);
 }
 
@@ -689,6 +686,7 @@
 BENCHMARK(BM_Regexp_NullWalk)->ThreadRange(1, NumCPUs());
 BENCHMARK(BM_RE2_Compile)->ThreadRange(1, NumCPUs());
 
+
 // Makes text of size nbytes, then calls run to search
 // the text for regexp iters times.
 void SearchPhone(int iters, int nbytes, ParseImpl* search) {
diff --git a/third_party/re2/re2/testing/regexp_generator.cc b/third_party/re2/re2/testing/regexp_generator.cc
index fd085db..cf2db11 100644
--- a/third_party/re2/re2/testing/regexp_generator.cc
+++ b/third_party/re2/re2/testing/regexp_generator.cc
@@ -111,7 +111,7 @@
 
   // Add atoms if there is room.
   if (atoms < maxatoms_) {
-    for (size_t i = 0; i < atoms_.size(); i++) {
+    for (int i = 0; i < atoms_.size(); i++) {
       post->push_back(atoms_[i]);
       GeneratePostfix(post, nstk + 1, ops, atoms + 1);
       post->pop_back();
@@ -120,7 +120,7 @@
 
   // Add operators if there are enough arguments.
   if (ops < maxops_) {
-    for (size_t i = 0; i < ops_.size(); i++) {
+    for (int i = 0; i < ops_.size(); i++) {
       const string& fmt = ops_[i];
       int nargs = CountArgs(fmt);
       if (nargs <= nstk) {
@@ -134,7 +134,7 @@
 
 // Generates a random postfix command sequence.
 // Stops and returns true once a single sequence has been generated.
-bool RegexpGenerator::GenerateRandomPostfix(vector<string>* post, int nstk,
+bool RegexpGenerator::GenerateRandomPostfix(vector<string> *post, int nstk,
                                             int ops, int atoms) {
   for (;;) {
     // Stop if we get to a single element, but only sometimes.
@@ -151,7 +151,7 @@
 
     // Add operators if there are enough arguments.
     if (ops < maxops_ && acm_->Uniform(2) == 0) {
-      const string& fmt = ops_[acm_->Uniform(static_cast<int32>(ops_.size()))];
+      const string& fmt = ops_[acm_->Uniform(ops_.size())];
       int nargs = CountArgs(fmt);
       if (nargs <= nstk) {
         post->push_back(fmt);
@@ -165,7 +165,7 @@
 
     // Add atoms if there is room.
     if (atoms < maxatoms_ && acm_->Uniform(2) == 0) {
-      post->push_back(atoms_[acm_->Uniform(static_cast<int32>(atoms_.size()))]);
+      post->push_back(atoms_[acm_->Uniform(atoms_.size())]);
       bool ret = GenerateRandomPostfix(post, nstk + 1, ops, atoms + 1);
       post->pop_back();
       if (ret)
@@ -179,7 +179,7 @@
 // in (?: ) to avoid needing to maintain a precedence table.
 void RegexpGenerator::RunPostfix(const vector<string>& post) {
   stack<string> regexps;
-  for (size_t i = 0; i < post.size(); i++) {
+  for (int i = 0; i < post.size(); i++) {
     switch (CountArgs(post[i])) {
       default:
         LOG(FATAL) << "Bad operator: " << post[i];
@@ -208,7 +208,7 @@
   if (regexps.size() != 1) {
     // Internal error - should never happen.
     printf("Bad regexp program:\n");
-    for (size_t i = 0; i < post.size(); i++) {
+    for (int i = 0; i < post.size(); i++) {
       printf("  %s\n", CEscape(post[i]).c_str());
     }
     printf("Stack after running program:\n");
diff --git a/third_party/re2/re2/testing/regexp_generator.h b/third_party/re2/re2/testing/regexp_generator.h
index 3ba0d70..b4506f2 100644
--- a/third_party/re2/re2/testing/regexp_generator.h
+++ b/third_party/re2/re2/testing/regexp_generator.h
@@ -53,7 +53,7 @@
   vector<string> atoms_;   // Possible atoms.
   vector<string> ops_;     // Possible ops.
   ACMRandom* acm_;         // Random generator.
-  DISALLOW_COPY_AND_ASSIGN(RegexpGenerator);
+  DISALLOW_EVIL_CONSTRUCTORS(RegexpGenerator);
 };
 
 // Helpers for preparing arguments to RegexpGenerator constructor.
diff --git a/third_party/re2/re2/testing/regexp_test.cc b/third_party/re2/re2/testing/regexp_test.cc
index 31c76a3b..f317cbc 100644
--- a/third_party/re2/re2/testing/regexp_test.cc
+++ b/third_party/re2/re2/testing/regexp_test.cc
@@ -29,11 +29,10 @@
   Regexp* x;
   x = Regexp::Parse("x", Regexp::NoParseFlags, NULL);
   vector<Regexp*> v(90000, x);  // ToString bails out at 100000
-  for (size_t i = 0; i < v.size(); i++)
+  for (int i = 0; i < v.size(); i++)
     x->Incref();
-  CHECK_EQ(x->Ref(), 1 + static_cast<int>(v.size())) << x->Ref();
-  Regexp* re = Regexp::Concat(v.data(), static_cast<int>(v.size()),
-                              Regexp::NoParseFlags);
+  CHECK_EQ(x->Ref(), 1 + v.size()) << x->Ref();
+  Regexp* re = Regexp::Concat(&v[0], v.size(), Regexp::NoParseFlags);
   CHECK_EQ(re->ToString(), string(v.size(), 'x'));
   re->Decref();
   CHECK_EQ(x->Ref(), 1) << x->Ref();
diff --git a/third_party/re2/re2/testing/required_prefix_test.cc b/third_party/re2/re2/testing/required_prefix_test.cc
index aed41f7..1f0b216 100644
--- a/third_party/re2/re2/testing/required_prefix_test.cc
+++ b/third_party/re2/re2/testing/required_prefix_test.cc
@@ -28,7 +28,7 @@
 
   // Otherwise, it should work.
   { "^abc$", true, "abc", false, "(?-m:$)" },
-  { "^abc", true, "abc", false, "" },
+  { "^abc", "true", "abc", false, "" },
   { "^(?i)abc", true, "abc", true, "" },
   { "^abcd*", true, "abc", false, "d*" },
   { "^[Aa][Bb]cd*", true, "ab", true, "cd*" },
diff --git a/third_party/re2/re2/testing/set_test.cc b/third_party/re2/re2/testing/set_test.cc
index 4e267ae062..74058a4 100644
--- a/third_party/re2/re2/testing/set_test.cc
+++ b/third_party/re2/re2/testing/set_test.cc
@@ -71,10 +71,10 @@
 
 TEST(Set, UnanchoredDollar) {
   RE2::Set s(RE2::DefaultOptions, RE2::UNANCHORED);
-
+  
   CHECK_EQ(s.Add("foo$", NULL), 0);
   CHECK_EQ(s.Compile(), true);
-
+  
   vector<int> v;
   CHECK_EQ(s.Match("foo", &v), true);
   CHECK_EQ(v.size(), 1);
@@ -107,34 +107,8 @@
   CHECK_EQ(s.Match("bar", &v), true);
   CHECK_EQ(v.size(), 1);
   CHECK_EQ(v[0], 1);
-}
 
-TEST(Set, EmptyUnanchored) {
-  RE2::Set s(RE2::DefaultOptions, RE2::UNANCHORED);
-
-  CHECK_EQ(s.Compile(), true);
-
-  vector<int> v;
-  CHECK_EQ(s.Match("", &v), false);
-  CHECK_EQ(v.size(), 0);
-
-  v.clear();
-  CHECK_EQ(s.Match("foobar", &v), false);
-  CHECK_EQ(v.size(), 0);
-}
-
-TEST(Set, EmptyAnchored) {
-  RE2::Set s(RE2::DefaultOptions, RE2::ANCHOR_BOTH);
-
-  CHECK_EQ(s.Compile(), true);
-
-  vector<int> v;
-  CHECK_EQ(s.Match("", &v), false);
-  CHECK_EQ(v.size(), 0);
-
-  v.clear();
-  CHECK_EQ(s.Match("foobar", &v), false);
-  CHECK_EQ(v.size(), 0);
 }
 
 }  // namespace re2
+
diff --git a/third_party/re2/re2/testing/simplify_test.cc b/third_party/re2/re2/testing/simplify_test.cc
index 9db41eeb..d54837c 100644
--- a/third_party/re2/re2/testing/simplify_test.cc
+++ b/third_party/re2/re2/testing/simplify_test.cc
@@ -136,99 +136,6 @@
   { "(){1}", "()" },
   { "(){1,}", "()+" },
   { "(){0,2}", "(?:()()?)?" },
-
-  // Test that coalescing occurs and that the resulting repeats are simplified.
-  // Two-op combinations of *, +, ?, {n}, {n,} and {n,m} with a literal:
-  { "a*a*", "a*" },
-  { "a*a+", "a+" },
-  { "a*a?", "a*" },
-  { "a*a{2}", "aa+" },
-  { "a*a{2,}", "aa+" },
-  { "a*a{2,3}", "aa+" },
-  { "a+a*", "a+" },
-  { "a+a+", "aa+" },
-  { "a+a?", "a+" },
-  { "a+a{2}", "aaa+" },
-  { "a+a{2,}", "aaa+" },
-  { "a+a{2,3}", "aaa+" },
-  { "a?a*", "a*" },
-  { "a?a+", "a+" },
-  { "a?a?", "(?:aa?)?" },
-  { "a?a{2}", "aaa?" },
-  { "a?a{2,}", "aa+" },
-  { "a?a{2,3}", "aa(?:aa?)?" },
-  { "a{2}a*", "aa+" },
-  { "a{2}a+", "aaa+" },
-  { "a{2}a?", "aaa?" },
-  { "a{2}a{2}", "aaaa" },
-  { "a{2}a{2,}", "aaaa+" },
-  { "a{2}a{2,3}", "aaaaa?" },
-  { "a{2,}a*", "aa+" },
-  { "a{2,}a+", "aaa+" },
-  { "a{2,}a?", "aa+" },
-  { "a{2,}a{2}", "aaaa+" },
-  { "a{2,}a{2,}", "aaaa+" },
-  { "a{2,}a{2,3}", "aaaa+" },
-  { "a{2,3}a*", "aa+" },
-  { "a{2,3}a+", "aaa+" },
-  { "a{2,3}a?", "aa(?:aa?)?" },
-  { "a{2,3}a{2}", "aaaaa?" },
-  { "a{2,3}a{2,}", "aaaa+" },
-  { "a{2,3}a{2,3}", "aaaa(?:aa?)?" },
-  // With a char class, any char and any byte:
-  { "\\d*\\d*", "[0-9]*" },
-  { ".*.*", ".*" },
-  { "\\C*\\C*", "\\C*" },
-  // FoldCase works, but must be consistent:
-  { "(?i)A*a*", "[Aa]*" },
-  { "(?i)a+A+", "[Aa][Aa]+" },
-  { "(?i)A*(?-i)a*", "[Aa]*a*" },
-  { "(?i)a+(?-i)A+", "[Aa]+A+" },
-  // NonGreedy works, but must be consistent:
-  { "a*?a*?", "a*?" },
-  { "a+?a+?", "aa+?" },
-  { "a*?a*", "a*?a*" },
-  { "a+a+?", "a+a+?" },
-  // The second element is the literal, char class, any char or any byte:
-  { "a*a", "a+" },
-  { "\\d*\\d", "[0-9]+" },
-  { ".*.", ".+" },
-  { "\\C*\\C", "\\C+" },
-  // FoldCase works, but must be consistent:
-  { "(?i)A*a", "[Aa]+" },
-  { "(?i)a+A", "[Aa][Aa]+" },
-  { "(?i)A*(?-i)a", "[Aa]*a" },
-  { "(?i)a+(?-i)A", "[Aa]+A" },
-  // The second element is a literal string that begins with the literal:
-  { "a*aa", "aa+" },
-  { "a*aab", "aa+b" },
-  // FoldCase works, but must be consistent:
-  { "(?i)a*aa", "[Aa][Aa]+" },
-  { "(?i)a*aab", "[Aa][Aa]+[Bb]" },
-  { "(?i)a*(?-i)aa", "[Aa]*aa" },
-  { "(?i)a*(?-i)aab", "[Aa]*aab" },
-  // Negative tests with mismatching ops:
-  { "a*b*", "a*b*" },
-  { "\\d*\\D*", "[0-9]*[^0-9]*" },
-  { "a+b", "a+b" },
-  { "\\d+\\D", "[0-9]+[^0-9]" },
-  { "a?bb", "a?bb" },
-  // Negative tests with capturing groups:
-  { "(a*)a*", "(a*)a*" },
-  { "a+(a)", "a+(a)" },
-  { "(a?)(aa)", "(a?)(aa)" },
-  // Just for fun:
-  { "aa*aa+aa?aa{2}aaa{2,}aaa{2,3}a", "aaaaaaaaaaaaaaaa+" },
-
-  // During coalescing, the child of the repeat changes, so we build a new
-  // repeat. The new repeat must have the min and max of the old repeat.
-  // Failure to copy them results in min=0 and max=0 -> empty match.
-  { "(?:a*aab){2}", "aa+baa+b" },
-
-  // During coalescing, the child of the capture changes, so we build a new
-  // capture. The new capture must have the cap of the old capture.
-  // Failure to copy it results in cap=0 -> ToString() logs a fatal error.
-  { "(a*aab)", "(aa+b)" },
 };
 
 TEST(TestSimplify, SimpleRegexps) {
diff --git a/third_party/re2/re2/testing/string_generator.cc b/third_party/re2/re2/testing/string_generator.cc
index f96ff20..5be6d3e 100644
--- a/third_party/re2/re2/testing/string_generator.cc
+++ b/third_party/re2/re2/testing/string_generator.cc
@@ -43,14 +43,14 @@
 // Returns false if all the numbers have been used.
 bool StringGenerator::IncrementDigits() {
   // First try to increment the current number.
-  for (int i = static_cast<int>(digits_.size()) - 1; i >= 0; i--) {
-    if (++digits_[i] < static_cast<int>(alphabet_.size()))
+  for (int i = digits_.size() - 1; i >= 0; i--) {
+    if (++digits_[i] < alphabet_.size())
       return true;
     digits_[i] = 0;
   }
 
   // If that failed, make a longer number.
-  if (static_cast<int>(digits_.size()) < maxlen_) {
+  if (digits_.size() < maxlen_) {
     digits_.push_back(0);
     return true;
   }
@@ -68,7 +68,7 @@
   int len = acm_->Uniform(maxlen_+1);
   digits_.resize(len);
   for (int i = 0; i < len; i++)
-    digits_[i] = acm_->Uniform(static_cast<int32>(alphabet_.size()));
+    digits_[i] = acm_->Uniform(alphabet_.size());
   return true;
 }
 
@@ -84,7 +84,7 @@
     return sp_;
   }
   s_.clear();
-  for (size_t i = 0; i < digits_.size(); i++) {
+  for (int i = 0; i < digits_.size(); i++) {
     s_ += alphabet_[digits_[i]];
   }
   hasnext_ = random_ ? RandomDigits() : IncrementDigits();
@@ -110,3 +110,4 @@
 }
 
 }  // namespace re2
+
diff --git a/third_party/re2/re2/testing/string_generator.h b/third_party/re2/re2/testing/string_generator.h
index 52e5e22c..6a9ef42 100644
--- a/third_party/re2/re2/testing/string_generator.h
+++ b/third_party/re2/re2/testing/string_generator.h
@@ -50,7 +50,7 @@
   bool random_;              // Whether generated strings are random.
   int nrandom_;              // Number of random strings left to generate.
   ACMRandom* acm_;           // Random number generator
-  DISALLOW_COPY_AND_ASSIGN(StringGenerator);
+  DISALLOW_EVIL_CONSTRUCTORS(StringGenerator);
 };
 
 }  // namespace re2
diff --git a/third_party/re2/re2/testing/tester.cc b/third_party/re2/re2/testing/tester.cc
index cb12bad..003dc5ad 100644
--- a/third_party/re2/re2/testing/tester.cc
+++ b/third_party/re2/re2/testing/tester.cc
@@ -246,7 +246,6 @@
   // 2. It treats $ as this weird thing meaning end of string
   //    or before the \n at the end of the string.
   // 3. It doesn't implement POSIX leftmost-longest matching.
-  // 4. It lets \s match vertical tab.
   // MimicsPCRE() detects 1 and 2.
   if ((Engines() & (1<<kEnginePCRE)) && regexp_->MimicsPCRE() &&
       kind_ != Prog::kLongestMatch) {
@@ -344,8 +343,7 @@
                                Prog::kAnchored, Prog::kLongestMatch,
                                result->submatch,
                                &result->skipped, NULL)) {
-          LOG(ERROR) << "Reverse DFA inconsistency: "
-                     << CEscape(regexp_str_)
+          LOG(ERROR) << "Reverse DFA inconsistency: " << CEscape(regexp_str_)
                      << " on " << CEscape(text);
           result->matched = false;
         }
@@ -392,13 +390,10 @@
       if (kind_ == Prog::kFullMatch)
         re_anchor = RE2::ANCHOR_BOTH;
 
-      result->matched = re2_->Match(
-          context,
-          static_cast<int>(text.begin() - context.begin()),
-          static_cast<int>(text.end() - context.begin()),
-          re_anchor,
-          result->submatch,
-          nsubmatch);
+      result->matched = re2_->Match(context,
+                                    text.begin() - context.begin(),
+                                    text.end() - context.begin(),
+                                    re_anchor, result->submatch, nsubmatch);
       result->have_submatch = nsubmatch > 0;
       break;
     }
@@ -410,14 +405,6 @@
         break;
       }
 
-      // PCRE 8.34 or so started allowing vertical tab to match \s,
-      // following a change made in Perl 5.18. RE2 does not.
-      if ((regexp_str_.contains("\\s") || regexp_str_.contains("\\S")) &&
-          text.contains("\v")) {
-        result->skipped = true;
-        break;
-      }
-
       const PCRE::Arg **argptr = new const PCRE::Arg*[nsubmatch];
       PCRE::Arg *a = new PCRE::Arg[nsubmatch];
       for (int i = 0; i < nsubmatch; i++) {
@@ -518,7 +505,7 @@
     }
 
     // We disagree with PCRE on the meaning of some Unicode matches.
-    // In particular, we treat non-ASCII UTF-8 as non-word characters.
+    // In particular, we treat all non-ASCII UTF-8 as word characters.
     // We also treat "empty" character sets like [^\w\W] as being
     // impossible to match, while PCRE apparently excludes some code
     // points (e.g., 0x0080) from both \w and \W.
@@ -605,14 +592,14 @@
 }
 
 Tester::~Tester() {
-  for (size_t i = 0; i < v_.size(); i++)
+  for (int i = 0; i < v_.size(); i++)
     delete v_[i];
 }
 
 bool Tester::TestCase(const StringPiece& text, const StringPiece& context,
                          Prog::Anchor anchor) {
   bool okay = true;
-  for (size_t i = 0; i < v_.size(); i++)
+  for (int i = 0; i < v_.size(); i++)
     okay &= (!v_[i]->error() && v_[i]->RunCase(text, context, anchor));
   return okay;
 }
diff --git a/third_party/re2/re2/testing/tester.h b/third_party/re2/re2/testing/tester.h
index d1e1b22a..6e16e77 100644
--- a/third_party/re2/re2/testing/tester.h
+++ b/third_party/re2/re2/testing/tester.h
@@ -84,7 +84,7 @@
   PCRE* re_;                        // PCRE implementation
   RE2* re2_;                        // RE2 implementation
 
-  DISALLOW_COPY_AND_ASSIGN(TestInstance);
+  DISALLOW_EVIL_CONSTRUCTORS(TestInstance);
 };
 
 // A group of TestInstances for all possible configurations.
@@ -110,7 +110,7 @@
   bool error_;
   vector<TestInstance*> v_;
 
-  DISALLOW_COPY_AND_ASSIGN(Tester);
+  DISALLOW_EVIL_CONSTRUCTORS(Tester);
 };
 
 // Run all possible tests using regexp and text.
diff --git a/third_party/re2/re2/testing/unicode_test.py b/third_party/re2/re2/testing/unicode_test.py
new file mode 100755
index 0000000..a88a3ad
--- /dev/null
+++ b/third_party/re2/re2/testing/unicode_test.py
@@ -0,0 +1,207 @@
+#!/usr/bin/python2.4
+#
+# Copyright 2008 The RE2 Authors.  All Rights Reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+"""Unittest for the util/regexp/re2/unicode.py module."""
+
+import os
+import StringIO
+from google3.pyglib import flags
+from google3.testing.pybase import googletest
+from google3.util.regexp.re2 import unicode
+
+_UNICODE_DIR = os.path.join(flags.FLAGS.test_srcdir, "google3", "third_party",
+                            "unicode", "ucd-5.1.0")
+
+
+class ConvertTest(googletest.TestCase):
+  """Test the conversion functions."""
+
+  def testUInt(self):
+    self.assertEquals(0x0000, unicode._UInt("0000"))
+    self.assertEquals(0x263A, unicode._UInt("263A"))
+    self.assertEquals(0x10FFFF, unicode._UInt("10FFFF"))
+    self.assertRaises(unicode.InputError, unicode._UInt, "263")
+    self.assertRaises(unicode.InputError, unicode._UInt, "263AAAA")
+    self.assertRaises(unicode.InputError, unicode._UInt, "110000")
+
+  def testURange(self):
+    self.assertEquals([1, 2, 3], unicode._URange("0001..0003"))
+    self.assertEquals([1], unicode._URange("0001"))
+    self.assertRaises(unicode.InputError, unicode._URange, "0001..0003..0005")
+    self.assertRaises(unicode.InputError, unicode._URange, "0003..0001")
+    self.assertRaises(unicode.InputError, unicode._URange, "0001..0001")
+
+  def testUStr(self):
+    self.assertEquals("0x263A", unicode._UStr(0x263a))
+    self.assertEquals("0x10FFFF", unicode._UStr(0x10FFFF))
+    self.assertRaises(unicode.InputError, unicode._UStr, 0x110000)
+    self.assertRaises(unicode.InputError, unicode._UStr, -1)
+
+
+_UNICODE_TABLE = """# Commented line, should be ignored.
+# The next line is blank and should be ignored.
+
+0041;Capital A;Line 1
+0061..007A;Lowercase;Line 2
+1F00;<Greek, First>;Ignored
+1FFE;<Greek, Last>;Line 3
+10FFFF;Runemax;Line 4
+0000;Zero;Line 5
+"""
+
+_BAD_TABLE1 = """
+111111;Not a code point;
+"""
+
+_BAD_TABLE2 = """
+0000;<Zero, First>;Missing <Zero, Last>
+"""
+
+_BAD_TABLE3 = """
+0010..0001;Bad range;
+"""
+
+
+class AbortError(Exception):
+  """Function should not have been called."""
+
+
+def Abort():
+  raise AbortError("Abort")
+
+
+def StringTable(s, n, f):
+  unicode.ReadUnicodeTable(StringIO.StringIO(s), n, f)
+
+
+class ReadUnicodeTableTest(googletest.TestCase):
+  """Test the ReadUnicodeTable function."""
+
+  def testSimpleTable(self):
+
+    ncall = [0]  # can't assign to ordinary int in DoLine
+
+    def DoLine(codes, fields):
+      self.assertEquals(3, len(fields))
+      ncall[0] += 1
+      self.assertEquals("Line %d" % (ncall[0],), fields[2])
+      if ncall[0] == 1:
+        self.assertEquals([0x0041], codes)
+        self.assertEquals("0041", fields[0])
+        self.assertEquals("Capital A", fields[1])
+      elif ncall[0] == 2:
+        self.assertEquals(range(0x0061, 0x007A + 1), codes)
+        self.assertEquals("0061..007A", fields[0])
+        self.assertEquals("Lowercase", fields[1])
+      elif ncall[0] == 3:
+        self.assertEquals(range(0x1F00, 0x1FFE + 1), codes)
+        self.assertEquals("1F00..1FFE", fields[0])
+        self.assertEquals("Greek", fields[1])
+      elif ncall[0] == 4:
+        self.assertEquals([0x10FFFF], codes)
+        self.assertEquals("10FFFF", fields[0])
+        self.assertEquals("Runemax", fields[1])
+      elif ncall[0] == 5:
+        self.assertEquals([0x0000], codes)
+        self.assertEquals("0000", fields[0])
+        self.assertEquals("Zero", fields[1])
+
+    StringTable(_UNICODE_TABLE, 3, DoLine)
+    self.assertEquals(5, ncall[0])
+
+  def testErrorTables(self):
+    self.assertRaises(unicode.InputError, StringTable, _UNICODE_TABLE, 4, Abort)
+    self.assertRaises(unicode.InputError, StringTable, _UNICODE_TABLE, 2, Abort)
+    self.assertRaises(unicode.InputError, StringTable, _BAD_TABLE1, 3, Abort)
+    self.assertRaises(unicode.InputError, StringTable, _BAD_TABLE2, 3, Abort)
+    self.assertRaises(unicode.InputError, StringTable, _BAD_TABLE3, 3, Abort)
+
+
+class ParseContinueTest(googletest.TestCase):
+  """Test the ParseContinue function."""
+
+  def testParseContinue(self):
+    self.assertEquals(("Private Use", "First"),
+                      unicode._ParseContinue("<Private Use, First>"))
+    self.assertEquals(("Private Use", "Last"),
+                      unicode._ParseContinue("<Private Use, Last>"))
+    self.assertEquals(("<Private Use, Blah>", None),
+                      unicode._ParseContinue("<Private Use, Blah>"))
+
+
+class CaseGroupsTest(googletest.TestCase):
+  """Test the CaseGroups function (and the CaseFoldingReader)."""
+
+  def FindGroup(self, c):
+    if type(c) == str:
+      c = ord(c)
+    for g in self.groups:
+      if c in g:
+        return g
+    return None
+
+  def testCaseGroups(self):
+    self.groups = unicode.CaseGroups(unicode_dir=_UNICODE_DIR)
+    self.assertEquals([ord("A"), ord("a")], self.FindGroup("a"))
+    self.assertEquals(None, self.FindGroup("0"))
+
+
+class ScriptsTest(googletest.TestCase):
+  """Test the Scripts function (and the ScriptsReader)."""
+
+  def FindScript(self, c):
+    if type(c) == str:
+      c = ord(c)
+    for script, codes in self.scripts.items():
+      for code in codes:
+        if c == code:
+          return script
+    return None
+
+  def testScripts(self):
+    self.scripts = unicode.Scripts(unicode_dir=_UNICODE_DIR)
+    self.assertEquals("Latin", self.FindScript("a"))
+    self.assertEquals("Common", self.FindScript("0"))
+    self.assertEquals(None, self.FindScript(0xFFFE))
+
+
+class CategoriesTest(googletest.TestCase):
+  """Test the Categories function (and the UnicodeDataReader)."""
+
+  def FindCategory(self, c):
+    if type(c) == str:
+      c = ord(c)
+    short = None
+    for category, codes in self.categories.items():
+      for code in codes:
+        if code == c:
+          # prefer category Nd over N
+          if len(category) > 1:
+            return category
+          if short == None:
+            short = category
+    return short
+
+  def testCategories(self):
+    self.categories = unicode.Categories(unicode_dir=_UNICODE_DIR)
+    self.assertEquals("Ll", self.FindCategory("a"))
+    self.assertEquals("Nd", self.FindCategory("0"))
+    self.assertEquals("Lo", self.FindCategory(0xAD00))  # in First, Last range
+    self.assertEquals(None, self.FindCategory(0xFFFE))
+    self.assertEquals("Lo", self.FindCategory(0x8B5A))
+    self.assertEquals("Lo", self.FindCategory(0x6C38))
+    self.assertEquals("Lo", self.FindCategory(0x92D2))
+    self.assertTrue(ord("a") in self.categories["L"])
+    self.assertTrue(ord("0") in self.categories["N"])
+    self.assertTrue(0x8B5A in self.categories["L"])
+    self.assertTrue(0x6C38 in self.categories["L"])
+    self.assertTrue(0x92D2 in self.categories["L"])
+
+def main():
+  googletest.main()
+
+if __name__ == "__main__":
+  main()
diff --git a/third_party/re2/re2/tostring.cc b/third_party/re2/re2/tostring.cc
index 0230c8c..555524f 100644
--- a/third_party/re2/re2/tostring.cc
+++ b/third_party/re2/re2/tostring.cc
@@ -42,7 +42,7 @@
  private:
   string* t_;  // The string the walker appends to.
 
-  DISALLOW_COPY_AND_ASSIGN(ToStringWalker);
+  DISALLOW_EVIL_CONSTRUCTORS(ToStringWalker);
 };
 
 string Regexp::ToString() {
@@ -94,8 +94,6 @@
 
     case kRegexpCapture:
       t_->append("(");
-      if (re->cap() == 0)
-        LOG(DFATAL) << "kRegexpCapture cap() == 0";
       if (re->name()) {
         t_->append("?P<");
         t_->append(*re->name());
@@ -122,13 +120,13 @@
 static void AppendLiteral(string *t, Rune r, bool foldcase) {
   if (r != 0 && r < 0x80 && strchr("(){}[]*+?|.^$\\", r)) {
     t->append(1, '\\');
-    t->append(1, static_cast<char>(r));
+    t->append(1, r);
   } else if (foldcase && 'a' <= r && r <= 'z') {
     if ('a' <= r && r <= 'z')
       r += 'A' - 'a';
     t->append(1, '[');
-    t->append(1, static_cast<char>(r));
-    t->append(1, static_cast<char>(r) + 'a' - 'A');
+    t->append(1, r);
+    t->append(1, r + 'a' - 'A');
     t->append(1, ']');
   } else {
     AppendCCRange(t, r, r);
@@ -156,14 +154,12 @@
       break;
 
     case kRegexpLiteral:
-      AppendLiteral(t_, re->rune(),
-                    (re->parse_flags() & Regexp::FoldCase) != 0);
+      AppendLiteral(t_, re->rune(), re->parse_flags() & Regexp::FoldCase);
       break;
 
     case kRegexpLiteralString:
       for (int i = 0; i < re->nrunes(); i++)
-        AppendLiteral(t_, re->runes()[i],
-                      (re->parse_flags() & Regexp::FoldCase) != 0);
+        AppendLiteral(t_, re->runes()[i], re->parse_flags() & Regexp::FoldCase);
       if (prec < PrecConcat)
         t_->append(")");
       break;
@@ -301,7 +297,7 @@
   if (0x20 <= r && r <= 0x7E) {
     if (strchr("[]^-\\", r))
       t->append("\\");
-    t->append(1, static_cast<char>(r));
+    t->append(1, r);
     return;
   }
   switch (r) {
diff --git a/third_party/re2/re2/unicode.py b/third_party/re2/re2/unicode.py
index 6dfe87bb..8d78312 100644
--- a/third_party/re2/re2/unicode.py
+++ b/third_party/re2/re2/unicode.py
@@ -9,7 +9,7 @@
 import urllib2
 
 # Directory or URL where Unicode tables reside.
-_UNICODE_DIR = "http://www.unicode.org/Public/6.3.0/ucd"
+_UNICODE_DIR = "http://www.unicode.org/Public/6.0.0/ucd"
 
 # Largest valid Unicode code value.
 _RUNE_MAX = 0x10FFFF
diff --git a/third_party/re2/re2/unicode_casefold.cc b/third_party/re2/re2/unicode_casefold.cc
index 2293cc7..6d4e878 100644
--- a/third_party/re2/re2/unicode_casefold.cc
+++ b/third_party/re2/re2/unicode_casefold.cc
@@ -7,8 +7,8 @@
 namespace re2 {
 
 
-// 1034 groups, 2089 pairs, 289 ranges
-const CaseFold unicode_casefold[] = {
+// 1029 groups, 2079 pairs, 282 ranges
+CaseFold unicode_casefold[] = {
 	{ 65, 90, 32 },
 	{ 97, 106, -32 },
 	{ 107, 107, 8383 },
@@ -108,7 +108,6 @@
 	{ 608, 608, -205 },
 	{ 611, 611, -207 },
 	{ 613, 613, 42280 },
-	{ 614, 614, 42308 },
 	{ 616, 616, -209 },
 	{ 617, 617, -211 },
 	{ 619, 619, 10743 },
@@ -187,8 +186,6 @@
 	{ 1329, 1366, 48 },
 	{ 1377, 1414, -48 },
 	{ 4256, 4293, 7264 },
-	{ 4295, 4295, 7264 },
-	{ 4301, 4301, 7264 },
 	{ 7545, 7545, 35332 },
 	{ 7549, 7549, 3814 },
 	{ 7680, 7776, EvenOdd },
@@ -278,10 +275,7 @@
 	{ 11390, 11391, -10815 },
 	{ 11392, 11491, EvenOdd },
 	{ 11499, 11502, OddEven },
-	{ 11506, 11507, EvenOdd },
 	{ 11520, 11557, -7264 },
-	{ 11559, 11559, -7264 },
-	{ 11565, 11565, -7264 },
 	{ 42560, 42605, EvenOdd },
 	{ 42624, 42647, EvenOdd },
 	{ 42786, 42799, EvenOdd },
@@ -291,18 +285,17 @@
 	{ 42878, 42887, EvenOdd },
 	{ 42891, 42892, OddEven },
 	{ 42893, 42893, -42280 },
-	{ 42896, 42899, EvenOdd },
+	{ 42896, 42897, EvenOdd },
 	{ 42912, 42921, EvenOdd },
-	{ 42922, 42922, -42308 },
 	{ 65313, 65338, 32 },
 	{ 65345, 65370, -32 },
 	{ 66560, 66599, 40 },
 	{ 66600, 66639, -40 },
 };
-const int num_unicode_casefold = 289;
+int num_unicode_casefold = 282;
 
-// 1034 groups, 1055 pairs, 167 ranges
-const CaseFold unicode_tolower[] = {
+// 1029 groups, 1050 pairs, 163 ranges
+CaseFold unicode_tolower[] = {
 	{ 65, 90, 32 },
 	{ 181, 181, 775 },
 	{ 192, 214, 32 },
@@ -400,8 +393,6 @@
 	{ 1232, 1318, EvenOddSkip },
 	{ 1329, 1366, 48 },
 	{ 4256, 4293, 7264 },
-	{ 4295, 4295, 7264 },
-	{ 4301, 4301, 7264 },
 	{ 7680, 7828, EvenOddSkip },
 	{ 7835, 7835, -58 },
 	{ 7838, 7838, -7615 },
@@ -455,7 +446,6 @@
 	{ 11390, 11391, -10815 },
 	{ 11392, 11490, EvenOddSkip },
 	{ 11499, 11501, OddEvenSkip },
-	{ 11506, 11506, EvenOdd },
 	{ 42560, 42604, EvenOddSkip },
 	{ 42624, 42646, EvenOddSkip },
 	{ 42786, 42798, EvenOddSkip },
@@ -465,13 +455,12 @@
 	{ 42878, 42886, EvenOddSkip },
 	{ 42891, 42891, OddEven },
 	{ 42893, 42893, -42280 },
-	{ 42896, 42898, EvenOddSkip },
+	{ 42896, 42896, EvenOdd },
 	{ 42912, 42920, EvenOddSkip },
-	{ 42922, 42922, -42308 },
 	{ 65313, 65338, 32 },
 	{ 66560, 66599, 40 },
 };
-const int num_unicode_tolower = 167;
+int num_unicode_tolower = 163;
 
 
 
diff --git a/third_party/re2/re2/unicode_casefold.h b/third_party/re2/re2/unicode_casefold.h
index 1671140..160b07ea 100644
--- a/third_party/re2/re2/unicode_casefold.h
+++ b/third_party/re2/re2/unicode_casefold.h
@@ -51,24 +51,24 @@
 };
 
 struct CaseFold {
-  Rune lo;
-  Rune hi;
+  uint32 lo;
+  uint32 hi;
   int32 delta;
 };
 
-extern const CaseFold unicode_casefold[];
-extern const int num_unicode_casefold;
+extern CaseFold unicode_casefold[];
+extern int num_unicode_casefold;
 
-extern const CaseFold unicode_tolower[];
-extern const int num_unicode_tolower;
+extern CaseFold unicode_tolower[];
+extern int num_unicode_tolower;
 
 // Returns the CaseFold* in the tables that contains rune.
 // If rune is not in the tables, returns the first CaseFold* after rune.
 // If rune is larger than any value in the tables, returns NULL.
-extern const CaseFold* LookupCaseFold(const CaseFold*, int, Rune rune);
+extern CaseFold* LookupCaseFold(CaseFold*, int, Rune rune);
 
 // Returns the result of applying the fold f to the rune r.
-extern Rune ApplyFold(const CaseFold *f, Rune r);
+extern Rune ApplyFold(CaseFold *f, Rune r);
 
 }  // namespace re2
 
diff --git a/third_party/re2/re2/unicode_groups.cc b/third_party/re2/re2/unicode_groups.cc
index 0df585e3..b57a327 100644
--- a/third_party/re2/re2/unicode_groups.cc
+++ b/third_party/re2/re2/unicode_groups.cc
@@ -7,7 +7,7 @@
 namespace re2 {
 
 
-static const URange16 Ps_range16[] = {
+static URange16 Ps_range16[] = {
 	{ 40, 40 },
 	{ 91, 91 },
 	{ 123, 123 },
@@ -19,8 +19,6 @@
 	{ 8261, 8261 },
 	{ 8317, 8317 },
 	{ 8333, 8333 },
-	{ 8968, 8968 },
-	{ 8970, 8970 },
 	{ 9001, 9001 },
 	{ 10088, 10088 },
 	{ 10090, 10090 },
@@ -83,7 +81,7 @@
 	{ 65375, 65375 },
 	{ 65378, 65378 },
 };
-static const URange16 Nl_range16[] = {
+static URange16 Nl_range16[] = {
 	{ 5870, 5872 },
 	{ 8544, 8578 },
 	{ 8581, 8584 },
@@ -92,14 +90,14 @@
 	{ 12344, 12346 },
 	{ 42726, 42735 },
 };
-static const URange32 Nl_range32[] = {
+static URange32 Nl_range32[] = {
 	{ 65856, 65908 },
 	{ 66369, 66369 },
 	{ 66378, 66378 },
 	{ 66513, 66517 },
 	{ 74752, 74850 },
 };
-static const URange16 No_range16[] = {
+static URange16 No_range16[] = {
 	{ 178, 179 },
 	{ 185, 185 },
 	{ 188, 190 },
@@ -123,13 +121,12 @@
 	{ 11517, 11517 },
 	{ 12690, 12693 },
 	{ 12832, 12841 },
-	{ 12872, 12879 },
 	{ 12881, 12895 },
 	{ 12928, 12937 },
 	{ 12977, 12991 },
 	{ 43056, 43061 },
 };
-static const URange32 No_range32[] = {
+static URange32 No_range32[] = {
 	{ 65799, 65843 },
 	{ 65909, 65912 },
 	{ 65930, 65930 },
@@ -145,9 +142,7 @@
 	{ 119648, 119665 },
 	{ 127232, 127242 },
 };
-static const URange16 Lo_range16[] = {
-	{ 170, 170 },
-	{ 186, 186 },
+static URange16 Lo_range16[] = {
 	{ 443, 443 },
 	{ 448, 451 },
 	{ 660, 660 },
@@ -168,8 +163,6 @@
 	{ 1994, 2026 },
 	{ 2048, 2069 },
 	{ 2112, 2136 },
-	{ 2208, 2208 },
-	{ 2210, 2220 },
 	{ 2308, 2361 },
 	{ 2365, 2365 },
 	{ 2384, 2384 },
@@ -274,7 +267,7 @@
 	{ 3762, 3763 },
 	{ 3773, 3773 },
 	{ 3776, 3780 },
-	{ 3804, 3807 },
+	{ 3804, 3805 },
 	{ 3840, 3840 },
 	{ 3904, 3911 },
 	{ 3913, 3948 },
@@ -289,7 +282,7 @@
 	{ 4213, 4225 },
 	{ 4238, 4238 },
 	{ 4304, 4346 },
-	{ 4349, 4680 },
+	{ 4352, 4680 },
 	{ 4682, 4685 },
 	{ 4688, 4694 },
 	{ 4696, 4696 },
@@ -335,15 +328,14 @@
 	{ 6981, 6987 },
 	{ 7043, 7072 },
 	{ 7086, 7087 },
-	{ 7098, 7141 },
+	{ 7104, 7141 },
 	{ 7168, 7203 },
 	{ 7245, 7247 },
 	{ 7258, 7287 },
 	{ 7401, 7404 },
 	{ 7406, 7409 },
-	{ 7413, 7414 },
 	{ 8501, 8504 },
-	{ 11568, 11623 },
+	{ 11568, 11621 },
 	{ 11648, 11670 },
 	{ 11680, 11686 },
 	{ 11688, 11694 },
@@ -364,7 +356,7 @@
 	{ 12704, 12730 },
 	{ 12784, 12799 },
 	{ 13312, 19893 },
-	{ 19968, 40908 },
+	{ 19968, 40907 },
 	{ 40960, 40980 },
 	{ 40982, 42124 },
 	{ 42192, 42231 },
@@ -398,8 +390,6 @@
 	{ 43712, 43712 },
 	{ 43714, 43714 },
 	{ 43739, 43740 },
-	{ 43744, 43754 },
-	{ 43762, 43762 },
 	{ 43777, 43782 },
 	{ 43785, 43790 },
 	{ 43793, 43798 },
@@ -409,7 +399,8 @@
 	{ 44032, 55203 },
 	{ 55216, 55238 },
 	{ 55243, 55291 },
-	{ 63744, 64109 },
+	{ 63744, 64045 },
+	{ 64048, 64109 },
 	{ 64112, 64217 },
 	{ 64285, 64285 },
 	{ 64287, 64296 },
@@ -433,7 +424,7 @@
 	{ 65490, 65495 },
 	{ 65498, 65500 },
 };
-static const URange32 Lo_range32[] = {
+static URange32 Lo_range32[] = {
 	{ 65536, 65547 },
 	{ 65549, 65574 },
 	{ 65576, 65594 },
@@ -458,8 +449,6 @@
 	{ 67647, 67669 },
 	{ 67840, 67861 },
 	{ 67872, 67897 },
-	{ 67968, 68023 },
-	{ 68030, 68031 },
 	{ 68096, 68096 },
 	{ 68112, 68115 },
 	{ 68117, 68119 },
@@ -471,58 +460,20 @@
 	{ 68608, 68680 },
 	{ 69635, 69687 },
 	{ 69763, 69807 },
-	{ 69840, 69864 },
-	{ 69891, 69926 },
-	{ 70019, 70066 },
-	{ 70081, 70084 },
-	{ 71296, 71338 },
 	{ 73728, 74606 },
 	{ 77824, 78894 },
 	{ 92160, 92728 },
-	{ 93952, 94020 },
-	{ 94032, 94032 },
 	{ 110592, 110593 },
-	{ 126464, 126467 },
-	{ 126469, 126495 },
-	{ 126497, 126498 },
-	{ 126500, 126500 },
-	{ 126503, 126503 },
-	{ 126505, 126514 },
-	{ 126516, 126519 },
-	{ 126521, 126521 },
-	{ 126523, 126523 },
-	{ 126530, 126530 },
-	{ 126535, 126535 },
-	{ 126537, 126537 },
-	{ 126539, 126539 },
-	{ 126541, 126543 },
-	{ 126545, 126546 },
-	{ 126548, 126548 },
-	{ 126551, 126551 },
-	{ 126553, 126553 },
-	{ 126555, 126555 },
-	{ 126557, 126557 },
-	{ 126559, 126559 },
-	{ 126561, 126562 },
-	{ 126564, 126564 },
-	{ 126567, 126570 },
-	{ 126572, 126578 },
-	{ 126580, 126583 },
-	{ 126585, 126588 },
-	{ 126590, 126590 },
-	{ 126592, 126601 },
-	{ 126603, 126619 },
-	{ 126625, 126627 },
-	{ 126629, 126633 },
-	{ 126635, 126651 },
 	{ 131072, 173782 },
 	{ 173824, 177972 },
 	{ 177984, 178205 },
 	{ 194560, 195101 },
 };
-static const URange16 Ll_range16[] = {
+static URange16 Ll_range16[] = {
 	{ 97, 122 },
+	{ 170, 170 },
 	{ 181, 181 },
+	{ 186, 186 },
 	{ 223, 246 },
 	{ 248, 255 },
 	{ 257, 257 },
@@ -788,7 +739,7 @@
 	{ 1319, 1319 },
 	{ 1377, 1415 },
 	{ 7424, 7467 },
-	{ 7531, 7543 },
+	{ 7522, 7543 },
 	{ 7545, 7578 },
 	{ 7681, 7681 },
 	{ 7683, 7683 },
@@ -952,7 +903,7 @@
 	{ 11372, 11372 },
 	{ 11377, 11377 },
 	{ 11379, 11380 },
-	{ 11382, 11387 },
+	{ 11382, 11388 },
 	{ 11393, 11393 },
 	{ 11395, 11395 },
 	{ 11397, 11397 },
@@ -1005,10 +956,7 @@
 	{ 11491, 11492 },
 	{ 11500, 11500 },
 	{ 11502, 11502 },
-	{ 11507, 11507 },
 	{ 11520, 11557 },
-	{ 11559, 11559 },
-	{ 11565, 11565 },
 	{ 42561, 42561 },
 	{ 42563, 42563 },
 	{ 42565, 42565 },
@@ -1093,7 +1041,6 @@
 	{ 42892, 42892 },
 	{ 42894, 42894 },
 	{ 42897, 42897 },
-	{ 42899, 42899 },
 	{ 42913, 42913 },
 	{ 42915, 42915 },
 	{ 42917, 42917 },
@@ -1104,7 +1051,7 @@
 	{ 64275, 64279 },
 	{ 65345, 65370 },
 };
-static const URange32 Ll_range32[] = {
+static URange32 Ll_range32[] = {
 	{ 66600, 66639 },
 	{ 119834, 119859 },
 	{ 119886, 119892 },
@@ -1135,7 +1082,7 @@
 	{ 120772, 120777 },
 	{ 120779, 120779 },
 };
-static const URange16 Lm_range16[] = {
+static URange16 Lm_range16[] = {
 	{ 688, 705 },
 	{ 710, 721 },
 	{ 736, 740 },
@@ -1159,13 +1106,13 @@
 	{ 6211, 6211 },
 	{ 6823, 6823 },
 	{ 7288, 7293 },
-	{ 7468, 7530 },
+	{ 7468, 7521 },
 	{ 7544, 7544 },
 	{ 7579, 7615 },
 	{ 8305, 8305 },
 	{ 8319, 8319 },
 	{ 8336, 8348 },
-	{ 11388, 11389 },
+	{ 11389, 11389 },
 	{ 11631, 11631 },
 	{ 11823, 11823 },
 	{ 12293, 12293 },
@@ -1180,18 +1127,13 @@
 	{ 42775, 42783 },
 	{ 42864, 42864 },
 	{ 42888, 42888 },
-	{ 43000, 43001 },
 	{ 43471, 43471 },
 	{ 43632, 43632 },
 	{ 43741, 43741 },
-	{ 43763, 43764 },
 	{ 65392, 65392 },
 	{ 65438, 65439 },
 };
-static const URange32 Lm_range32[] = {
-	{ 94099, 94111 },
-};
-static const URange16 Nd_range16[] = {
+static URange16 Nd_range16[] = {
 	{ 48, 57 },
 	{ 1632, 1641 },
 	{ 1776, 1785 },
@@ -1228,16 +1170,12 @@
 	{ 44016, 44025 },
 	{ 65296, 65305 },
 };
-static const URange32 Nd_range32[] = {
+static URange32 Nd_range32[] = {
 	{ 66720, 66729 },
 	{ 69734, 69743 },
-	{ 69872, 69881 },
-	{ 69942, 69951 },
-	{ 70096, 70105 },
-	{ 71360, 71369 },
 	{ 120782, 120831 },
 };
-static const URange16 Pc_range16[] = {
+static URange16 Pc_range16[] = {
 	{ 95, 95 },
 	{ 8255, 8256 },
 	{ 8276, 8276 },
@@ -1245,7 +1183,7 @@
 	{ 65101, 65103 },
 	{ 65343, 65343 },
 };
-static const URange16 Lt_range16[] = {
+static URange16 Lt_range16[] = {
 	{ 453, 453 },
 	{ 456, 456 },
 	{ 459, 459 },
@@ -1257,7 +1195,7 @@
 	{ 8140, 8140 },
 	{ 8188, 8188 },
 };
-static const URange16 Lu_range16[] = {
+static URange16 Lu_range16[] = {
 	{ 65, 90 },
 	{ 192, 214 },
 	{ 216, 222 },
@@ -1526,8 +1464,6 @@
 	{ 1318, 1318 },
 	{ 1329, 1366 },
 	{ 4256, 4293 },
-	{ 4295, 4295 },
-	{ 4301, 4301 },
 	{ 7680, 7680 },
 	{ 7682, 7682 },
 	{ 7684, 7684 },
@@ -1742,7 +1678,6 @@
 	{ 11490, 11490 },
 	{ 11499, 11499 },
 	{ 11501, 11501 },
-	{ 11506, 11506 },
 	{ 42560, 42560 },
 	{ 42562, 42562 },
 	{ 42564, 42564 },
@@ -1826,16 +1761,14 @@
 	{ 42891, 42891 },
 	{ 42893, 42893 },
 	{ 42896, 42896 },
-	{ 42898, 42898 },
 	{ 42912, 42912 },
 	{ 42914, 42914 },
 	{ 42916, 42916 },
 	{ 42918, 42918 },
 	{ 42920, 42920 },
-	{ 42922, 42922 },
 	{ 65313, 65338 },
 };
-static const URange32 Lu_range32[] = {
+static URange32 Lu_range32[] = {
 	{ 66560, 66599 },
 	{ 119808, 119833 },
 	{ 119860, 119885 },
@@ -1869,7 +1802,7 @@
 	{ 120720, 120744 },
 	{ 120778, 120778 },
 };
-static const URange16 Pf_range16[] = {
+static URange16 Pf_range16[] = {
 	{ 187, 187 },
 	{ 8217, 8217 },
 	{ 8221, 8221 },
@@ -1881,7 +1814,7 @@
 	{ 11805, 11805 },
 	{ 11809, 11809 },
 };
-static const URange16 Pd_range16[] = {
+static URange16 Pd_range16[] = {
 	{ 45, 45 },
 	{ 1418, 1418 },
 	{ 1470, 1470 },
@@ -1890,7 +1823,6 @@
 	{ 8208, 8213 },
 	{ 11799, 11799 },
 	{ 11802, 11802 },
-	{ 11834, 11835 },
 	{ 12316, 12316 },
 	{ 12336, 12336 },
 	{ 12448, 12448 },
@@ -1899,7 +1831,7 @@
 	{ 65123, 65123 },
 	{ 65293, 65293 },
 };
-static const URange16 Pe_range16[] = {
+static URange16 Pe_range16[] = {
 	{ 41, 41 },
 	{ 93, 93 },
 	{ 125, 125 },
@@ -1909,8 +1841,6 @@
 	{ 8262, 8262 },
 	{ 8318, 8318 },
 	{ 8334, 8334 },
-	{ 8969, 8969 },
-	{ 8971, 8971 },
 	{ 9002, 9002 },
 	{ 10089, 10089 },
 	{ 10091, 10091 },
@@ -1973,7 +1903,7 @@
 	{ 65376, 65376 },
 	{ 65379, 65379 },
 };
-static const URange16 Pi_range16[] = {
+static URange16 Pi_range16[] = {
 	{ 171, 171 },
 	{ 8216, 8216 },
 	{ 8219, 8220 },
@@ -1986,7 +1916,7 @@
 	{ 11804, 11804 },
 	{ 11808, 11808 },
 };
-static const URange16 Po_range16[] = {
+static URange16 Po_range16[] = {
 	{ 33, 35 },
 	{ 37, 39 },
 	{ 42, 42 },
@@ -1996,8 +1926,7 @@
 	{ 63, 64 },
 	{ 92, 92 },
 	{ 161, 161 },
-	{ 167, 167 },
-	{ 182, 183 },
+	{ 183, 183 },
 	{ 191, 191 },
 	{ 894, 894 },
 	{ 903, 903 },
@@ -2019,18 +1948,16 @@
 	{ 2142, 2142 },
 	{ 2404, 2405 },
 	{ 2416, 2416 },
-	{ 2800, 2800 },
 	{ 3572, 3572 },
 	{ 3663, 3663 },
 	{ 3674, 3675 },
 	{ 3844, 3858 },
-	{ 3860, 3860 },
 	{ 3973, 3973 },
 	{ 4048, 4052 },
 	{ 4057, 4058 },
 	{ 4170, 4175 },
 	{ 4347, 4347 },
-	{ 4960, 4968 },
+	{ 4961, 4968 },
 	{ 5741, 5742 },
 	{ 5867, 5869 },
 	{ 5941, 5942 },
@@ -2046,7 +1973,6 @@
 	{ 7164, 7167 },
 	{ 7227, 7231 },
 	{ 7294, 7295 },
-	{ 7360, 7367 },
 	{ 7379, 7379 },
 	{ 8214, 8215 },
 	{ 8224, 8231 },
@@ -2067,7 +1993,7 @@
 	{ 11803, 11803 },
 	{ 11806, 11807 },
 	{ 11818, 11822 },
-	{ 11824, 11833 },
+	{ 11824, 11825 },
 	{ 12289, 12291 },
 	{ 12349, 12349 },
 	{ 12539, 12539 },
@@ -2085,7 +2011,6 @@
 	{ 43486, 43487 },
 	{ 43612, 43615 },
 	{ 43742, 43743 },
-	{ 43760, 43761 },
 	{ 44011, 44011 },
 	{ 65040, 65046 },
 	{ 65049, 65049 },
@@ -2108,8 +2033,8 @@
 	{ 65377, 65377 },
 	{ 65380, 65381 },
 };
-static const URange32 Po_range32[] = {
-	{ 65792, 65794 },
+static URange32 Po_range32[] = {
+	{ 65792, 65793 },
 	{ 66463, 66463 },
 	{ 66512, 66512 },
 	{ 67671, 67671 },
@@ -2121,34 +2046,31 @@
 	{ 69703, 69709 },
 	{ 69819, 69820 },
 	{ 69822, 69825 },
-	{ 69952, 69955 },
-	{ 70085, 70088 },
 	{ 74864, 74867 },
 };
-static const URange16 Me_range16[] = {
+static URange16 Me_range16[] = {
 	{ 1160, 1161 },
 	{ 8413, 8416 },
 	{ 8418, 8420 },
 	{ 42608, 42610 },
 };
-static const URange16 C_range16[] = {
+static URange16 C_range16[] = {
 	{ 0, 31 },
 	{ 127, 159 },
 	{ 173, 173 },
-	{ 1536, 1540 },
-	{ 1564, 1564 },
+	{ 1536, 1539 },
 	{ 1757, 1757 },
 	{ 1807, 1807 },
-	{ 6158, 6158 },
+	{ 6068, 6069 },
 	{ 8203, 8207 },
 	{ 8234, 8238 },
 	{ 8288, 8292 },
-	{ 8294, 8303 },
+	{ 8298, 8303 },
 	{ 55296, 63743 },
 	{ 65279, 65279 },
 	{ 65529, 65531 },
 };
-static const URange32 C_range32[] = {
+static URange32 C_range32[] = {
 	{ 69821, 69821 },
 	{ 119155, 119162 },
 	{ 917505, 917505 },
@@ -2156,7 +2078,7 @@
 	{ 983040, 1048573 },
 	{ 1048576, 1114109 },
 };
-static const URange16 Mc_range16[] = {
+static URange16 Mc_range16[] = {
 	{ 2307, 2307 },
 	{ 2363, 2363 },
 	{ 2366, 2368 },
@@ -2223,7 +2145,7 @@
 	{ 6451, 6456 },
 	{ 6576, 6592 },
 	{ 6600, 6601 },
-	{ 6681, 6682 },
+	{ 6681, 6683 },
 	{ 6741, 6741 },
 	{ 6743, 6743 },
 	{ 6753, 6753 },
@@ -2238,7 +2160,6 @@
 	{ 7073, 7073 },
 	{ 7078, 7079 },
 	{ 7082, 7082 },
-	{ 7084, 7085 },
 	{ 7143, 7143 },
 	{ 7146, 7148 },
 	{ 7150, 7150 },
@@ -2246,8 +2167,7 @@
 	{ 7204, 7211 },
 	{ 7220, 7221 },
 	{ 7393, 7393 },
-	{ 7410, 7411 },
-	{ 12334, 12335 },
+	{ 7410, 7410 },
 	{ 43043, 43044 },
 	{ 43047, 43047 },
 	{ 43136, 43137 },
@@ -2261,32 +2181,21 @@
 	{ 43571, 43572 },
 	{ 43597, 43597 },
 	{ 43643, 43643 },
-	{ 43755, 43755 },
-	{ 43758, 43759 },
-	{ 43765, 43765 },
 	{ 44003, 44004 },
 	{ 44006, 44007 },
 	{ 44009, 44010 },
 	{ 44012, 44012 },
 };
-static const URange32 Mc_range32[] = {
+static URange32 Mc_range32[] = {
 	{ 69632, 69632 },
 	{ 69634, 69634 },
 	{ 69762, 69762 },
 	{ 69808, 69810 },
 	{ 69815, 69816 },
-	{ 69932, 69932 },
-	{ 70018, 70018 },
-	{ 70067, 70069 },
-	{ 70079, 70080 },
-	{ 71340, 71340 },
-	{ 71342, 71343 },
-	{ 71350, 71350 },
-	{ 94033, 94078 },
 	{ 119141, 119142 },
 	{ 119149, 119154 },
 };
-static const URange16 Mn_range16[] = {
+static URange16 Mn_range16[] = {
 	{ 768, 879 },
 	{ 1155, 1159 },
 	{ 1425, 1469 },
@@ -2310,7 +2219,6 @@
 	{ 2085, 2087 },
 	{ 2089, 2093 },
 	{ 2137, 2139 },
-	{ 2276, 2302 },
 	{ 2304, 2306 },
 	{ 2362, 2362 },
 	{ 2364, 2364 },
@@ -2396,7 +2304,6 @@
 	{ 5938, 5940 },
 	{ 5970, 5971 },
 	{ 6002, 6003 },
-	{ 6068, 6069 },
 	{ 6071, 6077 },
 	{ 6086, 6086 },
 	{ 6089, 6099 },
@@ -2408,7 +2315,6 @@
 	{ 6450, 6450 },
 	{ 6457, 6459 },
 	{ 6679, 6680 },
-	{ 6683, 6683 },
 	{ 6742, 6742 },
 	{ 6744, 6750 },
 	{ 6752, 6752 },
@@ -2425,7 +2331,6 @@
 	{ 7040, 7041 },
 	{ 7074, 7077 },
 	{ 7080, 7081 },
-	{ 7083, 7083 },
 	{ 7142, 7142 },
 	{ 7144, 7145 },
 	{ 7149, 7149 },
@@ -2436,7 +2341,6 @@
 	{ 7380, 7392 },
 	{ 7394, 7400 },
 	{ 7405, 7405 },
-	{ 7412, 7412 },
 	{ 7616, 7654 },
 	{ 7676, 7679 },
 	{ 8400, 8412 },
@@ -2445,11 +2349,10 @@
 	{ 11503, 11505 },
 	{ 11647, 11647 },
 	{ 11744, 11775 },
-	{ 12330, 12333 },
+	{ 12330, 12335 },
 	{ 12441, 12442 },
 	{ 42607, 42607 },
-	{ 42612, 42621 },
-	{ 42655, 42655 },
+	{ 42620, 42621 },
 	{ 42736, 42737 },
 	{ 43010, 43010 },
 	{ 43014, 43014 },
@@ -2473,8 +2376,6 @@
 	{ 43703, 43704 },
 	{ 43710, 43711 },
 	{ 43713, 43713 },
-	{ 43756, 43757 },
-	{ 43766, 43766 },
 	{ 44005, 44005 },
 	{ 44008, 44008 },
 	{ 44013, 44013 },
@@ -2482,7 +2383,7 @@
 	{ 65024, 65039 },
 	{ 65056, 65062 },
 };
-static const URange32 Mn_range32[] = {
+static URange32 Mn_range32[] = {
 	{ 66045, 66045 },
 	{ 68097, 68099 },
 	{ 68101, 68102 },
@@ -2494,16 +2395,6 @@
 	{ 69760, 69761 },
 	{ 69811, 69814 },
 	{ 69817, 69818 },
-	{ 69888, 69890 },
-	{ 69927, 69931 },
-	{ 69933, 69940 },
-	{ 70016, 70017 },
-	{ 70070, 70078 },
-	{ 71339, 71339 },
-	{ 71341, 71341 },
-	{ 71344, 71349 },
-	{ 71351, 71351 },
-	{ 94095, 94098 },
 	{ 119143, 119145 },
 	{ 119163, 119170 },
 	{ 119173, 119179 },
@@ -2511,7 +2402,7 @@
 	{ 119362, 119364 },
 	{ 917760, 917999 },
 };
-static const URange16 M_range16[] = {
+static URange16 M_range16[] = {
 	{ 768, 879 },
 	{ 1155, 1161 },
 	{ 1425, 1469 },
@@ -2535,7 +2426,6 @@
 	{ 2085, 2087 },
 	{ 2089, 2093 },
 	{ 2137, 2139 },
-	{ 2276, 2302 },
 	{ 2304, 2307 },
 	{ 2362, 2364 },
 	{ 2366, 2383 },
@@ -2630,7 +2520,7 @@
 	{ 5938, 5940 },
 	{ 5970, 5971 },
 	{ 6002, 6003 },
-	{ 6068, 6099 },
+	{ 6070, 6099 },
 	{ 6109, 6109 },
 	{ 6155, 6157 },
 	{ 6313, 6313 },
@@ -2646,13 +2536,13 @@
 	{ 6964, 6980 },
 	{ 7019, 7027 },
 	{ 7040, 7042 },
-	{ 7073, 7085 },
+	{ 7073, 7082 },
 	{ 7142, 7155 },
 	{ 7204, 7223 },
 	{ 7376, 7378 },
 	{ 7380, 7400 },
 	{ 7405, 7405 },
-	{ 7410, 7412 },
+	{ 7410, 7410 },
 	{ 7616, 7654 },
 	{ 7676, 7679 },
 	{ 8400, 8432 },
@@ -2662,8 +2552,7 @@
 	{ 12330, 12335 },
 	{ 12441, 12442 },
 	{ 42607, 42610 },
-	{ 42612, 42621 },
-	{ 42655, 42655 },
+	{ 42620, 42621 },
 	{ 42736, 42737 },
 	{ 43010, 43010 },
 	{ 43014, 43014 },
@@ -2685,15 +2574,13 @@
 	{ 43703, 43704 },
 	{ 43710, 43711 },
 	{ 43713, 43713 },
-	{ 43755, 43759 },
-	{ 43765, 43766 },
 	{ 44003, 44010 },
 	{ 44012, 44013 },
 	{ 64286, 64286 },
 	{ 65024, 65039 },
 	{ 65056, 65062 },
 };
-static const URange32 M_range32[] = {
+static URange32 M_range32[] = {
 	{ 66045, 66045 },
 	{ 68097, 68099 },
 	{ 68101, 68102 },
@@ -2704,13 +2591,6 @@
 	{ 69688, 69702 },
 	{ 69760, 69762 },
 	{ 69808, 69818 },
-	{ 69888, 69890 },
-	{ 69927, 69940 },
-	{ 70016, 70018 },
-	{ 70067, 70080 },
-	{ 71339, 71351 },
-	{ 94033, 94078 },
-	{ 94095, 94098 },
 	{ 119141, 119145 },
 	{ 119149, 119154 },
 	{ 119163, 119170 },
@@ -2719,7 +2599,7 @@
 	{ 119362, 119364 },
 	{ 917760, 917999 },
 };
-static const URange16 L_range16[] = {
+static URange16 L_range16[] = {
 	{ 65, 90 },
 	{ 97, 122 },
 	{ 170, 170 },
@@ -2767,8 +2647,6 @@
 	{ 2084, 2084 },
 	{ 2088, 2088 },
 	{ 2112, 2136 },
-	{ 2208, 2208 },
-	{ 2210, 2220 },
 	{ 2308, 2361 },
 	{ 2365, 2365 },
 	{ 2384, 2384 },
@@ -2874,7 +2752,7 @@
 	{ 3773, 3773 },
 	{ 3776, 3780 },
 	{ 3782, 3782 },
-	{ 3804, 3807 },
+	{ 3804, 3805 },
 	{ 3840, 3840 },
 	{ 3904, 3911 },
 	{ 3913, 3948 },
@@ -2889,10 +2767,9 @@
 	{ 4213, 4225 },
 	{ 4238, 4238 },
 	{ 4256, 4293 },
-	{ 4295, 4295 },
-	{ 4301, 4301 },
 	{ 4304, 4346 },
-	{ 4348, 4680 },
+	{ 4348, 4348 },
+	{ 4352, 4680 },
 	{ 4682, 4685 },
 	{ 4688, 4694 },
 	{ 4696, 4696 },
@@ -2939,13 +2816,12 @@
 	{ 6981, 6987 },
 	{ 7043, 7072 },
 	{ 7086, 7087 },
-	{ 7098, 7141 },
+	{ 7104, 7141 },
 	{ 7168, 7203 },
 	{ 7245, 7247 },
 	{ 7258, 7293 },
 	{ 7401, 7404 },
 	{ 7406, 7409 },
-	{ 7413, 7414 },
 	{ 7424, 7615 },
 	{ 7680, 7957 },
 	{ 7960, 7965 },
@@ -2987,11 +2863,8 @@
 	{ 11312, 11358 },
 	{ 11360, 11492 },
 	{ 11499, 11502 },
-	{ 11506, 11507 },
 	{ 11520, 11557 },
-	{ 11559, 11559 },
-	{ 11565, 11565 },
-	{ 11568, 11623 },
+	{ 11568, 11621 },
 	{ 11631, 11631 },
 	{ 11648, 11670 },
 	{ 11680, 11686 },
@@ -3015,7 +2888,7 @@
 	{ 12704, 12730 },
 	{ 12784, 12799 },
 	{ 13312, 19893 },
-	{ 19968, 40908 },
+	{ 19968, 40907 },
 	{ 40960, 42124 },
 	{ 42192, 42237 },
 	{ 42240, 42508 },
@@ -3027,9 +2900,9 @@
 	{ 42775, 42783 },
 	{ 42786, 42888 },
 	{ 42891, 42894 },
-	{ 42896, 42899 },
-	{ 42912, 42922 },
-	{ 43000, 43009 },
+	{ 42896, 42897 },
+	{ 42912, 42921 },
+	{ 43002, 43009 },
 	{ 43011, 43013 },
 	{ 43015, 43018 },
 	{ 43020, 43042 },
@@ -3054,8 +2927,6 @@
 	{ 43712, 43712 },
 	{ 43714, 43714 },
 	{ 43739, 43741 },
-	{ 43744, 43754 },
-	{ 43762, 43764 },
 	{ 43777, 43782 },
 	{ 43785, 43790 },
 	{ 43793, 43798 },
@@ -3065,7 +2936,8 @@
 	{ 44032, 55203 },
 	{ 55216, 55238 },
 	{ 55243, 55291 },
-	{ 63744, 64109 },
+	{ 63744, 64045 },
+	{ 64048, 64109 },
 	{ 64112, 64217 },
 	{ 64256, 64262 },
 	{ 64275, 64279 },
@@ -3091,7 +2963,7 @@
 	{ 65490, 65495 },
 	{ 65498, 65500 },
 };
-static const URange32 L_range32[] = {
+static URange32 L_range32[] = {
 	{ 65536, 65547 },
 	{ 65549, 65574 },
 	{ 65576, 65594 },
@@ -3116,8 +2988,6 @@
 	{ 67647, 67669 },
 	{ 67840, 67861 },
 	{ 67872, 67897 },
-	{ 67968, 68023 },
-	{ 68030, 68031 },
 	{ 68096, 68096 },
 	{ 68112, 68115 },
 	{ 68117, 68119 },
@@ -3129,17 +2999,9 @@
 	{ 68608, 68680 },
 	{ 69635, 69687 },
 	{ 69763, 69807 },
-	{ 69840, 69864 },
-	{ 69891, 69926 },
-	{ 70019, 70066 },
-	{ 70081, 70084 },
-	{ 71296, 71338 },
 	{ 73728, 74606 },
 	{ 77824, 78894 },
 	{ 92160, 92728 },
-	{ 93952, 94020 },
-	{ 94032, 94032 },
-	{ 94099, 94111 },
 	{ 110592, 110593 },
 	{ 119808, 119892 },
 	{ 119894, 119964 },
@@ -3171,45 +3033,12 @@
 	{ 120714, 120744 },
 	{ 120746, 120770 },
 	{ 120772, 120779 },
-	{ 126464, 126467 },
-	{ 126469, 126495 },
-	{ 126497, 126498 },
-	{ 126500, 126500 },
-	{ 126503, 126503 },
-	{ 126505, 126514 },
-	{ 126516, 126519 },
-	{ 126521, 126521 },
-	{ 126523, 126523 },
-	{ 126530, 126530 },
-	{ 126535, 126535 },
-	{ 126537, 126537 },
-	{ 126539, 126539 },
-	{ 126541, 126543 },
-	{ 126545, 126546 },
-	{ 126548, 126548 },
-	{ 126551, 126551 },
-	{ 126553, 126553 },
-	{ 126555, 126555 },
-	{ 126557, 126557 },
-	{ 126559, 126559 },
-	{ 126561, 126562 },
-	{ 126564, 126564 },
-	{ 126567, 126570 },
-	{ 126572, 126578 },
-	{ 126580, 126583 },
-	{ 126585, 126588 },
-	{ 126590, 126590 },
-	{ 126592, 126601 },
-	{ 126603, 126619 },
-	{ 126625, 126627 },
-	{ 126629, 126633 },
-	{ 126635, 126651 },
 	{ 131072, 173782 },
 	{ 173824, 177972 },
 	{ 177984, 178205 },
 	{ 194560, 195101 },
 };
-static const URange16 N_range16[] = {
+static URange16 N_range16[] = {
 	{ 48, 57 },
 	{ 178, 179 },
 	{ 185, 185 },
@@ -3261,7 +3090,6 @@
 	{ 12344, 12346 },
 	{ 12690, 12693 },
 	{ 12832, 12841 },
-	{ 12872, 12879 },
 	{ 12881, 12895 },
 	{ 12928, 12937 },
 	{ 12977, 12991 },
@@ -3275,7 +3103,7 @@
 	{ 44016, 44025 },
 	{ 65296, 65305 },
 };
-static const URange32 N_range32[] = {
+static URange32 N_range32[] = {
 	{ 65799, 65843 },
 	{ 65856, 65912 },
 	{ 65930, 65930 },
@@ -3292,16 +3120,12 @@
 	{ 68472, 68479 },
 	{ 69216, 69246 },
 	{ 69714, 69743 },
-	{ 69872, 69881 },
-	{ 69942, 69951 },
-	{ 70096, 70105 },
-	{ 71360, 71369 },
 	{ 74752, 74850 },
 	{ 119648, 119665 },
 	{ 120782, 120831 },
 	{ 127232, 127242 },
 };
-static const URange16 Sk_range16[] = {
+static URange16 Sk_range16[] = {
 	{ 94, 94 },
 	{ 96, 96 },
 	{ 168, 168 },
@@ -3330,7 +3154,7 @@
 	{ 65344, 65344 },
 	{ 65507, 65507 },
 };
-static const URange16 P_range16[] = {
+static URange16 P_range16[] = {
 	{ 33, 35 },
 	{ 37, 42 },
 	{ 44, 47 },
@@ -3341,9 +3165,8 @@
 	{ 123, 123 },
 	{ 125, 125 },
 	{ 161, 161 },
-	{ 167, 167 },
 	{ 171, 171 },
-	{ 182, 183 },
+	{ 183, 183 },
 	{ 187, 187 },
 	{ 191, 191 },
 	{ 894, 894 },
@@ -3367,19 +3190,17 @@
 	{ 2142, 2142 },
 	{ 2404, 2405 },
 	{ 2416, 2416 },
-	{ 2800, 2800 },
 	{ 3572, 3572 },
 	{ 3663, 3663 },
 	{ 3674, 3675 },
 	{ 3844, 3858 },
-	{ 3860, 3860 },
 	{ 3898, 3901 },
 	{ 3973, 3973 },
 	{ 4048, 4052 },
 	{ 4057, 4058 },
 	{ 4170, 4175 },
 	{ 4347, 4347 },
-	{ 4960, 4968 },
+	{ 4961, 4968 },
 	{ 5120, 5120 },
 	{ 5741, 5742 },
 	{ 5787, 5788 },
@@ -3396,7 +3217,6 @@
 	{ 7164, 7167 },
 	{ 7227, 7231 },
 	{ 7294, 7295 },
-	{ 7360, 7367 },
 	{ 7379, 7379 },
 	{ 8208, 8231 },
 	{ 8240, 8259 },
@@ -3404,7 +3224,6 @@
 	{ 8275, 8286 },
 	{ 8317, 8318 },
 	{ 8333, 8334 },
-	{ 8968, 8971 },
 	{ 9001, 9002 },
 	{ 10088, 10101 },
 	{ 10181, 10182 },
@@ -3416,7 +3235,7 @@
 	{ 11518, 11519 },
 	{ 11632, 11632 },
 	{ 11776, 11822 },
-	{ 11824, 11835 },
+	{ 11824, 11825 },
 	{ 12289, 12291 },
 	{ 12296, 12305 },
 	{ 12308, 12319 },
@@ -3438,7 +3257,6 @@
 	{ 43486, 43487 },
 	{ 43612, 43615 },
 	{ 43742, 43743 },
-	{ 43760, 43761 },
 	{ 44011, 44011 },
 	{ 64830, 64831 },
 	{ 65040, 65049 },
@@ -3458,8 +3276,8 @@
 	{ 65373, 65373 },
 	{ 65375, 65381 },
 };
-static const URange32 P_range32[] = {
-	{ 65792, 65794 },
+static URange32 P_range32[] = {
+	{ 65792, 65793 },
 	{ 66463, 66463 },
 	{ 66512, 66512 },
 	{ 67671, 67671 },
@@ -3471,11 +3289,9 @@
 	{ 69703, 69709 },
 	{ 69819, 69820 },
 	{ 69822, 69825 },
-	{ 69952, 69955 },
-	{ 70085, 70088 },
 	{ 74864, 74867 },
 };
-static const URange16 S_range16[] = {
+static URange16 S_range16[] = {
 	{ 36, 36 },
 	{ 43, 43 },
 	{ 60, 62 },
@@ -3483,11 +3299,11 @@
 	{ 96, 96 },
 	{ 124, 124 },
 	{ 126, 126 },
-	{ 162, 166 },
-	{ 168, 169 },
+	{ 162, 169 },
 	{ 172, 172 },
 	{ 174, 177 },
 	{ 180, 180 },
+	{ 182, 182 },
 	{ 184, 184 },
 	{ 215, 215 },
 	{ 247, 247 },
@@ -3500,7 +3316,6 @@
 	{ 900, 901 },
 	{ 1014, 1014 },
 	{ 1154, 1154 },
-	{ 1423, 1423 },
 	{ 1542, 1544 },
 	{ 1547, 1547 },
 	{ 1550, 1551 },
@@ -3517,8 +3332,7 @@
 	{ 3449, 3449 },
 	{ 3647, 3647 },
 	{ 3841, 3843 },
-	{ 3859, 3859 },
-	{ 3861, 3863 },
+	{ 3859, 3863 },
 	{ 3866, 3871 },
 	{ 3892, 3892 },
 	{ 3894, 3894 },
@@ -3528,6 +3342,7 @@
 	{ 4046, 4047 },
 	{ 4053, 4056 },
 	{ 4254, 4255 },
+	{ 4960, 4960 },
 	{ 5008, 5017 },
 	{ 6107, 6107 },
 	{ 6464, 6464 },
@@ -3544,7 +3359,7 @@
 	{ 8274, 8274 },
 	{ 8314, 8316 },
 	{ 8330, 8332 },
-	{ 8352, 8378 },
+	{ 8352, 8377 },
 	{ 8448, 8449 },
 	{ 8451, 8454 },
 	{ 8456, 8457 },
@@ -3559,8 +3374,7 @@
 	{ 8512, 8516 },
 	{ 8522, 8525 },
 	{ 8527, 8527 },
-	{ 8592, 8967 },
-	{ 8972, 9000 },
+	{ 8592, 9000 },
 	{ 9003, 9203 },
 	{ 9216, 9254 },
 	{ 9280, 9290 },
@@ -3568,7 +3382,9 @@
 	{ 9472, 9983 },
 	{ 9985, 10087 },
 	{ 10132, 10180 },
-	{ 10183, 10213 },
+	{ 10183, 10186 },
+	{ 10188, 10188 },
+	{ 10190, 10213 },
 	{ 10224, 10626 },
 	{ 10649, 10711 },
 	{ 10716, 10747 },
@@ -3589,8 +3405,7 @@
 	{ 12694, 12703 },
 	{ 12736, 12771 },
 	{ 12800, 12830 },
-	{ 12842, 12871 },
-	{ 12880, 12880 },
+	{ 12842, 12880 },
 	{ 12896, 12927 },
 	{ 12938, 12976 },
 	{ 12992, 13054 },
@@ -3620,7 +3435,8 @@
 	{ 65512, 65518 },
 	{ 65532, 65533 },
 };
-static const URange32 S_range32[] = {
+static URange32 S_range32[] = {
+	{ 65794, 65794 },
 	{ 65847, 65855 },
 	{ 65913, 65929 },
 	{ 65936, 65947 },
@@ -3645,7 +3461,6 @@
 	{ 120713, 120713 },
 	{ 120745, 120745 },
 	{ 120771, 120771 },
-	{ 126704, 126705 },
 	{ 126976, 127019 },
 	{ 127024, 127123 },
 	{ 127136, 127150 },
@@ -3653,7 +3468,7 @@
 	{ 127169, 127183 },
 	{ 127185, 127199 },
 	{ 127248, 127278 },
-	{ 127280, 127339 },
+	{ 127280, 127337 },
 	{ 127344, 127386 },
 	{ 127462, 127490 },
 	{ 127504, 127546 },
@@ -3671,18 +3486,29 @@
 	{ 128066, 128247 },
 	{ 128249, 128252 },
 	{ 128256, 128317 },
-	{ 128320, 128323 },
 	{ 128336, 128359 },
-	{ 128507, 128576 },
+	{ 128507, 128511 },
+	{ 128513, 128528 },
+	{ 128530, 128532 },
+	{ 128534, 128534 },
+	{ 128536, 128536 },
+	{ 128538, 128538 },
+	{ 128540, 128542 },
+	{ 128544, 128549 },
+	{ 128552, 128555 },
+	{ 128557, 128557 },
+	{ 128560, 128563 },
+	{ 128565, 128576 },
 	{ 128581, 128591 },
 	{ 128640, 128709 },
 	{ 128768, 128883 },
 };
-static const URange16 So_range16[] = {
-	{ 166, 166 },
+static URange16 So_range16[] = {
+	{ 166, 167 },
 	{ 169, 169 },
 	{ 174, 174 },
 	{ 176, 176 },
+	{ 182, 182 },
 	{ 1154, 1154 },
 	{ 1550, 1551 },
 	{ 1758, 1758 },
@@ -3696,8 +3522,7 @@
 	{ 3199, 3199 },
 	{ 3449, 3449 },
 	{ 3841, 3843 },
-	{ 3859, 3859 },
-	{ 3861, 3863 },
+	{ 3859, 3863 },
 	{ 3866, 3871 },
 	{ 3892, 3892 },
 	{ 3894, 3894 },
@@ -3707,6 +3532,7 @@
 	{ 4046, 4047 },
 	{ 4053, 4056 },
 	{ 4254, 4255 },
+	{ 4960, 4960 },
 	{ 5008, 5017 },
 	{ 6464, 6464 },
 	{ 6622, 6655 },
@@ -3770,8 +3596,7 @@
 	{ 12694, 12703 },
 	{ 12736, 12771 },
 	{ 12800, 12830 },
-	{ 12842, 12871 },
-	{ 12880, 12880 },
+	{ 12842, 12880 },
 	{ 12896, 12927 },
 	{ 12938, 12976 },
 	{ 12992, 13054 },
@@ -3788,7 +3613,8 @@
 	{ 65517, 65518 },
 	{ 65532, 65533 },
 };
-static const URange32 So_range32[] = {
+static URange32 So_range32[] = {
+	{ 65794, 65794 },
 	{ 65847, 65855 },
 	{ 65913, 65929 },
 	{ 65936, 65947 },
@@ -3810,7 +3636,7 @@
 	{ 127169, 127183 },
 	{ 127185, 127199 },
 	{ 127248, 127278 },
-	{ 127280, 127339 },
+	{ 127280, 127337 },
 	{ 127344, 127386 },
 	{ 127462, 127490 },
 	{ 127504, 127546 },
@@ -3828,14 +3654,24 @@
 	{ 128066, 128247 },
 	{ 128249, 128252 },
 	{ 128256, 128317 },
-	{ 128320, 128323 },
 	{ 128336, 128359 },
-	{ 128507, 128576 },
+	{ 128507, 128511 },
+	{ 128513, 128528 },
+	{ 128530, 128532 },
+	{ 128534, 128534 },
+	{ 128536, 128536 },
+	{ 128538, 128538 },
+	{ 128540, 128542 },
+	{ 128544, 128549 },
+	{ 128552, 128555 },
+	{ 128557, 128557 },
+	{ 128560, 128563 },
+	{ 128565, 128576 },
 	{ 128581, 128591 },
 	{ 128640, 128709 },
 	{ 128768, 128883 },
 };
-static const URange16 Sm_range16[] = {
+static URange16 Sm_range16[] = {
 	{ 43, 43 },
 	{ 60, 62 },
 	{ 124, 124 },
@@ -3863,6 +3699,7 @@
 	{ 8658, 8658 },
 	{ 8660, 8660 },
 	{ 8692, 8959 },
+	{ 8968, 8971 },
 	{ 8992, 8993 },
 	{ 9084, 9084 },
 	{ 9115, 9139 },
@@ -3872,7 +3709,9 @@
 	{ 9720, 9727 },
 	{ 9839, 9839 },
 	{ 10176, 10180 },
-	{ 10183, 10213 },
+	{ 10183, 10186 },
+	{ 10188, 10188 },
+	{ 10190, 10213 },
 	{ 10224, 10239 },
 	{ 10496, 10626 },
 	{ 10649, 10711 },
@@ -3890,7 +3729,7 @@
 	{ 65506, 65506 },
 	{ 65513, 65516 },
 };
-static const URange32 Sm_range32[] = {
+static URange32 Sm_range32[] = {
 	{ 120513, 120513 },
 	{ 120539, 120539 },
 	{ 120571, 120571 },
@@ -3901,12 +3740,10 @@
 	{ 120713, 120713 },
 	{ 120745, 120745 },
 	{ 120771, 120771 },
-	{ 126704, 126705 },
 };
-static const URange16 Sc_range16[] = {
+static URange16 Sc_range16[] = {
 	{ 36, 36 },
 	{ 162, 165 },
-	{ 1423, 1423 },
 	{ 1547, 1547 },
 	{ 2546, 2547 },
 	{ 2555, 2555 },
@@ -3914,7 +3751,7 @@
 	{ 3065, 3065 },
 	{ 3647, 3647 },
 	{ 6107, 6107 },
-	{ 8352, 8378 },
+	{ 8352, 8377 },
 	{ 43064, 43064 },
 	{ 65020, 65020 },
 	{ 65129, 65129 },
@@ -3922,69 +3759,70 @@
 	{ 65504, 65505 },
 	{ 65509, 65510 },
 };
-static const URange16 Z_range16[] = {
+static URange16 Z_range16[] = {
 	{ 32, 32 },
 	{ 160, 160 },
 	{ 5760, 5760 },
+	{ 6158, 6158 },
 	{ 8192, 8202 },
 	{ 8232, 8233 },
 	{ 8239, 8239 },
 	{ 8287, 8287 },
 	{ 12288, 12288 },
 };
-static const URange16 Zl_range16[] = {
+static URange16 Zl_range16[] = {
 	{ 8232, 8232 },
 };
-static const URange16 Co_range16[] = {
+static URange16 Co_range16[] = {
 	{ 57344, 63743 },
 };
-static const URange32 Co_range32[] = {
+static URange32 Co_range32[] = {
 	{ 983040, 1048573 },
 	{ 1048576, 1114109 },
 };
-static const URange16 Cc_range16[] = {
+static URange16 Cc_range16[] = {
 	{ 0, 31 },
 	{ 127, 159 },
 };
-static const URange16 Cf_range16[] = {
+static URange16 Cf_range16[] = {
 	{ 173, 173 },
-	{ 1536, 1540 },
-	{ 1564, 1564 },
+	{ 1536, 1539 },
 	{ 1757, 1757 },
 	{ 1807, 1807 },
-	{ 6158, 6158 },
+	{ 6068, 6069 },
 	{ 8203, 8207 },
 	{ 8234, 8238 },
 	{ 8288, 8292 },
-	{ 8294, 8303 },
+	{ 8298, 8303 },
 	{ 65279, 65279 },
 	{ 65529, 65531 },
 };
-static const URange32 Cf_range32[] = {
+static URange32 Cf_range32[] = {
 	{ 69821, 69821 },
 	{ 119155, 119162 },
 	{ 917505, 917505 },
 	{ 917536, 917631 },
 };
-static const URange16 Cs_range16[] = {
+static URange16 Cs_range16[] = {
 	{ 55296, 57343 },
 };
-static const URange16 Zp_range16[] = {
+static URange16 Zp_range16[] = {
 	{ 8233, 8233 },
 };
-static const URange16 Zs_range16[] = {
+static URange16 Zs_range16[] = {
 	{ 32, 32 },
 	{ 160, 160 },
 	{ 5760, 5760 },
+	{ 6158, 6158 },
 	{ 8192, 8202 },
 	{ 8239, 8239 },
 	{ 8287, 8287 },
 	{ 12288, 12288 },
 };
-static const URange16 Thaana_range16[] = {
+static URange16 Thaana_range16[] = {
 	{ 1920, 1969 },
 };
-static const URange16 Telugu_range16[] = {
+static URange16 Telugu_range16[] = {
 	{ 3073, 3075 },
 	{ 3077, 3084 },
 	{ 3086, 3088 },
@@ -4000,16 +3838,16 @@
 	{ 3174, 3183 },
 	{ 3192, 3199 },
 };
-static const URange16 Cyrillic_range16[] = {
+static URange16 Cyrillic_range16[] = {
 	{ 1024, 1156 },
 	{ 1159, 1319 },
 	{ 7467, 7467 },
 	{ 7544, 7544 },
 	{ 11744, 11775 },
-	{ 42560, 42647 },
-	{ 42655, 42655 },
+	{ 42560, 42611 },
+	{ 42620, 42647 },
 };
-static const URange16 Hangul_range16[] = {
+static URange16 Hangul_range16[] = {
 	{ 4352, 4607 },
 	{ 12334, 12335 },
 	{ 12593, 12686 },
@@ -4025,10 +3863,10 @@
 	{ 65490, 65495 },
 	{ 65498, 65500 },
 };
-static const URange32 Old_South_Arabian_range32[] = {
+static URange32 Old_South_Arabian_range32[] = {
 	{ 68192, 68223 },
 };
-static const URange16 Ethiopic_range16[] = {
+static URange16 Ethiopic_range16[] = {
 	{ 4608, 4680 },
 	{ 4682, 4685 },
 	{ 4688, 4694 },
@@ -4062,17 +3900,17 @@
 	{ 43808, 43814 },
 	{ 43816, 43822 },
 };
-static const URange16 Inherited_range16[] = {
+static URange16 Inherited_range16[] = {
 	{ 768, 879 },
 	{ 1157, 1158 },
 	{ 1611, 1621 },
+	{ 1631, 1631 },
 	{ 1648, 1648 },
 	{ 2385, 2386 },
 	{ 7376, 7378 },
 	{ 7380, 7392 },
 	{ 7394, 7400 },
 	{ 7405, 7405 },
-	{ 7412, 7412 },
 	{ 7616, 7654 },
 	{ 7676, 7679 },
 	{ 8204, 8205 },
@@ -4082,7 +3920,7 @@
 	{ 65024, 65039 },
 	{ 65056, 65062 },
 };
-static const URange32 Inherited_range32[] = {
+static URange32 Inherited_range32[] = {
 	{ 66045, 66045 },
 	{ 119143, 119145 },
 	{ 119163, 119170 },
@@ -4090,11 +3928,7 @@
 	{ 119210, 119213 },
 	{ 917760, 917999 },
 };
-static const URange32 Meroitic_Cursive_range32[] = {
-	{ 68000, 68023 },
-	{ 68030, 68031 },
-};
-static const URange16 Han_range16[] = {
+static URange16 Han_range16[] = {
 	{ 11904, 11929 },
 	{ 11931, 12019 },
 	{ 12032, 12245 },
@@ -4103,25 +3937,25 @@
 	{ 12321, 12329 },
 	{ 12344, 12347 },
 	{ 13312, 19893 },
-	{ 19968, 40908 },
-	{ 63744, 64109 },
+	{ 19968, 40907 },
+	{ 63744, 64045 },
+	{ 64048, 64109 },
 	{ 64112, 64217 },
 };
-static const URange32 Han_range32[] = {
+static URange32 Han_range32[] = {
 	{ 131072, 173782 },
 	{ 173824, 177972 },
 	{ 177984, 178205 },
 	{ 194560, 195101 },
 };
-static const URange16 Armenian_range16[] = {
+static URange16 Armenian_range16[] = {
 	{ 1329, 1366 },
 	{ 1369, 1375 },
 	{ 1377, 1415 },
 	{ 1418, 1418 },
-	{ 1423, 1423 },
 	{ 64275, 64279 },
 };
-static const URange16 Tamil_range16[] = {
+static URange16 Tamil_range16[] = {
 	{ 2946, 2947 },
 	{ 2949, 2954 },
 	{ 2958, 2960 },
@@ -4139,20 +3973,20 @@
 	{ 3031, 3031 },
 	{ 3046, 3066 },
 };
-static const URange16 Bopomofo_range16[] = {
+static URange16 Bopomofo_range16[] = {
 	{ 746, 747 },
 	{ 12549, 12589 },
 	{ 12704, 12730 },
 };
-static const URange16 Sundanese_range16[] = {
-	{ 7040, 7103 },
-	{ 7360, 7367 },
+static URange16 Sundanese_range16[] = {
+	{ 7040, 7082 },
+	{ 7086, 7097 },
 };
-static const URange16 Tagalog_range16[] = {
+static URange16 Tagalog_range16[] = {
 	{ 5888, 5900 },
 	{ 5902, 5908 },
 };
-static const URange16 Malayalam_range16[] = {
+static URange16 Malayalam_range16[] = {
 	{ 3330, 3331 },
 	{ 3333, 3340 },
 	{ 3342, 3344 },
@@ -4165,39 +3999,38 @@
 	{ 3430, 3445 },
 	{ 3449, 3455 },
 };
-static const URange32 Carian_range32[] = {
+static URange32 Carian_range32[] = {
 	{ 66208, 66256 },
 };
-static const URange16 Hiragana_range16[] = {
+static URange16 Hiragana_range16[] = {
 	{ 12353, 12438 },
 	{ 12445, 12447 },
 };
-static const URange32 Hiragana_range32[] = {
+static URange32 Hiragana_range32[] = {
 	{ 110593, 110593 },
 	{ 127488, 127488 },
 };
-static const URange16 Tagbanwa_range16[] = {
+static URange16 Tagbanwa_range16[] = {
 	{ 5984, 5996 },
 	{ 5998, 6000 },
 	{ 6002, 6003 },
 };
-static const URange16 Meetei_Mayek_range16[] = {
-	{ 43744, 43766 },
+static URange16 Meetei_Mayek_range16[] = {
 	{ 43968, 44013 },
 	{ 44016, 44025 },
 };
-static const URange16 Tai_Le_range16[] = {
+static URange16 Tai_Le_range16[] = {
 	{ 6480, 6509 },
 	{ 6512, 6516 },
 };
-static const URange16 Kayah_Li_range16[] = {
+static URange16 Kayah_Li_range16[] = {
 	{ 43264, 43311 },
 };
-static const URange16 Buginese_range16[] = {
+static URange16 Buginese_range16[] = {
 	{ 6656, 6683 },
 	{ 6686, 6687 },
 };
-static const URange32 Kharoshthi_range32[] = {
+static URange32 Kharoshthi_range32[] = {
 	{ 68096, 68099 },
 	{ 68101, 68102 },
 	{ 68108, 68115 },
@@ -4207,22 +4040,22 @@
 	{ 68159, 68167 },
 	{ 68176, 68184 },
 };
-static const URange16 Tai_Tham_range16[] = {
+static URange16 Tai_Tham_range16[] = {
 	{ 6688, 6750 },
 	{ 6752, 6780 },
 	{ 6783, 6793 },
 	{ 6800, 6809 },
 	{ 6816, 6829 },
 };
-static const URange32 Old_Italic_range32[] = {
+static URange32 Old_Italic_range32[] = {
 	{ 66304, 66334 },
 	{ 66336, 66339 },
 };
-static const URange32 Old_Persian_range32[] = {
+static URange32 Old_Persian_range32[] = {
 	{ 66464, 66499 },
 	{ 66504, 66517 },
 };
-static const URange16 Latin_range16[] = {
+static URange16 Latin_range16[] = {
 	{ 65, 90 },
 	{ 97, 122 },
 	{ 170, 170 },
@@ -4247,46 +4080,43 @@
 	{ 11360, 11391 },
 	{ 42786, 42887 },
 	{ 42891, 42894 },
-	{ 42896, 42899 },
-	{ 42912, 42922 },
-	{ 43000, 43007 },
+	{ 42896, 42897 },
+	{ 42912, 42921 },
+	{ 43002, 43007 },
 	{ 64256, 64262 },
 	{ 65313, 65338 },
 	{ 65345, 65370 },
 };
-static const URange16 Saurashtra_range16[] = {
+static URange16 Saurashtra_range16[] = {
 	{ 43136, 43204 },
 	{ 43214, 43225 },
 };
-static const URange32 Shavian_range32[] = {
+static URange32 Shavian_range32[] = {
 	{ 66640, 66687 },
 };
-static const URange16 Georgian_range16[] = {
+static URange16 Georgian_range16[] = {
 	{ 4256, 4293 },
-	{ 4295, 4295 },
-	{ 4301, 4301 },
 	{ 4304, 4346 },
-	{ 4348, 4351 },
+	{ 4348, 4348 },
 	{ 11520, 11557 },
-	{ 11559, 11559 },
-	{ 11565, 11565 },
 };
-static const URange16 Batak_range16[] = {
+static URange16 Batak_range16[] = {
 	{ 7104, 7155 },
 	{ 7164, 7167 },
 };
-static const URange16 Devanagari_range16[] = {
+static URange16 Devanagari_range16[] = {
 	{ 2304, 2384 },
 	{ 2387, 2403 },
-	{ 2406, 2423 },
+	{ 2406, 2415 },
+	{ 2417, 2423 },
 	{ 2425, 2431 },
 	{ 43232, 43259 },
 };
-static const URange16 Thai_range16[] = {
+static URange16 Thai_range16[] = {
 	{ 3585, 3642 },
 	{ 3648, 3675 },
 };
-static const URange16 Tibetan_range16[] = {
+static URange16 Tibetan_range16[] = {
 	{ 3840, 3911 },
 	{ 3913, 3948 },
 	{ 3953, 3991 },
@@ -4295,19 +4125,19 @@
 	{ 4046, 4052 },
 	{ 4057, 4058 },
 };
-static const URange16 Tifinagh_range16[] = {
-	{ 11568, 11623 },
+static URange16 Tifinagh_range16[] = {
+	{ 11568, 11621 },
 	{ 11631, 11632 },
 	{ 11647, 11647 },
 };
-static const URange32 Ugaritic_range32[] = {
+static URange32 Ugaritic_range32[] = {
 	{ 66432, 66461 },
 	{ 66463, 66463 },
 };
-static const URange16 Braille_range16[] = {
+static URange16 Braille_range16[] = {
 	{ 10240, 10495 },
 };
-static const URange16 Greek_range16[] = {
+static URange16 Greek_range16[] = {
 	{ 880, 883 },
 	{ 885, 887 },
 	{ 890, 893 },
@@ -4340,46 +4170,46 @@
 	{ 8182, 8190 },
 	{ 8486, 8486 },
 };
-static const URange32 Greek_range32[] = {
+static URange32 Greek_range32[] = {
 	{ 65856, 65930 },
 	{ 119296, 119365 },
 };
-static const URange32 Lycian_range32[] = {
+static URange32 Lycian_range32[] = {
 	{ 66176, 66204 },
 };
-static const URange16 Tai_Viet_range16[] = {
+static URange16 Tai_Viet_range16[] = {
 	{ 43648, 43714 },
 	{ 43739, 43743 },
 };
-static const URange16 Vai_range16[] = {
+static URange16 Vai_range16[] = {
 	{ 42240, 42539 },
 };
-static const URange16 Ogham_range16[] = {
+static URange16 Ogham_range16[] = {
 	{ 5760, 5788 },
 };
-static const URange32 Inscriptional_Parthian_range32[] = {
+static URange32 Inscriptional_Parthian_range32[] = {
 	{ 68416, 68437 },
 	{ 68440, 68447 },
 };
-static const URange16 Cham_range16[] = {
+static URange16 Cham_range16[] = {
 	{ 43520, 43574 },
 	{ 43584, 43597 },
 	{ 43600, 43609 },
 	{ 43612, 43615 },
 };
-static const URange16 Syriac_range16[] = {
+static URange16 Syriac_range16[] = {
 	{ 1792, 1805 },
 	{ 1807, 1866 },
 	{ 1869, 1871 },
 };
-static const URange16 Runic_range16[] = {
+static URange16 Runic_range16[] = {
 	{ 5792, 5866 },
 	{ 5870, 5872 },
 };
-static const URange32 Gothic_range32[] = {
+static URange32 Gothic_range32[] = {
 	{ 66352, 66378 },
 };
-static const URange16 Katakana_range16[] = {
+static URange16 Katakana_range16[] = {
 	{ 12449, 12538 },
 	{ 12541, 12543 },
 	{ 12784, 12799 },
@@ -4388,38 +4218,33 @@
 	{ 65382, 65391 },
 	{ 65393, 65437 },
 };
-static const URange32 Katakana_range32[] = {
+static URange32 Katakana_range32[] = {
 	{ 110592, 110592 },
 };
-static const URange32 Osmanya_range32[] = {
+static URange32 Osmanya_range32[] = {
 	{ 66688, 66717 },
 	{ 66720, 66729 },
 };
-static const URange16 New_Tai_Lue_range16[] = {
+static URange16 New_Tai_Lue_range16[] = {
 	{ 6528, 6571 },
 	{ 6576, 6601 },
 	{ 6608, 6618 },
 	{ 6622, 6623 },
 };
-static const URange16 Ol_Chiki_range16[] = {
+static URange16 Ol_Chiki_range16[] = {
 	{ 7248, 7295 },
 };
-static const URange16 Limbu_range16[] = {
+static URange16 Limbu_range16[] = {
 	{ 6400, 6428 },
 	{ 6432, 6443 },
 	{ 6448, 6459 },
 	{ 6464, 6464 },
 	{ 6468, 6479 },
 };
-static const URange16 Cherokee_range16[] = {
+static URange16 Cherokee_range16[] = {
 	{ 5024, 5108 },
 };
-static const URange32 Miao_range32[] = {
-	{ 93952, 94020 },
-	{ 94032, 94078 },
-	{ 94095, 94111 },
-};
-static const URange16 Oriya_range16[] = {
+static URange16 Oriya_range16[] = {
 	{ 2817, 2819 },
 	{ 2821, 2828 },
 	{ 2831, 2832 },
@@ -4435,11 +4260,7 @@
 	{ 2911, 2915 },
 	{ 2918, 2935 },
 };
-static const URange32 Sharada_range32[] = {
-	{ 70016, 70088 },
-	{ 70096, 70105 },
-};
-static const URange16 Gujarati_range16[] = {
+static URange16 Gujarati_range16[] = {
 	{ 2689, 2691 },
 	{ 2693, 2701 },
 	{ 2703, 2705 },
@@ -4452,45 +4273,43 @@
 	{ 2763, 2765 },
 	{ 2768, 2768 },
 	{ 2784, 2787 },
-	{ 2790, 2801 },
+	{ 2790, 2799 },
+	{ 2801, 2801 },
 };
-static const URange32 Inscriptional_Pahlavi_range32[] = {
+static URange32 Inscriptional_Pahlavi_range32[] = {
 	{ 68448, 68466 },
 	{ 68472, 68479 },
 };
-static const URange16 Khmer_range16[] = {
+static URange16 Khmer_range16[] = {
 	{ 6016, 6109 },
 	{ 6112, 6121 },
 	{ 6128, 6137 },
 	{ 6624, 6655 },
 };
-static const URange32 Cuneiform_range32[] = {
+static URange32 Cuneiform_range32[] = {
 	{ 73728, 74606 },
 	{ 74752, 74850 },
 	{ 74864, 74867 },
 };
-static const URange16 Mandaic_range16[] = {
+static URange16 Mandaic_range16[] = {
 	{ 2112, 2139 },
 	{ 2142, 2142 },
 };
-static const URange16 Syloti_Nagri_range16[] = {
+static URange16 Syloti_Nagri_range16[] = {
 	{ 43008, 43051 },
 };
-static const URange16 Nko_range16[] = {
+static URange16 Nko_range16[] = {
 	{ 1984, 2042 },
 };
-static const URange16 Canadian_Aboriginal_range16[] = {
+static URange16 Canadian_Aboriginal_range16[] = {
 	{ 5120, 5759 },
 	{ 6320, 6389 },
 };
-static const URange32 Meroitic_Hieroglyphs_range32[] = {
-	{ 67968, 67999 },
-};
-static const URange32 Phoenician_range32[] = {
+static URange32 Phoenician_range32[] = {
 	{ 67840, 67867 },
 	{ 67871, 67871 },
 };
-static const URange16 Bengali_range16[] = {
+static URange16 Bengali_range16[] = {
 	{ 2433, 2435 },
 	{ 2437, 2444 },
 	{ 2447, 2448 },
@@ -4506,22 +4325,18 @@
 	{ 2527, 2531 },
 	{ 2534, 2555 },
 };
-static const URange32 Kaithi_range32[] = {
+static URange32 Kaithi_range32[] = {
 	{ 69760, 69825 },
 };
-static const URange16 Glagolitic_range16[] = {
+static URange16 Glagolitic_range16[] = {
 	{ 11264, 11310 },
 	{ 11312, 11358 },
 };
-static const URange32 Imperial_Aramaic_range32[] = {
+static URange32 Imperial_Aramaic_range32[] = {
 	{ 67648, 67669 },
 	{ 67671, 67679 },
 };
-static const URange32 Sora_Sompeng_range32[] = {
-	{ 69840, 69864 },
-	{ 69872, 69881 },
-};
-static const URange16 Gurmukhi_range16[] = {
+static URange16 Gurmukhi_range16[] = {
 	{ 2561, 2563 },
 	{ 2565, 2570 },
 	{ 2575, 2576 },
@@ -4539,15 +4354,15 @@
 	{ 2654, 2654 },
 	{ 2662, 2677 },
 };
-static const URange16 Javanese_range16[] = {
+static URange16 Javanese_range16[] = {
 	{ 43392, 43469 },
-	{ 43472, 43481 },
+	{ 43471, 43481 },
 	{ 43486, 43487 },
 };
-static const URange16 Phags_Pa_range16[] = {
+static URange16 Phags_Pa_range16[] = {
 	{ 43072, 43127 },
 };
-static const URange32 Cypriot_range32[] = {
+static URange32 Cypriot_range32[] = {
 	{ 67584, 67589 },
 	{ 67592, 67592 },
 	{ 67594, 67637 },
@@ -4555,7 +4370,7 @@
 	{ 67644, 67644 },
 	{ 67647, 67647 },
 };
-static const URange16 Kannada_range16[] = {
+static URange16 Kannada_range16[] = {
 	{ 3202, 3203 },
 	{ 3205, 3212 },
 	{ 3214, 3216 },
@@ -4571,7 +4386,7 @@
 	{ 3302, 3311 },
 	{ 3313, 3314 },
 };
-static const URange16 Mongolian_range16[] = {
+static URange16 Mongolian_range16[] = {
 	{ 6144, 6145 },
 	{ 6148, 6148 },
 	{ 6150, 6158 },
@@ -4579,7 +4394,7 @@
 	{ 6176, 6263 },
 	{ 6272, 6314 },
 };
-static const URange16 Sinhala_range16[] = {
+static URange16 Sinhala_range16[] = {
 	{ 3458, 3459 },
 	{ 3461, 3478 },
 	{ 3482, 3505 },
@@ -4592,26 +4407,26 @@
 	{ 3544, 3551 },
 	{ 3570, 3572 },
 };
-static const URange32 Brahmi_range32[] = {
+static URange32 Brahmi_range32[] = {
 	{ 69632, 69709 },
 	{ 69714, 69743 },
 };
-static const URange32 Deseret_range32[] = {
+static URange32 Deseret_range32[] = {
 	{ 66560, 66639 },
 };
-static const URange16 Rejang_range16[] = {
+static URange16 Rejang_range16[] = {
 	{ 43312, 43347 },
 	{ 43359, 43359 },
 };
-static const URange16 Yi_range16[] = {
+static URange16 Yi_range16[] = {
 	{ 40960, 42124 },
 	{ 42128, 42182 },
 };
-static const URange16 Balinese_range16[] = {
+static URange16 Balinese_range16[] = {
 	{ 6912, 6987 },
 	{ 6992, 7036 },
 };
-static const URange16 Lao_range16[] = {
+static URange16 Lao_range16[] = {
 	{ 3713, 3714 },
 	{ 3716, 3716 },
 	{ 3719, 3720 },
@@ -4629,12 +4444,12 @@
 	{ 3782, 3782 },
 	{ 3784, 3789 },
 	{ 3792, 3801 },
-	{ 3804, 3807 },
+	{ 3804, 3805 },
 };
-static const URange16 Hanunoo_range16[] = {
+static URange16 Hanunoo_range16[] = {
 	{ 5920, 5940 },
 };
-static const URange32 Linear_B_range32[] = {
+static URange32 Linear_B_range32[] = {
 	{ 65536, 65547 },
 	{ 65549, 65574 },
 	{ 65576, 65594 },
@@ -4643,32 +4458,32 @@
 	{ 65616, 65629 },
 	{ 65664, 65786 },
 };
-static const URange32 Old_Turkic_range32[] = {
+static URange32 Old_Turkic_range32[] = {
 	{ 68608, 68680 },
 };
-static const URange16 Lepcha_range16[] = {
+static URange16 Lepcha_range16[] = {
 	{ 7168, 7223 },
 	{ 7227, 7241 },
 	{ 7245, 7247 },
 };
-static const URange32 Lydian_range32[] = {
+static URange32 Lydian_range32[] = {
 	{ 67872, 67897 },
 	{ 67903, 67903 },
 };
-static const URange32 Egyptian_Hieroglyphs_range32[] = {
+static URange32 Egyptian_Hieroglyphs_range32[] = {
 	{ 77824, 78894 },
 };
-static const URange16 Samaritan_range16[] = {
+static URange16 Samaritan_range16[] = {
 	{ 2048, 2093 },
 	{ 2096, 2110 },
 };
-static const URange16 Lisu_range16[] = {
+static URange16 Lisu_range16[] = {
 	{ 42192, 42239 },
 };
-static const URange16 Buhid_range16[] = {
+static URange16 Buhid_range16[] = {
 	{ 5952, 5971 },
 };
-static const URange16 Common_range16[] = {
+static URange16 Common_range16[] = {
 	{ 0, 64 },
 	{ 91, 96 },
 	{ 123, 169 },
@@ -4691,6 +4506,7 @@
 	{ 1632, 1641 },
 	{ 1757, 1757 },
 	{ 2404, 2405 },
+	{ 2416, 2416 },
 	{ 3647, 3647 },
 	{ 4053, 4056 },
 	{ 4347, 4347 },
@@ -4701,14 +4517,13 @@
 	{ 7379, 7379 },
 	{ 7393, 7393 },
 	{ 7401, 7404 },
-	{ 7406, 7411 },
-	{ 7413, 7414 },
+	{ 7406, 7410 },
 	{ 8192, 8203 },
 	{ 8206, 8292 },
-	{ 8294, 8304 },
+	{ 8298, 8304 },
 	{ 8308, 8318 },
 	{ 8320, 8334 },
-	{ 8352, 8378 },
+	{ 8352, 8377 },
 	{ 8448, 8485 },
 	{ 8487, 8489 },
 	{ 8492, 8497 },
@@ -4719,10 +4534,12 @@
 	{ 9216, 9254 },
 	{ 9280, 9290 },
 	{ 9312, 9983 },
-	{ 9985, 10239 },
+	{ 9985, 10186 },
+	{ 10188, 10188 },
+	{ 10190, 10239 },
 	{ 10496, 11084 },
 	{ 11088, 11097 },
-	{ 11776, 11835 },
+	{ 11776, 11825 },
 	{ 12272, 12283 },
 	{ 12288, 12292 },
 	{ 12294, 12294 },
@@ -4741,7 +4558,6 @@
 	{ 42752, 42785 },
 	{ 42888, 42890 },
 	{ 43056, 43065 },
-	{ 43471, 43471 },
 	{ 64830, 64831 },
 	{ 65021, 65021 },
 	{ 65040, 65049 },
@@ -4758,7 +4574,7 @@
 	{ 65512, 65518 },
 	{ 65529, 65533 },
 };
-static const URange32 Common_range32[] = {
+static URange32 Common_range32[] = {
 	{ 65792, 65794 },
 	{ 65799, 65843 },
 	{ 65847, 65855 },
@@ -4802,7 +4618,7 @@
 	{ 127185, 127199 },
 	{ 127232, 127242 },
 	{ 127248, 127278 },
-	{ 127280, 127339 },
+	{ 127280, 127337 },
 	{ 127344, 127386 },
 	{ 127462, 127487 },
 	{ 127489, 127490 },
@@ -4821,40 +4637,42 @@
 	{ 128066, 128247 },
 	{ 128249, 128252 },
 	{ 128256, 128317 },
-	{ 128320, 128323 },
 	{ 128336, 128359 },
-	{ 128507, 128576 },
+	{ 128507, 128511 },
+	{ 128513, 128528 },
+	{ 128530, 128532 },
+	{ 128534, 128534 },
+	{ 128536, 128536 },
+	{ 128538, 128538 },
+	{ 128540, 128542 },
+	{ 128544, 128549 },
+	{ 128552, 128555 },
+	{ 128557, 128557 },
+	{ 128560, 128563 },
+	{ 128565, 128576 },
 	{ 128581, 128591 },
 	{ 128640, 128709 },
 	{ 128768, 128883 },
 	{ 917505, 917505 },
 	{ 917536, 917631 },
 };
-static const URange16 Coptic_range16[] = {
+static URange16 Coptic_range16[] = {
 	{ 994, 1007 },
-	{ 11392, 11507 },
+	{ 11392, 11505 },
 	{ 11513, 11519 },
 };
-static const URange32 Chakma_range32[] = {
-	{ 69888, 69940 },
-	{ 69942, 69955 },
-};
-static const URange16 Arabic_range16[] = {
-	{ 1536, 1540 },
+static URange16 Arabic_range16[] = {
+	{ 1536, 1539 },
 	{ 1542, 1547 },
 	{ 1549, 1562 },
-	{ 1564, 1564 },
 	{ 1566, 1566 },
 	{ 1568, 1599 },
 	{ 1601, 1610 },
-	{ 1622, 1631 },
+	{ 1622, 1630 },
 	{ 1642, 1647 },
 	{ 1649, 1756 },
 	{ 1758, 1791 },
 	{ 1872, 1919 },
-	{ 2208, 2208 },
-	{ 2210, 2220 },
-	{ 2276, 2302 },
 	{ 64336, 64449 },
 	{ 64467, 64829 },
 	{ 64848, 64911 },
@@ -4863,58 +4681,24 @@
 	{ 65136, 65140 },
 	{ 65142, 65276 },
 };
-static const URange32 Arabic_range32[] = {
+static URange32 Arabic_range32[] = {
 	{ 69216, 69246 },
-	{ 126464, 126467 },
-	{ 126469, 126495 },
-	{ 126497, 126498 },
-	{ 126500, 126500 },
-	{ 126503, 126503 },
-	{ 126505, 126514 },
-	{ 126516, 126519 },
-	{ 126521, 126521 },
-	{ 126523, 126523 },
-	{ 126530, 126530 },
-	{ 126535, 126535 },
-	{ 126537, 126537 },
-	{ 126539, 126539 },
-	{ 126541, 126543 },
-	{ 126545, 126546 },
-	{ 126548, 126548 },
-	{ 126551, 126551 },
-	{ 126553, 126553 },
-	{ 126555, 126555 },
-	{ 126557, 126557 },
-	{ 126559, 126559 },
-	{ 126561, 126562 },
-	{ 126564, 126564 },
-	{ 126567, 126570 },
-	{ 126572, 126578 },
-	{ 126580, 126583 },
-	{ 126585, 126588 },
-	{ 126590, 126590 },
-	{ 126592, 126601 },
-	{ 126603, 126619 },
-	{ 126625, 126627 },
-	{ 126629, 126633 },
-	{ 126635, 126651 },
-	{ 126704, 126705 },
 };
-static const URange16 Bamum_range16[] = {
+static URange16 Bamum_range16[] = {
 	{ 42656, 42743 },
 };
-static const URange32 Bamum_range32[] = {
+static URange32 Bamum_range32[] = {
 	{ 92160, 92728 },
 };
-static const URange16 Myanmar_range16[] = {
+static URange16 Myanmar_range16[] = {
 	{ 4096, 4255 },
 	{ 43616, 43643 },
 };
-static const URange32 Avestan_range32[] = {
+static URange32 Avestan_range32[] = {
 	{ 68352, 68405 },
 	{ 68409, 68415 },
 };
-static const URange16 Hebrew_range16[] = {
+static URange16 Hebrew_range16[] = {
 	{ 1425, 1479 },
 	{ 1488, 1514 },
 	{ 1520, 1524 },
@@ -4925,14 +4709,10 @@
 	{ 64323, 64324 },
 	{ 64326, 64335 },
 };
-static const URange32 Takri_range32[] = {
-	{ 71296, 71351 },
-	{ 71360, 71369 },
-};
-// 3867 16-bit ranges, 723 32-bit ranges
-const UGroup unicode_groups[] = {
-	{ "Arabic", +1, Arabic_range16, 22, Arabic_range32, 35 },
-	{ "Armenian", +1, Armenian_range16, 6, 0, 0 },
+// 3804 16-bit ranges, 582 32-bit ranges
+UGroup unicode_groups[] = {
+	{ "Arabic", +1, Arabic_range16, 18, Arabic_range32, 1 },
+	{ "Armenian", +1, Armenian_range16, 5, 0, 0 },
 	{ "Avestan", +1, 0, 0, Avestan_range32, 2 },
 	{ "Balinese", +1, Balinese_range16, 2, 0, 0 },
 	{ "Bamum", +1, Bamum_range16, 1, Bamum_range32, 1 },
@@ -4943,32 +4723,31 @@
 	{ "Braille", +1, Braille_range16, 1, 0, 0 },
 	{ "Buginese", +1, Buginese_range16, 2, 0, 0 },
 	{ "Buhid", +1, Buhid_range16, 1, 0, 0 },
-	{ "C", +1, C_range16, 15, C_range32, 6 },
+	{ "C", +1, C_range16, 14, C_range32, 6 },
 	{ "Canadian_Aboriginal", +1, Canadian_Aboriginal_range16, 2, 0, 0 },
 	{ "Carian", +1, 0, 0, Carian_range32, 1 },
 	{ "Cc", +1, Cc_range16, 2, 0, 0 },
-	{ "Cf", +1, Cf_range16, 12, Cf_range32, 4 },
-	{ "Chakma", +1, 0, 0, Chakma_range32, 2 },
+	{ "Cf", +1, Cf_range16, 11, Cf_range32, 4 },
 	{ "Cham", +1, Cham_range16, 4, 0, 0 },
 	{ "Cherokee", +1, Cherokee_range16, 1, 0, 0 },
 	{ "Co", +1, Co_range16, 1, Co_range32, 2 },
-	{ "Common", +1, Common_range16, 88, Common_range32, 70 },
+	{ "Common", +1, Common_range16, 89, Common_range32, 80 },
 	{ "Coptic", +1, Coptic_range16, 3, 0, 0 },
 	{ "Cs", +1, Cs_range16, 1, 0, 0 },
 	{ "Cuneiform", +1, 0, 0, Cuneiform_range32, 3 },
 	{ "Cypriot", +1, 0, 0, Cypriot_range32, 6 },
 	{ "Cyrillic", +1, Cyrillic_range16, 7, 0, 0 },
 	{ "Deseret", +1, 0, 0, Deseret_range32, 1 },
-	{ "Devanagari", +1, Devanagari_range16, 5, 0, 0 },
+	{ "Devanagari", +1, Devanagari_range16, 6, 0, 0 },
 	{ "Egyptian_Hieroglyphs", +1, 0, 0, Egyptian_Hieroglyphs_range32, 1 },
 	{ "Ethiopic", +1, Ethiopic_range16, 32, 0, 0 },
-	{ "Georgian", +1, Georgian_range16, 8, 0, 0 },
+	{ "Georgian", +1, Georgian_range16, 4, 0, 0 },
 	{ "Glagolitic", +1, Glagolitic_range16, 2, 0, 0 },
 	{ "Gothic", +1, 0, 0, Gothic_range32, 1 },
 	{ "Greek", +1, Greek_range16, 31, Greek_range32, 2 },
-	{ "Gujarati", +1, Gujarati_range16, 13, 0, 0 },
+	{ "Gujarati", +1, Gujarati_range16, 14, 0, 0 },
 	{ "Gurmukhi", +1, Gurmukhi_range16, 16, 0, 0 },
-	{ "Han", +1, Han_range16, 11, Han_range32, 4 },
+	{ "Han", +1, Han_range16, 12, Han_range32, 4 },
 	{ "Hangul", +1, Hangul_range16, 14, 0, 0 },
 	{ "Hanunoo", +1, Hanunoo_range16, 1, 0, 0 },
 	{ "Hebrew", +1, Hebrew_range16, 9, 0, 0 },
@@ -4984,38 +4763,35 @@
 	{ "Kayah_Li", +1, Kayah_Li_range16, 1, 0, 0 },
 	{ "Kharoshthi", +1, 0, 0, Kharoshthi_range32, 8 },
 	{ "Khmer", +1, Khmer_range16, 4, 0, 0 },
-	{ "L", +1, L_range16, 370, L_range32, 116 },
+	{ "L", +1, L_range16, 362, L_range32, 73 },
 	{ "Lao", +1, Lao_range16, 18, 0, 0 },
 	{ "Latin", +1, Latin_range16, 30, 0, 0 },
 	{ "Lepcha", +1, Lepcha_range16, 3, 0, 0 },
 	{ "Limbu", +1, Limbu_range16, 5, 0, 0 },
 	{ "Linear_B", +1, 0, 0, Linear_B_range32, 7 },
 	{ "Lisu", +1, Lisu_range16, 1, 0, 0 },
-	{ "Ll", +1, Ll_range16, 582, Ll_range32, 29 },
-	{ "Lm", +1, Lm_range16, 51, Lm_range32, 1 },
-	{ "Lo", +1, Lo_range16, 286, Lo_range32, 85 },
+	{ "Ll", +1, Ll_range16, 580, Ll_range32, 29 },
+	{ "Lm", +1, Lm_range16, 49, 0, 0 },
+	{ "Lo", +1, Lo_range16, 280, Lo_range32, 43 },
 	{ "Lt", +1, Lt_range16, 10, 0, 0 },
-	{ "Lu", +1, Lu_range16, 576, Lu_range32, 32 },
+	{ "Lu", +1, Lu_range16, 571, Lu_range32, 32 },
 	{ "Lycian", +1, 0, 0, Lycian_range32, 1 },
 	{ "Lydian", +1, 0, 0, Lydian_range32, 2 },
-	{ "M", +1, M_range16, 180, M_range32, 24 },
+	{ "M", +1, M_range16, 176, M_range32, 17 },
 	{ "Malayalam", +1, Malayalam_range16, 11, 0, 0 },
 	{ "Mandaic", +1, Mandaic_range16, 2, 0, 0 },
-	{ "Mc", +1, Mc_range16, 111, Mc_range32, 15 },
+	{ "Mc", +1, Mc_range16, 106, Mc_range32, 7 },
 	{ "Me", +1, Me_range16, 4, 0, 0 },
-	{ "Meetei_Mayek", +1, Meetei_Mayek_range16, 3, 0, 0 },
-	{ "Meroitic_Cursive", +1, 0, 0, Meroitic_Cursive_range32, 2 },
-	{ "Meroitic_Hieroglyphs", +1, 0, 0, Meroitic_Hieroglyphs_range32, 1 },
-	{ "Miao", +1, 0, 0, Miao_range32, 3 },
-	{ "Mn", +1, Mn_range16, 194, Mn_range32, 27 },
+	{ "Meetei_Mayek", +1, Meetei_Mayek_range16, 2, 0, 0 },
+	{ "Mn", +1, Mn_range16, 186, Mn_range32, 17 },
 	{ "Mongolian", +1, Mongolian_range16, 6, 0, 0 },
 	{ "Myanmar", +1, Myanmar_range16, 2, 0, 0 },
-	{ "N", +1, N_range16, 64, N_range32, 24 },
-	{ "Nd", +1, Nd_range16, 35, Nd_range32, 7 },
+	{ "N", +1, N_range16, 63, N_range32, 20 },
+	{ "Nd", +1, Nd_range16, 35, Nd_range32, 3 },
 	{ "New_Tai_Lue", +1, New_Tai_Lue_range16, 4, 0, 0 },
 	{ "Nko", +1, Nko_range16, 1, 0, 0 },
 	{ "Nl", +1, Nl_range16, 7, Nl_range32, 5 },
-	{ "No", +1, No_range16, 28, No_range32, 14 },
+	{ "No", +1, No_range16, 27, No_range32, 14 },
 	{ "Ogham", +1, Ogham_range16, 1, 0, 0 },
 	{ "Ol_Chiki", +1, Ol_Chiki_range16, 1, 0, 0 },
 	{ "Old_Italic", +1, 0, 0, Old_Italic_range32, 2 },
@@ -5024,29 +4800,27 @@
 	{ "Old_Turkic", +1, 0, 0, Old_Turkic_range32, 1 },
 	{ "Oriya", +1, Oriya_range16, 14, 0, 0 },
 	{ "Osmanya", +1, 0, 0, Osmanya_range32, 2 },
-	{ "P", +1, P_range16, 126, P_range32, 15 },
+	{ "P", +1, P_range16, 120, P_range32, 13 },
 	{ "Pc", +1, Pc_range16, 6, 0, 0 },
-	{ "Pd", +1, Pd_range16, 16, 0, 0 },
-	{ "Pe", +1, Pe_range16, 72, 0, 0 },
+	{ "Pd", +1, Pd_range16, 15, 0, 0 },
+	{ "Pe", +1, Pe_range16, 70, 0, 0 },
 	{ "Pf", +1, Pf_range16, 10, 0, 0 },
 	{ "Phags_Pa", +1, Phags_Pa_range16, 1, 0, 0 },
 	{ "Phoenician", +1, 0, 0, Phoenician_range32, 2 },
 	{ "Pi", +1, Pi_range16, 11, 0, 0 },
-	{ "Po", +1, Po_range16, 120, Po_range32, 15 },
-	{ "Ps", +1, Ps_range16, 74, 0, 0 },
+	{ "Po", +1, Po_range16, 115, Po_range32, 13 },
+	{ "Ps", +1, Ps_range16, 72, 0, 0 },
 	{ "Rejang", +1, Rejang_range16, 2, 0, 0 },
 	{ "Runic", +1, Runic_range16, 2, 0, 0 },
-	{ "S", +1, S_range16, 143, S_range32, 56 },
+	{ "S", +1, S_range16, 142, S_range32, 66 },
 	{ "Samaritan", +1, Samaritan_range16, 2, 0, 0 },
 	{ "Saurashtra", +1, Saurashtra_range16, 2, 0, 0 },
-	{ "Sc", +1, Sc_range16, 17, 0, 0 },
-	{ "Sharada", +1, 0, 0, Sharada_range32, 2 },
+	{ "Sc", +1, Sc_range16, 16, 0, 0 },
 	{ "Shavian", +1, 0, 0, Shavian_range32, 1 },
 	{ "Sinhala", +1, Sinhala_range16, 11, 0, 0 },
 	{ "Sk", +1, Sk_range16, 27, 0, 0 },
-	{ "Sm", +1, Sm_range16, 53, Sm_range32, 11 },
-	{ "So", +1, So_range16, 108, So_range32, 45 },
-	{ "Sora_Sompeng", +1, 0, 0, Sora_Sompeng_range32, 2 },
+	{ "Sm", +1, Sm_range16, 56, Sm_range32, 10 },
+	{ "So", +1, So_range16, 108, So_range32, 56 },
 	{ "Sundanese", +1, Sundanese_range16, 2, 0, 0 },
 	{ "Syloti_Nagri", +1, Syloti_Nagri_range16, 1, 0, 0 },
 	{ "Syriac", +1, Syriac_range16, 3, 0, 0 },
@@ -5055,7 +4829,6 @@
 	{ "Tai_Le", +1, Tai_Le_range16, 2, 0, 0 },
 	{ "Tai_Tham", +1, Tai_Tham_range16, 5, 0, 0 },
 	{ "Tai_Viet", +1, Tai_Viet_range16, 2, 0, 0 },
-	{ "Takri", +1, 0, 0, Takri_range32, 2 },
 	{ "Tamil", +1, Tamil_range16, 16, 0, 0 },
 	{ "Telugu", +1, Telugu_range16, 14, 0, 0 },
 	{ "Thaana", +1, Thaana_range16, 1, 0, 0 },
@@ -5065,12 +4838,12 @@
 	{ "Ugaritic", +1, 0, 0, Ugaritic_range32, 2 },
 	{ "Vai", +1, Vai_range16, 1, 0, 0 },
 	{ "Yi", +1, Yi_range16, 2, 0, 0 },
-	{ "Z", +1, Z_range16, 8, 0, 0 },
+	{ "Z", +1, Z_range16, 9, 0, 0 },
 	{ "Zl", +1, Zl_range16, 1, 0, 0 },
 	{ "Zp", +1, Zp_range16, 1, 0, 0 },
-	{ "Zs", +1, Zs_range16, 7, 0, 0 },
+	{ "Zs", +1, Zs_range16, 8, 0, 0 },
 };
-const int num_unicode_groups = 138;
+int num_unicode_groups = 131;
 
 
 }  // namespace re2
diff --git a/third_party/re2/re2/unicode_groups.h b/third_party/re2/re2/unicode_groups.h
index fc1c2534..f91c51f5 100644
--- a/third_party/re2/re2/unicode_groups.h
+++ b/third_party/re2/re2/unicode_groups.h
@@ -30,34 +30,34 @@
 
 struct URange32
 {
-  Rune lo;
-  Rune hi;
+  uint32 lo;
+  uint32 hi;
 };
 
 struct UGroup
 {
   const char *name;
   int sign;  // +1 for [abc], -1 for [^abc]
-  const URange16 *r16;
+  URange16 *r16;
   int nr16;
-  const URange32 *r32;
+  URange32 *r32;
   int nr32;
 };
 
 // Named by property or script name (e.g., "Nd", "N", "Han").
 // Negated groups are not included.
-extern const UGroup unicode_groups[];
-extern const int num_unicode_groups;
+extern UGroup unicode_groups[];
+extern int num_unicode_groups;
 
 // Named by POSIX name (e.g., "[:alpha:]", "[:^lower:]").
 // Negated groups are included.
-extern const UGroup posix_groups[];
-extern const int num_posix_groups;
+extern UGroup posix_groups[];
+extern int num_posix_groups;
 
 // Named by Perl name (e.g., "\\d", "\\D").
 // Negated groups are included.
-extern const UGroup perl_groups[];
-extern const int num_perl_groups;
+extern UGroup perl_groups[];
+extern int num_perl_groups;
 
 }  // namespace re2
 
diff --git a/third_party/re2/re2/walker-inl.h b/third_party/re2/re2/walker-inl.h
index bdcf7f5..4d2045f 100644
--- a/third_party/re2/re2/walker-inl.h
+++ b/third_party/re2/re2/walker-inl.h
@@ -92,7 +92,7 @@
 
   T WalkInternal(Regexp* re, T top_arg, bool use_copy);
 
-  DISALLOW_COPY_AND_ASSIGN(Walker);
+  DISALLOW_EVIL_CONSTRUCTORS(Walker);
 };
 
 template<typename T> T Regexp::Walker<T>::PreVisit(Regexp* re,
diff --git a/third_party/re2/re2_test.bzl b/third_party/re2/re2_test.bzl
deleted file mode 100644
index a52cd9f..0000000
--- a/third_party/re2/re2_test.bzl
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2009 The RE2 Authors.  All Rights Reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# Define a bazel macro that creates cc_test for re2.
-def re2_test(name, deps=[]):
-  native.cc_test(
-      name=name,
-      srcs=["re2/testing/%s.cc" % (name)],
-      deps=[
-          ":re2",
-          ":test",
-      ] + deps
-  )
diff --git a/third_party/re2/testinstall.cc b/third_party/re2/testinstall.cc
index 97990c2c..17edfb40 100644
--- a/third_party/re2/testinstall.cc
+++ b/third_party/re2/testinstall.cc
@@ -14,8 +14,6 @@
 	f.Add("a.*b.*c", RE2::DefaultOptions, &id);
 	vector<string> v;
 	f.Compile(&v);
-	vector<int> ids;
-	f.FirstMatch("abbccc", ids);
 
 	if(RE2::FullMatch("axbyc", "a.*b.*c")) {
 		printf("PASS\n");
diff --git a/third_party/re2/util/arena.cc b/third_party/re2/util/arena.cc
new file mode 100644
index 0000000..25753c5d
--- /dev/null
+++ b/third_party/re2/util/arena.cc
@@ -0,0 +1,168 @@
+// Copyright 2000 The RE2 Authors.  All Rights Reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "util/util.h"
+
+namespace re2 {
+
+// ----------------------------------------------------------------------
+// UnsafeArena::UnsafeArena()
+// UnsafeArena::~UnsafeArena()
+//    Destroying the arena automatically calls Reset()
+// ----------------------------------------------------------------------
+
+
+UnsafeArena::UnsafeArena(const size_t block_size)
+  : block_size_(block_size),
+    freestart_(NULL),                   // set for real in Reset()
+    last_alloc_(NULL),
+    remaining_(0),
+    blocks_alloced_(1),
+    overflow_blocks_(NULL) {
+  assert(block_size > kDefaultAlignment);
+
+  first_blocks_[0].mem = reinterpret_cast<char*>(malloc(block_size_));
+  first_blocks_[0].size = block_size_;
+
+  Reset();
+}
+
+UnsafeArena::~UnsafeArena() {
+  FreeBlocks();
+  assert(overflow_blocks_ == NULL);    // FreeBlocks() should do that
+  // The first X blocks stay allocated always by default.  Delete them now.
+  for (int i = 0; i < blocks_alloced_; i++)
+    free(first_blocks_[i].mem);
+}
+
+// ----------------------------------------------------------------------
+// UnsafeArena::Reset()
+//    Clears all the memory an arena is using.
+// ----------------------------------------------------------------------
+
+void UnsafeArena::Reset() {
+  FreeBlocks();
+  freestart_ = first_blocks_[0].mem;
+  remaining_ = first_blocks_[0].size;
+  last_alloc_ = NULL;
+
+  // We do not know for sure whether or not the first block is aligned,
+  // so we fix that right now.
+  const int overage = reinterpret_cast<uintptr_t>(freestart_) &
+                      (kDefaultAlignment-1);
+  if (overage > 0) {
+    const int waste = kDefaultAlignment - overage;
+    freestart_ += waste;
+    remaining_ -= waste;
+  }
+  freestart_when_empty_ = freestart_;
+  assert(!(reinterpret_cast<uintptr_t>(freestart_)&(kDefaultAlignment-1)));
+}
+
+// -------------------------------------------------------------
+// UnsafeArena::AllocNewBlock()
+//    Adds and returns an AllocatedBlock.
+//    The returned AllocatedBlock* is valid until the next call
+//    to AllocNewBlock or Reset.  (i.e. anything that might
+//    affect overflow_blocks_).
+// -------------------------------------------------------------
+
+UnsafeArena::AllocatedBlock* UnsafeArena::AllocNewBlock(const size_t block_size) {
+  AllocatedBlock *block;
+  // Find the next block.
+  if ( blocks_alloced_ < arraysize(first_blocks_) ) {
+    // Use one of the pre-allocated blocks
+    block = &first_blocks_[blocks_alloced_++];
+  } else {                   // oops, out of space, move to the vector
+    if (overflow_blocks_ == NULL) overflow_blocks_ = new vector<AllocatedBlock>;
+    // Adds another block to the vector.
+    overflow_blocks_->resize(overflow_blocks_->size()+1);
+    // block points to the last block of the vector.
+    block = &overflow_blocks_->back();
+  }
+
+  block->mem = reinterpret_cast<char*>(malloc(block_size));
+  block->size = block_size;
+
+  return block;
+}
+
+// ----------------------------------------------------------------------
+// UnsafeArena::GetMemoryFallback()
+//    We take memory out of our pool, aligned on the byte boundary
+//    requested.  If we don't have space in our current pool, we
+//    allocate a new block (wasting the remaining space in the
+//    current block) and give you that.  If your memory needs are
+//    too big for a single block, we make a special your-memory-only
+//    allocation -- this is equivalent to not using the arena at all.
+// ----------------------------------------------------------------------
+
+void* UnsafeArena::GetMemoryFallback(const size_t size, const int align) {
+  if (size == 0)
+    return NULL;             // stl/stl_alloc.h says this is okay
+
+  assert(align > 0 && 0 == (align & (align - 1)));  // must be power of 2
+
+  // If the object is more than a quarter of the block size, allocate
+  // it separately to avoid wasting too much space in leftover bytes
+  if (block_size_ == 0 || size > block_size_/4) {
+    // then it gets its own block in the arena
+    assert(align <= kDefaultAlignment);   // because that's what new gives us
+    // This block stays separate from the rest of the world; in particular
+    // we don't update last_alloc_ so you can't reclaim space on this block.
+    return AllocNewBlock(size)->mem;
+  }
+
+  const int overage =
+    (reinterpret_cast<uintptr_t>(freestart_) & (align-1));
+  if (overage) {
+    const int waste = align - overage;
+    freestart_ += waste;
+    if (waste < remaining_) {
+      remaining_ -= waste;
+    } else {
+      remaining_ = 0;
+    }
+  }
+  if (size > remaining_) {
+    AllocatedBlock *block = AllocNewBlock(block_size_);
+    freestart_ = block->mem;
+    remaining_ = block->size;
+  }
+  remaining_ -= size;
+  last_alloc_ = freestart_;
+  freestart_ += size;
+  assert((reinterpret_cast<uintptr_t>(last_alloc_) & (align-1)) == 0);
+  return reinterpret_cast<void*>(last_alloc_);
+}
+
+// ----------------------------------------------------------------------
+// UnsafeArena::FreeBlocks()
+//    Unlike GetMemory(), which does actual work, ReturnMemory() is a
+//    no-op: we don't "free" memory until Reset() is called.  We do
+//    update some stats, though.  Note we do no checking that the
+//    pointer you pass in was actually allocated by us, or that it
+//    was allocated for the size you say, so be careful here!
+//       FreeBlocks() does the work for Reset(), actually freeing all
+//    memory allocated in one fell swoop.
+// ----------------------------------------------------------------------
+
+void UnsafeArena::FreeBlocks() {
+  for ( int i = 1; i < blocks_alloced_; ++i ) {  // keep first block alloced
+    free(first_blocks_[i].mem);
+    first_blocks_[i].mem = NULL;
+    first_blocks_[i].size = 0;
+  }
+  blocks_alloced_ = 1;
+  if (overflow_blocks_ != NULL) {
+    vector<AllocatedBlock>::iterator it;
+    for (it = overflow_blocks_->begin(); it != overflow_blocks_->end(); ++it) {
+      free(it->mem);
+    }
+    delete overflow_blocks_;             // These should be used very rarely
+    overflow_blocks_ = NULL;
+  }
+}
+
+}  // namespace re2
diff --git a/third_party/re2/util/arena.h b/third_party/re2/util/arena.h
new file mode 100644
index 0000000..7eb385b
--- /dev/null
+++ b/third_party/re2/util/arena.h
@@ -0,0 +1,103 @@
+// Copyright 2000 The RE2 Authors.  All Rights Reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Sometimes it is necessary to allocate a large number of small
+// objects.  Doing this the usual way (malloc, new) is slow,
+// especially for multithreaded programs.  An UnsafeArena provides a
+// mark/release method of memory management: it asks for a large chunk
+// from the operating system and doles it out bit by bit as required.
+// Then you free all the memory at once by calling UnsafeArena::Reset().
+// The "Unsafe" refers to the fact that UnsafeArena is not safe to
+// call from multiple threads.
+//
+// The global operator new that can be used as follows:
+//
+//   #include "lib/arena-inl.h"
+//
+//   UnsafeArena arena(1000);
+//   Foo* foo = new (AllocateInArena, &arena) Foo;
+//
+
+#ifndef RE2_UTIL_ARENA_H_
+#define RE2_UTIL_ARENA_H_
+
+namespace re2 {
+
+// This class is thread-compatible.
+class UnsafeArena {
+ public:
+  UnsafeArena(const size_t block_size);
+  virtual ~UnsafeArena();
+
+  void Reset();
+
+  // This should be the worst-case alignment for any type.  This is
+  // good for IA-32, SPARC version 7 (the last one I know), and
+  // supposedly Alpha.  i386 would be more time-efficient with a
+  // default alignment of 8, but ::operator new() uses alignment of 4,
+  // and an assertion will fail below after the call to MakeNewBlock()
+  // if you try to use a larger alignment.
+#ifdef __i386__
+  static const int kDefaultAlignment = 4;
+#else
+  static const int kDefaultAlignment = 8;
+#endif
+
+ private:
+  void* GetMemoryFallback(const size_t size, const int align);
+
+ public:
+  void* GetMemory(const size_t size, const int align) {
+    if ( size > 0 && size < remaining_ && align == 1 ) {       // common case
+      last_alloc_ = freestart_;
+      freestart_ += size;
+      remaining_ -= size;
+      return reinterpret_cast<void*>(last_alloc_);
+    }
+    return GetMemoryFallback(size, align);
+  }
+
+ private:
+  struct AllocatedBlock {
+    char *mem;
+    size_t size;
+  };
+
+  // The returned AllocatedBlock* is valid until the next call to AllocNewBlock
+  // or Reset (i.e. anything that might affect overflow_blocks_).
+  AllocatedBlock *AllocNewBlock(const size_t block_size);
+
+  const AllocatedBlock *IndexToBlock(int index) const;
+
+  const size_t block_size_;
+  char* freestart_;         // beginning of the free space in most recent block
+  char* freestart_when_empty_;  // beginning of the free space when we're empty
+  char* last_alloc_;         // used to make sure ReturnBytes() is safe
+  size_t remaining_;
+  // STL vector isn't as efficient as it could be, so we use an array at first
+  int blocks_alloced_;       // how many of the first_blocks_ have been alloced
+  AllocatedBlock first_blocks_[16];   // the length of this array is arbitrary
+  // if the first_blocks_ aren't enough, expand into overflow_blocks_.
+  vector<AllocatedBlock>* overflow_blocks_;
+
+  void FreeBlocks();         // Frees all except first block
+
+  DISALLOW_EVIL_CONSTRUCTORS(UnsafeArena);
+};
+
+// Operators for allocation on the arena
+// Syntax: new (AllocateInArena, arena) MyClass;
+// STL containers, etc.
+enum AllocateInArenaType { AllocateInArena };
+
+}  // namespace re2
+
+inline void* operator new(size_t size,
+                          re2::AllocateInArenaType /* unused */,
+                          re2::UnsafeArena *arena) {
+  return reinterpret_cast<char*>(arena->GetMemory(size, 1));
+}
+
+#endif  // RE2_UTIL_ARENA_H_
+
diff --git a/third_party/re2/util/atomicops.h b/third_party/re2/util/atomicops.h
index dc944e7..11c1196 100644
--- a/third_party/re2/util/atomicops.h
+++ b/third_party/re2/util/atomicops.h
@@ -5,35 +5,6 @@
 #ifndef RE2_UTIL_ATOMICOPS_H__
 #define RE2_UTIL_ATOMICOPS_H__
 
-// The memory ordering constraints resemble the ones in C11.
-// RELAXED - no memory ordering, just an atomic operation.
-// CONSUME - data-dependent ordering.
-// ACQUIRE - prevents memory accesses from hoisting above the operation.
-// RELEASE - prevents memory accesses from sinking below the operation.
-
-#ifndef __has_builtin
-#define __has_builtin(x) 0
-#endif
-
-#if !defined(OS_NACL) && (__has_builtin(__atomic_load_n) || (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__ >= 40801))
-
-#define ATOMIC_LOAD_RELAXED(x, p) do { (x) = __atomic_load_n((p), __ATOMIC_RELAXED); } while (0)
-#define ATOMIC_LOAD_CONSUME(x, p) do { (x) = __atomic_load_n((p), __ATOMIC_CONSUME); } while (0)
-#define ATOMIC_LOAD_ACQUIRE(x, p) do { (x) = __atomic_load_n((p), __ATOMIC_ACQUIRE); } while (0)
-#define ATOMIC_STORE_RELAXED(p, v) __atomic_store_n((p), (v), __ATOMIC_RELAXED)
-#define ATOMIC_STORE_RELEASE(p, v) __atomic_store_n((p), (v), __ATOMIC_RELEASE)
-
-#else  // old compiler
-
-#define ATOMIC_LOAD_RELAXED(x, p) do { (x) = *(p); } while (0)
-#define ATOMIC_LOAD_CONSUME(x, p) do { (x) = *(p); MaybeReadMemoryBarrier(); } while (0)
-#define ATOMIC_LOAD_ACQUIRE(x, p) do { (x) = *(p); ReadMemoryBarrier(); } while (0)
-#define ATOMIC_STORE_RELAXED(p, v) do { *(p) = (v); } while (0)
-#define ATOMIC_STORE_RELEASE(p, v) do { WriteMemoryBarrier(); *(p) = (v); } while (0)
-
-// WriteMemoryBarrier(), ReadMemoryBarrier() and MaybeReadMemoryBarrier()
-// are an implementation detail and must not be used in the rest of the code.
-
 #if defined(__i386__)
 
 static inline void WriteMemoryBarrier() {
@@ -50,16 +21,10 @@
   __asm__ __volatile__("sfence" : : : "memory");
 }
 
-#elif defined(__ppc__) || defined(__powerpc64__)
+#elif defined(__ppc__)
 
 static inline void WriteMemoryBarrier() {
-  __asm__ __volatile__("lwsync" : : : "memory");
-}
-
-#elif defined(__aarch64__)
-
-static inline void WriteMemoryBarrier() {
-  __asm__ __volatile__("dmb st" : : : "memory");
+  __asm__ __volatile__("eieio" : : : "memory");
 }
 
 #elif defined(__alpha__)
@@ -68,43 +33,6 @@
   __asm__ __volatile__("wmb" : : : "memory");
 }
 
-#elif defined(__arm__) && defined(__linux__)
-
-// Linux on ARM puts a suitable memory barrier at a magic address for us to call.
-static inline void WriteMemoryBarrier() {
-  ((void(*)(void))0xffff0fa0)();
-}
-
-#elif defined(__windows__) || defined(_WIN32)
-
-#include <intrin.h>
-#include <windows.h>
-
-static inline void WriteMemoryBarrier() {
-#if defined(_M_IX86) || defined(_M_X64)
-  // x86 and x64 CPUs have a strong memory model that prohibits most types of
-  // reordering, so a non-instruction intrinsic to suppress compiler reordering
-  // is sufficient. _WriteBarrier is deprecated, but is still appropriate for
-  // the "old compiler" path (pre C++11).
-  _WriteBarrier();
-#else
-  LONG x;
-  ::InterlockedExchange(&x, 0);
-#endif
-}
-
-#elif defined(OS_NACL)
-
-static inline void WriteMemoryBarrier() {
-  __sync_synchronize();
-}
-
-#elif defined(__mips__)
-
-static inline void WriteMemoryBarrier() {
-  __asm__ __volatile__("sync" : : : "memory");
-}
-
 #else
 
 #include "util/mutex.h"
@@ -122,9 +50,19 @@
   re2::MutexLock l(&mu);
 }
 
+/*
+#error Need WriteMemoryBarrier for architecture.
+
+// Windows
+inline void WriteMemoryBarrier() {
+  LONG x;
+  ::InterlockedExchange(&x, 0);
+}
+*/
+
 #endif
 
-// Alpha has very weak memory ordering. If relying on WriteBarriers, one must
+// Alpha has very weak memory ordering. If relying on WriteBarriers, must one
 // use read barriers for the readers too.
 #if defined(__alpha__)
 
@@ -136,44 +74,6 @@
 
 static inline void MaybeReadMemoryBarrier() {}
 
-#endif  // __alpha__
-
-// Read barrier for various targets.
-
-#if defined(__ppc__) || defined(__powerpc64__)
-
-static inline void ReadMemoryBarrier() {
-  __asm__ __volatile__("lwsync" : : : "memory");
-}
-
-#elif defined(__aarch64__)
-
-static inline void ReadMemoryBarrier() {
-  __asm__ __volatile__("dmb ld" : : : "memory");
-}
-
-#elif defined(__alpha__)
-
-static inline void ReadMemoryBarrier() {
-  __asm__ __volatile__("mb" : : : "memory");
-}
-
-#elif defined(__mips__)
-
-static inline void ReadMemoryBarrier() {
-  __asm__ __volatile__("sync" : : : "memory");
-}
-
-#else
-
-static inline void ReadMemoryBarrier() {}
-
-#endif
-
-#endif  // old compiler
-
-#ifndef NO_THREAD_SAFETY_ANALYSIS
-#define NO_THREAD_SAFETY_ANALYSIS
-#endif
+#endif // __alpha__
 
 #endif  // RE2_UTIL_ATOMICOPS_H__
diff --git a/third_party/re2/util/benchmark.cc b/third_party/re2/util/benchmark.cc
index b77e22d..c3aad7e 100644
--- a/third_party/re2/util/benchmark.cc
+++ b/third_party/re2/util/benchmark.cc
@@ -25,29 +25,10 @@
 }
 
 static int64 nsec() {
-#if defined(__APPLE__)
 	struct timeval tv;
 	if(gettimeofday(&tv, 0) < 0)
 		return -1;
 	return (int64)tv.tv_sec*1000*1000*1000 + tv.tv_usec*1000;
-#elif defined(_WIN32)
-	// https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408.aspx
-	// describes how to query ticks and convert to microseconds. Of course,
-	// what we want in this case are nanoseconds. Also, note that .QuadPart
-	// is a signed 64-bit integer, so casting to int64 shouldn't be needed.
-	LARGE_INTEGER freq;
-	QueryPerformanceFrequency(&freq);
-	LARGE_INTEGER ticks;
-	QueryPerformanceCounter(&ticks);
-	ticks.QuadPart *= 1000*1000*1000;
-	ticks.QuadPart /= freq.QuadPart;
-	return ticks.QuadPart;
-#else
-	struct timespec tp;
-	if(clock_gettime(CLOCK_REALTIME, &tp) < 0)
-		return -1;
-	return (int64)tp.tv_sec*1000*1000*1000 + tp.tv_nsec;
-#endif
 }
 
 static int64 bytes;
@@ -124,9 +105,9 @@
 	while(ns < (int)1e9 && n < (int)1e9) {
 		last = n;
 		if(ns/n == 0)
-			n = (int)1e9;
+			n = 1e9;
 		else
-			n = (int)1e9 / static_cast<int>(ns/n);
+			n = 1e9 / (ns/n);
 		
 		n = max(last+1, min(n+n/2, 100*last));
 		n = round(n);
diff --git a/third_party/re2/util/flags.h b/third_party/re2/util/flags.h
index 98d5c06..77a06a22 100644
--- a/third_party/re2/util/flags.h
+++ b/third_party/re2/util/flags.h
@@ -5,7 +5,7 @@
 // Simplified version of Google's command line flags.
 // Does not support parsing the command line.
 // If you want to do that, see
-// https://gflags.github.io/gflags/
+// http://code.google.com/p/google-gflags
 
 #ifndef RE2_UTIL_FLAGS_H__
 #define RE2_UTIL_FLAGS_H__
diff --git a/third_party/re2/util/logging.cc b/third_party/re2/util/logging.cc
deleted file mode 100644
index 8a59862..0000000
--- a/third_party/re2/util/logging.cc
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2015 The RE2 Authors.  All Rights Reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "util/logging.h"
-
-DEFINE_int32(minloglevel, 0,  // INFO
-             "Messages logged at a lower level than this don't actually get "
-             "logged anywhere");
diff --git a/third_party/re2/util/logging.h b/third_party/re2/util/logging.h
index feac199..d0a2d875 100644
--- a/third_party/re2/util/logging.h
+++ b/third_party/re2/util/logging.h
@@ -7,13 +7,13 @@
 #ifndef RE2_UTIL_LOGGING_H__
 #define RE2_UTIL_LOGGING_H__
 
-#include <stdio.h>  /* for fwrite */
+#ifndef WIN32
+#include <unistd.h>  /* for write */
+#endif
 #include <sstream>
-
-#include "util/util.h"
-#include "util/flags.h"
-
-DECLARE_int32(minloglevel);
+#ifdef WIN32
+#include <io.h>
+#endif
 
 // Debug-only checking.
 #define DCHECK(condition) assert(condition)
@@ -33,16 +33,13 @@
 #define CHECK_EQ(x, y)	CHECK((x) == (y))
 #define CHECK_NE(x, y)	CHECK((x) != (y))
 
-#define LOG_INFO LogMessage(__FILE__, __LINE__, 0)
-#define LOG_WARNING LogMessage(__FILE__, __LINE__, 1)
-#define LOG_ERROR LogMessage(__FILE__, __LINE__, 2)
+#define LOG_INFO LogMessage(__FILE__, __LINE__)
+#define LOG_ERROR LOG_INFO
+#define LOG_WARNING LOG_INFO
 #define LOG_FATAL LogMessageFatal(__FILE__, __LINE__)
 #define LOG_QFATAL LOG_FATAL
 
-// It seems that one of the Windows header files defines ERROR as 0.
-#ifdef _WIN32
-#define LOG_0 LOG_INFO
-#endif
+#define VLOG(x) if((x)>0){}else LOG_INFO.stream()
 
 #ifdef NDEBUG
 #define DEBUG_MODE 0
@@ -54,21 +51,16 @@
 
 #define LOG(severity) LOG_ ## severity.stream()
 
-#define VLOG(x) if((x)>0){}else LOG_INFO.stream()
-
 class LogMessage {
  public:
-  LogMessage(const char* file, int line, int severity)
-      : severity_(severity), flushed_(false) {
+  LogMessage(const char* file, int line) : flushed_(false) {
     stream() << file << ":" << line << ": ";
   }
   void Flush() {
     stream() << "\n";
-    if (severity_ >= re2::FLAGS_minloglevel) {
-      string s = str_.str();
-      size_t n = s.size();
-      if (fwrite(s.data(), 1, n, stderr) < n) {}  // shut up gcc
-    }
+    string s = str_.str();
+    int n = (int)s.size(); // shut up msvc
+    if(write(2, s.data(), n) < 0) {}  // shut up gcc
     flushed_ = true;
   }
   ~LogMessage() {
@@ -77,33 +69,23 @@
     }
   }
   ostream& stream() { return str_; }
-
+ 
  private:
-  const int severity_;
   bool flushed_;
   std::ostringstream str_;
-  DISALLOW_COPY_AND_ASSIGN(LogMessage);
+  DISALLOW_EVIL_CONSTRUCTORS(LogMessage);
 };
 
-#ifdef _WIN32
-#pragma warning(push)
-#pragma warning(disable: 4722) // destructor never returns
-#endif
-
 class LogMessageFatal : public LogMessage {
  public:
   LogMessageFatal(const char* file, int line)
-      : LogMessage(file, line, 3) {}
+    : LogMessage(file, line) { }
   ~LogMessageFatal() {
     Flush();
     abort();
   }
  private:
-  DISALLOW_COPY_AND_ASSIGN(LogMessageFatal);
+  DISALLOW_EVIL_CONSTRUCTORS(LogMessageFatal);
 };
 
-#ifdef _WIN32
-#pragma warning(pop)
-#endif
-
 #endif  // RE2_UTIL_LOGGING_H__
diff --git a/third_party/re2/util/mutex.h b/third_party/re2/util/mutex.h
index b479e481..e321fae 100644
--- a/third_party/re2/util/mutex.h
+++ b/third_party/re2/util/mutex.h
@@ -10,40 +10,19 @@
 #ifndef RE2_UTIL_MUTEX_H_
 #define RE2_UTIL_MUTEX_H_
 
-#include <stdlib.h>
-
-#if !defined(_WIN32)
-#include <unistd.h>  // For POSIX options
-#endif
-
 namespace re2 {
 
-#if !defined(_WIN32)
-  // Possible values of POSIX options:
-  //   -1 means not supported,
-  //    0 means maybe supported (query at runtime),
-  //   >0 means supported.
-# if defined(_POSIX_THREADS) && _POSIX_THREADS > 0
-#   define HAVE_PTHREAD 1
-# else
-#   define HAVE_PTHREAD 0
-# endif
-# if defined(_POSIX_READER_WRITER_LOCKS) && _POSIX_READER_WRITER_LOCKS > 0
-#   define HAVE_RWLOCK 1
-# else
-#   define HAVE_RWLOCK 0
-# endif
-#else
-# define HAVE_PTHREAD 0
-# define HAVE_RWLOCK 0
+#ifndef WIN32
+#define HAVE_PTHREAD 1
+#define HAVE_RWLOCK 1
 #endif
 
 #if defined(NO_THREADS)
   typedef int MutexType;      // to keep a lock-count
-#elif HAVE_PTHREAD && HAVE_RWLOCK
+#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
   // Needed for pthread_rwlock_*.  If it causes problems, you could take it
-  // out, but then you'd have to set HAVE_RWLOCK to 0 (at least on linux --
-  // it *does* cause problems for FreeBSD, or MacOSX, but isn't needed
+  // out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it
+  // *does* cause problems for FreeBSD, or MacOSX, but isn't needed
   // for locking there.)
 # ifdef __linux__
 #   undef _XOPEN_SOURCE
@@ -51,12 +30,12 @@
 # endif
 # include <pthread.h>
   typedef pthread_rwlock_t MutexType;
-#elif HAVE_PTHREAD
+#elif defined(HAVE_PTHREAD)
 # include <pthread.h>
   typedef pthread_mutex_t MutexType;
-#elif defined(_WIN32)
+#elif defined(WIN32)
 # ifndef WIN32_LEAN_AND_MEAN
-#   define WIN32_LEAN_AND_MEAN  // We only need minimal includes
+#  define WIN32_LEAN_AND_MEAN  // We only need minimal includes
 # endif
 # ifdef GMUTEX_TRYLOCK
   // We need Windows NT or later for TryEnterCriticalSection().  If you
@@ -125,8 +104,9 @@
 void Mutex::ReaderLock()   { assert(++mutex_ > 0); }
 void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
 
-#elif HAVE_PTHREAD && HAVE_RWLOCK
+#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
 
+#include <stdlib.h>      // for abort()
 #define SAFE_PTHREAD(fncall)  do { if ((fncall) != 0) abort(); } while (0)
 
 Mutex::Mutex()             { SAFE_PTHREAD(pthread_rwlock_init(&mutex_, NULL)); }
@@ -139,8 +119,9 @@
 
 #undef SAFE_PTHREAD
 
-#elif HAVE_PTHREAD
+#elif defined(HAVE_PTHREAD)
 
+#include <stdlib.h>      // for abort()
 #define SAFE_PTHREAD(fncall)  do { if ((fncall) != 0) abort(); } while (0)
 
 Mutex::Mutex()             { SAFE_PTHREAD(pthread_mutex_init(&mutex_, NULL)); }
@@ -152,7 +133,7 @@
 void Mutex::ReaderUnlock() { Unlock(); }
 #undef SAFE_PTHREAD
 
-#elif defined(_WIN32)
+#elif defined(WIN32)
 
 Mutex::Mutex()             { InitializeCriticalSection(&mutex_); }
 Mutex::~Mutex()            { DeleteCriticalSection(&mutex_); }
@@ -209,7 +190,7 @@
 #define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
 
 // Provide safe way to declare and use global, linker-initialized mutex. Sigh.
-#if HAVE_PTHREAD
+#ifdef HAVE_PTHREAD
 
 #define GLOBAL_MUTEX(name) \
 	static pthread_mutex_t (name) = PTHREAD_MUTEX_INITIALIZER
diff --git a/third_party/re2/util/pcre.cc b/third_party/re2/util/pcre.cc
index 9a3f32d..1602133 100644
--- a/third_party/re2/util/pcre.cc
+++ b/third_party/re2/util/pcre.cc
@@ -7,11 +7,15 @@
 // compilation as PCRE in namespace re2.
 
 #include <errno.h>
-#include <limits>
 #include "util/util.h"
 #include "util/flags.h"
 #include "util/pcre.h"
 
+#ifdef WIN32
+#define strtoll _strtoi64
+#define strtoull _strtoui64
+#endif
+
 #define PCREPORT(level) LOG(level)
 
 // Default PCRE limits.
@@ -23,42 +27,6 @@
 DEFINE_int32(regexp_match_limit, 1000000,
              "default PCRE match limit (function calls)");
 
-#ifndef USEPCRE
-
-// Fake just enough of the PCRE API to allow this file to build. :)
-
-struct pcre_extra {
-  int flags;
-  int match_limit;
-  int match_limit_recursion;
-};
-
-#define PCRE_EXTRA_MATCH_LIMIT 0
-#define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0
-#define PCRE_ANCHORED 0
-#define PCRE_NOTEMPTY 0
-#define PCRE_ERROR_NOMATCH 1
-#define PCRE_ERROR_MATCHLIMIT 2
-#define PCRE_ERROR_RECURSIONLIMIT 3
-#define PCRE_INFO_CAPTURECOUNT 0
-
-void pcre_free(void*) {
-}
-
-pcre* pcre_compile(const char*, int, const char**, int*, const unsigned char*) {
-  return NULL;
-}
-
-int pcre_exec(const pcre*, const pcre_extra*, const char*, int, int, int, int*, int) {
-  return 0;
-}
-
-int pcre_fullinfo(const pcre*, const pcre_extra*, int, void*) {
-  return 0;
-}
-
-#endif
-
 namespace re2 {
 
 // Maximum number of args we can set
@@ -150,7 +118,7 @@
   //    ANCHOR_BOTH     Tack a "\z" to the end of the original pattern
   //                    and use a pcre anchored match.
 
-  const char* error = "";
+  const char* error;
   int eoffset;
   pcre* re;
   if (anchor != ANCHOR_BOTH) {
@@ -215,7 +183,7 @@
 done:
 
   int consumed;
-  int vec[kVecSize] = {};
+  int vec[kVecSize];
   return re.DoMatchImpl(text, ANCHOR_BOTH, &consumed, args, n, vec, kVecSize);
 }
 
@@ -258,7 +226,7 @@
 done:
 
   int consumed;
-  int vec[kVecSize] = {};
+  int vec[kVecSize];
   return re.DoMatchImpl(text, UNANCHORED, &consumed, args, n, vec, kVecSize);
 }
 
@@ -301,7 +269,7 @@
 done:
 
   int consumed;
-  int vec[kVecSize] = {};
+  int vec[kVecSize];
   if (pattern.DoMatchImpl(*input, ANCHOR_START, &consumed,
                           args, n, vec, kVecSize)) {
     input->remove_prefix(consumed);
@@ -350,7 +318,7 @@
 done:
 
   int consumed;
-  int vec[kVecSize] = {};
+  int vec[kVecSize];
   if (pattern.DoMatchImpl(*input, UNANCHORED, &consumed,
                           args, n, vec, kVecSize)) {
     input->remove_prefix(consumed);
@@ -363,7 +331,7 @@
 bool PCRE::Replace(string *str,
                  const PCRE& pattern,
                  const StringPiece& rewrite) {
-  int vec[kVecSize] = {};
+  int vec[kVecSize];
   int matches = pattern.TryMatch(*str, 0, UNANCHORED, true, vec, kVecSize);
   if (matches == 0)
     return false;
@@ -382,12 +350,12 @@
                       const PCRE& pattern,
                       const StringPiece& rewrite) {
   int count = 0;
-  int vec[kVecSize] = {};
+  int vec[kVecSize];
   string out;
   int start = 0;
   bool last_match_was_empty_string = false;
 
-  while (start <= static_cast<int>(str->size())) {
+  for (; start <= str->length();) {
     // If the previous match was for the empty string, we shouldn't
     // just match again: we'll match in the same way and get an
     // infinite loop.  Instead, we do the match in a special way:
@@ -403,15 +371,14 @@
       matches = pattern.TryMatch(*str, start, ANCHOR_START, false,
                                  vec, kVecSize);
       if (matches <= 0) {
-        if (start < static_cast<int>(str->size()))
+        if (start < str->length())
           out.push_back((*str)[start]);
         start++;
         last_match_was_empty_string = false;
         continue;
       }
     } else {
-      matches = pattern.TryMatch(*str, start, UNANCHORED, true,
-                                 vec, kVecSize);
+      matches = pattern.TryMatch(*str, start, UNANCHORED, true, vec, kVecSize);
       if (matches <= 0)
         break;
     }
@@ -429,8 +396,8 @@
   if (count == 0)
     return 0;
 
-  if (start < static_cast<int>(str->size()))
-    out.append(*str, start, static_cast<int>(str->size()) - start);
+  if (start < str->length())
+    out.append(*str, start, str->length() - start);
   swap(out, *str);
   return count;
 }
@@ -439,7 +406,7 @@
                  const PCRE& pattern,
                  const StringPiece &rewrite,
                  string *out) {
-  int vec[kVecSize] = {};
+  int vec[kVecSize];
   int matches = pattern.TryMatch(text, 0, UNANCHORED, true, vec, kVecSize);
   if (matches == 0)
     return false;
@@ -485,7 +452,7 @@
 /***** Actual matching and rewriting code *****/
 
 bool PCRE::HitLimit() {
-  return hit_limit_ != 0;
+  return hit_limit_;
 }
 
 void PCRE::ClearHitLimit() {
@@ -633,9 +600,9 @@
                  const Arg* const args[],
                  int n) const {
   assert(n >= 0);
-  const int vecsize = (1 + n) * 3;  // results + PCRE workspace
-                                    // (as for kVecSize)
-  int* vec = new int[vecsize];
+  size_t const vecsize = (1 + n) * 3;  // results + PCRE workspace
+                                       // (as for kVecSize)
+  int *vec = new int[vecsize];
   bool b = DoMatchImpl(text, anchor, consumed, args, n, vec, vecsize);
   delete[] vec;
   return b;
@@ -841,7 +808,7 @@
   if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse
   if ((short)r != r) return false;       // Out of range
   if (dest == NULL) return true;
-  *(reinterpret_cast<short*>(dest)) = (short)r;
+  *(reinterpret_cast<short*>(dest)) = r;
   return true;
 }
 
@@ -853,7 +820,7 @@
   if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse
   if ((ushort)r != r) return false;                      // Out of range
   if (dest == NULL) return true;
-  *(reinterpret_cast<unsigned short*>(dest)) = (ushort)r;
+  *(reinterpret_cast<unsigned short*>(dest)) = r;
   return true;
 }
 
@@ -931,7 +898,7 @@
   char* end;
   double r = strtod(buf, &end);
   if (end != buf + n) {
-#ifdef _WIN32
+#ifdef COMPILER_MSVC
     // Microsoft's strtod() doesn't handle inf and nan, so we have to
     // handle it explicitly.  Speed is not important here because this
     // code is only called in unit tests.
@@ -944,11 +911,11 @@
       ++i;
     }
     if (0 == stricmp(i, "inf") || 0 == stricmp(i, "infinity")) {
-      r = std::numeric_limits<double>::infinity();
+      r = numeric_limits<double>::infinity();
       if (!pos)
         r = -r;
     } else if (0 == stricmp(i, "nan")) {
-      r = std::numeric_limits<double>::quiet_NaN();
+      r = numeric_limits<double>::quiet_NaN();
     } else {
       return false;
     }
diff --git a/third_party/re2/util/pcre.h b/third_party/re2/util/pcre.h
index 20b10c0..771ac91 100644
--- a/third_party/re2/util/pcre.h
+++ b/third_party/re2/util/pcre.h
@@ -167,9 +167,28 @@
 const bool UsingPCRE = true;
 }  // namespace re2
 #else
-struct pcre;  // opaque
 namespace re2 {
 const bool UsingPCRE = false;
+struct pcre;
+struct pcre_extra { int flags, match_limit, match_limit_recursion; };
+#define pcre_free(x) {}
+#define PCRE_EXTRA_MATCH_LIMIT 0
+#define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0
+#define PCRE_ANCHORED 0
+#define PCRE_NOTEMPTY 0
+#define PCRE_ERROR_NOMATCH 1
+#define PCRE_ERROR_MATCHLIMIT 2
+#define PCRE_ERROR_RECURSIONLIMIT 3
+#define PCRE_INFO_CAPTURECOUNT 0
+#ifndef WIN32
+#define pcre_compile(a,b,c,d,e) ({ (void)(a); (void)(b); *(c)=""; *(d)=0; (void)(e); ((pcre*)0); })
+#define pcre_exec(a, b, c, d, e, f, g, h) ({ (void)(a); (void)(b); (void)(c); (void)(d); (void)(e); (void)(f); (void)(g); (void)(h); 0; })
+#define pcre_fullinfo(a, b, c, d) ({ (void)(a); (void)(b); (void)(c); *(d) = 0; 0; })
+#else
+#define pcre_compile(a,b,c,d,e) NULL
+#define pcre_exec(a, b, c, d, e, f, g, h) NULL
+#define pcre_fullinfo(a, b, c, d) NULL
+#endif
 }  // namespace re2
 #endif
 
@@ -497,7 +516,7 @@
   int               match_limit_;    // Limit on execution resources
   int               stack_limit_;    // Limit on stack resources (bytes)
   mutable int32_t  hit_limit_;  // Hit limit during execution (bool)?
-  DISALLOW_COPY_AND_ASSIGN(PCRE);
+  DISALLOW_EVIL_CONSTRUCTORS(PCRE);
 };
 
 // PCRE_Options allow you to set the PCRE::Options, plus any pcre
diff --git a/third_party/re2/util/rune.cc b/third_party/re2/util/rune.cc
index e6231ce..26442b0a 100644
--- a/third_party/re2/util/rune.cc
+++ b/third_party/re2/util/rune.cc
@@ -133,7 +133,7 @@
 	 */
 	c = *rune;
 	if(c <= Rune1) {
-		str[0] = static_cast<char>(c);
+		str[0] = c;
 		return 1;
 	}
 
@@ -142,7 +142,7 @@
 	 *	0080-07FF => T2 Tx
 	 */
 	if(c <= Rune2) {
-		str[0] = T2 | static_cast<char>(c >> 1*Bitx);
+		str[0] = T2 | (c >> 1*Bitx);
 		str[1] = Tx | (c & Maskx);
 		return 2;
 	}
@@ -161,9 +161,9 @@
 	 *	0800-FFFF => T3 Tx Tx
 	 */
 	if (c <= Rune3) {
-		str[0] = T3 | static_cast<char>(c >> 2*Bitx);
+		str[0] = T3 |  (c >> 2*Bitx);
 		str[1] = Tx | ((c >> 1*Bitx) & Maskx);
-		str[2] = Tx | (c & Maskx);
+		str[2] = Tx |  (c & Maskx);
 		return 3;
 	}
 
@@ -171,7 +171,7 @@
 	 * four character sequence (21-bit value)
 	 *     10000-1FFFFF => T4 Tx Tx Tx
 	 */
-	str[0] = T4 | static_cast<char>(c >> 3*Bitx);
+	str[0] = T4 | (c >> 3*Bitx);
 	str[1] = Tx | ((c >> 2*Bitx) & Maskx);
 	str[2] = Tx | ((c >> 1*Bitx) & Maskx);
 	str[3] = Tx | (c & Maskx);
diff --git a/third_party/re2/util/sparse_array.h b/third_party/re2/util/sparse_array.h
index 8f71fa0..7bc3a86 100644
--- a/third_party/re2/util/sparse_array.h
+++ b/third_party/re2/util/sparse_array.h
@@ -220,25 +220,19 @@
   // and at the beginning and end of all public non-const member functions.
   inline void DebugCheckInvariants() const;
 
-  static bool InitMemory() {
-#ifdef MEMORY_SANITIZER
-    return true;
-#else
-    return RunningOnValgrind();
-#endif
-  }
-
   int size_;
   int max_size_;
   int* sparse_to_dense_;
   vector<IndexValue> dense_;
+  bool valgrind_;
 
-  DISALLOW_COPY_AND_ASSIGN(SparseArray);
+  DISALLOW_EVIL_CONSTRUCTORS(SparseArray);
 };
 
 template<typename Value>
 SparseArray<Value>::SparseArray()
-    : size_(0), max_size_(0), sparse_to_dense_(NULL), dense_() {}
+    : size_(0), max_size_(0), sparse_to_dense_(NULL), dense_(),
+      valgrind_(RunningOnValgrindOrMemorySanitizer()) {}
 
 // IndexValue pairs: exposed in SparseArray::iterator.
 template<typename Value>
@@ -281,20 +275,14 @@
       memmove(a, sparse_to_dense_, max_size_*sizeof a[0]);
       delete[] sparse_to_dense_;
     }
+    // Don't need to zero the memory but appease Valgrind.
+    if (valgrind_) {
+      for (int i = max_size_; i < new_max_size; i++)
+        a[i] = 0xababababU;
+    }
     sparse_to_dense_ = a;
 
     dense_.resize(new_max_size);
-
-    // These don't need to be initialized for correctness,
-    // but Valgrind will warn about use of uninitialized memory,
-    // so initialize the new memory when compiling debug binaries.
-    // Initialize it to garbage to detect bugs in the future.
-    if (InitMemory()) {
-      for (int i = max_size_; i < new_max_size; i++) {
-        sparse_to_dense_[i] = 0xababababU;
-        dense_[i].index_ = 0xababababU;
-      }
-    }
   }
   max_size_ = new_max_size;
   if (size_ > max_size_)
@@ -307,7 +295,7 @@
 bool SparseArray<Value>::has_index(int i) const {
   DCHECK_GE(i, 0);
   DCHECK_LT(i, max_size_);
-  if (static_cast<uint>(i) >= static_cast<uint>(max_size_)) {
+  if (static_cast<uint>(i) >= max_size_) {
     return false;
   }
   // Unsigned comparison avoids checking sparse_to_dense_[i] < 0.
@@ -319,7 +307,7 @@
 template<typename Value>
 typename SparseArray<Value>::iterator SparseArray<Value>::set(int i, Value v) {
   DebugCheckInvariants();
-  if (static_cast<uint>(i) >= static_cast<uint>(max_size_)) {
+  if (static_cast<uint>(i) >= max_size_) {
     // Semantically, end() would be better here, but we already know
     // the user did something stupid, so begin() insulates them from
     // dereferencing an invalid pointer.
@@ -381,7 +369,7 @@
 typename SparseArray<Value>::iterator
 SparseArray<Value>::set_new(int i, Value v) {
   DebugCheckInvariants();
-  if (static_cast<uint>(i) >= static_cast<uint>(max_size_)) {
+  if (static_cast<uint>(i) >= max_size_) {
     // Semantically, end() would be better here, but we already know
     // the user did something stupid, so begin() insulates them from
     // dereferencing an invalid pointer.
@@ -431,9 +419,10 @@
 template<typename Value> SparseArray<Value>::SparseArray(int max_size) {
   max_size_ = max_size;
   sparse_to_dense_ = new int[max_size];
+  valgrind_ = RunningOnValgrindOrMemorySanitizer();
   dense_.resize(max_size);
   // Don't need to zero the new memory, but appease Valgrind.
-  if (InitMemory()) {
+  if (valgrind_) {
     for (int i = 0; i < max_size; i++) {
       sparse_to_dense_[i] = 0xababababU;
       dense_[i].index_ = 0xababababU;
diff --git a/third_party/re2/util/sparse_array_test.cc b/third_party/re2/util/sparse_array_test.cc
new file mode 100644
index 0000000..bc7a19f8
--- /dev/null
+++ b/third_party/re2/util/sparse_array_test.cc
@@ -0,0 +1,150 @@
+// Copyright 2006 The RE2 Authors.  All Rights Reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Simple tests that SparseArray behaves.
+
+#include "util/util.h"
+#include "utest/utest.h"
+
+namespace re2 {
+
+static const string kNotFound = "NOT FOUND";
+
+TEST(SparseArray, BasicOperations) {
+  static const int n = 50;
+  SparseArray<int> set(n);
+
+  int order[n];
+  int value[n];
+  for (int i = 0; i < n; i++)
+    order[i] = i;
+  for (int i = 0; i < n; i++)
+    value[i] = rand()%1000 + 1;
+  for (int i = 1; i < n; i++) {
+    int j = rand()%i;
+    int t = order[i];
+    order[i] = order[j];
+    order[j] = t;
+  }
+
+  for (int i = 0;; i++) {
+    for (int j = 0; j < i; j++) {
+      ASSERT_TRUE(set.has_index(order[j]));
+      ASSERT_EQ(value[order[j]], set.get(order[j], -1));
+    }
+    if (i >= n)
+      break;
+    for (int j = i; j < n; j++)
+      ASSERT_FALSE(set.has_index(order[j]));
+    set.set(order[i], value[order[i]]);
+  }
+
+  int nn = 0;
+  for (SparseArray<int>::iterator i = set.begin(); i != set.end(); ++i) {
+    ASSERT_EQ(order[nn++], i->index());
+    ASSERT_EQ(value[i->index()], i->value());
+  }
+  ASSERT_EQ(nn, n);
+
+  set.clear();
+  for (int i = 0; i < n; i++)
+    ASSERT_FALSE(set.has_index(i));
+
+  ASSERT_EQ(0, set.size());
+  ASSERT_EQ(0, distance(set.begin(), set.end()));
+}
+
+class SparseArrayStringTest : public testing::Test {
+ protected:
+  SparseArrayStringTest()
+      : str_map_(10) {
+    InsertOrUpdate(&str_map_, 1, "a");
+    InsertOrUpdate(&str_map_, 5, "b");
+    InsertOrUpdate(&str_map_, 2, "c");
+    InsertOrUpdate(&str_map_, 7, "d");
+  }
+
+  SparseArray<string> str_map_;
+  typedef SparseArray<string>::iterator iterator;
+};
+
+TEST_F(SparseArrayStringTest, FindGetsPresentElement) {
+  iterator it = str_map_.find(2);
+  ASSERT_TRUE(str_map_.end() != it);
+  EXPECT_EQ("c", it->second);
+}
+
+TEST_F(SparseArrayStringTest, FindDoesNotFindAbsentElement) {
+  iterator it = str_map_.find(3);
+  ASSERT_TRUE(str_map_.end() == it);
+}
+
+TEST_F(SparseArrayStringTest, ContainsKey) {
+  EXPECT_TRUE(ContainsKey(str_map_, 1));
+  EXPECT_TRUE(ContainsKey(str_map_, 2));
+  EXPECT_FALSE(ContainsKey(str_map_, 3));
+}
+
+TEST_F(SparseArrayStringTest, InsertIfNotPresent) {
+  EXPECT_FALSE(ContainsKey(str_map_, 3));
+  EXPECT_TRUE(InsertIfNotPresent(&str_map_, 3, "r"));
+  EXPECT_EQ("r", FindWithDefault(str_map_, 3, kNotFound));
+  EXPECT_FALSE(InsertIfNotPresent(&str_map_, 3, "other value"));
+  EXPECT_EQ("r", FindWithDefault(str_map_, 3, kNotFound));
+}
+
+TEST(SparseArrayTest, Erase) {
+  SparseArray<string> str_map(5);
+  str_map.set(1, "a");
+  str_map.set(2, "b");
+  EXPECT_EQ("a", FindWithDefault(str_map, 1, kNotFound));
+  EXPECT_EQ("b", FindWithDefault(str_map, 2, kNotFound));
+  str_map.erase(1);
+  EXPECT_EQ("NOT FOUND", FindWithDefault(str_map, 1, kNotFound));
+  EXPECT_EQ("b", FindWithDefault(str_map, 2, kNotFound));
+}
+
+typedef SparseArrayStringTest SparseArrayStringSurvivesInvalidIndexTest;
+// TODO(jyasskin): Cover invalid arguments to every method.
+
+TEST_F(SparseArrayStringSurvivesInvalidIndexTest, SetNegative) {
+  EXPECT_DEBUG_DEATH(str_map_.set(-123456789, "hi"),
+                     "\\(jyasskin\\) Illegal index -123456789 passed to"
+                     " SparseArray\\(10\\).set\\(\\).");
+  EXPECT_EQ(4, str_map_.size());
+}
+
+TEST_F(SparseArrayStringSurvivesInvalidIndexTest, SetTooBig) {
+  EXPECT_DEBUG_DEATH(str_map_.set(12345678, "hi"),
+                     "\\(jyasskin\\) Illegal index 12345678 passed to"
+                     " SparseArray\\(10\\).set\\(\\).");
+  EXPECT_EQ(4, str_map_.size());
+}
+
+TEST_F(SparseArrayStringSurvivesInvalidIndexTest, SetNew_Negative) {
+  EXPECT_DEBUG_DEATH(str_map_.set_new(-123456789, "hi"),
+                     "\\(jyasskin\\) Illegal index -123456789 passed to"
+                     " SparseArray\\(10\\).set_new\\(\\).");
+  EXPECT_EQ(4, str_map_.size());
+}
+
+TEST_F(SparseArrayStringSurvivesInvalidIndexTest, SetNew_Existing) {
+  EXPECT_DEBUG_DEATH({
+    str_map_.set_new(2, "hi");
+    EXPECT_EQ("hi", FindWithDefault(str_map_, 2, kNotFound));
+
+    // The old value for 2 is still present, but can never be removed.
+    // This risks crashing later, if the map fills up.
+    EXPECT_EQ(5, str_map_.size());
+  }, "Check failed: !has_index\\(i\\)");
+}
+
+TEST_F(SparseArrayStringSurvivesInvalidIndexTest, SetNew_TooBig) {
+  EXPECT_DEBUG_DEATH(str_map_.set_new(12345678, "hi"),
+                     "\\(jyasskin\\) Illegal index 12345678 passed to"
+                     " SparseArray\\(10\\).set_new\\(\\).");
+  EXPECT_EQ(4, str_map_.size());
+}
+
+}  // namespace re2
diff --git a/third_party/re2/util/sparse_set.h b/third_party/re2/util/sparse_set.h
index 9dd41ee..4a324d7 100644
--- a/third_party/re2/util/sparse_set.h
+++ b/third_party/re2/util/sparse_set.h
@@ -54,15 +54,17 @@
 class SparseSet {
  public:
   SparseSet()
-    : size_(0), max_size_(0), sparse_to_dense_(NULL), dense_(NULL) {}
+    : size_(0), max_size_(0), sparse_to_dense_(NULL), dense_(NULL),
+      valgrind_(RunningOnValgrindOrMemorySanitizer()) {}
 
   SparseSet(int max_size) {
     max_size_ = max_size;
     sparse_to_dense_ = new int[max_size];
     dense_ = new int[max_size];
+    valgrind_ = RunningOnValgrindOrMemorySanitizer();
     // Don't need to zero the memory, but do so anyway
     // to appease Valgrind.
-    if (InitMemory()) {
+    if (valgrind_) {
       for (int i = 0; i < max_size; i++) {
         dense_[i] = 0xababababU;
         sparse_to_dense_[i] = 0xababababU;
@@ -94,7 +96,7 @@
       int* a = new int[new_max_size];
       if (sparse_to_dense_) {
         memmove(a, sparse_to_dense_, max_size_*sizeof a[0]);
-        if (InitMemory()) {
+        if (valgrind_) {
           for (int i = max_size_; i < new_max_size; i++)
             a[i] = 0xababababU;
         }
@@ -105,7 +107,7 @@
       a = new int[new_max_size];
       if (dense_) {
         memmove(a, dense_, size_*sizeof a[0]);
-        if (InitMemory()) {
+        if (valgrind_) {
           for (int i = size_; i < new_max_size; i++)
             a[i] = 0xababababU;
         }
@@ -127,7 +129,7 @@
   bool contains(int i) const {
     DCHECK_GE(i, 0);
     DCHECK_LT(i, max_size_);
-    if (static_cast<uint>(i) >= static_cast<uint>(max_size_)) {
+    if (static_cast<uint>(i) >= max_size_) {
       return false;
     }
     // Unsigned comparison avoids checking sparse_to_dense_[i] < 0.
@@ -144,7 +146,7 @@
   // Set the value at the new index i to v.
   // Fast but unsafe: only use if contains(i) is false.
   void insert_new(int i) {
-    if (static_cast<uint>(i) >= static_cast<uint>(max_size_)) {
+    if (static_cast<uint>(i) >= max_size_) {
       // Semantically, end() would be better here, but we already know
       // the user did something stupid, so begin() insulates them from
       // dereferencing an invalid pointer.
@@ -164,20 +166,13 @@
   static bool less(int a, int b) { return a < b; }
 
  private:
-  static bool InitMemory() {
-#ifdef MEMORY_SANITIZER
-    return true;
-#else
-    return RunningOnValgrind();
-#endif
-  }
-
   int size_;
   int max_size_;
   int* sparse_to_dense_;
   int* dense_;
+  bool valgrind_;
 
-  DISALLOW_COPY_AND_ASSIGN(SparseSet);
+  DISALLOW_EVIL_CONSTRUCTORS(SparseSet);
 };
 
 }  // namespace re2
diff --git a/third_party/re2/re2/stringpiece.cc b/third_party/re2/util/stringpiece.cc
similarity index 65%
rename from third_party/re2/re2/stringpiece.cc
rename to third_party/re2/util/stringpiece.cc
index 00f478a..37895b0 100644
--- a/third_party/re2/re2/stringpiece.cc
+++ b/third_party/re2/util/stringpiece.cc
@@ -33,33 +33,23 @@
   target->assign(ptr_, length_);
 }
 
-void StringPiece::AppendToString(string* target) const {
-  target->append(ptr_, length_);
-}
-
-StringPiece::size_type StringPiece::copy(char* buf, size_type n,
-                                         size_type pos) const {
-  size_type ret = min(length_ - pos, n);
+int StringPiece::copy(char* buf, size_type n, size_type pos) const {
+  int ret = min(length_ - pos, n);
   memcpy(buf, ptr_ + pos, ret);
   return ret;
 }
 
-bool StringPiece::contains(StringPiece s) const {
-  return find(s, 0) != npos;
-}
-
-StringPiece::size_type StringPiece::find(const StringPiece& s,
-                                         size_type pos) const {
+int StringPiece::find(const StringPiece& s, size_type pos) const {
   if (length_ < 0 || pos > static_cast<size_type>(length_))
     return npos;
 
   const char* result = std::search(ptr_ + pos, ptr_ + length_,
                                    s.ptr_, s.ptr_ + s.length_);
   const size_type xpos = result - ptr_;
-  return xpos + s.length_ <= static_cast<size_type>(length_) ? xpos : npos;
+  return xpos + s.length_ <= length_ ? xpos : npos;
 }
 
-StringPiece::size_type StringPiece::find(char c, size_type pos) const {
+int StringPiece::find(char c, size_type pos) const {
   if (length_ <= 0 || pos >= static_cast<size_type>(length_)) {
     return npos;
   }
@@ -67,10 +57,9 @@
   return result != ptr_ + length_ ? result - ptr_ : npos;
 }
 
-StringPiece::size_type StringPiece::rfind(const StringPiece& s,
-                                          size_type pos) const {
+int StringPiece::rfind(const StringPiece& s, size_type pos) const {
   if (length_ < s.length_) return npos;
-  const size_type ulen = length_;
+  const size_t ulen = length_;
   if (s.length_ == 0) return min(ulen, pos);
 
   const char* last = ptr_ + min(ulen - s.length_, pos) + s.length_;
@@ -78,9 +67,9 @@
   return result != last ? result - ptr_ : npos;
 }
 
-StringPiece::size_type StringPiece::rfind(char c, size_type pos) const {
+int StringPiece::rfind(char c, size_type pos) const {
   if (length_ <= 0) return npos;
-  for (int i = static_cast<int>(min(pos, static_cast<size_type>(length_ - 1)));
+  for (int i = min(pos, static_cast<size_type>(length_ - 1));
        i >= 0; --i) {
     if (ptr_[i] == c) {
       return i;
@@ -90,9 +79,9 @@
 }
 
 StringPiece StringPiece::substr(size_type pos, size_type n) const {
-  if (pos > static_cast<size_type>(length_)) pos = static_cast<size_type>(length_);
+  if (pos > length_) pos = length_;
   if (n > length_ - pos) n = length_ - pos;
-  return StringPiece(ptr_ + pos, static_cast<int>(n));
+  return StringPiece(ptr_ + pos, n);
 }
 
 const StringPiece::size_type StringPiece::npos = size_type(-1);
diff --git a/third_party/re2/util/stringprintf.cc b/third_party/re2/util/stringprintf.cc
index e71d9938..c908181e 100644
--- a/third_party/re2/util/stringprintf.cc
+++ b/third_party/re2/util/stringprintf.cc
@@ -4,7 +4,7 @@
 
 #include "util/util.h"
 
-namespace re2 {
+namespace re2 { 
 
 static void StringAppendV(string* dst, const char* format, va_list ap) {
   // First try with a small fixed size buffer
@@ -18,7 +18,7 @@
   int result = vsnprintf(space, sizeof(space), format, backup_ap);
   va_end(backup_ap);
 
-  if ((result >= 0) && (static_cast<unsigned long>(result) < sizeof(space))) {
+  if ((result >= 0) && (result < sizeof(space))) {
     // It fit
     dst->append(space, result);
     return;
@@ -38,14 +38,7 @@
 
     // Restore the va_list before we use it again
     va_copy(backup_ap, ap);
-#if !defined(_WIN32)
     result = vsnprintf(buf, length, format, backup_ap);
-#else
-    // On Windows, the function takes five arguments, not four. With an array,
-    // the buffer size will be inferred, but not with a pointer. C'est la vie.
-    // (See https://github.com/google/re2/issues/40 for more details.)
-    result = vsnprintf(buf, length, _TRUNCATE, format, backup_ap);
-#endif
     va_end(backup_ap);
 
     if ((result >= 0) && (result < length)) {
diff --git a/third_party/re2/util/strutil.cc b/third_party/re2/util/strutil.cc
index d3a02491..6ab79b3 100644
--- a/third_party/re2/util/strutil.cc
+++ b/third_party/re2/util/strutil.cc
@@ -20,7 +20,7 @@
   int used = 0;
 
   for (; src < src_end; src++) {
-    if (dest_len - used < 2)   // space for two-character escape
+    if (dest_len - used < 2)   // Need space for two letter escape
       return -1;
 
     unsigned char c = *src;
@@ -36,15 +36,9 @@
         // digit then that digit must be escaped too to prevent it being
         // interpreted as part of the character code by C.
         if (c < ' ' || c > '~') {
-          if (dest_len - used < 5)   // space for four-character escape + \0
+          if (dest_len - used < 4) // need space for 4 letter escape
             return -1;
-#if !defined(_WIN32)
-          snprintf(dest + used, 5, "\\%03o", c);
-#else
-          // On Windows, the function takes 4+VA arguments, not 3+VA. With an
-          // array, the buffer size will be inferred, but not with a pointer.
-          snprintf(dest + used, 5, _TRUNCATE, "\\%03o", c);
-#endif
+          sprintf(dest + used, "\\%03o", c);
           used += 4;
         } else {
           dest[used++] = c; break;
@@ -63,7 +57,7 @@
 // ----------------------------------------------------------------------
 // CEscape()
 //    Copies 'src' to result, escaping dangerous characters using
-//    C-style escape sequences.  'src' and 'dest' should not overlap.
+//    C-style escape sequences.  'src' and 'dest' should not overlap. 
 // ----------------------------------------------------------------------
 string CEscape(const StringPiece& src) {
   const int dest_length = src.size() * 4 + 1; // Maximum possible expansion
@@ -83,7 +77,7 @@
   // 255's, we just return the empty string.
   bool done = false;
   string limit(prefix.data(), prefix.size());
-  int index = static_cast<int>(limit.size()) - 1;
+  int index = limit.length() - 1;
   while (!done && index >= 0) {
     if ((limit[index]&255) == 255) {
       limit.erase(index);
diff --git a/third_party/re2/util/test.cc b/third_party/re2/util/test.cc
index b0167e74..2fe1bfa 100644
--- a/third_party/re2/util/test.cc
+++ b/third_party/re2/util/test.cc
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 #include <stdio.h>
-#ifndef _WIN32
+#ifndef WIN32
 #include <sys/resource.h>
 #endif
 #include "util/test.h"
@@ -23,6 +23,18 @@
   tests[ntests++].name = name;
 }
 
+namespace re2 {
+int64 VirtualProcessSize() {
+#ifndef WIN32
+  struct rusage ru;
+  getrusage(RUSAGE_SELF, &ru);
+  return (int64)ru.ru_maxrss*1024;
+#else
+  return 0;
+#endif
+}
+}  // namespace re2
+
 int main(int argc, char **argv) {
   for (int i = 0; i < ntests; i++) {
     printf("%s\n", tests[i].name);
diff --git a/third_party/re2/util/test.h b/third_party/re2/util/test.h
index 3701eabc..0f938655 100644
--- a/third_party/re2/util/test.h
+++ b/third_party/re2/util/test.h
@@ -31,15 +31,27 @@
 #define EXPECT_GE CHECK_GE
 #define EXPECT_FALSE(x) CHECK(!(x))
 
+#define ARRAYSIZE arraysize
+
+#define EXPECT_TRUE_M(x, y) CHECK(x) << (y)
+#define EXPECT_FALSE_M(x, y) CHECK(!(x)) << (y)
+#define ASSERT_TRUE_M(x, y) CHECK(x) << (y)
+#define ASSERT_EQUALS(x, y) CHECK_EQ(x, y)
+
+const bool UsingMallocCounter = false;
 namespace testing {
 class MallocCounter {
  public:
-  MallocCounter(int x) {}
+  MallocCounter(int x) { } 
   static const int THIS_THREAD_ONLY = 0;
   long long HeapGrowth() { return 0; }
   long long PeakHeapGrowth() { return 0; }
-  void Reset() {}
+  void Reset() { }
 };
 }  // namespace testing
 
+namespace re2 {
+int64 VirtualProcessSize();
+} // namespace re2
+
 #endif  // RE2_UTIL_TEST_H__
diff --git a/third_party/re2/util/thread.cc b/third_party/re2/util/thread.cc
index d97f14b..7349991 100644
--- a/third_party/re2/util/thread.cc
+++ b/third_party/re2/util/thread.cc
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "util/thread.h"
+#include <pthread.h>
+
 #include "util/util.h"
+#include "util/thread.h"
 
 Thread::Thread() {
   pid_ = 0;
diff --git a/third_party/re2/util/thread.h b/third_party/re2/util/thread.h
index fb67bdc..b9610e0 100644
--- a/third_party/re2/util/thread.h
+++ b/third_party/re2/util/thread.h
@@ -5,11 +5,7 @@
 #ifndef RE2_UTIL_THREAD_H__
 #define RE2_UTIL_THREAD_H__
 
-#ifdef _WIN32
-#include <windows.h>
-#else
 #include <pthread.h>
-#endif
 
 class Thread {
  public:
@@ -19,15 +15,12 @@
   void Join();
   void SetJoinable(bool);
   virtual void Run() = 0;
-
+ 
  private:
-#ifdef _WIN32
-  HANDLE pid_;
-#else
   pthread_t pid_;
-#endif
   bool running_;
   bool joinable_;
 };
 
 #endif  // RE2_UTIL_THREAD_H__
+
diff --git a/third_party/re2/util/threadwin.cc b/third_party/re2/util/threadwin.cc
deleted file mode 100644
index d68f2c5..0000000
--- a/third_party/re2/util/threadwin.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2009 The RE2 Authors.  All Rights Reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "util/thread.h"
-#include "util/util.h"
-
-Thread::Thread() {
-  pid_ = 0;
-  running_ = 0;
-  joinable_ = 0;
-}
-
-Thread::~Thread() {
-}
-
-DWORD WINAPI startThread(void *v) {
-  Thread* t = (Thread*)v;
-  t->Run();
-  return 0;
-}
-
-void Thread::Start() {
-  CHECK(!running_);
-  pid_ = CreateThread(NULL, 0, startThread, this, 0, NULL);
-  running_ = true;
-  if (!joinable_) {
-    CloseHandle(pid_);
-    pid_ = 0;
-  }
-}
-
-void Thread::Join() {
-  CHECK(running_);
-  CHECK(joinable_);
-  if (pid_ != 0)
-    WaitForSingleObject(pid_, INFINITE);
-  running_ = 0;
-}
-
-void Thread::SetJoinable(bool j) {
-  CHECK(!running_);
-  joinable_ = j;
-}
diff --git a/third_party/re2/util/util.h b/third_party/re2/util/util.h
index c59d91f2..a4fdfcc 100644
--- a/third_party/re2/util/util.h
+++ b/third_party/re2/util/util.h
@@ -9,18 +9,16 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
-#include <stddef.h>     // For size_t
+#include <stddef.h>         // For size_t
 #include <assert.h>
 #include <stdarg.h>
-#include <time.h>       // For clock_gettime, CLOCK_REALTIME
-#include <ctype.h>      // For isdigit, isalpha
-
-#if !defined(_WIN32)
-#include <sys/time.h>   // For gettimeofday
+#ifndef WIN32
+#include <sys/time.h>
 #endif
+#include <time.h>
+#include <ctype.h>	// For isdigit, isalpha.
 
 // C++
-#include <ctime>
 #include <vector>
 #include <string>
 #include <algorithm>
@@ -31,6 +29,9 @@
 #include <utility>
 #include <set>
 
+#include "build/build_config.h"
+#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
+
 // Use std names.
 using std::set;
 using std::pair;
@@ -45,7 +46,7 @@
 using std::swap;
 using std::make_pair;
 
-#if defined(__GNUC__) && !defined(USE_CXX0X) && !defined(_LIBCPP_ABI_VERSION)
+#if defined(__GNUC__) && !defined(USE_CXX0X) && !defined(_LIBCPP_ABI_VERSION) && !defined(OS_ANDROID)
 
 #include <tr1/unordered_set>
 using std::tr1::unordered_set;
@@ -53,7 +54,7 @@
 #else
 
 #include <unordered_set>
-#if defined(_WIN32)
+#if defined(WIN32) || (defined(OS_ANDROID) && !defined(_LIBCPP_ABI_VERSION))
 using std::tr1::unordered_set;
 #else
 using std::unordered_set;
@@ -61,17 +62,6 @@
 
 #endif
 
-#ifdef _WIN32
-
-#define snprintf _snprintf_s
-#define stricmp _stricmp
-#define strtof strtod /* not really correct but best we can do */
-#define strtoll _strtoi64
-#define strtoull _strtoui64
-#define vsnprintf vsnprintf_s
-
-#endif
-
 namespace re2 {
 
 typedef int8_t int8;
@@ -87,31 +77,35 @@
 typedef unsigned int uint;
 typedef unsigned short ushort;
 
-// Prevent the compiler from complaining about or optimizing away variables
-// that appear unused.
-#undef ATTRIBUTE_UNUSED
-#if defined(__GNUC__)
-#define ATTRIBUTE_UNUSED __attribute__ ((unused))
-#else
-#define ATTRIBUTE_UNUSED
-#endif
-
 // COMPILE_ASSERT causes a compile error about msg if expr is not true.
 #if __cplusplus >= 201103L
 #define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
 #else
 template<bool> struct CompileAssert {};
 #define COMPILE_ASSERT(expr, msg) \
-  typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] ATTRIBUTE_UNUSED
+  typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
 #endif
 
-// DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions.
+// DISALLOW_EVIL_CONSTRUCTORS disallows the copy and operator= functions.
 // It goes in the private: declarations in a class.
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
   TypeName(const TypeName&);                 \
   void operator=(const TypeName&)
 
-#define arraysize(array) (int)(sizeof(array)/sizeof((array)[0]))
+#define arraysize(array) (sizeof(array)/sizeof((array)[0]))
+
+// Fake lock annotations.  For real ones, see
+// http://code.google.com/p/data-race-test/
+#ifndef ANNOTATE_PUBLISH_MEMORY_RANGE
+#define ANNOTATE_PUBLISH_MEMORY_RANGE(a, b)
+#define ANNOTATE_IGNORE_WRITES_BEGIN()
+#define ANNOTATE_IGNORE_WRITES_END()
+#define ANNOTATE_BENIGN_RACE(a, b)
+#define NO_THREAD_SAFETY_ANALYSIS
+#define ANNOTATE_HAPPENS_BEFORE(x)
+#define ANNOTATE_HAPPENS_AFTER(x)
+#define ANNOTATE_UNPROTECTED_READ(x) (x)
+#endif
 
 class StringPiece;
 
@@ -138,10 +132,17 @@
   return ((uint64)x << 32) | y;
 }
 
-bool RunningOnValgrind();
+inline bool RunningOnValgrindOrMemorySanitizer() {
+#if defined(MEMORY_SANITIZER)
+  return true;
+#else
+  return RunningOnValgrind();
+#endif
+}
 
 }  // namespace re2
 
+#include "util/arena.h"
 #include "util/logging.h"
 #include "util/mutex.h"
 #include "util/utf.h"
diff --git a/third_party/re2/util/valgrind.cc b/third_party/re2/util/valgrind.cc
index 19ec22e..46f804b 100644
--- a/third_party/re2/util/valgrind.cc
+++ b/third_party/re2/util/valgrind.cc
@@ -3,17 +3,15 @@
 // license that can be found in the LICENSE file.
 
 #include "util/util.h"
-#ifndef _WIN32
 #include "util/valgrind.h"
-#endif
 
 namespace re2 {
 
-bool RunningOnValgrind() {
+int RunningOnValgrind() {
 #ifdef RUNNING_ON_VALGRIND
-  return RUNNING_ON_VALGRIND != 0;
+	return RUNNING_ON_VALGRIND;
 #else
-  return false;
+	return 0;
 #endif
 }
 
diff --git a/third_party/re2/util/valgrind.h b/third_party/re2/util/valgrind.h
index ca10b1a..d097b0c 100644
--- a/third_party/re2/util/valgrind.h
+++ b/third_party/re2/util/valgrind.h
@@ -4064,6 +4064,7 @@
 #endif /* PLAT_ppc64_aix5 */
 
 
+#ifndef WIN32
 /* ------------------------------------------------------------------ */
 /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS.               */
 /*                                                                    */
@@ -4170,7 +4171,7 @@
                                VG_USERREQ__DISCARD_TRANSLATIONS,  \
                                _qzz_addr, _qzz_len, 0, 0, 0);     \
    }
-
+#endif
 
 /* These requests are for getting Valgrind itself to print something.
    Possibly with a backtrace.  This is a really ugly hack.  The return value
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index f4004621..91a5e6c 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -45,6 +45,7 @@
     'gn_debug_static_bot': ['gn', 'debug_static_bot'],
     'gn_linux_upload': ['gn_linux_upload', 'official', 'goma'],
     'gn_official': ['gn', 'official'],
+    'gn_official_cfi': ['gn', 'official', 'cfi'],
     'gn_official_goma': ['gn', 'official', 'goma'],
     'gn_release_bot': ['gn', 'release_bot'],
     'gn_release_bot_minimal_symbols': ['gn', 'release_bot_minimal_symbols'],
@@ -516,6 +517,7 @@
     },
     'chromium.fyi': {
       'CFI Linux': 'gn_cfi_release_bot',
+      'CFI Linux ToT': 'gn_official_cfi',
       'CrWinClang64(dbg)': 'win_clang_debug_bot',
       'Libfuzzer Upload Linux': 'libfuzzer_upload_bot',
       'Site Isolation Linux': 'gn_release_trybot',
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 3c55c736..5409e9a 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -2996,6 +2996,15 @@
   </summary>
 </histogram>
 
+<histogram name="Blink.RestoredCachedStyleSheet"
+    enum="RestoredCachedStyleSheet">
+  <owner>kouhei@chromium.org</owner>
+  <summary>
+    On each link stylesheet tag resolve, record whether a Blink MemoryCached
+    StyleSheetContents was reused.
+  </summary>
+</histogram>
+
 <histogram name="Blink.XHR.setRequestHeader.HeaderValueCategoryInRFC7230"
     enum="XMLHttpRequestHeaderValueCategoryInRFC7230">
   <owner>hiroshige@chromium.org</owner>
@@ -8405,6 +8414,14 @@
   <summary>Whether a Domain Reliability upload succeeded.</summary>
 </histogram>
 
+<histogram name="DomDistiller.BarCloseButtonUsage" enum="BooleanPanelWasOpen">
+  <owner>mdjones@chromium.org</owner>
+  <summary>
+    Records if the close button was used before or after opening and viewing
+    Reader Mode content.
+  </summary>
+</histogram>
+
 <histogram name="DomDistiller.DistillationQuality" enum="BooleanSuccess">
   <owner>nyquist@chromium.org</owner>
   <summary>
@@ -8501,6 +8518,14 @@
   </summary>
 </histogram>
 
+<histogram name="DomDistiller.Time.ViewingReaderModePanel" units="milliseconds">
+  <owner>mdjones@chromium.org</owner>
+  <summary>
+    Records the amount of time between the Reader Mode panel opening and it
+    closing or returning to the peeking state.
+  </summary>
+</histogram>
+
 <histogram name="DOMStorage.clear" units="milliseconds">
   <obsolete>
     Deprecated 2012.
@@ -43097,6 +43122,9 @@
 <histogram name="ServiceWorker.DiskCacheMigrator.MigrationResult"
     enum="ServiceWorkerDiskCacheMigrationStatus">
   <owner>nhiroki@chromium.org</owner>
+  <obsolete>
+    Deprecated because the migrator was removed as of 12/2015.
+  </obsolete>
   <summary>
     Records result of ServiceWorkerDiskCacheMigrator::Start that migrates
     resources in BlockFile backend to Simple backend.
@@ -43106,6 +43134,9 @@
 <histogram name="ServiceWorker.DiskCacheMigrator.MigrationTime"
     units="milliseconds">
   <owner>nhiroki@chromium.org</owner>
+  <obsolete>
+    Deprecated because the migrator was removed as of 12/2015.
+  </obsolete>
   <summary>
     Execution time of ServiceWorkerDiskCache migration from BlockFile to Simple.
   </summary>
@@ -43114,6 +43145,9 @@
 <histogram name="ServiceWorker.DiskCacheMigrator.NumberOfMigratedResources"
     units="count">
   <owner>nhiroki@chromium.org</owner>
+  <obsolete>
+    Deprecated because the migrator was removed as of 12/2015.
+  </obsolete>
   <summary>
     The counts of resources migrated by ServiceWorkerDiskCacheMigrator. This
     includes the main script and imported scripts.
@@ -43419,6 +43453,9 @@
 <histogram name="ServiceWorker.Storage.DiskCacheMigrationResult"
     enum="ServiceWorkerDiskCacheMigrationResult">
   <owner>nhiroki@chromium.org</owner>
+  <obsolete>
+    Deprecated because the migrator was removed as of 12/2015.
+  </obsolete>
   <summary>
     Records the final result of diskcache migration in ServiceWorkerStorage.
     ServiceWorker.DiskCacheMigrator.MigrationResult records more detailed status
@@ -56862,6 +56899,11 @@
   <int value="1" label="Orphan"/>
 </enum>
 
+<enum name="BooleanPanelWasOpen" type="int">
+  <int value="0" label="Panel was closed"/>
+  <int value="1" label="Panel was open"/>
+</enum>
+
 <enum name="BooleanPopulated" type="int">
   <int value="0" label="Not populated"/>
   <int value="1" label="Populated"/>
@@ -68674,6 +68716,7 @@
   <int value="2121776031" label="auto-virtual-keyboard"/>
   <int value="2122023503" label="enable-win32k-lockdown-mimetypes"/>
   <int value="2122876605" label="enable-bleeding-edge-rendering-fast-paths"/>
+  <int value="2129929643" label="enable-use-zoom-for-dsf"/>
   <int value="2137347307" label="enable-drive-apps-in-app-list"/>
   <int value="2137599770" label="enable-win32k-renderer-lockdown"/>
   <int value="2141463681" label="enable-offer-upload-credit-cards"/>
@@ -74582,6 +74625,11 @@
   <int value="12" label="Import resource"/>
 </enum>
 
+<enum name="RestoredCachedStyleSheet" type="int">
+  <int value="0" label="No usable cache found"/>
+  <int value="1" label="Cached StyleSheetContents was reused"/>
+</enum>
+
 <enum name="RunningMode" type="int">
   <int value="0" label="Document Mode"/>
   <int value="1" label="Tabbed Mode"/>
@@ -75447,6 +75495,9 @@
 </enum>
 
 <enum name="ServiceWorkerDiskCacheMigrationResult" type="int">
+  <obsolete>
+    Deprecated because the migrator was removed as of 12/2015.
+  </obsolete>
   <int value="0" label="MIGRATION_OK"/>
   <int value="1" label="MIGRATION_NOT_NECESSARY"/>
   <int value="2" label="MIGRATION_ERROR_MIGRATION_FAILED"/>
@@ -75454,6 +75505,9 @@
 </enum>
 
 <enum name="ServiceWorkerDiskCacheMigrationStatus" type="int">
+  <obsolete>
+    Deprecated because the migrator was removed as of 12/2015.
+  </obsolete>
   <int value="0" label="MIGRATION_STATUS_OK"/>
   <int value="1" label="MIGRATION_ERROR_FAILED"/>
   <int value="2" label="MIGRATION_ERROR_MOVE_DISKCACHE"/>
diff --git a/tools/telemetry/catapult_base/dependency_manager/dependency_manager.py b/tools/telemetry/catapult_base/dependency_manager/dependency_manager.py
index 5ac9d3e..e1743ba 100644
--- a/tools/telemetry/catapult_base/dependency_manager/dependency_manager.py
+++ b/tools/telemetry/catapult_base/dependency_manager/dependency_manager.py
@@ -2,13 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import logging
 import os
 import sys
 
 sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(
     os.path.abspath(__file__)))))
-from catapult_base import support_binaries
 from catapult_base.dependency_manager import base_config
 from catapult_base.dependency_manager import exceptions
 
@@ -54,7 +52,7 @@
     for config in configs:
       self._UpdateDependencies(config)
 
-  def FetchPath(self, dependency, platform, try_support_binaries=False):
+  def FetchPath(self, dependency, platform):
     """Get a path to an executable for |dependency|, downloading as needed.
 
     A path to a default executable may be returned if a platform specific
@@ -66,9 +64,6 @@
         platform: Name of the platform the dependency will run on. Often of the
             form 'os_architecture'. Must match those specified in the config(s)
             used in this DependencyManager.
-        try_support_binaries: True if support_binaries should be queried if the
-            dependency_manager was not initialized with data for |dependency|.
-
     Returns:
         A path to an executable of |dependency| that will run on |platform|,
         downloading from cloud storage if needed.
@@ -90,22 +85,7 @@
     """
     dependency_info = self._GetDependencyInfo(dependency, platform)
     if not dependency_info:
-      if not try_support_binaries:
-        raise exceptions.NoPathFoundError(dependency, platform)
-      # TODO(aiolos): Remove the support_binaries call and always raise
-      # NoPathFound once the binary dependencies are moved over to the new
-      # system.
-
-      # platform should be of the form '%s_%s' % (os_name, arch_name) when
-      # called from the binary_manager.
-      platform_parts = platform.split('_', 1)
-      assert len(platform_parts) == 2
-      platform_os, platform_arch = platform_parts
-      logging.info('Calling into support_binaries with dependency %s, platform '
-                   '%s and arch %s. support_binaries is deprecated.'
-                   % (dependency, platform_os, platform_arch))
-      return support_binaries.FindPath(dependency, platform_arch,
-                                       platform_os)
+      raise exceptions.NoPathFoundError(dependency, platform)
     path = self._LocalPath(dependency_info)
     if not path or not os.path.exists(path):
       path = dependency_info.GetRemotePath()
@@ -113,7 +93,7 @@
         raise exceptions.NoPathFoundError(dependency, platform)
     return path
 
-  def LocalPath(self, dependency, platform, try_support_binaries=False):
+  def LocalPath(self, dependency, platform):
     """Get a path to a locally stored executable for |dependency|.
 
     A path to a default executable may be returned if a platform specific
@@ -126,23 +106,15 @@
         platform: Name of the platform the dependency will run on. Often of the
             form 'os_architecture'. Must match those specified in the config(s)
             used in this DependencyManager.
-        try_support_binaries: True if support_binaries should be queried if the
-            dependency_manager was not initialized with data for |dependency|.
-
     Returns:
         A path to an executable for |dependency| that will run on |platform|.
 
     Raises:
         NoPathFoundError: If a local copy of the executable cannot be found.
     """
-    # TODO(aiolos): Remove the support_binaries call and always raise
-    # NoPathFound once the binary dependencies are moved over to the new
-    # system.
     dependency_info = self._GetDependencyInfo(dependency, platform)
     if not dependency_info:
-      if not try_support_binaries:
-        raise exceptions.NoPathFoundError(dependency, platform)
-      return support_binaries.FindLocallyBuiltPath(dependency)
+      raise exceptions.NoPathFoundError(dependency, platform)
     local_path = self._LocalPath(dependency_info)
     if not local_path or not os.path.exists(local_path):
       raise exceptions.NoPathFoundError(dependency, platform)
diff --git a/tools/telemetry/catapult_base/dependency_manager/dependency_manager_unittest.py b/tools/telemetry/catapult_base/dependency_manager/dependency_manager_unittest.py
index 46c47de..0db6fc4 100644
--- a/tools/telemetry/catapult_base/dependency_manager/dependency_manager_unittest.py
+++ b/tools/telemetry/catapult_base/dependency_manager/dependency_manager_unittest.py
@@ -30,24 +30,20 @@
     with self.assertRaises(ValueError):
       dependency_manager.DependencyManager('config_file?')
 
-  @mock.patch('catapult_base.support_binaries.FindPath')
   @mock.patch(
       'catapult_base.dependency_manager.DependencyManager._GetDependencyInfo')
   @mock.patch(
       'catapult_base.dependency_manager.dependency_info.DependencyInfo.GetRemotePath')  # pylint: disable=line-too-long
   @mock.patch('catapult_base.dependency_manager.DependencyManager._LocalPath')
   def testFetchPathUnititializedDependency(
-      self, local_path_mock, cs_path_mock, dep_info_mock, sb_find_path_mock):
+      self, local_path_mock, cs_path_mock, dep_info_mock):
     dep_manager = dependency_manager.DependencyManager([])
     self.assertFalse(local_path_mock.call_args)
     self.assertFalse(cs_path_mock.call_args)
-    self.assertFalse(sb_find_path_mock.call_args)
-    sb_path = 'sb_path'
     local_path = 'local_path'
     cs_path = 'cs_path'
     local_path_mock.return_value = local_path
     cs_path_mock.return_value = cs_path
-    sb_find_path_mock.return_value = sb_path
     dep_info_mock.return_value = None
 
     # Empty lookup_dict
@@ -55,57 +51,30 @@
       dep_manager.FetchPath('dep', 'plat_arch_x86')
     dep_info_mock.reset_mock()
 
-    found_path = dep_manager.FetchPath(
-        'dep', 'plat_arch_x86', try_support_binaries=True)
-    self.assertEqual(sb_path, found_path)
-    self.assertFalse(local_path_mock.call_args)
-    self.assertFalse(cs_path_mock.call_args)
-    dep_info_mock.assert_called_once_with('dep', 'plat_arch_x86')
-    sb_find_path_mock.assert_called_once_with('dep', 'arch_x86', 'plat')
-    local_path_mock.reset_mock()
-    cs_path_mock.reset_mock()
-    sb_find_path_mock.reset_mock()
-    dep_info_mock.reset_mock()
-
     # Non-empty lookup dict that doesn't contain the dependency we're looking
     # for.
     dep_manager._lookup_dict = {'dep1': mock.MagicMock(),
                                 'dep2': mock.MagicMock()}
     with self.assertRaises(exceptions.NoPathFoundError):
       dep_manager.FetchPath('dep', 'plat_arch_x86')
-    dep_info_mock.reset_mock()
 
-    found_path = dep_manager.FetchPath(
-        'dep', 'plat_arch_x86', try_support_binaries=True)
-    self.assertEqual(sb_path, found_path)
-    self.assertFalse(local_path_mock.call_args)
-    self.assertFalse(cs_path_mock.call_args)
-    dep_info_mock.assert_called_once_with('dep', 'plat_arch_x86')
-    sb_find_path_mock.assert_called_once_with('dep', 'arch_x86', 'plat')
-    local_path_mock.reset_mock()
-    cs_path_mock.reset_mock()
-    sb_find_path_mock.reset_mock()
 
   @mock.patch('os.path')
-  @mock.patch('catapult_base.support_binaries.FindPath')
   @mock.patch(
       'catapult_base.dependency_manager.DependencyManager._GetDependencyInfo')
   @mock.patch(
       'catapult_base.dependency_manager.dependency_info.DependencyInfo.GetRemotePath')  # pylint: disable=line-too-long
   @mock.patch('catapult_base.dependency_manager.DependencyManager._LocalPath')
   def testFetchPathLocalFile(self, local_path_mock, cs_path_mock, dep_info_mock,
-                    sb_find_path_mock, path_mock):
+                             path_mock):
     dep_manager = dependency_manager.DependencyManager([])
     self.assertFalse(local_path_mock.call_args)
     self.assertFalse(cs_path_mock.call_args)
-    self.assertFalse(sb_find_path_mock.call_args)
-    sb_path = 'sb_path'
     local_path = 'local_path'
     cs_path = 'cs_path'
     dep_info = self.dep_info
     local_path_mock.return_value = local_path
     cs_path_mock.return_value = cs_path
-    sb_find_path_mock.return_value = sb_path
     # The DependencyInfo returned should be passed through to LocalPath.
     dep_info_mock.return_value = dep_info
 
@@ -120,27 +89,23 @@
     local_path_mock.assert_called_with(self.dep_info)
     dep_info_mock.assert_called_once_with('dep1', 'plat')
     self.assertFalse(cs_path_mock.call_args)
-    self.assertFalse(sb_find_path_mock.call_args)
     # If the below assert fails, the ordering assumption that determined the
     # path_mock return values is incorrect, and should be updated.
     path_mock.exists.assert_called_once_with('local_path')
     local_path_mock.reset_mock()
     cs_path_mock.reset_mock()
-    sb_find_path_mock.reset_mock()
     dep_info_mock.reset_mock()
 
 
   @mock.patch('os.path')
-  @mock.patch('catapult_base.support_binaries.FindPath')
   @mock.patch(
       'catapult_base.dependency_manager.dependency_info.DependencyInfo.GetRemotePath')  # pylint: disable=line-too-long
   @mock.patch('catapult_base.dependency_manager.DependencyManager._LocalPath')
   def testFetchPathRemoteFile(
-      self, local_path_mock, cs_path_mock, sb_find_path_mock, path_mock):
+      self, local_path_mock, cs_path_mock, path_mock):
     dep_manager = dependency_manager.DependencyManager([])
     self.assertFalse(local_path_mock.call_args)
     self.assertFalse(cs_path_mock.call_args)
-    self.assertFalse(sb_find_path_mock.call_args)
     local_path = 'local_path'
     cs_path = 'cs_path'
     cs_path_mock.return_value = cs_path
@@ -156,14 +121,12 @@
 
     self.assertEqual(cs_path, found_path)
     local_path_mock.assert_called_with(self.dep_info)
-    self.assertFalse(sb_find_path_mock.call_args)
     # If the below assert fails, the ordering assumption that determined the
     # path_mock return values is incorrect, and should be updated.
     path_mock.exists.assert_has_calls([mock.call(local_path),
                                        mock.call(cs_path)], any_order=False)
     local_path_mock.reset_mock()
     cs_path_mock.reset_mock()
-    sb_find_path_mock.reset_mock()
 
     # Non-empty lookup dict that contains the dependency we're looking for.
     # Local path isn't found, but cloud_storage_path is downloaded.
@@ -176,22 +139,19 @@
 
     self.assertEqual(cs_path, found_path)
     local_path_mock.assert_called_with(self.dep_info)
-    self.assertFalse(sb_find_path_mock.call_args)
     # If the below assert fails, the ordering assumption that determined the
     # path_mock return values is incorrect, and should be updated.
     path_mock.exists.assert_has_calls([mock.call(local_path),
                                        mock.call(cs_path)], any_order=False)
 
-  @mock.patch('catapult_base.support_binaries.FindPath')
   @mock.patch(
       'catapult_base.dependency_manager.dependency_info.DependencyInfo.GetRemotePath')  # pylint: disable=line-too-long
   @mock.patch('catapult_base.dependency_manager.DependencyManager._LocalPath')
   def testFetchPathError(
-      self, local_path_mock, cs_path_mock, sb_find_path_mock):
+      self, local_path_mock, cs_path_mock):
     dep_manager = dependency_manager.DependencyManager([])
     self.assertFalse(local_path_mock.call_args)
     self.assertFalse(cs_path_mock.call_args)
-    self.assertFalse(sb_find_path_mock.call_args)
     local_path_mock.return_value = None
     cs_path_mock.return_value = None
     dep_manager._lookup_dict = {'dep': {'platform' : self.dep_info,
@@ -216,20 +176,15 @@
                       dep_manager.FetchPath, 'dep', 'platform')
 
   @mock.patch('os.path')
-  @mock.patch('catapult_base.support_binaries.FindLocallyBuiltPath')
   @mock.patch(
       'catapult_base.dependency_manager.DependencyManager._GetDependencyInfo')
   @mock.patch('catapult_base.dependency_manager.DependencyManager._LocalPath')
-  def testLocalPath(self, local_path_mock, dep_info_mock, sb_find_path_mock,
-                    path_mock):
+  def testLocalPath(self, local_path_mock, dep_info_mock, path_mock):
     dep_manager = dependency_manager.DependencyManager([])
     self.assertFalse(local_path_mock.call_args)
-    self.assertFalse(sb_find_path_mock.call_args)
-    sb_path = 'sb_path'
     local_path = 'local_path'
     dep_info = 'dep_info'
     local_path_mock.return_value = local_path
-    sb_find_path_mock.return_value = sb_path
 
     # GetDependencyInfo should return None when missing from the lookup dict.
     dep_info_mock.return_value = None
@@ -239,16 +194,6 @@
       dep_manager.LocalPath('dep', 'plat')
     dep_info_mock.reset_mock()
 
-    found_path = dep_manager.LocalPath(
-        'dep', 'plat', try_support_binaries=True)
-    self.assertEqual(sb_path, found_path)
-    self.assertFalse(local_path_mock.call_args)
-    sb_find_path_mock.assert_called_once_with('dep')
-    dep_info_mock.assert_called_once_with('dep', 'plat')
-    local_path_mock.reset_mock()
-    sb_find_path_mock.reset_mock()
-    dep_info_mock.reset_mock()
-
     # Non-empty lookup dict that doesn't contain the dependency we're looking
     # for.
     dep_manager._lookup_dict = {'dep1': mock.MagicMock(),
@@ -257,16 +202,6 @@
       dep_manager.LocalPath('dep', 'plat')
     dep_info_mock.reset_mock()
 
-    found_path = dep_manager.LocalPath(
-        'dep', 'plat', try_support_binaries=True)
-    self.assertEqual(sb_path, found_path)
-    self.assertFalse(local_path_mock.call_args)
-    sb_find_path_mock.assert_called_once_with('dep')
-    dep_info_mock.assert_called_once_with('dep', 'plat')
-    local_path_mock.reset_mock()
-    sb_find_path_mock.reset_mock()
-    dep_info_mock.reset_mock()
-
     # The DependencyInfo returned should be passed through to LocalPath.
     dep_info_mock.return_value = dep_info
 
@@ -279,13 +214,11 @@
 
     self.assertEqual(local_path, found_path)
     local_path_mock.assert_called_with('dep_info')
-    self.assertFalse(sb_find_path_mock.call_args)
     # If the below assert fails, the ordering assumption that determined the
     # path_mock return values is incorrect, and should be updated.
     path_mock.exists.assert_called_once_with('local_path')
     dep_info_mock.assert_called_once_with('dep1', 'plat')
     local_path_mock.reset_mock()
-    sb_find_path_mock.reset_mock()
     dep_info_mock.reset_mock()
 
     # Non-empty lookup dict that contains the dependency we're looking for.
diff --git a/tools/telemetry/catapult_base/support_binaries.py b/tools/telemetry/catapult_base/support_binaries.py
deleted file mode 100644
index bb8de81..0000000
--- a/tools/telemetry/catapult_base/support_binaries.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import logging
-import os
-import stat
-
-from catapult_base import cloud_storage
-from telemetry.core import util
-
-
-def _GetBinPath(binary_name, arch_name, platform_name):
-  return os.path.join(
-      util.GetTelemetryDir(), 'bin', platform_name, arch_name, binary_name)
-
-
-def _IsInCloudStorage(binary_name, arch_name, platform_name):
-  return os.path.exists(
-      _GetBinPath(binary_name, arch_name, platform_name) + '.sha1')
-
-
-def FindLocallyBuiltPath(binary_name):
-  """Finds the most recently built |binary_name|."""
-  command = None
-  command_mtime = 0
-  chrome_root = util.GetChromiumSrcDir()
-  required_mode = os.X_OK
-  if binary_name.endswith('.apk'):
-    required_mode = os.R_OK
-  for build_dir, build_type in util.GetBuildDirectories():
-    candidate = os.path.join(chrome_root, build_dir, build_type, binary_name)
-    if os.path.isfile(candidate) and os.access(candidate, required_mode):
-      candidate_mtime = os.stat(candidate).st_mtime
-      if candidate_mtime > command_mtime:
-        command = candidate
-        command_mtime = candidate_mtime
-  return command
-
-
-def FindPath(binary_name, arch_name, platform_name):
-  """Returns the path to the given binary name, pulling from the cloud if
-  necessary."""
-  if platform_name == 'win':
-    binary_name += '.exe'
-  command = FindLocallyBuiltPath(binary_name)
-  if not command and _IsInCloudStorage(binary_name, arch_name, platform_name):
-    logging.info('checking cloud_storage')
-    command = _GetBinPath(binary_name, arch_name, platform_name)
-    cloud_storage.GetIfChanged(
-        command, cloud_storage.PUBLIC_BUCKET)
-
-    # Ensure the downloaded file is actually executable.
-    if command and os.path.exists(command):
-      os.chmod(command,
-               stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP)
-  if not command and platform_name == 'win' and arch_name != 'AMD64':
-    # This is an awful, awful hack to temporarily fix cloud_storage downloads
-    # on XP until the binary_manager is finished and migrated to.
-    # Please don't try this at home.
-    return FindPath(binary_name, 'AMD64', platform_name)
-
-  # Return an absolute path consistently.
-  if command:
-    command = os.path.abspath(command)
-  logging.info('SupportBinaries found path: %s for binary: %s on arch: %s and '
-               'platform :%s' % (command, binary_name, arch_name,
-                                 platform_name))
-  return command
diff --git a/tools/telemetry/catapult_base/support_binaries_unittest.py b/tools/telemetry/catapult_base/support_binaries_unittest.py
deleted file mode 100644
index 258fe25..0000000
--- a/tools/telemetry/catapult_base/support_binaries_unittest.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import os
-import stat
-import unittest
-
-from catapult_base import support_binaries
-from telemetry import decorators
-
-
-class SupportBinariesTest(unittest.TestCase):
-  @decorators.Enabled('linux')
-  def testFindPath(self):
-    md5sum_path = support_binaries.FindPath(
-        'md5sum_bin_host', 'x86_64', 'linux')
-    self.assertNotEquals(md5sum_path, None)
-    self.assertTrue(os.path.isabs(md5sum_path))
-    st = os.stat(md5sum_path)
-    self.assertTrue(st.st_mode & stat.S_IXUSR)
diff --git a/tools/telemetry/telemetry/internal/platform/android_platform_backend.py b/tools/telemetry/telemetry/internal/platform/android_platform_backend.py
index 33c68fd..3d04be7a 100644
--- a/tools/telemetry/telemetry/internal/platform/android_platform_backend.py
+++ b/tools/telemetry/telemetry/internal/platform/android_platform_backend.py
@@ -59,6 +59,25 @@
 _DEVICE_COPY_SCRIPT_LOCATION = (
     '/data/local/tmp/efficient_android_directory_copy.sh')
 
+# TODO(nednguyen): Remove this method and update the client config to point to
+# the correct binary instead.
+def _FindLocallyBuiltPath(binary_name):
+  """Finds the most recently built |binary_name|."""
+  command = None
+  command_mtime = 0
+  chrome_root = util.GetChromiumSrcDir()
+  required_mode = os.X_OK
+  if binary_name.endswith('.apk'):
+    required_mode = os.R_OK
+  for build_dir, build_type in util.GetBuildDirectories():
+    candidate = os.path.join(chrome_root, build_dir, build_type, binary_name)
+    if os.path.isfile(candidate) and os.access(candidate, required_mode):
+      candidate_mtime = os.stat(candidate).st_mtime
+      if candidate_mtime > command_mtime:
+        command = candidate
+        command_mtime = candidate_mtime
+  return command
+
 
 def _SetupPrebuiltTools(device):
   """Some of the android pylib scripts we depend on are lame and expect
@@ -94,8 +113,7 @@
   build_type = None
   for t in device_tools + host_tools:
     executable = os.path.basename(t)
-    locally_built_path = binary_manager.LocalPath(
-        t, platform_name, arch_name)
+    locally_built_path = _FindLocallyBuiltPath(t)
     if not build_type:
       build_type = _GetBuildTypeOfPath(locally_built_path) or 'Release'
       constants.SetBuildType(build_type)
diff --git a/tools/telemetry/telemetry/internal/platform/profiler/android_profiling_helper_unittest.py b/tools/telemetry/telemetry/internal/platform/profiler/android_profiling_helper_unittest.py
index f371bac..d178aac 100644
--- a/tools/telemetry/telemetry/internal/platform/profiler/android_profiling_helper_unittest.py
+++ b/tools/telemetry/telemetry/internal/platform/profiler/android_profiling_helper_unittest.py
@@ -102,6 +102,7 @@
 
 class TestAndroidProfilingHelper(unittest.TestCase):
 
+  @decorators.Enabled('linux')
   def testGetRequiredLibrariesForPerfProfile(self):
     perf_output = os.path.join(
         util.GetUnittestDataDir(), 'sample_perf_report_output.txt')
diff --git a/tools/telemetry/telemetry/internal/util/binary_manager.py b/tools/telemetry/telemetry/internal/util/binary_manager.py
index fb89615..a20ad64 100644
--- a/tools/telemetry/telemetry/internal/util/binary_manager.py
+++ b/tools/telemetry/telemetry/internal/util/binary_manager.py
@@ -48,7 +48,7 @@
     raise exceptions.InitializationError(
         'Called FetchPath with uninitialized binary manager.')
   return _dependency_manager.FetchPath(
-      binary_name, '%s_%s' % (platform, arch), try_support_binaries=True)
+      binary_name, '%s_%s' % (platform, arch))
 
 
 def LocalPath(binary_name, arch, platform):
@@ -61,4 +61,4 @@
     raise exceptions.InitializationError(
         'Called LocalPath with uninitialized binary manager.')
   return _dependency_manager.LocalPath(
-      binary_name, '%s_%s' % (platform, arch), try_support_binaries=True)
+      binary_name, '%s_%s' % (platform, arch))
diff --git a/tools/telemetry/third_party/WebKit/README.chromium b/tools/telemetry/third_party/WebKit/README.chromium
index e2d2879..798990b 100644
--- a/tools/telemetry/third_party/WebKit/README.chromium
+++ b/tools/telemetry/third_party/WebKit/README.chromium
@@ -3,7 +3,7 @@
 URL: http://www.chromium.org/blink
 Version: N/A
 License: BSD license
-License File: LICENSE
+License File: NOT_SHIPPED
 Security Critical: no
 Description: Blink javascripts libraries are used for visualize performance
 metrics.
diff --git a/tools/telemetry/third_party/altgraph/README.chromium b/tools/telemetry/third_party/altgraph/README.chromium
index 82dca2c4..f9f0caebd 100644
--- a/tools/telemetry/third_party/altgraph/README.chromium
+++ b/tools/telemetry/third_party/altgraph/README.chromium
@@ -3,7 +3,7 @@
 URL: https://pypi.python.org/pypi/altgraph/
 Version: 0.12
 License: MIT
-License File: doc/license.rst
+License File: NOT_SHIPPED
 Security Critical: no
 Description: altgraph is a fork of graphlib: a graph (network) package for
 constructing graphs, BFS and DFS traversals, topological sort, shortest paths,
diff --git a/tools/telemetry/third_party/chromite/README.chromium b/tools/telemetry/third_party/chromite/README.chromium
index a1c5546..b51feb8 100644
--- a/tools/telemetry/third_party/chromite/README.chromium
+++ b/tools/telemetry/third_party/chromite/README.chromium
@@ -3,7 +3,7 @@
 URL: https://chromium.googlesource.com/chromiumos/chromite
 Version: 0.0.2
 License: BSD
-License File: LICENSE
+License File: NOT_SHIPPED
 Security Critical: no
 
 Local modification: remove all the files except chromite/ssh_keys/ which contain
diff --git a/tools/telemetry/third_party/flot/README.chromium b/tools/telemetry/third_party/flot/README.chromium
index abbf2189..6bbf71a 100644
--- a/tools/telemetry/third_party/flot/README.chromium
+++ b/tools/telemetry/third_party/flot/README.chromium
@@ -3,7 +3,7 @@
 URL: http://www.flotcharts.org
 Version: 0.8.1
 License: MIT
-License File: LICENSE.txt
+License File: NOT_SHIPPED
 Security Critical: yes
 Description: Flot is used in the webui for performance monitor and the visualizer for Deep Memory Profiler to draw charts of performance metrics.
 Local Modifications: All the files not needed by telemetry are removed. Only keep
diff --git a/tools/telemetry/third_party/mock/README.chromium b/tools/telemetry/third_party/mock/README.chromium
index f24511cd..2dc689b 100644
--- a/tools/telemetry/third_party/mock/README.chromium
+++ b/tools/telemetry/third_party/mock/README.chromium
@@ -3,7 +3,7 @@
 URL: http://www.voidspace.org.uk/python/mock/
 Version: 1.0.1
 License: BSD
-License File: LICENSE.txt
+License File: NOT_SHIPPED
 Security Critical: no
 
 Description:
diff --git a/tools/telemetry/third_party/modulegraph/README.chromium b/tools/telemetry/third_party/modulegraph/README.chromium
index e979104..937e677 100644
--- a/tools/telemetry/third_party/modulegraph/README.chromium
+++ b/tools/telemetry/third_party/modulegraph/README.chromium
@@ -3,7 +3,7 @@
 URL: https://pypi.python.org/pypi/modulegraph/
 Version: 0.12.1
 License: MIT
-License File: doc/license.rst
+License File: NOT_SHIPPED
 Security Critical: no
 Description: modulegraph determines a dependency graph between Python modules
 primarily by bytecode analysis for import statements. It's used by telemetry's
diff --git a/tools/telemetry/third_party/mox3/README.chromium b/tools/telemetry/third_party/mox3/README.chromium
index 78e05fc5..cecbc0a 100644
--- a/tools/telemetry/third_party/mox3/README.chromium
+++ b/tools/telemetry/third_party/mox3/README.chromium
@@ -3,7 +3,7 @@
 URL: https://github.com/openstack/mox3
 Version: 60dd893a8095f9d7957bf6635dc1620a7908d86b (commit hash)
 License: Apache License 2.0
-License File: COPYING.txt
+License File: NOT_SHIPPED
 Security Critical: no
 
 Local modification:
@@ -16,4 +16,4 @@
 with mox as possible, but small enhancements have been made. The library was
 tested on Python version 3.2, 2.7 and 2.6.
 
-This library is added since it's part of pyfakfs' dependency.
+This library is added since pyfakefs depends on it.
diff --git a/tools/telemetry/third_party/pyfakefs/README.chromium b/tools/telemetry/third_party/pyfakefs/README.chromium
index fe0d158..6b9dac7 100644
--- a/tools/telemetry/third_party/pyfakefs/README.chromium
+++ b/tools/telemetry/third_party/pyfakefs/README.chromium
@@ -3,7 +3,7 @@
 URL: https://github.com/jmcgeheeiv/pyfakefs
 Version: 7e8e097c0165ba9d51fa9d34a0888d8ec082d15b (commit hash)
 License: Apache License 2.0
-License File: pyfakefs/COPYING
+License File: NOT_SHIPPED
 Security Critical: no
 
 Local modification: create a pyfakefs as a project folder & move pyfakefs to
diff --git a/tools/telemetry/third_party/pyserial/README.chromium b/tools/telemetry/third_party/pyserial/README.chromium
index b8e3bc9..04593db 100644
--- a/tools/telemetry/third_party/pyserial/README.chromium
+++ b/tools/telemetry/third_party/pyserial/README.chromium
@@ -4,7 +4,7 @@
 Version: 2.7
 Date: 2013-10-17
 License: Python
-License File: LICENSE.txt
+License File: NOT_SHIPPED
 Security Critical: no
 
 Description:
diff --git a/tools/telemetry/third_party/webpagereplay/README.chromium b/tools/telemetry/third_party/webpagereplay/README.chromium
index 832eeac..de63579 100644
--- a/tools/telemetry/third_party/webpagereplay/README.chromium
+++ b/tools/telemetry/third_party/webpagereplay/README.chromium
@@ -3,7 +3,7 @@
 URL: https://github.com/chromium/web-page-replay
 Version: ac5d71a0938d98c82220398fbdc9036fdda1240f (commit hash)
 License: BSD
-License File: no
+License File: NOT_SHIPPED
 Security Critical: no
 
 Local modification: Remove webpagereplay/third_party/ipaddr/OWNERS to avoid
diff --git a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
index d74ade4f..494b1ce5 100644
--- a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
+++ b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
@@ -33,9 +33,6 @@
 # http://crbug.com/475172
 BasicExtensionSettingsWebUITest.testUninstall
 
-# https://crbug.com/501106
-CrElementsBrowserTest.CrElementsTest
-
 # https://crbug.com/504192
 NaClBrowserTestGLibc.ExitStatus0
 NaClBrowserTestGLibc.ExitStatusNeg2
diff --git a/tools/valgrind/gtest_exclude/content_unittests.gtest.txt b/tools/valgrind/gtest_exclude/content_unittests.gtest.txt
index b32ccd5..60e98f2e 100644
--- a/tools/valgrind/gtest_exclude/content_unittests.gtest.txt
+++ b/tools/valgrind/gtest_exclude/content_unittests.gtest.txt
@@ -14,8 +14,3 @@
 # Flaky: https://crbug.com/460578
 DesktopCaptureDeviceTest.InvertedFrame
 DesktopCaptureDeviceTest.UnpackedFrame
-
-# Flaky: https://crbug.com/502983
-ServiceWorkerDiskCacheMigratorTest.MigrateDiskCache
-ServiceWorkerDiskCacheMigratorTest.RemoveExistingResourcesFromDest
-ServiceWorkerDiskCacheMigratorTest.ThrottleInflightTasks
diff --git a/tools/valgrind/memcheck/suppressions_linux.txt b/tools/valgrind/memcheck/suppressions_linux.txt
index 293e8c0..a8f2dae8c 100644
--- a/tools/valgrind/memcheck/suppressions_linux.txt
+++ b/tools/valgrind/memcheck/suppressions_linux.txt
@@ -97,7 +97,7 @@
    obj:*
    ...
    fun:*LoadNativeLibrary*
-   fun:*CdmAdapterTest*
+   fun:*ExternalClearKeyTestHelper*
 }
 {
    b_555798_b
@@ -108,3 +108,11 @@
    fun:_dl_init
    fun:dl_open_worker
 }
+{
+   b_569736
+   Memcheck:Leak
+   fun:_Znw*
+   obj:*
+   ...
+   fun:_ZN5media14CdmWrapperImplIN3cdm25ContentDecryptionModule_8EE7DecryptERKNS1_11InputBufferEPNS1_14DecryptedBlockE
+}
diff --git a/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc b/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc
index c32a87d..e043665 100644
--- a/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc
+++ b/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/files/file_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/posix/eintr_wrapper.h"
@@ -28,13 +29,6 @@
 
 namespace {
 
-static int SetNonBlocking(int fd) {
-  int flags = fcntl(fd, F_GETFL, 0);
-  if (flags == -1)
-    flags = 0;
-  return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-}
-
 const char kTestDevicePath[] = "/dev/input/test-device";
 
 const ui::DeviceAbsoluteAxis kWacomIntuos5SPenAbsAxes[] = {
@@ -149,7 +143,7 @@
   if (pipe(fds))
     PLOG(FATAL) << "failed pipe";
 
-  EXPECT_FALSE(SetNonBlocking(fds[0]) || SetNonBlocking(fds[1]))
+  EXPECT_TRUE(base::SetNonBlocking(fds[0]) || base::SetNonBlocking(fds[1]))
     << "failed to set non-blocking: " << strerror(errno);
 
   read_pipe_ = fds[0];
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
index b51e61e..fbd571e 100644
--- a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
+++ b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include <errno.h>
-#include <fcntl.h>
 #include <linux/input.h>
 #include <unistd.h>
 
@@ -11,6 +10,7 @@
 
 #include "base/bind.h"
 #include "base/command_line.h"
+#include "base/files/file_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/run_loop.h"
@@ -31,13 +31,6 @@
 
 namespace {
 
-static int SetNonBlocking(int fd) {
-  int flags = fcntl(fd, F_GETFL, 0);
-  if (flags == -1)
-    flags = 0;
-  return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-}
-
 const char kTestDevicePath[] = "/dev/input/test-device";
 
 void InitPixelTouchscreen(TouchEventConverterEvdev* device) {
@@ -135,7 +128,7 @@
   if (pipe(fds))
     PLOG(FATAL) << "failed pipe";
 
-  EXPECT_FALSE(SetNonBlocking(fds[0]) || SetNonBlocking(fds[1]))
+  EXPECT_TRUE(base::SetNonBlocking(fds[0]) || base::SetNonBlocking(fds[1]))
     << "failed to set non-blocking: " << strerror(errno);
 
   read_pipe_ = fds[0];
diff --git a/ui/gfx/vector_icons/incognito.1x.icon b/ui/gfx/vector_icons/incognito.1x.icon
index fbb73fb..4f9d36d 100644
--- a/ui/gfx/vector_icons/incognito.1x.icon
+++ b/ui/gfx/vector_icons/incognito.1x.icon
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 CANVAS_DIMENSIONS, 24,
-MOVE_TO, 11, 18,
+MOVE_TO, 11, 17,
 R_CUBIC_TO, 0, 1.66f, -1.34f, 3, -3, 3,
 R_CUBIC_TO, -1.66f, 0, -3, -1.34f, -3, -3,
 R_CUBIC_TO, 0, -1.66f, 1.34f, -3, 3, -3,
@@ -15,7 +15,7 @@
 R_CUBIC_TO, -1.11f, 0, -2, 0.9f, -2, 2,
 R_CUBIC_TO, 0, 1.1f, 0.9f, 2, 2, 2,
 CLOSE,
-MOVE_TO, 19, 18,
+MOVE_TO, 19, 17,
 R_CUBIC_TO, 0, 1.66f, -1.34f, 3, -3, 3,
 R_CUBIC_TO, -1.66f, 0, -3, -1.34f, -3, -3,
 R_CUBIC_TO, 0, -1.66f, 1.34f, -3, 3, -3,
@@ -28,7 +28,7 @@
 R_CUBIC_TO, 0, -1.1f, -0.89f, -2, -2, -2,
 CLOSE,
 NEW_PATH,
-MOVE_TO, 12, 18,
+MOVE_TO, 12, 17,
 R_CUBIC_TO, 0.93f, 0, 1.71f, 0.64f, 1.93f, 1.5f,
 R_CUBIC_TO, 0.04f, -0.16f, 0.07f, -0.33f, 0.07f, -0.5f,
 R_CUBIC_TO, 0, -1.1f, -0.9f, -2, -2, -2,
@@ -36,15 +36,15 @@
 R_CUBIC_TO, 0, 0.17f, 0.03f, 0.34f, 0.07f, 0.5f,
 R_CUBIC_TO, 0.22f, -0.86f, 1, -1.5f, 1.93f, -1.5f,
 NEW_PATH,
-MOVE_TO, 16.39f, 9,
-LINE_TO, 15, 5,
+MOVE_TO, 16.39f, 8,
+LINE_TO, 15, 4,
 R_LINE_TO, -3, 1,
 R_LINE_TO, -3, -1,
 R_LINE_TO, -1.3f, 4,
 R_H_LINE_TO, 8.7f,
 CLOSE,
 R_MOVE_TO, -9.46f, 2,
-LINE_TO, 3, 13,
+LINE_TO, 3, 12,
 R_H_LINE_TO, 18,
 R_LINE_TO, -3.8f, -2,
 H_LINE_TO, 6.93f,
diff --git a/ui/ozone/ozone.gni b/ui/ozone/ozone.gni
index 05994bd5..c5855dfe 100644
--- a/ui/ozone/ozone.gni
+++ b/ui/ozone/ozone.gni
@@ -40,8 +40,10 @@
 
         # For desktop Chromecast builds, override the default "headless"
         # platform with --ozone-platform=egltest
-        # TODO(slan|halliwell): Make the default platform "cast" on desktop too.
-        if (target_os == "linux" && target_cpu != "arm") {
+        # TODO(halliwell): Create a libcast_graphics implementation for desktop
+        # using X11, and disable these two platforms. "cast" platform should be
+        # the default on every A/V build.
+        if (is_cast_desktop_build) {
           ozone_platform_egltest = true
           ozone_platform_ozonex = true
         } else {
diff --git a/ui/shell_dialogs/select_file_dialog_mac.mm b/ui/shell_dialogs/select_file_dialog_mac.mm
index 9a4a5fd3..2cad05f5 100644
--- a/ui/shell_dialogs/select_file_dialog_mac.mm
+++ b/ui/shell_dialogs/select_file_dialog_mac.mm
@@ -55,6 +55,23 @@
 
 @end
 
+// Target for NSPopupButton control in file dialog's accessory view.
+@interface ExtensionDropdownHandler : NSObject {
+ @private
+  // The file dialog to which this target object corresponds. Weak reference
+  // since the dialog_ will stay alive longer than this object.
+  NSSavePanel* dialog_;
+
+  // An array whose each item corresponds to an array of different extensions in
+  // an extension group.
+  base::scoped_nsobject<NSArray> fileTypeLists_;
+}
+
+- (id)initWithDialog:(NSSavePanel*)dialog fileTypeLists:(NSArray*)fileTypeLists;
+
+- (void)popupAction:(id)sender;
+@end
+
 // Implementation of SelectFileDialog that shows Cocoa dialogs for choosing a
 // file or folder.
 class SelectFileDialogImpl : public ui::SelectFileDialog {
@@ -87,25 +104,39 @@
                       void* params) override;
 
  private:
+  // Struct to store data associated with a file dialog while it is showing.
+  struct DialogData {
+    DialogData(void* params_,
+               base::scoped_nsobject<ExtensionDropdownHandler> handler)
+        : params(params_), extension_dropdown_handler(handler) {}
+
+    // |params| user data associated with this file dialog.
+    void* params;
+
+    // Extension dropdown handler corresponding to this file dialog.
+    base::scoped_nsobject<ExtensionDropdownHandler> extension_dropdown_handler;
+  };
+
   ~SelectFileDialogImpl() override;
 
-  // Gets the accessory view for the save dialog.
-  NSView* GetAccessoryView(const FileTypeInfo* file_types,
-                           int file_type_index);
+  // Sets the accessory view for the |dialog| and returns the associated
+  // ExtensionDropdownHandler.
+  static base::scoped_nsobject<ExtensionDropdownHandler> SetAccessoryView(
+      NSSavePanel* dialog,
+      const FileTypeInfo* file_types,
+      int file_type_index,
+      const base::FilePath::StringType& default_extension);
 
   bool HasMultipleFileTypeChoicesImpl() override;
 
   // The bridge for results from Cocoa to return to us.
   base::scoped_nsobject<SelectFileDialogBridge> bridge_;
 
-  // A map from file dialogs to the |params| user data associated with them.
-  std::map<NSSavePanel*, void*> params_map_;
-
   // The set of all parent windows for which we are currently running dialogs.
   std::set<NSWindow*> parents_;
 
-  // A map from file dialogs to their types.
-  std::map<NSSavePanel*, Type> type_map_;
+  // A map from file dialogs to the DialogData associated with them.
+  std::map<NSSavePanel*, DialogData> dialog_data_map_;
 
   bool hasMultipleFileTypeChoices_;
 
@@ -134,10 +165,12 @@
     bool is_multi,
     const std::vector<base::FilePath>& files,
     int index) {
-  void* params = params_map_[dialog];
-  params_map_.erase(dialog);
   parents_.erase(parent_window);
-  type_map_.erase(dialog);
+
+  auto it = dialog_data_map_.find(dialog);
+  DCHECK(it != dialog_data_map_.end());
+  void* params = it->second.params;
+  dialog_data_map_.erase(it);
 
   [dialog setDelegate:nil];
 
@@ -197,61 +230,22 @@
     }
   }
 
-  NSArray* allowed_file_types = nil;
+  base::scoped_nsobject<ExtensionDropdownHandler> handler;
   if (file_types) {
-    if (!file_types->extensions.empty()) {
-      // While the example given in the header for FileTypeInfo lists an example
-      // |file_types->extensions| value as
-      //   { { "htm", "html" }, { "txt" } }
-      // it is not always the case that the given extensions in one of the sub-
-      // lists are all synonyms. In fact, in the case of a <select> element with
-      // multiple "accept" types, all the extensions allowed for all the types
-      // will be part of one list. To be safe, allow the types of all the
-      // specified extensions.
-      NSMutableSet* file_type_set = [NSMutableSet set];
-      for (size_t i = 0; i < file_types->extensions.size(); ++i) {
-        const std::vector<base::FilePath::StringType>& ext_list =
-            file_types->extensions[i];
-        for (size_t j = 0; j < ext_list.size(); ++j) {
-          base::ScopedCFTypeRef<CFStringRef> uti(
-              CreateUTIFromExtension(ext_list[j]));
-          [file_type_set addObject:base::mac::CFToNSCast(uti.get())];
-
-          // Always allow the extension itself, in case the UTI doesn't map
-          // back to the original extension correctly. This occurs with dynamic
-          // UTIs on 10.7 and 10.8.
-          // See http://crbug.com/148840, http://openradar.me/12316273
-          base::ScopedCFTypeRef<CFStringRef> ext_cf(
-              base::SysUTF8ToCFStringRef(ext_list[j]));
-          [file_type_set addObject:base::mac::CFToNSCast(ext_cf.get())];
-        }
-      }
-      allowed_file_types = [file_type_set allObjects];
-    }
-    if (type == SELECT_SAVEAS_FILE)
-      [dialog setAllowedFileTypes:allowed_file_types];
-    // else we'll pass it in when we run the open panel
-
-    if (file_types->include_all_files || file_types->extensions.empty())
-      [dialog setAllowsOtherFileTypes:YES];
-
-    if (file_types->extension_description_overrides.size() > 1) {
-      NSView* accessory_view = GetAccessoryView(file_types, file_type_index);
-      [dialog setAccessoryView:accessory_view];
-    }
+    handler = SelectFileDialogImpl::SetAccessoryView(
+        dialog, file_types, file_type_index, default_extension);
   } else {
     // If no type info is specified, anything goes.
     [dialog setAllowsOtherFileTypes:YES];
   }
+
+  auto inserted = dialog_data_map_.insert(
+      std::make_pair(dialog, DialogData(params, handler)));
+  DCHECK(inserted.second);  // Dialog should never exist already.
+
   hasMultipleFileTypeChoices_ =
       file_types ? file_types->extensions.size() > 1 : true;
 
-  if (!default_extension.empty())
-    [dialog setAllowedFileTypes:@[base::SysUTF8ToNSString(default_extension)]];
-
-  params_map_[dialog] = params;
-  type_map_[dialog] = type;
-
   if (type == SELECT_SAVEAS_FILE) {
     // When file extensions are hidden and removing the extension from
     // the default filename gives one which still has an extension
@@ -289,7 +283,6 @@
     }
 
     [open_dialog setDelegate:bridge_.get()];
-    [open_dialog setAllowedFileTypes:allowed_file_types];
   }
   if (default_dir)
     [dialog setDirectoryURL:[NSURL fileURLWithPath:default_dir]];
@@ -309,38 +302,44 @@
   // to hold the pointers, since we can't delete from the map as we're iterating
   // through it.
   std::vector<NSSavePanel*> panels;
-  for (std::map<NSSavePanel*, void*>::iterator it = params_map_.begin();
-       it != params_map_.end(); ++it) {
-    panels.push_back(it->first);
-  }
+  for (const auto& value : dialog_data_map_)
+    panels.push_back(value.first);
 
-  for (std::vector<NSSavePanel*>::iterator it = panels.begin();
-       it != panels.end(); ++it) {
-    [*it cancel:*it];
-  }
+  for (const auto& panel : panels)
+    [panel cancel:panel];
 }
 
-NSView* SelectFileDialogImpl::GetAccessoryView(const FileTypeInfo* file_types,
-                                               int file_type_index) {
+// static
+base::scoped_nsobject<ExtensionDropdownHandler>
+SelectFileDialogImpl::SetAccessoryView(
+    NSSavePanel* dialog,
+    const FileTypeInfo* file_types,
+    int file_type_index,
+    const base::FilePath::StringType& default_extension) {
   DCHECK(file_types);
   NSView* accessory_view = ui::GetViewFromNib(@"SaveAccessoryView");
   if (!accessory_view)
-    return nil;
+    return base::scoped_nsobject<ExtensionDropdownHandler>();
+  [dialog setAccessoryView:accessory_view];
 
   NSPopUpButton* popup = [accessory_view viewWithTag:kFileTypePopupTag];
   DCHECK(popup);
 
-  size_t type_count = file_types->extensions.size();
-  for (size_t type = 0; type < type_count; ++type) {
+  // Create an array with each item corresponding to an array of different
+  // extensions in an extension group.
+  NSMutableArray* file_type_lists = [NSMutableArray array];
+  for (size_t i = 0; i < file_types->extensions.size(); ++i) {
+    const std::vector<base::FilePath::StringType>& ext_list =
+        file_types->extensions[i];
+
+    // Generate type description for the extension group.
     NSString* type_description;
-    if (type < file_types->extension_description_overrides.size()) {
+    if (i < file_types->extension_description_overrides.size()) {
       type_description = base::SysUTF16ToNSString(
-          file_types->extension_description_overrides[type]);
+          file_types->extension_description_overrides[i]);
     } else {
-      // No description given for a list of extensions; pick the first one from
-      // the list (arbitrarily) and use its description.
-      const std::vector<base::FilePath::StringType>& ext_list =
-          file_types->extensions[type];
+      // No description given for a list of extensions; pick the first one
+      // from the list (arbitrarily) and use its description.
       DCHECK(!ext_list.empty());
       base::ScopedCFTypeRef<CFStringRef> uti(
           CreateUTIFromExtension(ext_list[0]));
@@ -351,10 +350,50 @@
           [[base::mac::CFToNSCast(description.get()) retain] autorelease];
     }
     [popup addItemWithTitle:type_description];
+
+    // Populate file_type_lists.
+    // Set to store different extensions in the current extension group.
+    NSMutableSet* file_type_set = [NSMutableSet set];
+    for (const base::FilePath::StringType& ext : ext_list) {
+      base::ScopedCFTypeRef<CFStringRef> uti(CreateUTIFromExtension(ext));
+      [file_type_set addObject:base::mac::CFToNSCast(uti.get())];
+
+      // Always allow the extension itself, in case the UTI doesn't map
+      // back to the original extension correctly. This occurs with dynamic
+      // UTIs on 10.7 and 10.8.
+      // See http://crbug.com/148840, http://openradar.me/12316273
+      base::ScopedCFTypeRef<CFStringRef> ext_cf(
+          base::SysUTF8ToCFStringRef(ext));
+      [file_type_set addObject:base::mac::CFToNSCast(ext_cf.get())];
+    }
+    [file_type_lists addObject:[file_type_set allObjects]];
   }
 
-  [popup selectItemAtIndex:file_type_index - 1];  // 1-based
-  return accessory_view;
+  if (file_types->include_all_files || file_types->extensions.empty()) {
+    [popup addItemWithTitle:l10n_util::GetNSString(IDS_APP_SAVEAS_ALL_FILES)];
+    [dialog setAllowsOtherFileTypes:YES];
+  }
+
+  base::scoped_nsobject<ExtensionDropdownHandler> handler(
+      [[ExtensionDropdownHandler alloc] initWithDialog:dialog
+                                         fileTypeLists:file_type_lists]);
+
+  // This establishes a weak reference to handler. Hence we persist it as part
+  // of dialog_data_map_.
+  [popup setTarget:handler];
+  [popup setAction:@selector(popupAction:)];
+
+  if (default_extension.empty()) {
+    // Select the first item.
+    [popup selectItemAtIndex:0];
+    [handler popupAction:popup];
+  } else {
+    [popup selectItemAtIndex:-1];
+    [dialog
+        setAllowedFileTypes:@[ base::SysUTF8ToNSString(default_extension) ]];
+  }
+
+  return handler;
 }
 
 bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() {
@@ -364,8 +403,7 @@
 @implementation SelectFileDialogBridge
 
 - (id)initWithSelectFileDialogImpl:(SelectFileDialogImpl*)s {
-  self = [super init];
-  if (self != nil) {
+  if ((self = [super init])) {
     selectFileDialogImpl_ = s;
   }
   return self;
@@ -418,6 +456,31 @@
 
 @end
 
+@implementation ExtensionDropdownHandler
+
+- (id)initWithDialog:(NSSavePanel*)dialog
+       fileTypeLists:(NSArray*)fileTypeLists {
+  if ((self = [super init])) {
+    dialog_ = dialog;
+    fileTypeLists_.reset([fileTypeLists retain]);
+  }
+  return self;
+}
+
+- (void)popupAction:(id)sender {
+  NSUInteger index = [sender indexOfSelectedItem];
+  if (index < [fileTypeLists_ count]) {
+    // For save dialogs, this causes the first item in the allowedFileTypes
+    // array to be used as the extension for the save panel.
+    [dialog_ setAllowedFileTypes:[fileTypeLists_ objectAtIndex:index]];
+  } else {
+    // The user selected "All files" option.
+    [dialog_ setAllowedFileTypes:nil];
+  }
+}
+
+@end
+
 namespace ui {
 
 SelectFileDialog* CreateMacSelectFileDialog(
diff --git a/ui/strings/ui_strings.grd b/ui/strings/ui_strings.grd
index 0de39886..03256ea 100644
--- a/ui/strings/ui_strings.grd
+++ b/ui/strings/ui_strings.grd
@@ -275,10 +275,12 @@
           Untitled Webpage
         </message>
       </if>
-      <if expr="is_win">
+      <if expr="is_win or is_macosx">
         <message name="IDS_APP_SAVEAS_ALL_FILES" desc="Save As dialog box default text">
           All Files
         </message>
+      </if>
+      <if expr="is_win">
         <message name="IDS_APP_SAVEAS_EXTENSION_FORMAT" desc="Save As dialog box extension format text">
           <ph name="SAVEAS_EXTENSION_TYPE">$1<ex>EXE</ex></ph> File (.<ph name="SAVEAS_EXTENSION_NAME">$2<ex>exe</ex></ph>)
         </message>